diff --git a/.gitignore b/.gitignore index 059ce10..fd8c1c6 100644 --- a/.gitignore +++ b/.gitignore @@ -434,3 +434,316 @@ firefox-3.6.4.source.tar.bz2 /firefox-langpacks-83.0-20201112.tar.xz /firefox-langpacks-83.0-20201116.tar.xz /firefox-testing.tar.gz +/site-packages.tar.gz +/mochitest-python.tar.gz +/firefox-84.0.source.tar.xz +/firefox-langpacks-84.0-20201210.tar.xz +/firefox-langpacks-84.0-20201214.tar.xz +/firefox-84.0.1.source.tar.xz +/firefox-langpacks-84.0.1-20201222.tar.xz +/firefox-84.0.2.source.tar.xz +/firefox-langpacks-84.0.2-20210106.tar.xz +/firefox-85.0.source.tar.xz +/firefox-langpacks-85.0-20210120.tar.xz +/firefox-85.0.1.source.tar.xz +/firefox-langpacks-85.0.1-20210208.tar.xz +/firefox-86.0.source.tar.xz +/firefox-langpacks-86.0-20210222.tar.xz +/firefox-86.0.1.source.tar.xz +/firefox-langpacks-86.0.1-20210312.tar.xz +/firefox-87.0.source.tar.xz +/firefox-langpacks-87.0-20210322.tar.xz +/firefox-langpacks-88.0-20210419.tar.xz +/firefox-88.0.source.tar.xz +/firefox-88.0.1.source.tar.xz +/firefox-langpacks-88.0.1-20210510.tar.xz +/firefox-langpacks-89.0-20210601.tar.xz +/firefox-89.0.source.tar.xz +/firefox-89.0.2.source.tar.xz +/firefox-langpacks-89.0.2-20210624.tar.xz +/firefox-90.0.source.tar.xz +/firefox-langpacks-90.0-20210712.tar.xz +/firefox-90.0.1.source.tar.xz +/firefox-langpacks-90.0.1-20210721.tar.xz +/firefox-90.0.2.source.tar.xz +/firefox-langpacks-90.0.2-20210722.tar.xz +/firefox-91.0.source.tar.xz +/firefox-langpacks-91.0-20210810.tar.xz +/firefox-91.0.2.source.tar.xz +/firefox-langpacks-91.0.2-20210826.tar.xz +/firefox-langpacks-92.0-20210903.tar.xz +/firefox-92.0.source.tar.xz +/firefox-92.0.1.source.tar.xz +/firefox-langpacks-92.0.1-20210927.tar.xz +/firefox-93.0.source.tar.xz +/firefox-langpacks-93.0-20210929.tar.xz +/firefox-94.0.source.tar.xz +/firefox-langpacks-94.0-20211031.tar.xz +/firefox-94.0.2.source.tar.xz +/firefox-langpacks-94.0.2-20211125.tar.xz +/firefox-95.0.source.tar.xz +/firefox-langpacks-95.0-20211203.tar.xz +/firefox-95.0.2.source.tar.xz +/firefox-langpacks-95.0.2-20211220.tar.xz +/firefox-96.0.source.tar.xz +/firefox-langpacks-96.0-20220111.tar.xz +/firefox-langpacks-96.0.1-20220118.tar.xz +/firefox-96.0.1.source.tar.xz +/firefox-96.0.3.source.tar.xz +/firefox-langpacks-96.0.3-20220131.tar.xz +/firefox-97.0.source.tar.xz +/firefox-langpacks-97.0-20220208.tar.xz +/firefox-97.0.1.source.tar.xz +/firefox-langpacks-97.0.1-20220218.tar.xz +/firefox-98.0.source.tar.xz +/firefox-langpacks-98.0-20220301.tar.xz +/firefox-langpacks-98.0-20220304.tar.xz +/firefox-langpacks-98.0-20220305.tar.xz +/firefox-98.0.2.source.tar.xz +/firefox-langpacks-98.0.2-20220331.tar.xz +/firefox-99.0.source.tar.xz +/firefox-langpacks-99.0-20220331.tar.xz +/firefox-langpacks-99.0.1-20220413.tar.xz +/firefox-99.0.1.source.tar.xz +/firefox-100.0.source.tar.xz +/firefox-langpacks-100.0-20220502.tar.xz +/firefox-100.0.1.source.tar.xz +/firefox-langpacks-100.0.1-20220518.tar.xz +/firefox-100.0.2.source.tar.xz +/firefox-langpacks-100.0.2-20220520.tar.xz +/firefox-101.0.source.tar.xz +/firefox-langpacks-101.0-20220530.tar.xz +/firefox-101.0.1.source.tar.xz +/firefox-langpacks-101.0.1-20220609.tar.xz +/firefox-102.0.source.tar.xz +/firefox-langpacks-102.0-20220628.tar.xz +/firefox-103.0.source.tar.xz +/firefox-langpacks-103.0-20220721.tar.xz +/firefox-103.0.1.source.tar.xz +/firefox-langpacks-103.0.1-20220802.tar.xz +/firefox-103.0.2.source.tar.xz +/firefox-langpacks-103.0.2-20220812.tar.xz +/firefox-104.0.source.tar.xz +/firefox-langpacks-104.0-20220816.tar.xz +/firefox-langpacks-104.0-20220822.tar.xz +/firefox-langpacks-104.0.1-20220830.tar.xz +/firefox-104.0.1.source.tar.xz +/firefox-104.0.2.source.tar.xz +/firefox-langpacks-104.0.2-20220906.tar.xz +/firefox-langpacks-105.0-20220920.tar.xz +/firefox-105.0.source.tar.xz +/firefox-105.0.1.source.tar.xz +/firefox-langpacks-105.0.1-20220922.tar.xz +/firefox-105.0.2.source.tar.xz +/firefox-langpacks-105.0.2-20221005.tar.xz +/firefox-langpacks-106.0-20221014.tar.xz +/firefox-106.0.source.tar.xz +/firefox-106.0.1.source.tar.xz +/firefox-langpacks-106.0.1-20221023.tar.xz +/firefox-106.0.3.source.tar.xz +/firefox-langpacks-106.0.3-20221031.tar.xz +/firefox-langpacks-107.0-20221114.tar.xz +/firefox-107.0.source.tar.xz +/firefox-107.0.1.source.tar.xz +/firefox-langpacks-107.0.1-20221206.tar.xz +/firefox-108.0.source.tar.xz +/firefox-langpacks-108.0-20221206.tar.xz +/firefox-langpacks-108.0-20221214.tar.xz +/firefox-108.0.1.source.tar.xz +/firefox-langpacks-108.0.1-20221218.tar.xz +/firefox-108.0.2.source.tar.xz +/firefox-langpacks-108.0.2-20230112.tar.xz +/firefox-109.0.source.tar.xz +/firefox-langpacks-109.0-20230111.tar.xz +/firefox-109.0.1.source.tar.xz +/firefox-langpacks-109.0.1-20230201.tar.xz +/firefox-110.0.source.tar.xz +/firefox-langpacks-110.0-20230210.tar.xz +/firefox-langpacks-110.0-20230214.tar.xz +/firefox-111.0.source.tar.xz +/firefox-langpacks-111.0-20230320.tar.xz +/firefox-langpacks-111.0.1-20230322.tar.xz +/firefox-111.0.1.source.tar.xz +/firefox-112.0.source.tar.xz +/firefox-langpacks-112.0-20230405.tar.xz +/firefox-langpacks-112.0-20230406.tar.xz +/firefox-langpacks-112.0.1-20230417.tar.xz +/firefox-112.0.1.source.tar.xz +/firefox-langpacks-112.0.2-20230427.tar.xz +/firefox-112.0.2.source.tar.xz +/firefox-langpacks-113.0-20230509.tar.xz +/firefox-113.0.source.tar.xz +/firefox-langpacks-113.0.1-20230515.tar.xz +/firefox-113.0.1.source.tar.xz +/firefox-114.0.source.tar.xz +/firefox-langpacks-114.0-20230605.tar.xz +/firefox-langpacks-114.0.2-20230620.tar.xz +/firefox-114.0.2.source.tar.xz +/firefox-langpacks-115.0-20230629.tar.xz +/firefox-115.0.source.tar.xz +/firefox-langpacks-115.0-20230703.tar.xz +/firefox-115.0.2.source.tar.xz +/firefox-langpacks-115.0.2-20230717.tar.xz +/firefox-116.0.source.tar.xz +/firefox-langpacks-116.0-20230725.tar.xz +/firefox-langpacks-116.0-20230731.tar.xz +/firefox-116.0.1.source.tar.xz +/firefox-langpacks-116.0.1-20230804.tar.xz +/firefox-langpacks-116.0.2-20230807.tar.xz +/firefox-116.0.2.source.tar.xz +/firefox-langpacks-116.0.3-20230817.tar.xz +/firefox-116.0.3.source.tar.xz +/firefox-117.0.source.tar.xz +/firefox-langpacks-117.0-20230828.tar.xz +/firefox-117.0.1.source.tar.xz +/firefox-langpacks-117.0.1-20230913.tar.xz +/firefox-118.0.source.tar.xz +/firefox-langpacks-118.0-20230925.tar.xz +/firefox-langpacks-118.0.1-20230929.tar.xz +/firefox-118.0.1.source.tar.xz +/firefox-118.0.2.source.tar.xz +/firefox-langpacks-118.0.2-20231010.tar.xz +/dump_syms-vendor.tar.xz +/firefox-langpacks-119.0.1-20231110.tar.xz +/firefox-119.0.1.source.tar.xz +/firefox-120.0.source.tar.xz +/firefox-langpacks-120.0-20231114.tar.xz +/firefox-langpacks-120.0-20231120.tar.xz +/firefox-120.0.1.source.tar.xz +/firefox-langpacks-120.0.1-20231201.tar.xz +/firefox-121.0.source.tar.xz +/firefox-langpacks-121.0-20231218.tar.xz +/firefox-121.0.1.source.tar.xz +/firefox-langpacks-121.0.1-20240112.tar.xz +/firefox-122.0.source.tar.xz +/firefox-langpacks-122.0-20240119.tar.xz +/firefox-langpacks-122.0.1-20240213.tar.xz +/firefox-122.0.1.source.tar.xz +/firefox-langpacks-123.0-20240219.tar.xz +/firefox-123.0.source.tar.xz +/firefox-123.0.1.source.tar.xz +/firefox-langpacks-123.0.1-20240307.tar.xz +/firefox-124.0.source.tar.xz +/firefox-langpacks-124.0-20240313.tar.xz +/firefox-124.0.1.source.tar.xz +/firefox-langpacks-124.0.1-20240322.tar.xz +/wasi-sdk-20.tar.gz +/wasi-sdk-20-1.fc39.src.rpm +/firefox-124.0.2.source.tar.xz +/firefox-langpacks-124.0.2-20240404.tar.xz +/firefox-langpacks-125.0-20240409.tar.xz +/firefox-125.0.source.tar.xz +/firefox-125.0.2.source.tar.xz +/firefox-langpacks-125.0.2-20240420.tar.xz +/firefox-125.0.3.source.tar.xz +/firefox-langpacks-125.0.3-20240429.tar.xz +/firefox-126.0.source.tar.xz +/firefox-langpacks-126.0-20240507.tar.xz +/firefox-127.0.source.tar.xz +/firefox-langpacks-127.0-20240610.tar.xz +/firefox-langpacks-127.0.2-20240625.tar.xz +/firefox-127.0.2.source.tar.xz +/firefox-128.0.source.tar.xz +/firefox-langpacks-128.0-20240702.tar.xz +/firefox-langpacks-128.0-20240708.tar.xz +/firefox-128.0.3.source.tar.xz +/firefox-langpacks-128.0.3-20240729.tar.xz +/firefox-129.0.source.tar.xz +/firefox-langpacks-129.0-20240730.tar.xz +/firefox-langpacks-129.0-20240802.tar.xz +/firefox-129.0.2.source.tar.xz +/firefox-langpacks-192.0.2-20240820.tar.xz +/firefox-langpacks-129.0.2-20240820.tar.xz +/firefox-langpacks-130.0-20240828.tar.xz +/firefox-130.0.source.tar.xz +/firefox-130.0.1.source.tar.xz +/firefox-langpacks-130.0.1-20240918.tar.xz +/firefox-langpacks-131.0-20240924.tar.xz +/firefox-131.0.source.tar.xz +/firefox-131.0.2.source.tar.xz +/firefox-langpacks-131.0.2-20241009.tar.xz +/firefox-131.0.3.source.tar.xz +/firefox-langpacks-131.0.3-20241015.tar.xz +/firefox-132.0.source.tar.xz +/firefox-langpacks-132.0-20241023.tar.xz +/firefox-132.0.1.source.tar.xz +/firefox-langpacks-132.0.1-20241105.tar.xz +/firefox-langpacks-132.0.2-20241115.tar.xz +/firefox-132.0.2.source.tar.xz +/firefox-133.0.source.tar.xz +/firefox-langpacks-133.0-20241122.tar.xz +/firefox-langpacks-133.0.3-20241211.tar.xz +/firefox-133.0.3.source.tar.xz +/firefox-langpacks-134.0-20250102.tar.xz +/firefox-134.0.source.tar.xz +/firefox-langpacks-134.0.1-20250115.tar.xz +/firefox-134.0.1.source.tar.xz +/firefox-134.0.2.source.tar.xz +/firefox-langpacks-134.0.2-20250122.tar.xz +/wasi-sdk-25.tar.gz +/wasm-component-ld-vendor.tar.xz +/firefox-135.0.source.tar.xz +/firefox-langpacks-135.0-20250204.tar.xz +/firefox-136.0.source.tar.xz +/firefox-langpacks-136.0-20250225.tar.xz +/firefox-langpacks-136.0-20250228.tar.xz +/firefox-136.0.1.source.tar.xz +/firefox-langpacks-136.0.1-20250312.tar.xz +/firefox-langpacks-136.0.2-20250319.tar.xz +/firefox-136.0.2.source.tar.xz +/firefox-136.0.3.source.tar.xz +/firefox-langpacks-136.0.3-20250325.tar.xz +/firefox-langpacks-137.0-20250326.tar.xz +/firefox-137.0.source.tar.xz +/firefox-langpacks-137.0-20250331.tar.xz +/firefox-137.0.1.source.tar.xz +/firefox-langpacks-137.0.1-20250414.tar.xz +/firefox-138.0.source.tar.xz +/firefox-langpacks-138.0-20250422.tar.xz +/firefox-langpacks-138.0.1-20250501.tar.xz +/firefox-138.0.1.source.tar.xz +/firefox-138.0.3.source.tar.xz +/firefox-langpacks-138.0.3-20250512.tar.xz +/firefox-langpacks-138.0.4-20250519.tar.xz +/firefox-138.0.4.source.tar.xz +/firefox-139.0.source.tar.xz +/firefox-langpacks-139.0-20250527.tar.xz +/firefox-langpacks-139.0.4-20250610.tar.xz +/firefox-139.0.4.source.tar.xz +/firefox-140.0.source.tar.xz +/firefox-langpacks-140.0-20250617.tar.xz +/firefox-140.0.1.source.tar.xz +/firefox-langpacks-140.0.1-20250627.tar.xz +/firefox-140.0.4.source.tar.xz +/firefox-langpacks-140.0.4-20250708.tar.xz +/firefox-141.0.source.tar.xz +/firefox-langpacks-141.0-20250717.tar.xz +/firefox-langpacks-141.0-20250718.tar.xz +/firefox-langpacks-141.2.0-20250806.tar.xz +/firefox-141.0.2.source.tar.xz +/firefox-langpacks-141.0.2-20250806.tar.xz +/firefox-langpacks-141.0.3-20250811.tar.xz +/firefox-141.0.3.source.tar.xz +/firefox-142.0.source.tar.xz +/firefox-langpacks-142.0-20250812.tar.xz +/firefox-langpacks-142.0.1-20250827.tar.xz +/firefox-142.0.1.source.tar.xz +/firefox-143.0.1.source.tar.xz +/firefox-langpacks-143.0.1-20250919.tar.xz +/firefox-langpacks-143.0.3-20250930.tar.xz +/firefox-143.0.3.source.tar.xz +/firefox-langpacks-144.0-20251009.tar.xz +/firefox-144.0.source.tar.xz +/firefox-langpacks-144.0-20251010.tar.xz +/firefox-145.0.source.tar.xz +/firefox-langpacks-145.0-20251105.tar.xz +/firefox-langpacks-145.0-20251111.tar.xz +/firefox-145.0.1.source.tar.xz +/firefox-langpacks-145.0.1-20251119.tar.xz +/firefox-146.0.source.tar.xz +/firefox-langpacks-146.0-20251202.tar.xz +/firefox-langpacks-146.0-20251208.tar.xz +/firefox-146.0.1.source.tar.xz +/firefox-langpacks-146.0.1-20251219.tar.xz +/firefox-langpacks-147.0-20260106.tar.xz +/firefox-147.0.source.tar.xz diff --git a/0001-GLIBCXX-fix-for-GCC-12.patch b/0001-GLIBCXX-fix-for-GCC-12.patch new file mode 100644 index 0000000..55153a1 --- /dev/null +++ b/0001-GLIBCXX-fix-for-GCC-12.patch @@ -0,0 +1,31 @@ +diff -up firefox-142.0/build/unix/stdc++compat/stdc++compat.cpp.0001-GLIBCXX-fix-for-GCC-12 firefox-142.0/build/unix/stdc++compat/stdc++compat.cpp +--- firefox-142.0/build/unix/stdc++compat/stdc++compat.cpp.0001-GLIBCXX-fix-for-GCC-12 2025-08-11 20:04:27.000000000 +0200 ++++ firefox-142.0/build/unix/stdc++compat/stdc++compat.cpp 2025-08-14 15:02:05.496137133 +0200 +@@ -24,6 +24,7 @@ + GLIBCXX_3.4.27 is from gcc 10 + GLIBCXX_3.4.28 is from gcc 10 + GLIBCXX_3.4.29 is from gcc 11 ++ GLIBCXX_3.4.30 is from gcc 12 + + This file adds the necessary compatibility tricks to avoid symbols with + version GLIBCXX_3.4.20 and bigger, keeping binary compatibility with +@@ -94,6 +95,19 @@ void operator delete(void* ptr, size_t s + } + # endif + ++#if _GLIBCXX_RELEASE >= 12 ++namespace std { ++ ++/* This avoids the GLIBCXX_3.4.30 symbol version. */ ++void __attribute__((weak)) ++__glibcxx_assert_fail(const char* __file, int __line, const char* __function, ++ const char* __condition) { ++ MOZ_CRASH(); ++} ++ ++} // namespace std ++#endif ++ + /* While we generally don't build with exceptions, we have some host tools + * that do use them. libstdc++ from GCC 5.0 added exception constructors with + * char const* argument. Older versions only have a constructor with diff --git a/0025-Add-KDE-integration-to-Firefox-toolkit-parts.patch b/0025-Add-KDE-integration-to-Firefox-toolkit-parts.patch new file mode 100644 index 0000000..bd543b3 --- /dev/null +++ b/0025-Add-KDE-integration-to-Firefox-toolkit-parts.patch @@ -0,0 +1,1343 @@ +diff -up firefox-119.0/modules/libpref/moz.build.integration firefox-119.0/modules/libpref/moz.build +--- firefox-119.0/modules/libpref/moz.build.integration 2023-10-19 21:54:34.000000000 +0200 ++++ firefox-119.0/modules/libpref/moz.build 2023-10-31 08:59:03.719124766 +0100 +@@ -126,6 +126,10 @@ UNIFIED_SOURCES += [ + "SharedPrefMap.cpp", + ] + ++LOCAL_INCLUDES += [ ++ '/toolkit/xre' ++] ++ + gen_all_tuple = tuple(gen_h + gen_cpp + gen_rs) + + GeneratedFile( +diff -up firefox-119.0/modules/libpref/Preferences.cpp.integration firefox-119.0/modules/libpref/Preferences.cpp +--- firefox-119.0/modules/libpref/Preferences.cpp.integration 2023-10-19 21:54:34.000000000 +0200 ++++ firefox-119.0/modules/libpref/Preferences.cpp 2023-10-31 08:59:03.719124766 +0100 +@@ -95,6 +95,7 @@ + #ifdef MOZ_BACKGROUNDTASKS + # include "mozilla/BackgroundTasks.h" + #endif ++#include "nsKDEUtils.h" + + #ifdef DEBUG + # include +diff -up firefox-119.0/python/mozbuild/mozpack/chrome/flags.py.integration firefox-119.0/python/mozbuild/mozpack/chrome/flags.py +--- firefox-119.0/python/mozbuild/mozpack/chrome/flags.py.integration 2023-10-19 21:54:34.000000000 +0200 ++++ firefox-119.0/python/mozbuild/mozpack/chrome/flags.py 2023-10-31 08:59:03.719124766 +0100 +@@ -234,6 +234,7 @@ class Flags(OrderedDict): + "tablet": Flag, + "process": StringFlag, + "backgroundtask": StringFlag, ++ "desktop": StringFlag, + } + RE = re.compile(r"([!<>=]+)") + +diff -up firefox-119.0/python/mozbuild/mozpack/chrome/manifest.py.integration firefox-119.0/python/mozbuild/mozpack/chrome/manifest.py +--- firefox-119.0/python/mozbuild/mozpack/chrome/manifest.py.integration 2023-10-19 21:54:34.000000000 +0200 ++++ firefox-119.0/python/mozbuild/mozpack/chrome/manifest.py 2023-10-31 08:59:03.719124766 +0100 +@@ -43,6 +43,7 @@ class ManifestEntry(object): + "process", + "contentaccessible", + "backgroundtask", ++ "desktop", + ] + + def __init__(self, base, *flags): +diff -up firefox-119.0/toolkit/components/downloads/moz.build.integration firefox-119.0/toolkit/components/downloads/moz.build +--- firefox-119.0/toolkit/components/downloads/moz.build.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/toolkit/components/downloads/moz.build 2023-10-31 08:59:03.720124801 +0100 +@@ -51,5 +51,9 @@ if CONFIG["MOZ_PLACES"]: + + FINAL_LIBRARY = "xul" + ++LOCAL_INCLUDES += [ ++ '/toolkit/xre' ++] ++ + with Files("**"): + BUG_COMPONENT = ("Toolkit", "Downloads API") +diff -up firefox-119.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs.integration firefox-119.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs +--- firefox-119.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/toolkit/mozapps/downloads/HelperAppDlg.sys.mjs 2023-10-31 08:59:03.720124801 +0100 +@@ -1246,26 +1246,56 @@ nsUnknownContentTypeDialog.prototype = { + this.chosenApp = params.handlerApp; + } + } else if ("@mozilla.org/applicationchooser;1" in Cc) { +- var nsIApplicationChooser = Ci.nsIApplicationChooser; +- var appChooser = Cc["@mozilla.org/applicationchooser;1"].createInstance( +- nsIApplicationChooser +- ); +- appChooser.init( +- this.mDialog, +- this.dialogElement("strings").getString("chooseAppFilePickerTitle") +- ); +- var contentTypeDialogObj = this; +- let appChooserCallback = function appChooserCallback_done(aResult) { +- if (aResult) { +- contentTypeDialogObj.chosenApp = aResult.QueryInterface( +- Ci.nsILocalHandlerApp +- ); +- } +- contentTypeDialogObj.finishChooseApp(); +- }; +- appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback); +- // The finishChooseApp is called from appChooserCallback +- return; ++ // handle the KDE case which is implemented in the filepicker ++ // therefore falling back to Gtk2 like behaviour if KDE is running ++ // FIXME this should be better handled in the nsIApplicationChooser ++ // interface ++ var env = Components.classes["@mozilla.org/process/environment;1"] ++ .getService(Components.interfaces.nsIEnvironment); ++ if (env.get('KDE_FULL_SESSION') == "true") ++ { ++ var nsIFilePicker = Ci.nsIFilePicker; ++ var fp = Cc["@mozilla.org/filepicker;1"] ++ .createInstance(nsIFilePicker); ++ fp.init(this.mDialog, ++ this.dialogElement("strings").getString("chooseAppFilePickerTitle"), ++ nsIFilePicker.modeOpen); ++ ++ fp.appendFilters(nsIFilePicker.filterApps); ++ ++ fp.open(aResult => { ++ if (aResult == nsIFilePicker.returnOK && fp.file) { ++ // Remember the file they chose to run. ++ var localHandlerApp = ++ Cc["@mozilla.org/uriloader/local-handler-app;1"]. ++ createInstance(Ci.nsILocalHandlerApp); ++ localHandlerApp.executable = fp.file; ++ this.chosenApp = localHandlerApp; ++ } ++ this.finishChooseApp(); ++ }); ++ } else { ++ var nsIApplicationChooser = Ci.nsIApplicationChooser; ++ var appChooser = Cc["@mozilla.org/applicationchooser;1"].createInstance( ++ nsIApplicationChooser ++ ); ++ appChooser.init( ++ this.mDialog, ++ this.dialogElement("strings").getString("chooseAppFilePickerTitle") ++ ); ++ var contentTypeDialogObj = this; ++ let appChooserCallback = function appChooserCallback_done(aResult) { ++ if (aResult) { ++ contentTypeDialogObj.chosenApp = aResult.QueryInterface( ++ Ci.nsILocalHandlerApp ++ ); ++ } ++ contentTypeDialogObj.finishChooseApp(); ++ }; ++ appChooser.open(this.mLauncher.MIMEInfo.MIMEType, appChooserCallback); ++ // The finishChooseApp is called from appChooserCallback ++ return; ++ } + } else { + var nsIFilePicker = Ci.nsIFilePicker; + var fp = Cc["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); +diff -up firefox-119.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.integration firefox-119.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp +--- firefox-119.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/toolkit/system/unixproxy/nsUnixSystemProxySettings.cpp 2023-10-31 08:59:03.720124801 +0100 +@@ -16,6 +16,8 @@ + #include "nsISupportsPrimitives.h" + #include "nsIGSettingsService.h" + #include "nsReadableUtils.h" ++#include "nsPrintfCString.h" ++#include "nsKDEUtils.h" + + using namespace mozilla; + +@@ -39,6 +41,8 @@ class nsUnixSystemProxySettings final : + nsACString& aResult); + nsresult SetProxyResultFromGSettings(const char* aKeyBase, const char* aType, + nsACString& aResult); ++ nsresult GetProxyFromKDE(const nsACString& aScheme, const nsACString& aHost, ++ PRInt32 aPort, nsACString& aResult); + }; + + NS_IMPL_ISUPPORTS(nsUnixSystemProxySettings, nsISystemProxySettings) +@@ -393,6 +397,9 @@ nsresult nsUnixSystemProxySettings::GetP + const nsACString& aHost, + const int32_t aPort, + nsACString& aResult) { ++ if (nsKDEUtils::kdeSupport()) ++ return GetProxyFromKDE(aScheme, aHost, aPort, aResult); ++ + if (mProxySettings) { + nsresult rv = GetProxyFromGSettings(aScheme, aHost, aPort, aResult); + if (NS_SUCCEEDED(rv)) return rv; +@@ -401,6 +408,28 @@ nsresult nsUnixSystemProxySettings::GetP + return GetProxyFromEnvironment(aScheme, aHost, aPort, aResult); + } + ++nsresult nsUnixSystemProxySettings::GetProxyFromKDE(const nsACString& aScheme, ++ const nsACString& aHost, ++ PRInt32 aPort, ++ nsACString& aResult) { ++ nsAutoCString url; ++ url = aScheme; ++ url += "://"; ++ url += aHost; ++ if (aPort >= 0) { ++ url += ":"; ++ url += nsPrintfCString("%d", aPort); ++ } ++ nsTArray command; ++ command.AppendElement("GETPROXY"_ns); ++ command.AppendElement(url); ++ nsTArray result; ++ if (!nsKDEUtils::command(command, &result) || result.Length() != 1) ++ return NS_ERROR_FAILURE; ++ aResult = result[0]; ++ return NS_OK; ++} ++ + NS_IMPL_COMPONENT_FACTORY(nsUnixSystemProxySettings) { + auto result = MakeRefPtr(); + result->Init(); +diff -up firefox-119.0/toolkit/xre/moz.build.integration firefox-119.0/toolkit/xre/moz.build +--- firefox-119.0/toolkit/xre/moz.build.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/toolkit/xre/moz.build 2023-10-31 08:59:03.720124801 +0100 +@@ -96,7 +96,9 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "ui + "UIKitDirProvider.mm", + ] + elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": ++ EXPORTS += ['nsKDEUtils.h'] + UNIFIED_SOURCES += [ ++ "nsKDEUtils.cpp", + "nsNativeAppSupportUnix.cpp", + ] + CXXFLAGS += CONFIG["MOZ_X11_SM_CFLAGS"] +diff -up firefox-119.0/toolkit/xre/nsKDEUtils.cpp.integration firefox-119.0/toolkit/xre/nsKDEUtils.cpp +--- firefox-119.0/toolkit/xre/nsKDEUtils.cpp.integration 2023-10-31 08:59:03.721124836 +0100 ++++ firefox-119.0/toolkit/xre/nsKDEUtils.cpp 2023-10-31 08:59:03.721124836 +0100 +@@ -0,0 +1,286 @@ ++/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "nsKDEUtils.h" ++#include "nsIWidget.h" ++#include "nsISupportsPrimitives.h" ++#include "nsIMutableArray.h" ++#include "nsComponentManagerUtils.h" ++#include "nsArrayUtils.h" ++ ++#include ++ ++#include ++#include ++#include ++#include ++#include ++#include ++// copied from X11/X.h as a hack since for an unknown ++// reason it's not picked up from X11/X.h ++#ifndef None ++# define None 0L /* universal null resource or null atom */ ++#endif ++ ++// #define DEBUG_KDE ++#ifdef DEBUG_KDE ++# define KMOZILLAHELPER "kmozillahelper" ++#else ++// not need for lib64, it's a binary ++# define KMOZILLAHELPER "/usr/lib/mozilla/kmozillahelper" ++#endif ++ ++#define KMOZILLAHELPER_VERSION 6 ++#define MAKE_STR2(n) #n ++#define MAKE_STR(n) MAKE_STR2(n) ++ ++static bool getKdeSession() { ++ if (PR_GetEnv("KDE_FULL_SESSION")) { ++ return true; ++ } ++ return false; ++} ++ ++static bool getKdeSupport() { ++ nsTArray command; ++ command.AppendElement("CHECK"_ns); ++ command.AppendElement("KMOZILLAHELPER_VERSION"_ns); ++ bool kde = nsKDEUtils::command(command); ++#ifdef DEBUG_KDE ++ fprintf(stderr, "KDE RUNNING %d\n", kde); ++#endif ++ return kde; ++} ++ ++nsKDEUtils::nsKDEUtils() : commandFile(NULL), replyFile(NULL) {} ++ ++nsKDEUtils::~nsKDEUtils() { ++ // closeHelper(); not actually useful, exiting will close the fd too ++} ++ ++nsKDEUtils* nsKDEUtils::self() { ++ static nsKDEUtils s; ++ return &s; ++} ++ ++static bool helperRunning = false; ++static bool helperFailed = false; ++ ++bool nsKDEUtils::kdeSession() { ++ static bool session = getKdeSession(); ++ return session; ++} ++ ++bool nsKDEUtils::kdeSupport() { ++ static bool support = kdeSession() && getKdeSupport(); ++ return support && helperRunning; ++} ++ ++struct nsKDECommandData { ++ FILE* file; ++ nsTArray* output; ++ GMainLoop* loop; ++ bool success; ++}; ++ ++static gboolean kdeReadFunc(GIOChannel*, GIOCondition, gpointer data) { ++ nsKDECommandData* p = static_cast(data); ++ char buf[8192]; // TODO big enough ++ bool command_done = false; ++ bool command_failed = false; ++ while (!command_done && !command_failed && ++ fgets(buf, 8192, p->file) != ++ NULL) { // TODO what if the kernel splits a line into two chunks? ++ // #ifdef DEBUG_KDE ++ // fprintf( stderr, "READ: %s %d\n", buf, feof( p->file )); ++ // #endif ++ if (char* eol = strchr(buf, '\n')) *eol = '\0'; ++ command_done = (strcmp(buf, "\\1") == 0); ++ command_failed = (strcmp(buf, "\\0") == 0); ++ nsAutoCString line(buf); ++ line.ReplaceSubstring("\\n", "\n"); ++ line.ReplaceSubstring( ++ "\\" ++ "\\", ++ "\\"); // \\ -> \ , i.e. unescape ++ if (p->output && !(command_done || command_failed)) ++ p->output->AppendElement(nsCString(buf)); // TODO utf8? ++ } ++ bool quit = false; ++ if (feof(p->file) || command_failed) { ++ quit = true; ++ p->success = false; ++ } ++ if (command_done) { // reading one reply finished ++ quit = true; ++ p->success = true; ++ } ++ if (quit) { ++ if (p->loop) g_main_loop_quit(p->loop); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++bool nsKDEUtils::command(const nsTArray& command, ++ nsTArray* output) { ++ return self()->internalCommand(command, NULL, false, output); ++} ++ ++bool nsKDEUtils::command(nsIArray* command, nsIArray** output) { ++ nsTArray in; ++ PRUint32 length; ++ command->GetLength(&length); ++ for (PRUint32 i = 0; i < length; i++) { ++ nsCOMPtr str = do_QueryElementAt(command, i); ++ if (str) { ++ nsAutoCString s; ++ str->GetData(s); ++ in.AppendElement(s); ++ } ++ } ++ ++ nsTArray out; ++ bool ret = self()->internalCommand(in, NULL, false, &out); ++ ++ if (!output) return ret; ++ ++ nsCOMPtr result = do_CreateInstance(NS_ARRAY_CONTRACTID); ++ if (!result) return false; ++ ++ for (PRUint32 i = 0; i < out.Length(); i++) { ++ nsCOMPtr rstr = ++ do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID); ++ if (!rstr) return false; ++ ++ rstr->SetData(out[i]); ++ result->AppendElement(rstr); ++ } ++ ++ NS_ADDREF(*output = result); ++ return ret; ++} ++ ++bool nsKDEUtils::commandBlockUi(const nsTArray& command, ++ GtkWindow* parent, ++ nsTArray* output) { ++ return self()->internalCommand(command, parent, true, output); ++} ++ ++bool nsKDEUtils::internalCommand(const nsTArray& command, ++ GtkWindow* parent, bool blockUi, ++ nsTArray* output) { ++ if (!startHelper()) return false; ++ feedCommand(command); ++ // do not store the data in 'this' but in extra structure, just in case there ++ // is reentrancy (can there be? the event loop is re-entered) ++ nsKDECommandData data; ++ data.file = replyFile; ++ data.output = output; ++ data.success = false; ++ if (blockUi) { ++ data.loop = g_main_loop_new(NULL, FALSE); ++ GtkWidget* window = gtk_window_new(GTK_WINDOW_TOPLEVEL); ++ if (parent && gtk_window_get_group(parent)) ++ gtk_window_group_add_window(gtk_window_get_group(parent), ++ GTK_WINDOW(window)); ++ gtk_widget_realize(window); ++ gtk_widget_set_sensitive(window, TRUE); ++ gtk_grab_add(window); ++ GIOChannel* channel = g_io_channel_unix_new(fileno(data.file)); ++ g_io_add_watch(channel, ++ static_cast(G_IO_IN | G_IO_ERR | G_IO_HUP), ++ kdeReadFunc, &data); ++ g_io_channel_unref(channel); ++ g_main_loop_run(data.loop); ++ g_main_loop_unref(data.loop); ++ gtk_grab_remove(window); ++ gtk_widget_destroy(window); ++ } else { ++ data.loop = NULL; ++ while (kdeReadFunc(NULL, static_cast(0), &data)) ++ ; ++ } ++ return data.success; ++} ++ ++bool nsKDEUtils::startHelper() { ++ if (helperRunning) return true; ++ if (helperFailed) return false; ++ helperFailed = true; ++ int fdcommand[2]; ++ int fdreply[2]; ++ if (pipe(fdcommand) < 0) return false; ++ if (pipe(fdreply) < 0) { ++ close(fdcommand[0]); ++ close(fdcommand[1]); ++ return false; ++ } ++ char* args[2] = {const_cast(KMOZILLAHELPER), NULL}; ++ switch (fork()) { ++ case -1: { ++ close(fdcommand[0]); ++ close(fdcommand[1]); ++ close(fdreply[0]); ++ close(fdreply[1]); ++ return false; ++ } ++ case 0: // child ++ { ++ if (dup2(fdcommand[0], STDIN_FILENO) < 0) _exit(1); ++ if (dup2(fdreply[1], STDOUT_FILENO) < 0) _exit(1); ++ int maxfd = 1024; // close all other fds ++ struct rlimit rl; ++ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) maxfd = rl.rlim_max; ++ for (int i = 3; i < maxfd; ++i) close(i); ++#ifdef DEBUG_KDE ++ execvp(KMOZILLAHELPER, args); ++#else ++ execv(KMOZILLAHELPER, args); ++#endif ++ _exit(1); // failed ++ } ++ default: // parent ++ { ++ commandFile = fdopen(fdcommand[1], "w"); ++ replyFile = fdopen(fdreply[0], "r"); ++ close(fdcommand[0]); ++ close(fdreply[1]); ++ if (commandFile == NULL || replyFile == NULL) { ++ closeHelper(); ++ return false; ++ } ++ // ok, helper ready, getKdeRunning() will check if it works ++ } ++ } ++ helperFailed = false; ++ helperRunning = true; ++ return true; ++} ++ ++void nsKDEUtils::closeHelper() { ++ if (commandFile != NULL) ++ fclose(commandFile); // this will also make the helper quit ++ if (replyFile != NULL) fclose(replyFile); ++ helperRunning = false; ++} ++ ++void nsKDEUtils::feedCommand(const nsTArray& command) { ++ for (int i = 0; i < command.Length(); ++i) { ++ nsCString line = command[i]; ++ line.ReplaceSubstring("\\", ++ "\\" ++ "\\"); // \ -> \\ , i.e. escape ++ line.ReplaceSubstring("\n", "\\n"); ++#ifdef DEBUG_KDE ++ fprintf(stderr, "COMM: %s\n", line.get()); ++#endif ++ fputs(line.get(), commandFile); ++ fputs("\n", commandFile); ++ } ++ fputs("\\E\n", ++ commandFile); // done as \E, so it cannot happen in normal data ++ fflush(commandFile); ++} +diff -up firefox-119.0/toolkit/xre/nsKDEUtils.h.integration firefox-119.0/toolkit/xre/nsKDEUtils.h +--- firefox-119.0/toolkit/xre/nsKDEUtils.h.integration 2023-10-31 08:59:03.721124836 +0100 ++++ firefox-119.0/toolkit/xre/nsKDEUtils.h 2023-10-31 08:59:03.721124836 +0100 +@@ -0,0 +1,53 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#ifndef nsKDEUtils_h__ ++#define nsKDEUtils_h__ ++ ++#include "nsString.h" ++#include "nsTArray.h" ++#include ++ ++typedef struct _GtkWindow GtkWindow; ++ ++class nsIArray; ++ ++class NS_EXPORT nsKDEUtils { ++ public: ++ /* Returns true if running inside a KDE session (regardless of whether there ++ is KDE support available for Firefox). This should be used e.g. when ++ determining dialog button order but not for code that requires the KDE ++ support. */ ++ static bool kdeSession(); ++ /* Returns true if running inside a KDE session and KDE support is available ++ for Firefox. This should be used everywhere where the external helper is ++ needed. */ ++ static bool kdeSupport(); ++ /* Executes the given helper command, returns true if helper returned success. ++ */ ++ static bool command(const nsTArray& command, ++ nsTArray* output = NULL); ++ static bool command(nsIArray* command, nsIArray** output = NULL); ++ /* Like command(), but additionally blocks the parent widget like if there was ++ a modal dialog shown and enters the event loop (i.e. there are still paint ++ updates, this is for commands that take long). */ ++ static bool commandBlockUi(const nsTArray& command, ++ GtkWindow* parent, ++ nsTArray* output = NULL); ++ ++ private: ++ nsKDEUtils(); ++ ~nsKDEUtils(); ++ static nsKDEUtils* self(); ++ bool startHelper(); ++ void closeHelper(); ++ void feedCommand(const nsTArray& command); ++ bool internalCommand(const nsTArray& command, GtkWindow* parent, ++ bool isParent, nsTArray* output); ++ FILE* commandFile; ++ FILE* replyFile; ++}; ++ ++#endif // nsKDEUtils +diff -up firefox-119.0/uriloader/exthandler/HandlerServiceParent.cpp.integration firefox-119.0/uriloader/exthandler/HandlerServiceParent.cpp +--- firefox-119.0/uriloader/exthandler/HandlerServiceParent.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/uriloader/exthandler/HandlerServiceParent.cpp 2023-10-31 08:59:03.721124836 +0100 +@@ -18,7 +18,7 @@ + #include "nsComponentManagerUtils.h" + #include "nsServiceManagerUtils.h" + #ifdef MOZ_WIDGET_GTK +-# include "unix/nsGNOMERegistry.h" ++# include "unix/nsCommonRegistry.h" + #endif + + using mozilla::dom::ContentHandlerService; +@@ -310,8 +310,8 @@ mozilla::ipc::IPCResult HandlerServicePa + } + #ifdef MOZ_WIDGET_GTK + // Check the GNOME registry for a protocol handler +- *aHandlerExists = +- nsGNOMERegistry::HandlerExists(PromiseFlatCString(aProtocolScheme).get()); ++ *aHandlerExists = nsCommonRegistry::HandlerExists( ++ PromiseFlatCString(aProtocolScheme).get()); + #else + *aHandlerExists = false; + #endif +diff -up firefox-119.0/uriloader/exthandler/moz.build.integration firefox-119.0/uriloader/exthandler/moz.build +--- firefox-119.0/uriloader/exthandler/moz.build.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/uriloader/exthandler/moz.build 2023-10-31 08:59:03.721124836 +0100 +@@ -86,7 +86,9 @@ else: + + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + UNIFIED_SOURCES += [ ++ "unix/nsCommonRegistry.cpp", + "unix/nsGNOMERegistry.cpp", ++ "unix/nsKDERegistry.cpp", + "unix/nsMIMEInfoUnix.cpp", + ] + elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "android": +@@ -134,6 +136,7 @@ LOCAL_INCLUDES += [ + "/dom/ipc", + "/netwerk/base", + "/netwerk/protocol/http", ++ "/toolkit/xre", + ] + + if CONFIG["MOZ_ENABLE_DBUS"]: +diff -up firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.integration firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.cpp +--- firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.cpp.integration 2023-10-31 08:59:03.721124836 +0100 ++++ firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.cpp 2023-10-31 08:59:03.721124836 +0100 +@@ -0,0 +1,42 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "nsCommonRegistry.h" ++ ++#include "nsGNOMERegistry.h" ++#include "nsKDERegistry.h" ++#include "nsString.h" ++#include "nsKDEUtils.h" ++ ++/* static */ bool nsCommonRegistry::HandlerExists(const char* aProtocolScheme) { ++ if (nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::HandlerExists(aProtocolScheme); ++ return nsGNOMERegistry::HandlerExists(aProtocolScheme); ++} ++ ++/* static */ nsresult nsCommonRegistry::LoadURL(nsIURI* aURL) { ++ if (nsKDEUtils::kdeSupport()) return nsKDERegistry::LoadURL(aURL); ++ return nsGNOMERegistry::LoadURL(aURL); ++} ++ ++/* static */ void nsCommonRegistry::GetAppDescForScheme( ++ const nsACString& aScheme, nsAString& aDesc) { ++ if (nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetAppDescForScheme(aScheme, aDesc); ++ return nsGNOMERegistry::GetAppDescForScheme(aScheme, aDesc); ++} ++ ++/* static */ already_AddRefed ++nsCommonRegistry::GetFromExtension(const nsACString& aFileExt) { ++ if (nsKDEUtils::kdeSupport()) ++ return nsKDERegistry::GetFromExtension(aFileExt); ++ return nsGNOMERegistry::GetFromExtension(aFileExt); ++} ++ ++/* static */ already_AddRefed nsCommonRegistry::GetFromType( ++ const nsACString& aMIMEType) { ++ if (nsKDEUtils::kdeSupport()) return nsKDERegistry::GetFromType(aMIMEType); ++ return nsGNOMERegistry::GetFromType(aMIMEType); ++} +diff -up firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.h.integration firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.h +--- firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.h.integration 2023-10-31 08:59:03.721124836 +0100 ++++ firefox-119.0/uriloader/exthandler/unix/nsCommonRegistry.h 2023-10-31 08:59:03.721124836 +0100 +@@ -0,0 +1,28 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#ifndef nsCommonRegistry_h__ ++#define nsCommonRegistry_h__ ++ ++#include "nsIURI.h" ++#include "nsCOMPtr.h" ++ ++class nsMIMEInfoBase; ++ ++class nsCommonRegistry { ++ public: ++ static bool HandlerExists(const char* aProtocolScheme); ++ ++ static nsresult LoadURL(nsIURI* aURL); ++ ++ static void GetAppDescForScheme(const nsACString& aScheme, nsAString& aDesc); ++ ++ static already_AddRefed GetFromExtension( ++ const nsACString& aFileExt); ++ ++ static already_AddRefed GetFromType( ++ const nsACString& aMIMEType); ++}; ++ ++#endif +diff -up firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.cpp.integration firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.cpp +--- firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.cpp.integration 2023-10-31 08:59:03.722124870 +0100 ++++ firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.cpp 2023-10-31 08:59:03.722124870 +0100 +@@ -0,0 +1,75 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "mozilla/StaticPrefs_browser.h" ++#include "nsKDERegistry.h" ++#include "prlink.h" ++#include "prmem.h" ++#include "nsString.h" ++#include "nsMIMEInfoUnix.h" ++#include "nsKDEUtils.h" ++ ++/* static */ bool nsKDERegistry::HandlerExists(const char* aProtocolScheme) { ++ nsTArray command; ++ command.AppendElement("HANDLEREXISTS"_ns); ++ command.AppendElement(nsAutoCString(aProtocolScheme)); ++ return nsKDEUtils::command(command); ++} ++ ++/* static */ nsresult nsKDERegistry::LoadURL(nsIURI* aURL) { ++ nsTArray command; ++ command.AppendElement("OPEN"_ns); ++ nsCString url; ++ aURL->GetSpec(url); ++ command.AppendElement(url); ++ bool rv = nsKDEUtils::command(command); ++ if (!rv) return NS_ERROR_FAILURE; ++ ++ return NS_OK; ++} ++ ++/* static */ void nsKDERegistry::GetAppDescForScheme(const nsACString& aScheme, ++ nsAString& aDesc) { ++ nsTArray command; ++ command.AppendElement("GETAPPDESCFORSCHEME"_ns); ++ command.AppendElement(aScheme); ++ nsTArray output; ++ if (nsKDEUtils::command(command, &output) && output.Length() == 1) ++ CopyUTF8toUTF16(output[0], aDesc); ++} ++ ++/* static */ already_AddRefed nsKDERegistry::GetFromExtension( ++ const nsACString& aFileExt) { ++ NS_ASSERTION(aFileExt[0] != '.', "aFileExt shouldn't start with a dot"); ++ nsTArray command; ++ command.AppendElement("GETFROMEXTENSION"_ns); ++ command.AppendElement(aFileExt); ++ return GetFromHelper(command); ++} ++ ++/* static */ already_AddRefed nsKDERegistry::GetFromType( ++ const nsACString& aMIMEType) { ++ nsTArray command; ++ command.AppendElement("GETFROMTYPE"_ns); ++ command.AppendElement(aMIMEType); ++ return GetFromHelper(command); ++} ++ ++/* static */ already_AddRefed nsKDERegistry::GetFromHelper( ++ const nsTArray& command) { ++ nsTArray output; ++ if (nsKDEUtils::command(command, &output) && output.Length() == 3) { ++ nsCString mimetype = output[0]; ++ RefPtr mimeInfo = new nsMIMEInfoUnix(mimetype); ++ NS_ENSURE_TRUE(mimeInfo, nullptr); ++ nsCString description = output[1]; ++ mimeInfo->SetDescription(NS_ConvertUTF8toUTF16(description)); ++ nsCString handlerAppName = output[2]; ++ mimeInfo->SetPreferredAction(nsIMIMEInfo::saveToDisk); ++ mimeInfo->SetDefaultDescription(NS_ConvertUTF8toUTF16(handlerAppName)); ++ return mimeInfo.forget(); ++ } ++ return nullptr; ++} +diff -up firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.h.integration firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.h +--- firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.h.integration 2023-10-31 08:59:03.722124870 +0100 ++++ firefox-119.0/uriloader/exthandler/unix/nsKDERegistry.h 2023-10-31 08:59:03.722124870 +0100 +@@ -0,0 +1,35 @@ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#ifndef nsKDERegistry_h__ ++#define nsKDERegistry_h__ ++ ++#include "nsIURI.h" ++#include "nsCOMPtr.h" ++#include "nsTArray.h" ++ ++class nsMIMEInfoBase; ++// class nsAutoCString; ++// class nsCString; ++ ++class nsKDERegistry { ++ public: ++ static bool HandlerExists(const char* aProtocolScheme); ++ ++ static nsresult LoadURL(nsIURI* aURL); ++ ++ static void GetAppDescForScheme(const nsACString& aScheme, nsAString& aDesc); ++ ++ static already_AddRefed GetFromExtension( ++ const nsACString& aFileExt); ++ ++ static already_AddRefed GetFromType( ++ const nsACString& aMIMEType); ++ ++ private: ++ static already_AddRefed GetFromHelper( ++ const nsTArray& command); ++}; ++ ++#endif // nsKDERegistry_h__ +diff -up firefox-119.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.integration firefox-119.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp +--- firefox-119.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/uriloader/exthandler/unix/nsMIMEInfoUnix.cpp 2023-10-31 08:59:03.722124870 +0100 +@@ -5,16 +5,19 @@ + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + #include "nsMIMEInfoUnix.h" +-#include "nsGNOMERegistry.h" ++#include "nsCommonRegistry.h" + #include "nsIGIOService.h" + #include "nsNetCID.h" + #include "nsIIOService.h" + #ifdef MOZ_ENABLE_DBUS + # include "nsDBusHandlerApp.h" + #endif ++#if defined(XP_UNIX) && !defined(XP_MACOSX) ++# include "nsKDEUtils.h" ++#endif + + nsresult nsMIMEInfoUnix::LoadUriInternal(nsIURI* aURI) { +- return nsGNOMERegistry::LoadURL(aURI); ++ return nsCommonRegistry::LoadURL(aURI); + } + + NS_IMETHODIMP +@@ -29,15 +32,15 @@ nsMIMEInfoUnix::GetHasDefaultHandler(boo + *_retval = false; + + if (mClass == eProtocolInfo) { +- *_retval = nsGNOMERegistry::HandlerExists(mSchemeOrType.get()); ++ *_retval = nsCommonRegistry::HandlerExists(mSchemeOrType.get()); + } else { + RefPtr mimeInfo = +- nsGNOMERegistry::GetFromType(mSchemeOrType); ++ nsCommonRegistry::GetFromType(mSchemeOrType); + if (!mimeInfo) { + nsAutoCString ext; + nsresult rv = GetPrimaryExtension(ext); + if (NS_SUCCEEDED(rv)) { +- mimeInfo = nsGNOMERegistry::GetFromExtension(ext); ++ mimeInfo = nsCommonRegistry::GetFromExtension(ext); + } + } + if (mimeInfo) *_retval = true; +@@ -59,6 +62,21 @@ nsresult nsMIMEInfoUnix::LaunchDefaultWi + nsAutoCString nativePath; + aFile->GetNativePath(nativePath); + ++ if (nsKDEUtils::kdeSupport()) { ++ bool supports; ++ if (NS_SUCCEEDED(GetHasDefaultHandler(&supports)) && supports) { ++ nsTArray command; ++ command.AppendElement("OPEN"_ns); ++ command.AppendElement(nativePath); ++ command.AppendElement("MIMETYPE"_ns); ++ command.AppendElement(mSchemeOrType); ++ if (nsKDEUtils::command(command)) return NS_OK; ++ } ++ if (!GetDefaultApplication()) return NS_ERROR_FILE_NOT_FOUND; ++ ++ return LaunchWithIProcess(GetDefaultApplication(), nativePath); ++ } ++ + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); + if (!giovfs) { + return NS_ERROR_FAILURE; +diff -up firefox-119.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.integration firefox-119.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp +--- firefox-119.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp.integration 2023-10-19 21:54:42.000000000 +0200 ++++ firefox-119.0/uriloader/exthandler/unix/nsOSHelperAppService.cpp 2023-10-31 08:59:03.722124870 +0100 +@@ -10,7 +10,7 @@ + #include "nsOSHelperAppService.h" + #include "nsMIMEInfoUnix.h" + #ifdef MOZ_WIDGET_GTK +-# include "nsGNOMERegistry.h" ++# include "nsCommonRegistry.h" + # ifdef MOZ_BUILD_APP_IS_BROWSER + # include "nsIToolkitShellService.h" + # include "nsIGNOMEShellService.h" +@@ -1106,7 +1106,7 @@ nsresult nsOSHelperAppService::OSProtoco + if (!XRE_IsContentProcess()) { + #ifdef MOZ_WIDGET_GTK + // Check the GNOME registry for a protocol handler +- *aHandlerExists = nsGNOMERegistry::HandlerExists(aProtocolScheme); ++ *aHandlerExists = nsCommonRegistry::HandlerExists(aProtocolScheme); + #else + *aHandlerExists = false; + #endif +@@ -1126,7 +1126,7 @@ nsresult nsOSHelperAppService::OSProtoco + NS_IMETHODIMP nsOSHelperAppService::GetApplicationDescription( + const nsACString& aScheme, nsAString& _retval) { + #ifdef MOZ_WIDGET_GTK +- nsGNOMERegistry::GetAppDescForScheme(aScheme, _retval); ++ nsCommonRegistry::GetAppDescForScheme(aScheme, _retval); + return _retval.IsEmpty() ? NS_ERROR_NOT_AVAILABLE : NS_OK; + #else + return NS_ERROR_NOT_AVAILABLE; +@@ -1231,7 +1231,7 @@ already_AddRefed nsOSHel + #ifdef MOZ_WIDGET_GTK + LOG("Looking in GNOME registry\n"); + RefPtr gnomeInfo = +- nsGNOMERegistry::GetFromExtension(aFileExt); ++ nsCommonRegistry::GetFromExtension(aFileExt); + if (gnomeInfo) { + LOG("Got MIMEInfo from GNOME registry\n"); + return gnomeInfo.forget(); +@@ -1344,7 +1344,7 @@ already_AddRefed nsOSHel + + #ifdef MOZ_WIDGET_GTK + if (handler.IsEmpty()) { +- RefPtr gnomeInfo = nsGNOMERegistry::GetFromType(aMIMEType); ++ RefPtr gnomeInfo = nsCommonRegistry::GetFromType(aMIMEType); + if (gnomeInfo) { + LOG("Got MIMEInfo from GNOME registry without extensions; setting them " + "to %s\n", +diff -up firefox-119.0/widget/gtk/moz.build.integration firefox-119.0/widget/gtk/moz.build +--- firefox-119.0/widget/gtk/moz.build.integration 2023-10-31 08:59:03.704124244 +0100 ++++ firefox-119.0/widget/gtk/moz.build 2023-10-31 08:59:03.723124906 +0100 +@@ -161,6 +161,7 @@ LOCAL_INCLUDES += [ + "/layout/xul", + "/other-licenses/atk-1.0", + "/third_party/cups/include", ++ "/toolkit/xre", + "/widget", + "/widget/headless", + "/widget/x11", +diff -up firefox-119.0/widget/gtk/nsFilePicker.cpp.integration firefox-119.0/widget/gtk/nsFilePicker.cpp +--- firefox-119.0/widget/gtk/nsFilePicker.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/widget/gtk/nsFilePicker.cpp 2023-10-31 08:59:03.723124906 +0100 +@@ -5,6 +5,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -30,6 +31,8 @@ + #include "WidgetUtilsGtk.h" + + #include "nsFilePicker.h" ++#include "nsKDEUtils.h" ++#include "nsURLHelper.h" + + #undef LOG + #ifdef MOZ_LOGGING +@@ -310,7 +313,8 @@ NS_IMETHODIMP + nsFilePicker::AppendFilter(const nsAString& aTitle, const nsAString& aFilter) { + if (aFilter.EqualsLiteral("..apps")) { + // No platform specific thing we can do here, really.... +- return NS_OK; ++ // Unless it's KDE. ++ if (mMode != modeOpen || !nsKDEUtils::kdeSupport()) return NS_OK; + } + + nsAutoCString filter, name; +@@ -420,6 +424,31 @@ nsFilePicker::Open(nsIFilePickerShownCal + // Can't show two dialogs concurrently with the same filepicker + if (mRunning) return NS_ERROR_NOT_AVAILABLE; + ++ // KDE file picker is not handled via callback ++ if (nsKDEUtils::kdeSupport()) { ++ mCallback = aCallback; ++ mRunning = true; ++ NS_ADDREF_THIS(); ++ g_idle_add( ++ [](gpointer data) -> gboolean { ++ nsFilePicker* queuedPicker = (nsFilePicker*)data; ++ nsIFilePicker::ResultCode result; ++ queuedPicker->kdeFileDialog(&result); ++ if (queuedPicker->mCallback) { ++ queuedPicker->mCallback->Done(result); ++ queuedPicker->mCallback = nullptr; ++ } else { ++ queuedPicker->mResult = result; ++ } ++ queuedPicker->mRunning = false; ++ NS_RELEASE(queuedPicker); ++ return G_SOURCE_REMOVE; ++ }, ++ this); ++ ++ return NS_OK; ++ } ++ + NS_ConvertUTF16toUTF8 title(mTitle); + + GtkWindow* parent_widget = +@@ -701,6 +730,205 @@ void nsFilePicker::Done(void* file_choos + NS_RELEASE_THIS(); + } + ++nsCString nsFilePicker::kdeMakeFilter(int index) { ++ nsCString buf = mFilters[index]; ++ for (PRUint32 i = 0; i < buf.Length(); ++i) ++ if (buf[i] == ';') // KDE separates just using spaces ++ buf.SetCharAt(' ', i); ++ if (!mFilterNames[index].IsEmpty()) { ++ buf += "|"; ++ buf += mFilterNames[index].get(); ++ } ++ return buf; ++} ++ ++static PRInt32 windowToXid(nsIWidget* widget) { ++ GtkWindow* parent_widget = ++ GTK_WINDOW(widget->GetNativeData(NS_NATIVE_SHELLWIDGET)); ++ GdkWindow* gdk_window = ++ gtk_widget_get_window(gtk_widget_get_toplevel(GTK_WIDGET(parent_widget))); ++ return GDK_WINDOW_XID(gdk_window); ++} ++ ++NS_IMETHODIMP nsFilePicker::kdeFileDialog(nsIFilePicker::ResultCode* aReturn) { ++ NS_ENSURE_ARG_POINTER(aReturn); ++ ++ if (mMode == modeOpen && mFilters.Length() == 1 && ++ mFilters[0].EqualsLiteral("..apps")) ++ return kdeAppsDialog(aReturn); ++ ++ nsCString title; ++ title.Adopt(ToNewUTF8String(mTitle)); ++ ++ const char* arg = NULL; ++ if (mAllowURLs) { ++ switch (mMode) { ++ case nsIFilePicker::modeOpen: ++ case nsIFilePicker::modeOpenMultiple: ++ arg = "GETOPENURL"; ++ break; ++ case nsIFilePicker::modeSave: ++ arg = "GETSAVEURL"; ++ break; ++ case nsIFilePicker::modeGetFolder: ++ arg = "GETDIRECTORYURL"; ++ break; ++ } ++ } else { ++ switch (mMode) { ++ case nsIFilePicker::modeOpen: ++ case nsIFilePicker::modeOpenMultiple: ++ arg = "GETOPENFILENAME"; ++ break; ++ case nsIFilePicker::modeSave: ++ arg = "GETSAVEFILENAME"; ++ break; ++ case nsIFilePicker::modeGetFolder: ++ arg = "GETDIRECTORYFILENAME"; ++ break; ++ } ++ } ++ ++ nsAutoCString directory; ++ if (mDisplayDirectory) { ++ mDisplayDirectory->GetNativePath(directory); ++ } else if (mPrevDisplayDirectory) { ++ mPrevDisplayDirectory->GetNativePath(directory); ++ } ++ ++ nsAutoCString startdir; ++ if (!directory.IsEmpty()) { ++ startdir = directory; ++ } ++ if (mMode == nsIFilePicker::modeSave) { ++ if (!startdir.IsEmpty()) { ++ startdir += "/"; ++ startdir += ToNewUTF8String(mDefault); ++ } else ++ startdir = ToNewUTF8String(mDefault); ++ } ++ ++ nsAutoCString filters; ++ PRInt32 count = mFilters.Length(); ++ if (count == 0) // just in case ++ filters = "*"; ++ else { ++ filters = kdeMakeFilter(0); ++ for (PRInt32 i = 1; i < count; ++i) { ++ filters += "\n"; ++ filters += kdeMakeFilter(i); ++ } ++ } ++ ++ nsTArray command; ++ command.AppendElement(nsAutoCString(arg)); ++ command.AppendElement(startdir); ++ if (mMode != nsIFilePicker::modeGetFolder) { ++ command.AppendElement(filters); ++ nsAutoCString selected; ++ selected.AppendInt(mSelectedType); ++ command.AppendElement(selected); ++ } ++ command.AppendElement(title); ++ if (mMode == nsIFilePicker::modeOpenMultiple) ++ command.AppendElement("MULTIPLE"_ns); ++ if (PRInt32 xid = windowToXid(mParentWidget)) { ++ command.AppendElement("PARENT"_ns); ++ nsAutoCString parent; ++ parent.AppendInt(xid); ++ command.AppendElement(parent); ++ } ++ ++ nsTArray output; ++ if (nsKDEUtils::commandBlockUi( ++ command, ++ GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), ++ &output)) { ++ *aReturn = nsIFilePicker::returnOK; ++ mFiles.Clear(); ++ if (mMode != nsIFilePicker::modeGetFolder) { ++ mSelectedType = atoi(output[0].get()); ++ output.RemoveElementAt(0); ++ } ++ if (mMode == nsIFilePicker::modeOpenMultiple) { ++ mFileURL.Truncate(); ++ PRUint32 count = output.Length(); ++ for (PRUint32 i = 0; i < count; ++i) { ++ nsCOMPtr localfile; ++ nsresult rv = NS_NewNativeLocalFile(output[i], PR_FALSE, ++ getter_AddRefs(localfile)); ++ if (NS_SUCCEEDED(rv)) mFiles.AppendObject(localfile); ++ } ++ } else { ++ if (output.Length() == 0) ++ mFileURL = nsCString(); ++ else if (mAllowURLs) ++ mFileURL = output[0]; ++ else // GetFile() actually requires it to be url even for local files :-/ ++ { ++ nsCOMPtr localfile; ++ nsresult rv = NS_NewNativeLocalFile(output[0], PR_FALSE, ++ getter_AddRefs(localfile)); ++ if (NS_SUCCEEDED(rv)) ++ rv = net_GetURLSpecFromActualFile(localfile, mFileURL); ++ } ++ } ++ // Remember last used directory. ++ nsCOMPtr file; ++ GetFile(getter_AddRefs(file)); ++ if (file) { ++ nsCOMPtr dir; ++ file->GetParent(getter_AddRefs(dir)); ++ nsCOMPtr localDir(dir); ++ if (localDir) { ++ localDir.swap(mPrevDisplayDirectory); ++ } ++ } ++ if (mMode == nsIFilePicker::modeSave) { ++ nsCOMPtr file; ++ GetFile(getter_AddRefs(file)); ++ if (file) { ++ bool exists = false; ++ file->Exists(&exists); ++ if (exists) // TODO do overwrite check in the helper app ++ *aReturn = nsIFilePicker::returnReplace; ++ } ++ } ++ } else { ++ *aReturn = nsIFilePicker::returnCancel; ++ } ++ return NS_OK; ++} ++ ++NS_IMETHODIMP nsFilePicker::kdeAppsDialog(nsIFilePicker::ResultCode* aReturn) { ++ NS_ENSURE_ARG_POINTER(aReturn); ++ ++ nsCString title; ++ title.Adopt(ToNewUTF8String(mTitle)); ++ ++ nsTArray command; ++ command.AppendElement("APPSDIALOG"_ns); ++ command.AppendElement(title); ++ if (PRInt32 xid = windowToXid(mParentWidget)) { ++ command.AppendElement("PARENT"_ns); ++ nsAutoCString parent; ++ parent.AppendInt(xid); ++ command.AppendElement(parent); ++ } ++ ++ nsTArray output; ++ if (nsKDEUtils::commandBlockUi( ++ command, ++ GTK_WINDOW(mParentWidget->GetNativeData(NS_NATIVE_SHELLWIDGET)), ++ &output)) { ++ *aReturn = nsIFilePicker::returnOK; ++ mFileURL = output.Length() > 0 ? output[0] : nsCString(); ++ } else { ++ *aReturn = nsIFilePicker::returnCancel; ++ } ++ return NS_OK; ++} ++ + // All below functions available as of GTK 3.20+ + void* nsFilePicker::GtkFileChooserNew(const gchar* title, GtkWindow* parent, + GtkFileChooserAction action, +diff -up firefox-119.0/widget/gtk/nsFilePicker.h.integration firefox-119.0/widget/gtk/nsFilePicker.h +--- firefox-119.0/widget/gtk/nsFilePicker.h.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/widget/gtk/nsFilePicker.h 2023-10-31 08:59:03.723124906 +0100 +@@ -76,6 +76,12 @@ class nsFilePicker : public nsBaseFilePi + private: + static nsIFile* mPrevDisplayDirectory; + ++ bool kdeRunning(); ++ bool getKdeRunning(); ++ NS_IMETHODIMP kdeFileDialog(nsIFilePicker::ResultCode* aReturn); ++ NS_IMETHODIMP kdeAppsDialog(nsIFilePicker::ResultCode* aReturn); ++ nsCString kdeMakeFilter(int index); ++ + void* GtkFileChooserNew(const gchar* title, GtkWindow* parent, + GtkFileChooserAction action, + const gchar* accept_label); +diff -up firefox-119.0/xpcom/components/ManifestParser.cpp.integration firefox-119.0/xpcom/components/ManifestParser.cpp +--- firefox-119.0/xpcom/components/ManifestParser.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/xpcom/components/ManifestParser.cpp 2023-10-31 08:59:03.723124906 +0100 +@@ -43,6 +43,7 @@ + #include "nsIScriptError.h" + #include "nsIXULAppInfo.h" + #include "nsIXULRuntime.h" ++#include "nsKDEUtils.h" + + using namespace mozilla; + +@@ -394,6 +395,7 @@ void ParseManifest(NSLocationType aType, + constexpr auto kOs = u"os"_ns; + constexpr auto kOsVersion = u"osversion"_ns; + constexpr auto kABI = u"abi"_ns; ++ constexpr auto kDesktop = u"desktop"_ns; + constexpr auto kProcess = u"process"_ns; + #if defined(MOZ_WIDGET_ANDROID) + constexpr auto kTablet = u"tablet"_ns; +@@ -453,6 +455,7 @@ void ParseManifest(NSLocationType aType, + } + + nsAutoString osVersion; ++ nsAutoString desktop; + #if defined(XP_WIN) + # pragma warning(push) + # pragma warning(disable : 4996) // VC12+ deprecates GetVersionEx +@@ -461,14 +464,17 @@ void ParseManifest(NSLocationType aType, + nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", info.dwMajorVersion, + info.dwMinorVersion); + } ++ desktop = u"win"_ns; + # pragma warning(pop) + #elif defined(MOZ_WIDGET_COCOA) + SInt32 majorVersion = nsCocoaFeatures::macOSVersionMajor(); + SInt32 minorVersion = nsCocoaFeatures::macOSVersionMinor(); + nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", majorVersion, minorVersion); ++ desktop = u"macosx"_ns); + #elif defined(MOZ_WIDGET_GTK) + nsTextFormatter::ssprintf(osVersion, u"%ld.%ld", gtk_major_version, + gtk_minor_version); ++ desktop = nsKDEUtils::kdeSession() ? u"kde"_ns : u"gnome"_ns; + #elif defined(MOZ_WIDGET_ANDROID) + bool isTablet = false; + if (jni::IsAvailable()) { +@@ -476,6 +482,7 @@ void ParseManifest(NSLocationType aType, + osVersion.Assign(release->ToString()); + isTablet = java::GeckoAppShell::IsTablet(); + } ++ desktop = u"android"_ns; + #endif + + if (XRE_IsContentProcess()) { +@@ -576,6 +583,7 @@ void ParseManifest(NSLocationType aType, + : eUnspecified; + #endif + int flags = 0; ++ TriState stDesktop = eUnspecified; + + while ((token = nsCRT::strtok(whitespace, kWhitespace, &whitespace)) && + ok) { +@@ -585,6 +593,7 @@ void ParseManifest(NSLocationType aType, + if (CheckStringFlag(kApplication, wtoken, appID, stApp) || + CheckOsFlag(kOs, wtoken, osTarget, stOs) || + CheckStringFlag(kABI, wtoken, abi, stABI) || ++ CheckStringFlag(kDesktop, wtoken, desktop, stDesktop) || + CheckStringFlag(kProcess, wtoken, process, stProcess) || + CheckVersionFlag(kOsVersion, wtoken, osVersion, stOsVersion) || + CheckVersionFlag(kAppVersion, wtoken, appVersion, stAppVersion) || +@@ -644,6 +653,7 @@ void ParseManifest(NSLocationType aType, + + if (!ok || stApp == eBad || stAppVersion == eBad || + stGeckoVersion == eBad || stOs == eBad || stOsVersion == eBad || ++ stDesktop == eBad || + #ifdef MOZ_WIDGET_ANDROID + stTablet == eBad || + #endif +diff -up firefox-119.0/xpcom/components/moz.build.integration firefox-119.0/xpcom/components/moz.build +--- firefox-119.0/xpcom/components/moz.build.integration 2023-10-19 21:54:44.000000000 +0200 ++++ firefox-119.0/xpcom/components/moz.build 2023-10-31 08:59:03.723124906 +0100 +@@ -71,6 +71,7 @@ LOCAL_INCLUDES += [ + "/js/xpconnect/loader", + "/layout/build", + "/modules/libjar", ++ "/toolkit/xre", + ] + + if CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": +diff -up firefox-119.0/xpcom/io/nsLocalFileUnix.cpp.integration firefox-119.0/xpcom/io/nsLocalFileUnix.cpp +--- firefox-119.0/xpcom/io/nsLocalFileUnix.cpp.integration 2023-10-19 21:54:43.000000000 +0200 ++++ firefox-119.0/xpcom/io/nsLocalFileUnix.cpp 2023-10-31 08:59:03.724124940 +0100 +@@ -51,6 +51,7 @@ + + #ifdef MOZ_WIDGET_GTK + # include "nsIGIOService.h" ++# include "nsKDEUtils.h" + #endif + + #ifdef MOZ_WIDGET_COCOA +@@ -2172,10 +2173,18 @@ nsLocalFile::Reveal() { + } + + #ifdef MOZ_WIDGET_GTK ++ nsAutoCString url; + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); +- if (!giovfs) { +- return NS_ERROR_FAILURE; ++ url = mPath; ++ if (nsKDEUtils::kdeSupport()) { ++ nsTArray command; ++ command.AppendElement("REVEAL"_ns); ++ command.AppendElement(mPath); ++ return nsKDEUtils::command(command) ? NS_OK : NS_ERROR_FAILURE; + } ++ ++ if (!giovfs) return NS_ERROR_FAILURE; ++ + return giovfs->RevealFile(this); + #elif defined(MOZ_WIDGET_COCOA) + CFURLRef url; +@@ -2197,6 +2206,13 @@ nsLocalFile::Launch() { + } + + #ifdef MOZ_WIDGET_GTK ++ if (nsKDEUtils::kdeSupport()) { ++ nsTArray command; ++ command.AppendElement("OPEN"_ns); ++ command.AppendElement(mPath); ++ return nsKDEUtils::command(command) ? NS_OK : NS_ERROR_FAILURE; ++ } ++ + nsCOMPtr giovfs = do_GetService(NS_GIOSERVICE_CONTRACTID); + if (!giovfs) { + return NS_ERROR_FAILURE; diff --git a/0026-Add-KDE-integration-to-Firefox.patch b/0026-Add-KDE-integration-to-Firefox.patch new file mode 100644 index 0000000..1e2e938 --- /dev/null +++ b/0026-Add-KDE-integration-to-Firefox.patch @@ -0,0 +1,279 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Martin Sirringhaus +Date: Tue, 8 Aug 2023 16:18:24 +0300 +Subject: [PATCH] Add KDE integration to Firefox + +Bug: https://bugzilla.mozilla.org/show_bug.cgi?id=140751 +Bug: https://bugzilla.suse.com/show_bug.cgi?id=170055 + +How to apply this patch: + +1. Import and apply it +2. cp browser/base/content/browser.xul browser/base/content/browser-kde.xul +3. Find editBookmarkPanelDoneButton +4. Replace #ifndef with #ifdef in the line above (this hanges the button order from Gnome-style to KDE-style) +5. hg qrefresh +--- + browser/components/preferences/main.js | 18 +++ + browser/components/shell/moz.build | 2 + + .../components/shell/nsKDEShellService.cpp | 109 ++++++++++++++++++ + browser/components/shell/nsKDEShellService.h | 32 +++++ + .../components/shell/nsUnixShellService.cpp | 22 ++++ + browser/components/shell/nsUnixShellService.h | 15 +++ + 6 files changed, 198 insertions(+) + create mode 100644 browser/components/shell/nsKDEShellService.cpp + create mode 100644 browser/components/shell/nsKDEShellService.h + create mode 100644 browser/components/shell/nsUnixShellService.cpp + create mode 100644 browser/components/shell/nsUnixShellService.h + +diff --git a/browser/components/preferences/main.js b/browser/components/preferences/main.js +index 820e46fb006567bfdf93e2a46da5e3c07d42bf10..57d1c21bdecc2d55d0bed30246e684d3b97ad7fa 100644 +--- a/browser/components/preferences/main.js ++++ b/browser/components/preferences/main.js +@@ -294,6 +294,13 @@ var gMainPane = { + }, backoffTimes[this._backoffIndex]); + } + ++ var env = Components.classes["@mozilla.org/process/environment;1"] ++ .getService(Components.interfaces.nsIEnvironment); ++ var kde_session = 0; ++ if (env.get('KDE_FULL_SESSION') == "true") { ++ kde_session = 1; ++ } ++ + this.initBrowserContainers(); + this.buildContentProcessCountMenuList(); + +@@ -1727,6 +1734,17 @@ var gMainPane = { + } + try { + shellSvc.setDefaultBrowser(true, false); ++ if (kde_session == 1) { ++ var shellObj = Components.classes["@mozilla.org/file/local;1"] ++ .createInstance(Components.interfaces.nsILocalFile); ++ shellObj.initWithPath("/usr/bin/kwriteconfig"); ++ var process = Components.classes["@mozilla.org/process/util;1"] ++ .createInstance(Components.interfaces.nsIProcess); ++ process.init(shellObj); ++ var args = ["--file", "kdeglobals", "--group", "General", "--key", ++ "BrowserApplication", "firefox"]; ++ process.run(false, args, args.length); ++ } + } catch (ex) { + console.error(ex); + return; +diff --git a/browser/components/shell/moz.build b/browser/components/shell/moz.build +index eb88cb287dc3f04022b74b978666118bbd5fa6b2..95277533781a7224d108e3c45731a6d9a89ba1a0 100644 +--- a/browser/components/shell/moz.build ++++ b/browser/components/shell/moz.build +@@ -36,6 +36,8 @@ elif CONFIG["MOZ_WIDGET_TOOLKIT"] == "gtk": + + SOURCES += [ + "nsGNOMEShellService.cpp", ++ "nsKDEShellService.cpp", ++ "nsUnixShellService.cpp", + ] + if CONFIG["MOZ_ENABLE_DBUS"]: + SOURCES += [ +diff --git a/browser/components/shell/nsKDEShellService.cpp b/browser/components/shell/nsKDEShellService.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..152a3aca87ea73477bc75c4e93c01e5a52dda102 +--- /dev/null ++++ b/browser/components/shell/nsKDEShellService.cpp +@@ -0,0 +1,109 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#include "mozilla/ArrayUtils.h" ++ ++#include "nsCOMPtr.h" ++#include "nsKDEShellService.h" ++#include "nsShellService.h" ++#include "nsKDEUtils.h" ++#include "nsIPrefService.h" ++#include "nsIProcess.h" ++#include "nsIFile.h" ++#include "nsServiceManagerUtils.h" ++#include "nsComponentManagerUtils.h" ++#include "nsIMutableArray.h" ++#include "nsISupportsPrimitives.h" ++#include "nsArrayUtils.h" ++ ++using namespace mozilla; ++ ++nsresult ++nsKDEShellService::Init() ++{ ++ if( !nsKDEUtils::kdeSupport()) ++ return NS_ERROR_NOT_AVAILABLE; ++ return NS_OK; ++} ++ ++NS_IMPL_ISUPPORTS(nsKDEShellService, nsIGNOMEShellService, nsIShellService) ++ ++NS_IMETHODIMP ++nsKDEShellService::IsDefaultBrowser(bool aForAllTypes, ++ bool* aIsDefaultBrowser) ++{ ++ *aIsDefaultBrowser = false; ++ ++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); ++ if (!command) ++ return NS_ERROR_FAILURE; ++ ++ nsCOMPtr str = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); ++ if (!str) ++ return NS_ERROR_FAILURE; ++ ++ str->SetData("ISDEFAULTBROWSER"_ns); ++ command->AppendElement( str ); ++ ++ if( nsKDEUtils::command( command )) ++ *aIsDefaultBrowser = true; ++ return NS_OK; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::SetDefaultBrowser(bool aClaimAllTypes, ++ bool aForAllUsers) ++{ ++ nsCOMPtr command = do_CreateInstance( NS_ARRAY_CONTRACTID ); ++ if (!command) ++ return NS_ERROR_FAILURE; ++ ++ nsCOMPtr cmdstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); ++ nsCOMPtr paramstr = do_CreateInstance( NS_SUPPORTS_CSTRING_CONTRACTID ); ++ if (!cmdstr || !paramstr) ++ return NS_ERROR_FAILURE; ++ ++ cmdstr->SetData("SETDEFAULTBROWSER"_ns); ++ command->AppendElement( cmdstr ); ++ ++ paramstr->SetData( aClaimAllTypes ? "ALLTYPES"_ns : "NORMAL"_ns ); ++ command->AppendElement( paramstr ); ++ ++ return nsKDEUtils::command( command ) ? NS_OK : NS_ERROR_FAILURE; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::GetCanSetDesktopBackground(bool* aResult) ++{ ++ *aResult = true; ++ return NS_OK; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::SetDesktopBackground(dom::Element* aElement, ++ int32_t aPosition, ++ const nsACString& aImageName) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::GetDesktopBackgroundColor(PRUint32 *aColor) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::SetDesktopBackgroundColor(PRUint32 aColor) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ ++NS_IMETHODIMP ++nsKDEShellService::IsDefaultForScheme(nsTSubstring const& aScheme, bool* aIsDefaultBrowser) ++{ ++ return NS_ERROR_NOT_IMPLEMENTED; ++} ++ +diff --git a/browser/components/shell/nsKDEShellService.h b/browser/components/shell/nsKDEShellService.h +new file mode 100644 +index 0000000000000000000000000000000000000000..8b0bb19164352453cfa453dd87c19263160b9ad8 +--- /dev/null ++++ b/browser/components/shell/nsKDEShellService.h +@@ -0,0 +1,32 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++#ifndef nskdeshellservice_h____ ++#define nskdeshellservice_h____ ++ ++#include "nsIGNOMEShellService.h" ++#include "nsToolkitShellService.h" ++#include "nsString.h" ++#include "mozilla/Attributes.h" ++ ++class nsKDEShellService final : public nsIGNOMEShellService, ++ public nsToolkitShellService ++{ ++public: ++ nsKDEShellService() : mCheckedThisSession(false) { } ++ ++ NS_DECL_ISUPPORTS ++ NS_DECL_NSISHELLSERVICE ++ NS_DECL_NSIGNOMESHELLSERVICE ++ ++ nsresult Init(); ++ ++private: ++ ~nsKDEShellService() {} ++ ++ bool mCheckedThisSession; ++}; ++ ++#endif // nskdeshellservice_h____ +diff --git a/browser/components/shell/nsUnixShellService.cpp b/browser/components/shell/nsUnixShellService.cpp +new file mode 100644 +index 0000000000000000000000000000000000000000..abf266ebdc52e136f495911da3454e69c770c6db +--- /dev/null ++++ b/browser/components/shell/nsUnixShellService.cpp +@@ -0,0 +1,22 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++ ++#include "nsUnixShellService.h" ++#include "nsGNOMEShellService.h" ++#include "nsKDEShellService.h" ++#include "nsKDEUtils.h" ++#include "mozilla/ModuleUtils.h" ++ ++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsGNOMEShellService, Init) ++NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsKDEShellService, Init) ++ ++NS_IMETHODIMP ++nsUnixShellServiceConstructor(REFNSIID aIID, void **aResult) ++{ ++ if( nsKDEUtils::kdeSupport()) ++ return nsKDEShellServiceConstructor( aIID, aResult ); ++ return nsGNOMEShellServiceConstructor( aIID, aResult ); ++} +diff --git a/browser/components/shell/nsUnixShellService.h b/browser/components/shell/nsUnixShellService.h +new file mode 100644 +index 0000000000000000000000000000000000000000..26b5dbac47dd9a8ec1fcb6c93575cca750692735 +--- /dev/null ++++ b/browser/components/shell/nsUnixShellService.h +@@ -0,0 +1,15 @@ ++/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ ++/* This Source Code Form is subject to the terms of the Mozilla Public ++ * License, v. 2.0. If a copy of the MPL was not distributed with this ++ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ ++ ++ ++#ifndef nsunixshellservice_h____ ++#define nsunixshellservice_h____ ++ ++#include "nsIGNOMEShellService.h" ++ ++NS_IMETHODIMP ++nsUnixShellServiceConstructor(nsISupports *aOuter, REFNSIID aIID, void **aResult); ++ ++#endif // nsunixshellservice_h____ diff --git a/build-aarch64-skia.patch b/build-aarch64-skia.patch index a63e3e8..9223bb8 100644 --- a/build-aarch64-skia.patch +++ b/build-aarch64-skia.patch @@ -1,45 +1,33 @@ -diff -up firefox-72.0/gfx/skia/skia/include/private/SkHalf.h.aarch64-skia firefox-72.0/gfx/skia/skia/include/private/SkHalf.h ---- firefox-72.0/gfx/skia/skia/include/private/SkHalf.h.aarch64-skia 2020-01-02 22:33:02.000000000 +0100 -+++ firefox-72.0/gfx/skia/skia/include/private/SkHalf.h 2020-01-03 09:00:37.537296105 +0100 -@@ -40,7 +40,7 @@ static inline Sk4h SkFloatToHalf_finite_ +diff -up firefox-134.0-build/firefox-134.0/gfx/skia/skia/modules/skcms/src/Transform_inl.h.aarch64-skia firefox-134.0-build/firefox-134.0/gfx/skia/skia/modules/skcms/src/Transform_inl.h +--- firefox-134.0/gfx/skia/skia/modules/skcms/src/Transform_inl.h.aarch64-skia 2024-12-30 19:30:46.000000000 +0100 ++++ firefox-134.0/gfx/skia/skia/modules/skcms/src/Transform_inl.h 2025-01-02 20:51:07.855087265 +0100 +@@ -151,7 +151,7 @@ SI U32 to_fixed(F f) { return (U32)cast - static inline Sk4f SkHalfToFloat_finite_ftz(uint64_t rgba) { - Sk4h hs = Sk4h::Load(&rgba); --#if !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64) -+#if 0 // !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64) - float32x4_t fs; - asm ("fcvtl %[fs].4s, %[hs].4h \n" // vcvt_f32_f16(...) - : [fs] "=w" (fs) // =w: write-only NEON register -@@ -62,7 +62,7 @@ static inline Sk4f SkHalfToFloat_finite_ - } - static inline Sk4h SkFloatToHalf_finite_ftz(const Sk4f& fs) { --#if !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64) -+#if 0 // !defined(SKNX_NO_SIMD) && defined(SK_CPU_ARM64) - float32x4_t vec = fs.fVec; - asm ("fcvtn %[vec].4h, %[vec].4s \n" // vcvt_f16_f32(vec) - : [vec] "+w" (vec)); // +w: read-write NEON register -diff -up firefox-72.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h.aarch64-skia firefox-72.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h ---- firefox-72.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h.aarch64-skia 2020-01-03 09:00:37.538296107 +0100 -+++ firefox-72.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h 2020-01-03 10:11:41.259219508 +0100 -@@ -1087,7 +1087,7 @@ SI F from_half(U16 h) { + SI F F_from_Half(U16 half) { +-#if defined(USING_NEON_F16C) ++#if 0 // defined(USING_NEON_F16C) + return vcvt_f32_f16((float16x4_t)half); + #elif defined(USING_AVX512F) + return (F)_mm512_cvtph_ps((__m256i)half); +@@ -178,7 +178,7 @@ SI F F_from_Half(U16 half) { + __attribute__((no_sanitize("unsigned-integer-overflow"))) + #endif + SI U16 Half_from_F(F f) { +-#if defined(USING_NEON_F16C) ++#if 0 //defined(USING_NEON_F16C) + return (U16)vcvt_f16_f32(f); + #elif defined(USING_AVX512F) + return (U16)_mm512_cvtps_ph((__m512 )f, _MM_FROUND_CUR_DIRECTION ); +diff -up firefox-134.0-build/firefox-134.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h.aarch64-skia firefox-134.0-build/firefox-134.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h +--- firefox-134.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h.aarch64-skia 2025-01-02 20:51:07.856087299 +0100 ++++ firefox-134.0/gfx/skia/skia/src/opts/SkRasterPipeline_opts.h 2025-01-02 23:09:47.802283444 +0100 +@@ -1421,7 +1421,7 @@ SI F from_half(U16 h) { } SI U16 to_half(F f) { --#if defined(JUMPER_IS_NEON) && defined(SK_CPU_ARM64) \ -+#if 0 //defined(JUMPER_IS_NEON) && defined(SK_CPU_ARM64) \ - && !defined(SK_BUILD_FOR_GOOGLE3) // Temporary workaround for some Google3 builds. - return vcvt_f16_f32(f); +-#if defined(SKRP_CPU_NEON) && defined(SK_CPU_ARM64) ++#if 0 // defined(SKRP_CPU_NEON) && defined(SK_CPU_ARM64) + return (U16)vcvt_f16_f32(f); -diff -up firefox-72.0/gfx/skia/skia/third_party/skcms/src/Transform_inl.h.aarch64-skia firefox-72.0/gfx/skia/skia/third_party/skcms/src/Transform_inl.h ---- firefox-72.0/gfx/skia/skia/third_party/skcms/src/Transform_inl.h.aarch64-skia 2020-01-03 09:00:37.538296107 +0100 -+++ firefox-72.0/gfx/skia/skia/third_party/skcms/src/Transform_inl.h 2020-01-03 10:11:53.513250979 +0100 -@@ -183,8 +183,6 @@ SI F F_from_Half(U16 half) { - SI U16 Half_from_F(F f) { - #if defined(USING_NEON_FP16) - return bit_pun(f); --#elif defined(USING_NEON_F16C) -- return (U16)vcvt_f16_f32(f); - #elif defined(USING_AVX512F) - return (U16)_mm512_cvtps_ph((__m512 )f, _MM_FROUND_CUR_DIRECTION ); - #elif defined(USING_AVX_F16C) + #elif defined(SKRP_CPU_SKX) diff --git a/build-arm-libaom.patch b/build-arm-libaom.patch deleted file mode 100644 index 985f01d..0000000 --- a/build-arm-libaom.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-73.0/media/libaom/moz.build.old firefox-73.0/media/libaom/moz.build ---- firefox-73.0/media/libaom/moz.build.old 2020-02-07 23:13:28.000000000 +0200 -+++ firefox-73.0/media/libaom/moz.build 2020-02-17 10:30:08.509805092 +0200 -@@ -55,7 +55,7 @@ elif CONFIG['CPU_ARCH'] == 'arm': - - for f in SOURCES: - if f.endswith('neon.c'): -- SOURCES[f].flags += CONFIG['VPX_ASFLAGS'] -+ SOURCES[f].flags += CONFIG['NEON_FLAGS'] - - if CONFIG['OS_TARGET'] == 'Android': - # For cpu-features.h diff --git a/build-arm-wasm.patch b/build-arm-wasm.patch deleted file mode 100644 index bd841ab..0000000 --- a/build-arm-wasm.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff -up firefox-72.0.2/js/src/wasm/WasmSignalHandlers.cpp.old firefox-72.0.2/js/src/wasm/WasmSignalHandlers.cpp ---- firefox-72.0.2/js/src/wasm/WasmSignalHandlers.cpp.old 2020-01-17 23:34:41.000000000 +0200 -+++ firefox-72.0.2/js/src/wasm/WasmSignalHandlers.cpp 2020-02-02 08:07:54.670341986 +0200 -@@ -249,7 +249,16 @@ using mozilla::DebugOnly; - #endif - - #ifdef WASM_EMULATE_ARM_UNALIGNED_FP_ACCESS --# include -+struct user_vfp { -+ unsigned long long fpregs[32]; -+ unsigned long fpscr; -+}; -+ -+struct user_vfp_exc { -+ unsigned long fpexc; -+ unsigned long fpinst; -+ unsigned long fpinst2; -+}; - #endif - - #if defined(ANDROID) diff --git a/build-c11-threads-avail.patch b/build-c11-threads-avail.patch new file mode 100644 index 0000000..f627a7b --- /dev/null +++ b/build-c11-threads-avail.patch @@ -0,0 +1,36 @@ +diff -up firefox-146.0/third_party/rust/glslopt/glsl-optimizer/include/c11/threads_posix.h.build-c11-threads-avail firefox-146.0/third_party/rust/glslopt/glsl-optimizer/include/c11/threads_posix.h +--- firefox-146.0/third_party/rust/glslopt/glsl-optimizer/include/c11/threads_posix.h.build-c11-threads-avail 2025-12-05 18:43:20.000000000 +0100 ++++ firefox-146.0/third_party/rust/glslopt/glsl-optimizer/include/c11/threads_posix.h 2025-12-11 13:30:50.463371937 +0100 +@@ -66,7 +66,7 @@ typedef pthread_cond_t cnd_t; + typedef pthread_t thrd_t; + typedef pthread_key_t tss_t; + typedef pthread_mutex_t mtx_t; +-typedef pthread_once_t once_flag; ++//typedef pthread_once_t once_flag; + + + /* +@@ -90,12 +90,13 @@ impl_thrd_routine(void *p) + + /*--------------- 7.25.2 Initialization functions ---------------*/ + // 7.25.2.1 +-static inline void ++// ++/*static inline void + call_once(once_flag *flag, void (*func)(void)) + { + pthread_once(flag, func); + } +- ++*/ + + /*------------- 7.25.3 Condition variable functions -------------*/ + // 7.25.3.1 +diff -up firefox-147.0/third_party/rust/glslopt/.cargo-checksum.json.backup firefox-147.0/third_party/rust/glslopt/.cargo-checksum.json +--- firefox-147.0/third_party/rust/glslopt/.cargo-checksum.json.backup 2026-01-07 12:48:27.390768071 +0100 ++++ firefox-147.0/third_party/rust/glslopt/.cargo-checksum.json 2026-01-07 12:48:29.538659136 +0100 +@@ -1 +1 @@ +-{"files":{"Cargo.lock":"f7970552595dc803ace9ef19b5f5d7b1fc784aac30cb27b2ebc3002d97122b9d","Cargo.toml":"7c53ee20d848f9913cacbfcb3ab2e89e30deee8d619d173c95130c7c5d065827","README.md":"4468e08c64c19977707d792bfab0080e35ff927b64990eab77873f8ba056ba1c","build.rs":"92e29699487c21389fc823c50b410cfbfc74cc774265d24958489909ee48a076","glsl-optimizer/CMakeLists.txt":"42ce94744e82ffa000da8b64d81fc140e293b9f5da7dd4cf6b49e7404a2448d9","glsl-optimizer/README.md":"b18eef11a92d267d88a937b1154f7670ee433c730b102fdf7e2da0b02722b146","glsl-optimizer/contrib/glslopt/Main.cpp":"14ba213210c62e234b8d9b0052105fed28eedd83d535ebe85acc10bda7322dd4","glsl-optimizer/contrib/glslopt/Readme":"65d2a6f1aa1dc61e903e090cdade027abad33e02e7c9c81e07dc80508acadec4","glsl-optimizer/generateParsers.sh":"878a97db5d3b69eb3b4c3a95780763b373cfcc0c02e0b28894f162dbbd1b8848","glsl-optimizer/include/GL/gl.h":"1989b51365b6d7d0c48ff6e8b181ef75e2cdf71bfb1626b1cc4362e2f54854a3","glsl-optimizer/include/GL/glext.h":"2ac3681045a35a2194a81a960cad395c04bef1c8a20ef46b799fb24af3ec5f70","glsl-optimizer/include/KHR/khrplatform.h":"1448141a0c054d7f46edfb63f4fe6c203acf9591974049481c32442fb03fd6ed","glsl-optimizer/include/c11/threads.h":"56e9e592b28df19f0db432125223cb3eb5c0c1f960c22db96a15692e14776337","glsl-optimizer/include/c11/threads_posix.h":"f8ad2b69fa472e332b50572c1b2dcc1c8a0fa783a1199aad245398d3df421b4b","glsl-optimizer/include/c11/threads_win32.h":"95bf19d7fc14d328a016889afd583e4c49c050a93bcfb114bd2e9130a4532488","glsl-optimizer/include/c11_compat.h":"103fedb48f658d36cb416c9c9e5ea4d70dff181aab551fcb1028107d098ffa3e","glsl-optimizer/include/c99_compat.h":"aafad02f1ea90a7857636913ea21617a0fcd6197256dcfc6dd97bb3410ba892e","glsl-optimizer/include/no_extern_c.h":"40069dbb6dd2843658d442f926e609c7799b9c296046a90b62b570774fd618f5","glsl-optimizer/license.txt":"e26a745226f4a46b3ca00ffbe8be18507362189a2863d04b4f563ba176a9a836","glsl-optimizer/src/compiler/builtin_type_macros.h":"5b4fc4d4da7b07f997b6eb569e37db79fa0735286575ef1fab08d419e76776ff","glsl-optimizer/src/compiler/glsl/README":"e7d408b621c1b605857c4cab63902f615edb06b530142b91ac040808df6e22f7","glsl-optimizer/src/compiler/glsl/TODO":"dd3b7a098e6f9c85ca8c99ce6dea49d65bb75d4cea243b917f29e4ad2c974603","glsl-optimizer/src/compiler/glsl/ast.h":"3e68ff374350c49211a9931f7f55a485d8d89fc4b21caaffbf6655009ad95bf8","glsl-optimizer/src/compiler/glsl/ast_array_index.cpp":"92b4d501f33e0544c00d14e4f8837753afd916c2b42e076ccc95c9e8fc37ba94","glsl-optimizer/src/compiler/glsl/ast_expr.cpp":"afd712a7b1beb2b633888f4a0911b0a8e4ae5eb5ab9c1e3f247d518cdaaa56d6","glsl-optimizer/src/compiler/glsl/ast_function.cpp":"74f4fbd490e366b37f4715168bb3465ecd9334d4130942f75dcc8e80e8e7f027","glsl-optimizer/src/compiler/glsl/ast_to_hir.cpp":"d0f798eb09271d41d068b9e7b18220d37f1ed0083300ab51eba30989698fe23d","glsl-optimizer/src/compiler/glsl/ast_type.cpp":"8eb790b24b26dfb72bdc333744b566c26d8464c5d47d20eae659461f5c4899f7","glsl-optimizer/src/compiler/glsl/builtin_functions.cpp":"454189d643c220fcb49116ee5c8a34f7b349aa67564040deb8607f6a41a15e70","glsl-optimizer/src/compiler/glsl/builtin_functions.h":"a37cad7ed09b522c5b8bec7b80115a36846e7ba6e0874a2a858e32f7f202c665","glsl-optimizer/src/compiler/glsl/builtin_int64.h":"619def6f3aebf180da3944ef08f159ab12a58b24767e41d8b985ac37ded54d62","glsl-optimizer/src/compiler/glsl/builtin_types.cpp":"afec060b62d6f3b00bfbf94e9fa5f96341ce096c128d1eef322791e6ed9cea4d","glsl-optimizer/src/compiler/glsl/builtin_variables.cpp":"6563bfb1345cbca4c77e00eef09ad152f3e1dc271d246a08c5ce9e1f4ce4250a","glsl-optimizer/src/compiler/glsl/float64.glsl":"1072fd888be48c2a7a5117cd2d92a65f034965a66375f598bb856bff5d7be766","glsl-optimizer/src/compiler/glsl/generate_ir.cpp":"e5f0175370a0d07f93c48d3f0f1b8233d12c64a7b02de02dcc753ef7b398ef0f","glsl-optimizer/src/compiler/glsl/glcpp/README":"a0332a1b221d047e9cce5181a64d4ac4056046fd878360ec8ae3a7b1e062bcff","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.c":"2d179879b1ffe84f58875eee5b0c19b6bae9c973b0c48e6bcd99978f2f501c80","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.l":"e4c5744c837200dafd7c15a912d13f650308ea552454d4fa67271bc0a5bde118","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.c":"03494f9ce1cb82260506e2559e73a3eeb622c4bd51b65eaa0a2c3351862bd4c8","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.h":"264d9a18421cde255ce34a0a62b3d8e73465359f0d167e64aa3973062aae5bdd","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.y":"fafb66e3a8f149d19e085f18a4273ba6d4c11af9e9a01d665cc784dddf97b79f","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.c":"37ed294403c2abfd17fd999d1ae8d11b170e5e9c878979fefac74a31195c96b0","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.h":"85ac8b444bcbd0822b66448a1da407b6ae5467b649f5afaf5c58325bd7569468","glsl-optimizer/src/compiler/glsl/glcpp/pp.c":"a52d94f1bcb3fb2747a95709c4a77c25de7eea8354d2b83bb18efd96976a4473","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.c":"d11aeb3acfe966d1b78f1ee49804093f2434214c41391d139ffcb67b69dc9862","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.h":"abbf1f36ec5a92d035bfbb841b9452287d147616e56373cdbee1c0e55af46406","glsl-optimizer/src/compiler/glsl/glsl_lexer.cpp":"272b9fc1383d72b81bfc03fa11fdf82270ed91a294e523f9ce2b4554bd3effa9","glsl-optimizer/src/compiler/glsl/glsl_lexer.ll":"2b57d9f9eb830c3d7961d4533048a158ee6f458c8d05c65bea7b7cfbc36e4458","glsl-optimizer/src/compiler/glsl/glsl_optimizer.cpp":"f8095d20629d0af70be930b0612e169edb274551a1d25a3cd1bf9995a11ce2e8","glsl-optimizer/src/compiler/glsl/glsl_optimizer.h":"22e843b4ec53ba5f6cd85ca5f7bad33922dca8061b19fb512d46f1caca8d4757","glsl-optimizer/src/compiler/glsl/glsl_parser.cpp":"126baf368d525aba301854e3d91ba60b5aee32e1102376af71416f32cb95ec48","glsl-optimizer/src/compiler/glsl/glsl_parser.h":"2ea9a50716098a8f7bef782d2a030d757b68da73afb01b4d4940d3e8381d44e8","glsl-optimizer/src/compiler/glsl/glsl_parser.yy":"6b1fd1576b29fce005dff744a6dbd0219e4c695c361d61864e1f3a8d6fa6b764","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.cpp":"aad64b5b66467da650091430681e8c6a820cf3cadc4db3c160bf2f15875390ae","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.h":"71fd0e92bbdb193dfb067d7bfdb1200d77392be2fbd0cbfc9ca89d1bb4c7e741","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.cpp":"6660fb83c0ddddbbd64581d46ccfdb9c84bfaa99d13348c289e6442ab00df046","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.h":"24682b8304e0ea3f6318ddb8c859686bd1faee23cd0511d1760977ae975d41bf","glsl-optimizer/src/compiler/glsl/hir_field_selection.cpp":"72a039b0fcab4161788def9e4bedac7ac06a20d8e13146529c6d246bd5202afd","glsl-optimizer/src/compiler/glsl/int64.glsl":"303dbe95dde44b91aee3e38b115b92028400d6a92f9268975d607471984e13eb","glsl-optimizer/src/compiler/glsl/ir.cpp":"2b4741cce90b5d4abff5d719c7324e2693c67294d4d99736cb241554adb281bc","glsl-optimizer/src/compiler/glsl/ir.h":"990b1c74447c4eb4835353ccb0ed9aea644f97fc1129ef1739cd935075d85d2e","glsl-optimizer/src/compiler/glsl/ir_array_refcount.cpp":"8cdc1cffe01e42e0566fa2193a75f789628e8025ad1b82f0ee6f204451b7f9f7","glsl-optimizer/src/compiler/glsl/ir_array_refcount.h":"75f06ec81342b379096ca52e1dc0fd5f19a11ff8e9b58203c20628179d644c12","glsl-optimizer/src/compiler/glsl/ir_basic_block.cpp":"1e2920b1c0ecb08424c745c558f84d0d7e44b74585cf2cc2265dc4dfede3fa2f","glsl-optimizer/src/compiler/glsl/ir_basic_block.h":"81be7da0fc0ee547cd13ec60c1fcd7d3ce3d70d7e5e988f01a3b43a827acdf05","glsl-optimizer/src/compiler/glsl/ir_builder.cpp":"daba29c5a1efdd5a9754f420eb3e2ebdf73485273497f40d4863dadeddb23c0d","glsl-optimizer/src/compiler/glsl/ir_builder.h":"2822e74dd3f6e3df8b300af27d5b11ea2dd99d0e5e7ca809b7bbcce9833c483c","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.cpp":"8c6df5abf2fe313363f285f171c19ca6c8ee4f3bc2ed79d33c0c88cc8be45c48","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.h":"799852adc3a0e54d04080655e7cebfa0d3bf5b6ffed5d8414f141380665d4db7","glsl-optimizer/src/compiler/glsl/ir_clone.cpp":"d897a4e1f5bbec4a6a2f15044c1be9a4d13899c73be77335b041049a4589aa5d","glsl-optimizer/src/compiler/glsl/ir_constant_expression.cpp":"78bd87ddb09db67f6c499067728d72aef4f16aa02721a99a4b769d1e0cfa9010","glsl-optimizer/src/compiler/glsl/ir_equals.cpp":"bca28533a6310b0fc152b56d80872368f1510dc62ed6e8ac199b9ffa7fac02e7","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.cpp":"7e918d4e1f237eca01396004015865ce345afe32a876c9dbc6728576a1a7eae4","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.h":"f45b66aa9497520e7e08e612d24b308477c34477fbd963ee9320eac664957f16","glsl-optimizer/src/compiler/glsl/ir_expression_operation.h":"cc9f10727dbd26cac506804f51456302c702650f9eeb59054a7e1575d5cf6687","glsl-optimizer/src/compiler/glsl/ir_expression_operation.py":"7b86c96021b9fbe165957f4ecb0b612fefcde1c2cf3c6d75e3cdb22e369216ba","glsl-optimizer/src/compiler/glsl/ir_expression_operation_constant.h":"9ad3346416392e3efa11e12ecf2feca7453c5253d241eb96c91dfb85d4f2b971","glsl-optimizer/src/compiler/glsl/ir_expression_operation_strings.h":"a6826daf496a8b9e89885bc2a161ac3445d501b23c6e0ac33e2c01b506b273c8","glsl-optimizer/src/compiler/glsl/ir_function.cpp":"7537365fc0fbe4b37a26b9a2146cc64d3e9a774d60eab63b65002ad165ae8fc7","glsl-optimizer/src/compiler/glsl/ir_function_can_inline.cpp":"faddbf112187a048d502716a3fb82570a322299ba2a3abd79388382c82040bfc","glsl-optimizer/src/compiler/glsl/ir_function_detect_recursion.cpp":"9176973eaf5c0a984701f953bb7a80f37dca43d59b5bce50fc69b3f02f2902d7","glsl-optimizer/src/compiler/glsl/ir_function_inlining.h":"9739493f99c489987d650762fccdd3fb3d432f6481d67f6c799176685bd59632","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.cpp":"3725861fbe2b98e0617f52d3b14cf6d3b25fb5ec00f5ef5d308b03642f592767","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.h":"e0560210e966c0c31e4ca843e80ea154e64db5a444b8c2df845b6ba5b3a43fc1","glsl-optimizer/src/compiler/glsl/ir_hv_accept.cpp":"caf7ce2cd9494aadd3c58bcf77f29de58368dc9e347a362bbf37f8bda9509b80","glsl-optimizer/src/compiler/glsl/ir_optimization.h":"8b3dcfc7f9e96b21a8dd47a0040d90be483a9e67a2cdce3a697188fb758d4630","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp":"f8e34a983452be0dcb5a695e9c8e895eead24f9e540992a8afe510ae85da4c4c","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.h":"1ad1bd3efd1ace39051c13f904c05fd80425d329444f9a8d47fd6d948faf46e0","glsl-optimizer/src/compiler/glsl/ir_print_visitor.cpp":"643f5a68aae3fb37267fd793f1216d1cfdeb2c09338c26b1f30e4c6deaef4de5","glsl-optimizer/src/compiler/glsl/ir_print_visitor.h":"4573eb93268a2654c14b505253dd651e2695d43dc745904d824da18305269b95","glsl-optimizer/src/compiler/glsl/ir_reader.cpp":"06bfba802c8354e5a8b2334b6d78d6297de18235bedd3f8fbb382c89870b02f2","glsl-optimizer/src/compiler/glsl/ir_reader.h":"63e3f7f1597936a7011d5b520e171b197bf82bee6c1560d822c3edf5aaa6f9e9","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.cpp":"84b5c5d746555adca85759c2912fe48010232b7c1c0bd2cf03bd04067a85e66f","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.h":"fd8c561b71085d3211fff85ed514fecb299d8ce19a04bc063419a55b6d840525","glsl-optimizer/src/compiler/glsl/ir_set_program_inouts.cpp":"ab9f115ce9e7f312d9c7978340ced0dc4ae6d13a80e08442ba9709d11d50cae5","glsl-optimizer/src/compiler/glsl/ir_uniform.h":"683ae6896b1a08470c090be5f822fc31cd434eab9216e954b9bba24a46975109","glsl-optimizer/src/compiler/glsl/ir_unused_structs.cpp":"9c1620c45f2fc071fe5ed828472040b14c5f42effe06aa0e3b8352c95ef78786","glsl-optimizer/src/compiler/glsl/ir_unused_structs.h":"13387b49c23093575276b25b9dfd31fedd8f131c5c4f3128ab04cf03e15b5295","glsl-optimizer/src/compiler/glsl/ir_validate.cpp":"6b232be5999a86ea278f4f15b2832d76843246509118d924243055a3b9b0299f","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.cpp":"2764a3cad937d53f36db7447c3a5b98b04bf153acf81074d971857fc5bca460d","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.h":"b0668e3eb1501ef65e38fe12830742ecb3d28e6039f30e366c8924efc29b4a39","glsl-optimizer/src/compiler/glsl/ir_visitor.h":"f21b3534c3d66d5fb707d1581fece7e1eb043523afbaedf89918cfb031c6df94","glsl-optimizer/src/compiler/glsl/link_atomics.cpp":"360f0209e11f367ba358223597b0a118bae095bff16337cf03f1fb89c5b80ca6","glsl-optimizer/src/compiler/glsl/link_functions.cpp":"de7895da8aa33a1e3c2c1eb2fdaf267ab5d1fbfdb79ae2e67f95211e946e294c","glsl-optimizer/src/compiler/glsl/link_interface_blocks.cpp":"1926cfa73810704eb19b916c1b2cdb9321155e2f98b2a0a57c7c3c6e960540cd","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.cpp":"1e14e06ca3b2c1089cfba2e8eaf0c1f373d9d6374b6082f320962dd71ae09611","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.h":"fd58c155af645295bb6aec08797889de586f4d919731de2bce57e8dce59bb048","glsl-optimizer/src/compiler/glsl/link_uniform_blocks.cpp":"09589f49776dce32e6c4044937de7e0c839a9754ad31960148f8f9e010658997","glsl-optimizer/src/compiler/glsl/link_uniform_initializers.cpp":"bf98e08c12db466acf9623cbeb8fa8e3b4002512722e7a6521287f558a099f37","glsl-optimizer/src/compiler/glsl/link_uniforms.cpp":"84bad5b1377362cecf259b05124239be5220b03ce1c0c61b59bd9a47e4379af2","glsl-optimizer/src/compiler/glsl/link_varyings.cpp":"a5f1a53e7c80d635515fe808ff223d89fef1767abb0f2b7aa28fa6773dca353f","glsl-optimizer/src/compiler/glsl/link_varyings.h":"b9dbe018f038df69763df2e928742ce81bbc6e3aaba26f50621e30a6d9aa6220","glsl-optimizer/src/compiler/glsl/linker.cpp":"40b1ecd5d4f6c7f13d5a87ce390561a51fdf6f3fcd9b2197b9c88b03a773ba94","glsl-optimizer/src/compiler/glsl/linker.h":"ecf94b4ad75ef461c27c557fda4bd25f34c91930822b8e1d729ec84520d4a049","glsl-optimizer/src/compiler/glsl/linker_util.cpp":"1663ad88e2a369305659aeeffaedb5bd752cf76340a2ba5797fc0bf600633cf9","glsl-optimizer/src/compiler/glsl/linker_util.h":"6db788daf9c8e87ae2764b61a8b37ebe419e69c1b82ddee01986e37c978c6993","glsl-optimizer/src/compiler/glsl/list.h":"b1f46ce0e552fe7c45b2a19408a9d97662e23e4b182ab335491c26f8cf25886f","glsl-optimizer/src/compiler/glsl/loop_analysis.cpp":"57ecd573477c68091c7cc99537faa7139a8f395935e3d4f10144cefdefb5a611","glsl-optimizer/src/compiler/glsl/loop_analysis.h":"a85f045a038ee5b5176063e85d7988865862c44ab0580f771b993a042d0b69cc","glsl-optimizer/src/compiler/glsl/loop_unroll.cpp":"bd4292ea2809f5a669bcb76ceaa1ac365772dcd638c579c3ed10275214901a54","glsl-optimizer/src/compiler/glsl/lower_blend_equation_advanced.cpp":"8cfbef140d9c4b4d2f57bfa05c9c374d31a121d0f87afce94333f049023b654a","glsl-optimizer/src/compiler/glsl/lower_buffer_access.cpp":"1ae221c3c7a95aeb867207e7a742be635f91b406c157747bfd6ddf10274d97fb","glsl-optimizer/src/compiler/glsl/lower_buffer_access.h":"807886953a576a323591798cbca5e2df24295ea893b28affd8ffb5926cebaa04","glsl-optimizer/src/compiler/glsl/lower_builtins.cpp":"4d81afc32cf58e1481fcb5e42888ab93dbe6820310a20ff7a9982b77b2152d9b","glsl-optimizer/src/compiler/glsl/lower_const_arrays_to_uniforms.cpp":"608403f0eeeedf21cfcd3014116e0f44e28cbdf6c4c32aac7e613e64e30205e1","glsl-optimizer/src/compiler/glsl/lower_cs_derived.cpp":"179905cd47a294122adeb5b0abfed6f2f67782dcde21b544d1ee2c1985154e66","glsl-optimizer/src/compiler/glsl/lower_discard.cpp":"3b361b2db0004d544d64611cb50d5a6e364cf6c5f2e60c449085d7d753dd7fb0","glsl-optimizer/src/compiler/glsl/lower_discard_flow.cpp":"f5c29b6a27690bb5c91f196d1a1cf9f6be4f1025292311fe2dac561ce6774dee","glsl-optimizer/src/compiler/glsl/lower_distance.cpp":"a118c85493d5d22b2c059a930c51a5854896d4b1dade76598eaa985e5a3dff8c","glsl-optimizer/src/compiler/glsl/lower_if_to_cond_assign.cpp":"469e617757fd1728709cce021aac5c8da05ee503bf5366977bdc4ef7a6d83950","glsl-optimizer/src/compiler/glsl/lower_instructions.cpp":"6ff5c396abe40d8a2145d571e99e2bbe9143393e15aafc28adc2803a01d821b6","glsl-optimizer/src/compiler/glsl/lower_int64.cpp":"d1ed41196880dd53c7b13e2782f9423f8442bf1d46186e8be92b1b66218a83ee","glsl-optimizer/src/compiler/glsl/lower_jumps.cpp":"34de7b493f281589fb0c2c0f6e885d0a0fabbe7a4e97a73de374dd714777a58c","glsl-optimizer/src/compiler/glsl/lower_mat_op_to_vec.cpp":"dff7a308edc4846c348ed4225c6699a9c75abac68d88f41f85954276552779f4","glsl-optimizer/src/compiler/glsl/lower_named_interface_blocks.cpp":"16063ac127bff75a68272070ab11c21c25101edbff62b4c68f4983b4cd941af0","glsl-optimizer/src/compiler/glsl/lower_offset_array.cpp":"3b00773399135aea85746a5a68b96ef000bc6841be1a2c8e6f25c516628b0949","glsl-optimizer/src/compiler/glsl/lower_output_reads.cpp":"a0fc9975d5aa1617e21fc6c353659a9802da9e83779a3eef4ec584f74b4dadc5","glsl-optimizer/src/compiler/glsl/lower_packed_varyings.cpp":"7550099d4ae123d71541c2fc88bc04fbfe9271ec75d7e210987d1c8cac3cf3ea","glsl-optimizer/src/compiler/glsl/lower_packing_builtins.cpp":"79a13d161fe505a410ab948d92769395708693ec888153630fa240e5b97e356f","glsl-optimizer/src/compiler/glsl/lower_precision.cpp":"f82a185b879872b977a1787d8061b9a80bc4cf8db1b970db6efba2ad9cc20fa2","glsl-optimizer/src/compiler/glsl/lower_shared_reference.cpp":"ea2dccf50a83bc19391bf6b7ab6aa53c0005f427af4066d25140340af9a4beef","glsl-optimizer/src/compiler/glsl/lower_subroutine.cpp":"f69fa53650eeb6f2944fce4d36a6e0a423e6705f3a3bd3389c7fadb83cfc8802","glsl-optimizer/src/compiler/glsl/lower_tess_level.cpp":"b196c9d424c0569f3e85d75c2d125af21566cb113d69036db87c0990703e0fa7","glsl-optimizer/src/compiler/glsl/lower_texture_projection.cpp":"4d247f244272adc8250fd888d8d932a140dd5de4d1efc7a58492c3c2b8291527","glsl-optimizer/src/compiler/glsl/lower_ubo_reference.cpp":"89bdbc6c1669230c644c0857db1ce2781ec61d349ecd08c7914146e1f4750a4a","glsl-optimizer/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp":"fce930f29ac9405b297d1f749d68f59506b89c70b4ee1b1ab8cf49a34cc71ecf","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp":"3c67d851a11a55fad1c49a550f3a0cfe50892d33a3f238ce266cd829eba510a8","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_swizzle.cpp":"f5ec666b73e1415cbab32519a53605ed385f3b03e889560373dbce69dda5000e","glsl-optimizer/src/compiler/glsl/lower_vector.cpp":"f7c13f5572ebe09b6a71553133b2cf003cd4b77b9657600672ee3b21bf890725","glsl-optimizer/src/compiler/glsl/lower_vector_derefs.cpp":"b05793da6dd620a531b43df5af8b2ecbc37b9db0c88910f5724ea10bcd057e19","glsl-optimizer/src/compiler/glsl/lower_vector_insert.cpp":"fee772ec17eea5e86a529bf9c5fa2ee0d29a5982bb75ebc6d68ed36cd19aa299","glsl-optimizer/src/compiler/glsl/lower_vertex_id.cpp":"690e8715182e03fead5cc5a35251fb4f41b357e4c71a1dfbc4bd7be19862b56d","glsl-optimizer/src/compiler/glsl/lower_xfb_varying.cpp":"58c0e8b270e4bbde54250be03cdb2f36966bcafb785372ad2e2b786835df7f9f","glsl-optimizer/src/compiler/glsl/main.cpp":"ae5e88abbbc8a12f769e1296bad938b9d7398cc6da0d3d0caeceeeb876536850","glsl-optimizer/src/compiler/glsl/opt_add_neg_to_sub.h":"f5054944bfd068810629080d0ea11df78b3f57a8f86df75e13ca50157ad1964d","glsl-optimizer/src/compiler/glsl/opt_algebraic.cpp":"25f45b20e1972ee8c789177a1aeda6e4286c25db2eae3a43ff83029ae64969c0","glsl-optimizer/src/compiler/glsl/opt_array_splitting.cpp":"19d3ce0e815438f4df9ab2890e767b03a4f3f191b53bb30c0217cf2ae6a95430","glsl-optimizer/src/compiler/glsl/opt_conditional_discard.cpp":"0e44e0e126711a3725c1f3a2aa65ff03c381fed08680ffc30101aae60f716c4e","glsl-optimizer/src/compiler/glsl/opt_constant_folding.cpp":"a088d04d9b45f9e55e235835648f614c89b7803c03a6d4f6a6d1a6bc1f0228bd","glsl-optimizer/src/compiler/glsl/opt_constant_propagation.cpp":"8a9440d77ecd6dcf13e683cbb99943aab6311c8fd4b5f6a9189a8d4f270746f4","glsl-optimizer/src/compiler/glsl/opt_constant_variable.cpp":"63d3ccd4dd09f19c9cf1a2f51592111bed41284504f29f3c0de4cadebc439a37","glsl-optimizer/src/compiler/glsl/opt_copy_propagation_elements.cpp":"ffa0f50863995e0d2e31f55a52e82319edc71e520987bebd7f7e561ea331c64b","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_variables.cpp":"84e8747b948232f01dd56b428b9315f96f9511f605f240119fc446fae28981a9","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_varyings.cpp":"761523e88f5b3ba785170f4d7205e94fa99acb7e74d29efbe40e1c010e1dbdb3","glsl-optimizer/src/compiler/glsl/opt_dead_code.cpp":"fd1ba2da7337d4e5dad17f5c2d73d9cc8880305f423e85d64cf94553588fa401","glsl-optimizer/src/compiler/glsl/opt_dead_code_local.cpp":"969a598b4df322baf222258a66cd64a326ea20e5b3125be9d8d1771f522c69e0","glsl-optimizer/src/compiler/glsl/opt_dead_functions.cpp":"774cae6536d02edf26e996a2a895e1f62d5098f16dc96b44798b4fc731a9a95f","glsl-optimizer/src/compiler/glsl/opt_flatten_nested_if_blocks.cpp":"3696a5c55f02e20056e085bc2714f73ac992f221b6f3387d655068e86b512046","glsl-optimizer/src/compiler/glsl/opt_flip_matrices.cpp":"44f0fe05b49329667671f88c96dc86ab3fe1459ff7b87f2b2d88de2d49829f9f","glsl-optimizer/src/compiler/glsl/opt_function_inlining.cpp":"fb56a33c90419a01676b57cbd91d0674a54cca40e6defaacc88dd33facebc131","glsl-optimizer/src/compiler/glsl/opt_if_simplification.cpp":"ac406eb35e379c357641d6c5749f50c65961455924d3dc884e2b90046fa92c5c","glsl-optimizer/src/compiler/glsl/opt_minmax.cpp":"8abd59d3b14ef60ff14a9c69660e6945f5cf10b97edb4afebe56be3f81d96316","glsl-optimizer/src/compiler/glsl/opt_rebalance_tree.cpp":"8bb6329dc0f299042368fc81934c2df019b45ab9f7aa0415d4e57b8d1ff98c9f","glsl-optimizer/src/compiler/glsl/opt_redundant_jumps.cpp":"222c73e2ac7a938ebb6428cc6c780c908ff6156d8ff935b04fed93a48fc10496","glsl-optimizer/src/compiler/glsl/opt_structure_splitting.cpp":"2edc79cc13f3177934e0443ad62f5976a1991f01f86ea303a803434849b13a47","glsl-optimizer/src/compiler/glsl/opt_swizzle.cpp":"015d0abddfe507f67c4b96c82988d861d018ededf7bf055e2bcbe9ea92da694e","glsl-optimizer/src/compiler/glsl/opt_tree_grafting.cpp":"46d28ac983ea244a4315bdc0e8892979ec4d1f9b9a96ac8a8a08006d9bc5e878","glsl-optimizer/src/compiler/glsl/opt_vectorize.cpp":"d80ee43bb97d9f016fb9c5e1e06f5b2afa569811f368ba067be794ec11d085fb","glsl-optimizer/src/compiler/glsl/program.h":"2982447e2abd35371e273ad87951722782a8b21c08294f67c39d987da1e1c55f","glsl-optimizer/src/compiler/glsl/propagate_invariance.cpp":"080943e21baa32494723a2eefb185915d2daae1f46d6df420145c5ad6857e119","glsl-optimizer/src/compiler/glsl/s_expression.cpp":"1ced972bc6ecc8eab4116ea71fb0212ab9ae5bcc0be3b47aa5d9d903566b3af1","glsl-optimizer/src/compiler/glsl/s_expression.h":"65b847e30e22a809b57d0bc70243049c99d9c6318803c5b8d0826aba55dc217e","glsl-optimizer/src/compiler/glsl/serialize.cpp":"be0eb4251348a9d921acb839a5c48c6023a2e9d116d602bb0432787ab623655d","glsl-optimizer/src/compiler/glsl/serialize.h":"57425732eba1233d928e5f07f88b623ce65af46b3bb034bf147f0a4b7f94f9a1","glsl-optimizer/src/compiler/glsl/shader_cache.cpp":"e0c5c433f2df3fccdf1d61281bfcb0ee5633433339b97c697d64db99611cbaaf","glsl-optimizer/src/compiler/glsl/shader_cache.h":"9217164d8d7f54aca0fe5922c7187095a6ae0cb703b196b79805aeef07a7e697","glsl-optimizer/src/compiler/glsl/standalone.cpp":"8e6c416a14d631261917a5fe4cc91880c287b22b2dfd70eb22028289a8fa5364","glsl-optimizer/src/compiler/glsl/standalone.h":"a7c397d1dfdd1e7fb2cfe99db35cd9df93251e642059208533202b7f20497f83","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.cpp":"970d14b7a9d58e5270321f97bf5d57795558b1c570a56678e04a65b26c60bf4f","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.h":"d921a617ea82b9e49413314492a645c44356de503581b1be3f1b57de236e480d","glsl-optimizer/src/compiler/glsl/string_to_uint_map.cpp":"d824bf5b839bd39498dc9e457103cdbe3e5289ddf7564107c27b1505948dd31f","glsl-optimizer/src/compiler/glsl/string_to_uint_map.h":"e2f18e66359c9d620e085de7f4a334a47df9c66e65a5bfe8b734c627bec04104","glsl-optimizer/src/compiler/glsl/test_optpass.h":"b27b8f35f5387e7ce4982bb51c7b63ccf14f91757f3108a5d02ed006925bb8a0","glsl-optimizer/src/compiler/glsl/xxd.py":"376484142f27f45090ea8203ae2621abf73f06175cb0ee8d96f44a3b9327f4bd","glsl-optimizer/src/compiler/glsl_types.cpp":"044bb6754f45419a3151e7a25c39202a82009ae3c6bc54ff7f0bb4258a5deefe","glsl-optimizer/src/compiler/glsl_types.h":"fd899a42f34ddeb8601bc3cd6c5e3aed82fc8aef4042dde1b39b3c01e1dcc219","glsl-optimizer/src/compiler/shader_enums.c":"436bff5216b11b0980bdfada5885fc6ac9afa2037a3027fcd6eea2a8635597ac","glsl-optimizer/src/compiler/shader_enums.h":"13220442a5c02e83540cf2c0ad4f8417b2fbda5f2586dec4e92082544c937cdd","glsl-optimizer/src/compiler/shader_info.h":"4c5453e81197ca83593ee4f365074b23530f2ab21c78e1733b63dec6f344c12a","glsl-optimizer/src/gallium/auxiliary/util/u_half.h":"3c2b37bda3ccb64387e44b723d29cf9046decab1a893bf42d842e9603398bdee","glsl-optimizer/src/gallium/include/pipe/p_compiler.h":"c75620096ce8523dae90599e50aa2ef6468d3b0e368a77795edeb20dd1abfc0c","glsl-optimizer/src/gallium/include/pipe/p_config.h":"a27692fc35f9e55df3224b7529e66b3001e911e94e6bc5f8f569e493e1ee3fb7","glsl-optimizer/src/gallium/include/pipe/p_defines.h":"be26d68c0acc67c5e44788c6299716a9eee415fd81d7d747e3738a829e3b6b38","glsl-optimizer/src/gallium/include/pipe/p_format.h":"5674215fc41d27496f037cf837717daefbf23ebb38d40ace7c0c414bc08182b0","glsl-optimizer/src/gallium/include/pipe/p_state.h":"d600593aba5f5a17072a6c38f6baa81e01c7994b0174250f7e433bb41684b702","glsl-optimizer/src/mapi/glapi/glapi.h":"73632a625c0ddabc401205e8b5a81eb8af8506868efe4b170d7979ec3619e9c5","glsl-optimizer/src/mesa/main/config.h":"5800259373099e5405de2eb52619f9de242552a479902a3a642a333c8cb3c1e7","glsl-optimizer/src/mesa/main/context.c":"2f3208473d99c94f734b1137ba91889d4a1babb9e7534bf1dc85d851ee98274e","glsl-optimizer/src/mesa/main/context.h":"cc7e4194797db9d007f01884e23d786c453b3860821f7f2ddcdf0f1bf3f8ffb1","glsl-optimizer/src/mesa/main/dd.h":"6a964acd06b6c2d88700e69fb75fe3c6b3b3d45bbc41db24f3f897a29695fe0c","glsl-optimizer/src/mesa/main/debug_output.h":"7312422e90b8c0e34028ac27280e438139b5cba525c99deb3ac883cd3d87e452","glsl-optimizer/src/mesa/main/draw.h":"7eaef3a9e27a60ea6f7937109bf3a6190b831162fde0479abb12077ce27c353d","glsl-optimizer/src/mesa/main/enums.h":"87d562a6764f51c014a2274fa7c3aca17c04441537ddd56b2554f13c6fffea92","glsl-optimizer/src/mesa/main/errors.h":"c79444b5df289c90fbb22a33b2d0c23917d9fc4510960088f0b79e53bb56b1b2","glsl-optimizer/src/mesa/main/extensions.h":"a38b2f87cc93c513994281350d69e06c84ff8eded5313ec0a1be33f375e0ebbd","glsl-optimizer/src/mesa/main/extensions_table.c":"17642d1a8c9a0bf2bd61060052d33ff14a005d2b962e6cf91465797a50851e85","glsl-optimizer/src/mesa/main/extensions_table.h":"2c879571c238d2e14461031ac740372fd0f9ac3a34c0d5541bb9b7ed4c0376c8","glsl-optimizer/src/mesa/main/formats.h":"02e2f7ec3e39286cf9f27e2641043e6df8ecb1dfde9e643313210e214af2a929","glsl-optimizer/src/mesa/main/glheader.h":"58217b33eead6aa6b23cd4a291cefeaa6cb84e465f4960daffca97c44d6d1c35","glsl-optimizer/src/mesa/main/glthread.h":"51fb2711f77e7eafcfc52d29d5b844978832b24c930d88accd48d143a6eb9c6f","glsl-optimizer/src/mesa/main/hash.h":"7e7f782034c16a8e693de48e00c31d4a90b0129f4029fd074033d7d16ccbe718","glsl-optimizer/src/mesa/main/macros.h":"73d15ddfd64f2b57b9b2ffeeb993b9c2c0899a80563e9d6ff337b11ccbe6eee5","glsl-optimizer/src/mesa/main/menums.h":"5dfac0e2279d60b0cd0c7b9fc2a5021620d0f6282ed2e738c420214e3af152d3","glsl-optimizer/src/mesa/main/mesa_private.h":"edda678b93438944279a551f663b8858ad84814a9fc88ba9672ef195599c24ae","glsl-optimizer/src/mesa/main/mtypes.h":"6efddefa099e4d2e3fdd97f0055644f47aba21711385edfeabc2d9b0676f2eec","glsl-optimizer/src/mesa/main/shaderobj.h":"9f0dfe96d0c2154201adef942bd36053533ac7b2492fb3786acda5bea514c75e","glsl-optimizer/src/mesa/main/uniforms.h":"4e331e6ad6e9cbded978b4082dbe0a57c1f8f01327446bb6892bfc179976c38b","glsl-optimizer/src/mesa/main/version.h":"9d0a13a758099302dc55cf7d045791834a89b0f9d4cf17b2692259b369a8a9a1","glsl-optimizer/src/mesa/math/m_matrix.h":"a37b19f182e070db3df93b0ede43c22fb8be8c2906504133ee6dbd7db1185d8b","glsl-optimizer/src/mesa/program/dummy_errors.c":"1820e305515b4c5e041f5e1623266a48ec8f076a155310be7d60637101f593e4","glsl-optimizer/src/mesa/program/ir_to_mesa.h":"b47f58d22e3ca2ae42d52501ea769d15c4476834944fa97eeccd3a3439211d00","glsl-optimizer/src/mesa/program/prog_instruction.h":"ab3832152a7e144b59e5a2264b2c29db56d93be31e76bbd958527a56771b40eb","glsl-optimizer/src/mesa/program/prog_parameter.h":"ba18c743284eadbc837c2c364c73e5d372321a7637a76e589d8d39fe8b5de225","glsl-optimizer/src/mesa/program/prog_statevars.h":"fc413698f84bc52d45fdeae0471934ee9904bfb7eac1a2b5f70446e54bcbbdca","glsl-optimizer/src/mesa/program/program.h":"1f01026a4eff440a3f122fd9b519d03546fe7f7d8be60dca834e95a2f8fbbfd2","glsl-optimizer/src/mesa/program/symbol_table.c":"6611cb9f078035bf5ff8c9112093a6c7d99f8af99a3931d0c07f227cc72283ea","glsl-optimizer/src/mesa/program/symbol_table.h":"631dc35ac48d5e87962d45507461920f6575610960ffcc42a08cefeb43300cda","glsl-optimizer/src/mesa/vbo/vbo.h":"6eb1dcd9a08c92f276c5fe08da184ff9d455d1be421913b8ad732a7b65e858fb","glsl-optimizer/src/util/bitscan.h":"9e49e694e6b34fe035bc685f32588827eb8cbe7d82878963c7ab52843e1c16aa","glsl-optimizer/src/util/bitset.h":"c40f78515c6230fed18345c6751ce33833a49da7a27901c7e6d7340cbdcbc5e7","glsl-optimizer/src/util/blob.c":"8f729846f66efc9c15485cc5fc24c6ec861fc1fecb2f652573f2a237d481b791","glsl-optimizer/src/util/blob.h":"93e1eaac866b9a7cd6fc03b533c18fb2edf0e97f03395eff4f3a605c4fc14d0c","glsl-optimizer/src/util/compiler.h":"79e3bf40a5bab704e6c949f23a1352759607bb57d80e5d8df2ef159755f10b68","glsl-optimizer/src/util/crc32.c":"2f3467a046b3a76784ecb9aa55d527698c8607fd0b12c622f6691aaa77b58505","glsl-optimizer/src/util/crc32.h":"59bd81865e51042b73a86f8fb117c312418df095fed2d828c5c1d1c8b6fc6cd4","glsl-optimizer/src/util/debug.c":"c3d68e9752ccc19e66c669562cd113cf1d0ac83cbb30174789e7fb8d1df58f9c","glsl-optimizer/src/util/debug.h":"50068d745c4199ccbd33d68dd4c8a36d2b5179c7869a21e75906ddd0718ca456","glsl-optimizer/src/util/detect_os.h":"343a8790d17a3710c6dd015ee367f84e3902ff3f2e36faca2bf93f9d725d3574","glsl-optimizer/src/util/disk_cache.c":"f533937e5a4fffe76e2739ef4b6b1e1da097d96d63eb808e68ebbc7027641c23","glsl-optimizer/src/util/disk_cache.h":"e83314fb14134a8e079b15e470a6376ba5a8253701f048c890a62b7e55d64bc8","glsl-optimizer/src/util/fast_urem_by_const.h":"e108fce804616c47d071dfe4a04163eec1126e448ed1aa89abb6b3a6d772bd5b","glsl-optimizer/src/util/fnv1a.h":"ab2596f19c6adf431ae27618f62c5743e24ad23ef83bb359a4c4c218245ab459","glsl-optimizer/src/util/format/u_format.h":"4cdfc0c59cbc99a092e5ec5a396910f2d93b9643e5d8141050b011e66f11e45b","glsl-optimizer/src/util/futex.h":"26f7c9d86e9ffef4c0fa2761f1aaa1918337302e20bd6ca10e61dc3c47356deb","glsl-optimizer/src/util/half_float.c":"11bc2584493d5d9d46e8c8a619a0307cf150bf5ab5d0f96bb764b061dc37a00e","glsl-optimizer/src/util/half_float.h":"7f7c380f126da1400a91758cc0392f24bf967bce1672890b62be26fe9fbd922b","glsl-optimizer/src/util/hash_table.c":"0ca40352e35dedab0a84c64c903f1b16d47e950bb5f43b4d22bb57d499bfea6e","glsl-optimizer/src/util/hash_table.h":"217191bb360592e2232f187473c10287d2cda8ae6fa5c53d0ef74c8c206118b4","glsl-optimizer/src/util/list.h":"9fab03c6a78186bb5f173269f825f6ce976b409d931852e3d93bac632e07989a","glsl-optimizer/src/util/macros.h":"63faf65b51058c483b17f1f77da51d1c53c8beab52678cb6bd01f1228a63b6b0","glsl-optimizer/src/util/mesa-sha1.c":"00c692ec353ebc02c06c57c5a71de0ab7a119f86a4146f452e65ec87e4944417","glsl-optimizer/src/util/mesa-sha1.h":"bff4c29f4bf7cdbcefb30fa0c996a7604a380eba8976467c2a60e7cd328f7e26","glsl-optimizer/src/util/mesa-sha1_test.c":"25da89a59d51469f77b4c468ca23ffdce0a7a1166a70b6cc23026a6800b0143c","glsl-optimizer/src/util/os_memory.h":"64555faf1760ae6954f42c83727c38dfc4c278e9152115779ffaad58b42adacf","glsl-optimizer/src/util/os_memory_aligned.h":"12d86fa94be38c13f7eeebdf313795e1267dd5a7187d2f0072e0e896f41702f6","glsl-optimizer/src/util/os_memory_stdc.h":"07360363b88c927065e10df71bebf6c8a0cc3b9167c9dfce55f2d65f11e6f787","glsl-optimizer/src/util/os_misc.c":"a9936e613ec84803abd59ad47c192c8e3939993c950ac91973fdc4cec1801bb8","glsl-optimizer/src/util/os_misc.h":"cc68eb12e05b5e749c54298cb4a6f4cd20cc5af7db3403e70b3c27b56090c740","glsl-optimizer/src/util/os_time.h":"73e775f7335244ff5964c678c27eedf1aea6abea44c4169d327ea8c7ce4a3a88","glsl-optimizer/src/util/ralloc.c":"4b51189595ef67bcef52c40cbf654d969041dbd15e15d4a893ad494ac060aeca","glsl-optimizer/src/util/ralloc.h":"e573c45875ff1530f0dbee9a93ae55535fdac8d5cc88a79ebc327c688824bde5","glsl-optimizer/src/util/rounding.h":"0450722353caf83de07e67f335949dbe95fe53b534052d4ee9d28d2781387614","glsl-optimizer/src/util/set.c":"86f8c9a830bead5a5a79bc970b0ff97809312af07b3beb39ef9d90af04d40a1b","glsl-optimizer/src/util/set.h":"3e39ca161e7ed4ec7c436cc9c7919ed9a55ed1b71edbf2caf6f9bcfd9bc578ed","glsl-optimizer/src/util/sha1/README":"00af7419af05247081858acb2902efd99fcda2ce16e331079f701645bb3729c0","glsl-optimizer/src/util/sha1/sha1.c":"1403bbe0aad42ba3e6be7e09f7cad87a6a8c4ad5b63962f7b92b9f37d8133b04","glsl-optimizer/src/util/sha1/sha1.h":"68d9f240eab2918026ecdf22be36811abbd4f1389f6c36e31258041aeaedd247","glsl-optimizer/src/util/simple_mtx.h":"12c6c3c4b7db9168bc656d5b3c65912075084d2b388c415d5c3d3f5953a9d6c7","glsl-optimizer/src/util/softfloat.c":"a97e51a96fe5e6a052c02aa6bbec683fe73fb88a8c087d9c930503e2120d8a2e","glsl-optimizer/src/util/softfloat.h":"66664b0250e83bf5dd4cc743acd119d076efcea624a0eab3d6b60718e6ee8811","glsl-optimizer/src/util/string_buffer.c":"63a1d1b1e34926c88ea00159cafbcd56568b805c4f64d1e8c97169fe313921fc","glsl-optimizer/src/util/string_buffer.h":"7b88d1b1d9c6cfb8e93331813535c127289437c75f822029e9a3bca8ea6b52ee","glsl-optimizer/src/util/strndup.h":"0273c4fdb7482cd7746881a63d3998648c6d63415ba85af1d1860f0e0dc504c6","glsl-optimizer/src/util/strtod.c":"5cf610d8a37373cf37cfb7aae903525d943b2674b1f32594c70b0eb19a8c9697","glsl-optimizer/src/util/strtod.h":"237396def4e264d35ed4bedea00ef9a4ceab6d7a11a18c770d9747d22c69ed2d","glsl-optimizer/src/util/u_atomic.h":"c02e809526c6c09ba8fe51f50b2490d1b6c8e5c7f3c4031ae958250d098fc3bb","glsl-optimizer/src/util/u_debug.c":"8c060e379b816618f3dd22c9ea523c68b9425c76c36a7dfe5d6d375b337f5f4a","glsl-optimizer/src/util/u_debug.h":"e11e26edd9b9e4e6f8e6a435e69f4d9edda27e9a379f68f4c82ea2525aaaea68","glsl-optimizer/src/util/u_dynarray.h":"853d0fa6ff2261614488be624deb8a2b01e57c2c8eabc28578cbeed4ccc95694","glsl-optimizer/src/util/u_endian.h":"3ccea7e529740318d8a4b05c00db3adc9d1e292a52bdc56a05c9fae99209720f","glsl-optimizer/src/util/u_math.c":"c868a8c0886dc78f1b06b13404ba8b253090449045774dd56893ac9d75795184","glsl-optimizer/src/util/u_math.h":"a04e32e126db016413f9de0a2028a3e71737137463b1289eae576f884b06fcf1","glsl-optimizer/src/util/u_memory.h":"c5db17c724c70283ddbe04165722f6988d4e0eb9aa3602ae472feff016649af9","glsl-optimizer/src/util/u_queue.h":"92930ce236c0528a98b695f5cea8c5c6aa9683beaf71a2227bdc5d33d1b21506","glsl-optimizer/src/util/u_string.h":"c5a2f4ef576d1547bda12c4ea219179fefa54414977743ac094abcaf696ef6ca","glsl-optimizer/src/util/u_thread.h":"00b708459b27f9910d18db92c18cc65cfc618ac2b3cd144e45f8640057b10d58","glsl-optimizer/src/util/xxhash.h":"2f2aff2fc6c0c929f52cf6ae7314122124c5be026d41ad1c357608383c4a37ad","src/bindings.rs":"79993db2058bde39f99ef483d02560d33b1cb882f6a552319e8b86eb6f9021e1","src/lib.rs":"04be1554cd829eb40864b06d80b491dd48117a4e3a601c7d482117f7a0391e67","wrapper.hpp":"f3ea34cc496f7d90b9bfcada3250b37b314c3524dac693b2ece9517bc7d274ac"},"package":"8ba4741358604ca0848c27ecc069d68e62e11cde81e38aac1da3c54b79ab5adf"} +\ No newline at end of file ++{"files":{"Cargo.lock":"f7970552595dc803ace9ef19b5f5d7b1fc784aac30cb27b2ebc3002d97122b9d","Cargo.toml":"7c53ee20d848f9913cacbfcb3ab2e89e30deee8d619d173c95130c7c5d065827","README.md":"4468e08c64c19977707d792bfab0080e35ff927b64990eab77873f8ba056ba1c","build.rs":"92e29699487c21389fc823c50b410cfbfc74cc774265d24958489909ee48a076","glsl-optimizer/CMakeLists.txt":"42ce94744e82ffa000da8b64d81fc140e293b9f5da7dd4cf6b49e7404a2448d9","glsl-optimizer/README.md":"b18eef11a92d267d88a937b1154f7670ee433c730b102fdf7e2da0b02722b146","glsl-optimizer/contrib/glslopt/Main.cpp":"14ba213210c62e234b8d9b0052105fed28eedd83d535ebe85acc10bda7322dd4","glsl-optimizer/contrib/glslopt/Readme":"65d2a6f1aa1dc61e903e090cdade027abad33e02e7c9c81e07dc80508acadec4","glsl-optimizer/generateParsers.sh":"878a97db5d3b69eb3b4c3a95780763b373cfcc0c02e0b28894f162dbbd1b8848","glsl-optimizer/include/GL/gl.h":"1989b51365b6d7d0c48ff6e8b181ef75e2cdf71bfb1626b1cc4362e2f54854a3","glsl-optimizer/include/GL/glext.h":"2ac3681045a35a2194a81a960cad395c04bef1c8a20ef46b799fb24af3ec5f70","glsl-optimizer/include/KHR/khrplatform.h":"1448141a0c054d7f46edfb63f4fe6c203acf9591974049481c32442fb03fd6ed","glsl-optimizer/include/c11/threads.h":"56e9e592b28df19f0db432125223cb3eb5c0c1f960c22db96a15692e14776337","glsl-optimizer/include/c11/threads_posix.h":"f922e2c8613582a9340aa5ae37a4f7bd962dbc30e33a7a6ab14bed2d2995bc2b","glsl-optimizer/include/c11/threads_win32.h":"95bf19d7fc14d328a016889afd583e4c49c050a93bcfb114bd2e9130a4532488","glsl-optimizer/include/c11_compat.h":"103fedb48f658d36cb416c9c9e5ea4d70dff181aab551fcb1028107d098ffa3e","glsl-optimizer/include/c99_compat.h":"aafad02f1ea90a7857636913ea21617a0fcd6197256dcfc6dd97bb3410ba892e","glsl-optimizer/include/no_extern_c.h":"40069dbb6dd2843658d442f926e609c7799b9c296046a90b62b570774fd618f5","glsl-optimizer/license.txt":"e26a745226f4a46b3ca00ffbe8be18507362189a2863d04b4f563ba176a9a836","glsl-optimizer/src/compiler/builtin_type_macros.h":"5b4fc4d4da7b07f997b6eb569e37db79fa0735286575ef1fab08d419e76776ff","glsl-optimizer/src/compiler/glsl/README":"e7d408b621c1b605857c4cab63902f615edb06b530142b91ac040808df6e22f7","glsl-optimizer/src/compiler/glsl/TODO":"dd3b7a098e6f9c85ca8c99ce6dea49d65bb75d4cea243b917f29e4ad2c974603","glsl-optimizer/src/compiler/glsl/ast.h":"3e68ff374350c49211a9931f7f55a485d8d89fc4b21caaffbf6655009ad95bf8","glsl-optimizer/src/compiler/glsl/ast_array_index.cpp":"92b4d501f33e0544c00d14e4f8837753afd916c2b42e076ccc95c9e8fc37ba94","glsl-optimizer/src/compiler/glsl/ast_expr.cpp":"afd712a7b1beb2b633888f4a0911b0a8e4ae5eb5ab9c1e3f247d518cdaaa56d6","glsl-optimizer/src/compiler/glsl/ast_function.cpp":"74f4fbd490e366b37f4715168bb3465ecd9334d4130942f75dcc8e80e8e7f027","glsl-optimizer/src/compiler/glsl/ast_to_hir.cpp":"d0f798eb09271d41d068b9e7b18220d37f1ed0083300ab51eba30989698fe23d","glsl-optimizer/src/compiler/glsl/ast_type.cpp":"8eb790b24b26dfb72bdc333744b566c26d8464c5d47d20eae659461f5c4899f7","glsl-optimizer/src/compiler/glsl/builtin_functions.cpp":"454189d643c220fcb49116ee5c8a34f7b349aa67564040deb8607f6a41a15e70","glsl-optimizer/src/compiler/glsl/builtin_functions.h":"a37cad7ed09b522c5b8bec7b80115a36846e7ba6e0874a2a858e32f7f202c665","glsl-optimizer/src/compiler/glsl/builtin_int64.h":"619def6f3aebf180da3944ef08f159ab12a58b24767e41d8b985ac37ded54d62","glsl-optimizer/src/compiler/glsl/builtin_types.cpp":"afec060b62d6f3b00bfbf94e9fa5f96341ce096c128d1eef322791e6ed9cea4d","glsl-optimizer/src/compiler/glsl/builtin_variables.cpp":"6563bfb1345cbca4c77e00eef09ad152f3e1dc271d246a08c5ce9e1f4ce4250a","glsl-optimizer/src/compiler/glsl/float64.glsl":"1072fd888be48c2a7a5117cd2d92a65f034965a66375f598bb856bff5d7be766","glsl-optimizer/src/compiler/glsl/generate_ir.cpp":"e5f0175370a0d07f93c48d3f0f1b8233d12c64a7b02de02dcc753ef7b398ef0f","glsl-optimizer/src/compiler/glsl/glcpp/README":"a0332a1b221d047e9cce5181a64d4ac4056046fd878360ec8ae3a7b1e062bcff","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.c":"2d179879b1ffe84f58875eee5b0c19b6bae9c973b0c48e6bcd99978f2f501c80","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-lex.l":"e4c5744c837200dafd7c15a912d13f650308ea552454d4fa67271bc0a5bde118","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.c":"03494f9ce1cb82260506e2559e73a3eeb622c4bd51b65eaa0a2c3351862bd4c8","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.h":"264d9a18421cde255ce34a0a62b3d8e73465359f0d167e64aa3973062aae5bdd","glsl-optimizer/src/compiler/glsl/glcpp/glcpp-parse.y":"fafb66e3a8f149d19e085f18a4273ba6d4c11af9e9a01d665cc784dddf97b79f","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.c":"37ed294403c2abfd17fd999d1ae8d11b170e5e9c878979fefac74a31195c96b0","glsl-optimizer/src/compiler/glsl/glcpp/glcpp.h":"85ac8b444bcbd0822b66448a1da407b6ae5467b649f5afaf5c58325bd7569468","glsl-optimizer/src/compiler/glsl/glcpp/pp.c":"a52d94f1bcb3fb2747a95709c4a77c25de7eea8354d2b83bb18efd96976a4473","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.c":"d11aeb3acfe966d1b78f1ee49804093f2434214c41391d139ffcb67b69dc9862","glsl-optimizer/src/compiler/glsl/glcpp/pp_standalone_scaffolding.h":"abbf1f36ec5a92d035bfbb841b9452287d147616e56373cdbee1c0e55af46406","glsl-optimizer/src/compiler/glsl/glsl_lexer.cpp":"272b9fc1383d72b81bfc03fa11fdf82270ed91a294e523f9ce2b4554bd3effa9","glsl-optimizer/src/compiler/glsl/glsl_lexer.ll":"2b57d9f9eb830c3d7961d4533048a158ee6f458c8d05c65bea7b7cfbc36e4458","glsl-optimizer/src/compiler/glsl/glsl_optimizer.cpp":"f8095d20629d0af70be930b0612e169edb274551a1d25a3cd1bf9995a11ce2e8","glsl-optimizer/src/compiler/glsl/glsl_optimizer.h":"22e843b4ec53ba5f6cd85ca5f7bad33922dca8061b19fb512d46f1caca8d4757","glsl-optimizer/src/compiler/glsl/glsl_parser.cpp":"126baf368d525aba301854e3d91ba60b5aee32e1102376af71416f32cb95ec48","glsl-optimizer/src/compiler/glsl/glsl_parser.h":"2ea9a50716098a8f7bef782d2a030d757b68da73afb01b4d4940d3e8381d44e8","glsl-optimizer/src/compiler/glsl/glsl_parser.yy":"6b1fd1576b29fce005dff744a6dbd0219e4c695c361d61864e1f3a8d6fa6b764","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.cpp":"aad64b5b66467da650091430681e8c6a820cf3cadc4db3c160bf2f15875390ae","glsl-optimizer/src/compiler/glsl/glsl_parser_extras.h":"71fd0e92bbdb193dfb067d7bfdb1200d77392be2fbd0cbfc9ca89d1bb4c7e741","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.cpp":"6660fb83c0ddddbbd64581d46ccfdb9c84bfaa99d13348c289e6442ab00df046","glsl-optimizer/src/compiler/glsl/glsl_symbol_table.h":"24682b8304e0ea3f6318ddb8c859686bd1faee23cd0511d1760977ae975d41bf","glsl-optimizer/src/compiler/glsl/hir_field_selection.cpp":"72a039b0fcab4161788def9e4bedac7ac06a20d8e13146529c6d246bd5202afd","glsl-optimizer/src/compiler/glsl/int64.glsl":"303dbe95dde44b91aee3e38b115b92028400d6a92f9268975d607471984e13eb","glsl-optimizer/src/compiler/glsl/ir.cpp":"2b4741cce90b5d4abff5d719c7324e2693c67294d4d99736cb241554adb281bc","glsl-optimizer/src/compiler/glsl/ir.h":"990b1c74447c4eb4835353ccb0ed9aea644f97fc1129ef1739cd935075d85d2e","glsl-optimizer/src/compiler/glsl/ir_array_refcount.cpp":"8cdc1cffe01e42e0566fa2193a75f789628e8025ad1b82f0ee6f204451b7f9f7","glsl-optimizer/src/compiler/glsl/ir_array_refcount.h":"75f06ec81342b379096ca52e1dc0fd5f19a11ff8e9b58203c20628179d644c12","glsl-optimizer/src/compiler/glsl/ir_basic_block.cpp":"1e2920b1c0ecb08424c745c558f84d0d7e44b74585cf2cc2265dc4dfede3fa2f","glsl-optimizer/src/compiler/glsl/ir_basic_block.h":"81be7da0fc0ee547cd13ec60c1fcd7d3ce3d70d7e5e988f01a3b43a827acdf05","glsl-optimizer/src/compiler/glsl/ir_builder.cpp":"daba29c5a1efdd5a9754f420eb3e2ebdf73485273497f40d4863dadeddb23c0d","glsl-optimizer/src/compiler/glsl/ir_builder.h":"2822e74dd3f6e3df8b300af27d5b11ea2dd99d0e5e7ca809b7bbcce9833c483c","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.cpp":"8c6df5abf2fe313363f285f171c19ca6c8ee4f3bc2ed79d33c0c88cc8be45c48","glsl-optimizer/src/compiler/glsl/ir_builder_print_visitor.h":"799852adc3a0e54d04080655e7cebfa0d3bf5b6ffed5d8414f141380665d4db7","glsl-optimizer/src/compiler/glsl/ir_clone.cpp":"d897a4e1f5bbec4a6a2f15044c1be9a4d13899c73be77335b041049a4589aa5d","glsl-optimizer/src/compiler/glsl/ir_constant_expression.cpp":"78bd87ddb09db67f6c499067728d72aef4f16aa02721a99a4b769d1e0cfa9010","glsl-optimizer/src/compiler/glsl/ir_equals.cpp":"bca28533a6310b0fc152b56d80872368f1510dc62ed6e8ac199b9ffa7fac02e7","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.cpp":"7e918d4e1f237eca01396004015865ce345afe32a876c9dbc6728576a1a7eae4","glsl-optimizer/src/compiler/glsl/ir_expression_flattening.h":"f45b66aa9497520e7e08e612d24b308477c34477fbd963ee9320eac664957f16","glsl-optimizer/src/compiler/glsl/ir_expression_operation.h":"cc9f10727dbd26cac506804f51456302c702650f9eeb59054a7e1575d5cf6687","glsl-optimizer/src/compiler/glsl/ir_expression_operation.py":"7b86c96021b9fbe165957f4ecb0b612fefcde1c2cf3c6d75e3cdb22e369216ba","glsl-optimizer/src/compiler/glsl/ir_expression_operation_constant.h":"9ad3346416392e3efa11e12ecf2feca7453c5253d241eb96c91dfb85d4f2b971","glsl-optimizer/src/compiler/glsl/ir_expression_operation_strings.h":"a6826daf496a8b9e89885bc2a161ac3445d501b23c6e0ac33e2c01b506b273c8","glsl-optimizer/src/compiler/glsl/ir_function.cpp":"7537365fc0fbe4b37a26b9a2146cc64d3e9a774d60eab63b65002ad165ae8fc7","glsl-optimizer/src/compiler/glsl/ir_function_can_inline.cpp":"faddbf112187a048d502716a3fb82570a322299ba2a3abd79388382c82040bfc","glsl-optimizer/src/compiler/glsl/ir_function_detect_recursion.cpp":"9176973eaf5c0a984701f953bb7a80f37dca43d59b5bce50fc69b3f02f2902d7","glsl-optimizer/src/compiler/glsl/ir_function_inlining.h":"9739493f99c489987d650762fccdd3fb3d432f6481d67f6c799176685bd59632","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.cpp":"3725861fbe2b98e0617f52d3b14cf6d3b25fb5ec00f5ef5d308b03642f592767","glsl-optimizer/src/compiler/glsl/ir_hierarchical_visitor.h":"e0560210e966c0c31e4ca843e80ea154e64db5a444b8c2df845b6ba5b3a43fc1","glsl-optimizer/src/compiler/glsl/ir_hv_accept.cpp":"caf7ce2cd9494aadd3c58bcf77f29de58368dc9e347a362bbf37f8bda9509b80","glsl-optimizer/src/compiler/glsl/ir_optimization.h":"8b3dcfc7f9e96b21a8dd47a0040d90be483a9e67a2cdce3a697188fb758d4630","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.cpp":"f8e34a983452be0dcb5a695e9c8e895eead24f9e540992a8afe510ae85da4c4c","glsl-optimizer/src/compiler/glsl/ir_print_glsl_visitor.h":"1ad1bd3efd1ace39051c13f904c05fd80425d329444f9a8d47fd6d948faf46e0","glsl-optimizer/src/compiler/glsl/ir_print_visitor.cpp":"643f5a68aae3fb37267fd793f1216d1cfdeb2c09338c26b1f30e4c6deaef4de5","glsl-optimizer/src/compiler/glsl/ir_print_visitor.h":"4573eb93268a2654c14b505253dd651e2695d43dc745904d824da18305269b95","glsl-optimizer/src/compiler/glsl/ir_reader.cpp":"06bfba802c8354e5a8b2334b6d78d6297de18235bedd3f8fbb382c89870b02f2","glsl-optimizer/src/compiler/glsl/ir_reader.h":"63e3f7f1597936a7011d5b520e171b197bf82bee6c1560d822c3edf5aaa6f9e9","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.cpp":"84b5c5d746555adca85759c2912fe48010232b7c1c0bd2cf03bd04067a85e66f","glsl-optimizer/src/compiler/glsl/ir_rvalue_visitor.h":"fd8c561b71085d3211fff85ed514fecb299d8ce19a04bc063419a55b6d840525","glsl-optimizer/src/compiler/glsl/ir_set_program_inouts.cpp":"ab9f115ce9e7f312d9c7978340ced0dc4ae6d13a80e08442ba9709d11d50cae5","glsl-optimizer/src/compiler/glsl/ir_uniform.h":"683ae6896b1a08470c090be5f822fc31cd434eab9216e954b9bba24a46975109","glsl-optimizer/src/compiler/glsl/ir_unused_structs.cpp":"9c1620c45f2fc071fe5ed828472040b14c5f42effe06aa0e3b8352c95ef78786","glsl-optimizer/src/compiler/glsl/ir_unused_structs.h":"13387b49c23093575276b25b9dfd31fedd8f131c5c4f3128ab04cf03e15b5295","glsl-optimizer/src/compiler/glsl/ir_validate.cpp":"6b232be5999a86ea278f4f15b2832d76843246509118d924243055a3b9b0299f","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.cpp":"2764a3cad937d53f36db7447c3a5b98b04bf153acf81074d971857fc5bca460d","glsl-optimizer/src/compiler/glsl/ir_variable_refcount.h":"b0668e3eb1501ef65e38fe12830742ecb3d28e6039f30e366c8924efc29b4a39","glsl-optimizer/src/compiler/glsl/ir_visitor.h":"f21b3534c3d66d5fb707d1581fece7e1eb043523afbaedf89918cfb031c6df94","glsl-optimizer/src/compiler/glsl/link_atomics.cpp":"360f0209e11f367ba358223597b0a118bae095bff16337cf03f1fb89c5b80ca6","glsl-optimizer/src/compiler/glsl/link_functions.cpp":"de7895da8aa33a1e3c2c1eb2fdaf267ab5d1fbfdb79ae2e67f95211e946e294c","glsl-optimizer/src/compiler/glsl/link_interface_blocks.cpp":"1926cfa73810704eb19b916c1b2cdb9321155e2f98b2a0a57c7c3c6e960540cd","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.cpp":"1e14e06ca3b2c1089cfba2e8eaf0c1f373d9d6374b6082f320962dd71ae09611","glsl-optimizer/src/compiler/glsl/link_uniform_block_active_visitor.h":"fd58c155af645295bb6aec08797889de586f4d919731de2bce57e8dce59bb048","glsl-optimizer/src/compiler/glsl/link_uniform_blocks.cpp":"09589f49776dce32e6c4044937de7e0c839a9754ad31960148f8f9e010658997","glsl-optimizer/src/compiler/glsl/link_uniform_initializers.cpp":"bf98e08c12db466acf9623cbeb8fa8e3b4002512722e7a6521287f558a099f37","glsl-optimizer/src/compiler/glsl/link_uniforms.cpp":"84bad5b1377362cecf259b05124239be5220b03ce1c0c61b59bd9a47e4379af2","glsl-optimizer/src/compiler/glsl/link_varyings.cpp":"a5f1a53e7c80d635515fe808ff223d89fef1767abb0f2b7aa28fa6773dca353f","glsl-optimizer/src/compiler/glsl/link_varyings.h":"b9dbe018f038df69763df2e928742ce81bbc6e3aaba26f50621e30a6d9aa6220","glsl-optimizer/src/compiler/glsl/linker.cpp":"40b1ecd5d4f6c7f13d5a87ce390561a51fdf6f3fcd9b2197b9c88b03a773ba94","glsl-optimizer/src/compiler/glsl/linker.h":"ecf94b4ad75ef461c27c557fda4bd25f34c91930822b8e1d729ec84520d4a049","glsl-optimizer/src/compiler/glsl/linker_util.cpp":"1663ad88e2a369305659aeeffaedb5bd752cf76340a2ba5797fc0bf600633cf9","glsl-optimizer/src/compiler/glsl/linker_util.h":"6db788daf9c8e87ae2764b61a8b37ebe419e69c1b82ddee01986e37c978c6993","glsl-optimizer/src/compiler/glsl/list.h":"b1f46ce0e552fe7c45b2a19408a9d97662e23e4b182ab335491c26f8cf25886f","glsl-optimizer/src/compiler/glsl/loop_analysis.cpp":"57ecd573477c68091c7cc99537faa7139a8f395935e3d4f10144cefdefb5a611","glsl-optimizer/src/compiler/glsl/loop_analysis.h":"a85f045a038ee5b5176063e85d7988865862c44ab0580f771b993a042d0b69cc","glsl-optimizer/src/compiler/glsl/loop_unroll.cpp":"bd4292ea2809f5a669bcb76ceaa1ac365772dcd638c579c3ed10275214901a54","glsl-optimizer/src/compiler/glsl/lower_blend_equation_advanced.cpp":"8cfbef140d9c4b4d2f57bfa05c9c374d31a121d0f87afce94333f049023b654a","glsl-optimizer/src/compiler/glsl/lower_buffer_access.cpp":"1ae221c3c7a95aeb867207e7a742be635f91b406c157747bfd6ddf10274d97fb","glsl-optimizer/src/compiler/glsl/lower_buffer_access.h":"807886953a576a323591798cbca5e2df24295ea893b28affd8ffb5926cebaa04","glsl-optimizer/src/compiler/glsl/lower_builtins.cpp":"4d81afc32cf58e1481fcb5e42888ab93dbe6820310a20ff7a9982b77b2152d9b","glsl-optimizer/src/compiler/glsl/lower_const_arrays_to_uniforms.cpp":"608403f0eeeedf21cfcd3014116e0f44e28cbdf6c4c32aac7e613e64e30205e1","glsl-optimizer/src/compiler/glsl/lower_cs_derived.cpp":"179905cd47a294122adeb5b0abfed6f2f67782dcde21b544d1ee2c1985154e66","glsl-optimizer/src/compiler/glsl/lower_discard.cpp":"3b361b2db0004d544d64611cb50d5a6e364cf6c5f2e60c449085d7d753dd7fb0","glsl-optimizer/src/compiler/glsl/lower_discard_flow.cpp":"f5c29b6a27690bb5c91f196d1a1cf9f6be4f1025292311fe2dac561ce6774dee","glsl-optimizer/src/compiler/glsl/lower_distance.cpp":"a118c85493d5d22b2c059a930c51a5854896d4b1dade76598eaa985e5a3dff8c","glsl-optimizer/src/compiler/glsl/lower_if_to_cond_assign.cpp":"469e617757fd1728709cce021aac5c8da05ee503bf5366977bdc4ef7a6d83950","glsl-optimizer/src/compiler/glsl/lower_instructions.cpp":"6ff5c396abe40d8a2145d571e99e2bbe9143393e15aafc28adc2803a01d821b6","glsl-optimizer/src/compiler/glsl/lower_int64.cpp":"d1ed41196880dd53c7b13e2782f9423f8442bf1d46186e8be92b1b66218a83ee","glsl-optimizer/src/compiler/glsl/lower_jumps.cpp":"34de7b493f281589fb0c2c0f6e885d0a0fabbe7a4e97a73de374dd714777a58c","glsl-optimizer/src/compiler/glsl/lower_mat_op_to_vec.cpp":"dff7a308edc4846c348ed4225c6699a9c75abac68d88f41f85954276552779f4","glsl-optimizer/src/compiler/glsl/lower_named_interface_blocks.cpp":"16063ac127bff75a68272070ab11c21c25101edbff62b4c68f4983b4cd941af0","glsl-optimizer/src/compiler/glsl/lower_offset_array.cpp":"3b00773399135aea85746a5a68b96ef000bc6841be1a2c8e6f25c516628b0949","glsl-optimizer/src/compiler/glsl/lower_output_reads.cpp":"a0fc9975d5aa1617e21fc6c353659a9802da9e83779a3eef4ec584f74b4dadc5","glsl-optimizer/src/compiler/glsl/lower_packed_varyings.cpp":"7550099d4ae123d71541c2fc88bc04fbfe9271ec75d7e210987d1c8cac3cf3ea","glsl-optimizer/src/compiler/glsl/lower_packing_builtins.cpp":"79a13d161fe505a410ab948d92769395708693ec888153630fa240e5b97e356f","glsl-optimizer/src/compiler/glsl/lower_precision.cpp":"f82a185b879872b977a1787d8061b9a80bc4cf8db1b970db6efba2ad9cc20fa2","glsl-optimizer/src/compiler/glsl/lower_shared_reference.cpp":"ea2dccf50a83bc19391bf6b7ab6aa53c0005f427af4066d25140340af9a4beef","glsl-optimizer/src/compiler/glsl/lower_subroutine.cpp":"f69fa53650eeb6f2944fce4d36a6e0a423e6705f3a3bd3389c7fadb83cfc8802","glsl-optimizer/src/compiler/glsl/lower_tess_level.cpp":"b196c9d424c0569f3e85d75c2d125af21566cb113d69036db87c0990703e0fa7","glsl-optimizer/src/compiler/glsl/lower_texture_projection.cpp":"4d247f244272adc8250fd888d8d932a140dd5de4d1efc7a58492c3c2b8291527","glsl-optimizer/src/compiler/glsl/lower_ubo_reference.cpp":"89bdbc6c1669230c644c0857db1ce2781ec61d349ecd08c7914146e1f4750a4a","glsl-optimizer/src/compiler/glsl/lower_variable_index_to_cond_assign.cpp":"fce930f29ac9405b297d1f749d68f59506b89c70b4ee1b1ab8cf49a34cc71ecf","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_cond_assign.cpp":"3c67d851a11a55fad1c49a550f3a0cfe50892d33a3f238ce266cd829eba510a8","glsl-optimizer/src/compiler/glsl/lower_vec_index_to_swizzle.cpp":"f5ec666b73e1415cbab32519a53605ed385f3b03e889560373dbce69dda5000e","glsl-optimizer/src/compiler/glsl/lower_vector.cpp":"f7c13f5572ebe09b6a71553133b2cf003cd4b77b9657600672ee3b21bf890725","glsl-optimizer/src/compiler/glsl/lower_vector_derefs.cpp":"b05793da6dd620a531b43df5af8b2ecbc37b9db0c88910f5724ea10bcd057e19","glsl-optimizer/src/compiler/glsl/lower_vector_insert.cpp":"fee772ec17eea5e86a529bf9c5fa2ee0d29a5982bb75ebc6d68ed36cd19aa299","glsl-optimizer/src/compiler/glsl/lower_vertex_id.cpp":"690e8715182e03fead5cc5a35251fb4f41b357e4c71a1dfbc4bd7be19862b56d","glsl-optimizer/src/compiler/glsl/lower_xfb_varying.cpp":"58c0e8b270e4bbde54250be03cdb2f36966bcafb785372ad2e2b786835df7f9f","glsl-optimizer/src/compiler/glsl/main.cpp":"ae5e88abbbc8a12f769e1296bad938b9d7398cc6da0d3d0caeceeeb876536850","glsl-optimizer/src/compiler/glsl/opt_add_neg_to_sub.h":"f5054944bfd068810629080d0ea11df78b3f57a8f86df75e13ca50157ad1964d","glsl-optimizer/src/compiler/glsl/opt_algebraic.cpp":"25f45b20e1972ee8c789177a1aeda6e4286c25db2eae3a43ff83029ae64969c0","glsl-optimizer/src/compiler/glsl/opt_array_splitting.cpp":"19d3ce0e815438f4df9ab2890e767b03a4f3f191b53bb30c0217cf2ae6a95430","glsl-optimizer/src/compiler/glsl/opt_conditional_discard.cpp":"0e44e0e126711a3725c1f3a2aa65ff03c381fed08680ffc30101aae60f716c4e","glsl-optimizer/src/compiler/glsl/opt_constant_folding.cpp":"a088d04d9b45f9e55e235835648f614c89b7803c03a6d4f6a6d1a6bc1f0228bd","glsl-optimizer/src/compiler/glsl/opt_constant_propagation.cpp":"8a9440d77ecd6dcf13e683cbb99943aab6311c8fd4b5f6a9189a8d4f270746f4","glsl-optimizer/src/compiler/glsl/opt_constant_variable.cpp":"63d3ccd4dd09f19c9cf1a2f51592111bed41284504f29f3c0de4cadebc439a37","glsl-optimizer/src/compiler/glsl/opt_copy_propagation_elements.cpp":"ffa0f50863995e0d2e31f55a52e82319edc71e520987bebd7f7e561ea331c64b","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_variables.cpp":"84e8747b948232f01dd56b428b9315f96f9511f605f240119fc446fae28981a9","glsl-optimizer/src/compiler/glsl/opt_dead_builtin_varyings.cpp":"761523e88f5b3ba785170f4d7205e94fa99acb7e74d29efbe40e1c010e1dbdb3","glsl-optimizer/src/compiler/glsl/opt_dead_code.cpp":"fd1ba2da7337d4e5dad17f5c2d73d9cc8880305f423e85d64cf94553588fa401","glsl-optimizer/src/compiler/glsl/opt_dead_code_local.cpp":"969a598b4df322baf222258a66cd64a326ea20e5b3125be9d8d1771f522c69e0","glsl-optimizer/src/compiler/glsl/opt_dead_functions.cpp":"774cae6536d02edf26e996a2a895e1f62d5098f16dc96b44798b4fc731a9a95f","glsl-optimizer/src/compiler/glsl/opt_flatten_nested_if_blocks.cpp":"3696a5c55f02e20056e085bc2714f73ac992f221b6f3387d655068e86b512046","glsl-optimizer/src/compiler/glsl/opt_flip_matrices.cpp":"44f0fe05b49329667671f88c96dc86ab3fe1459ff7b87f2b2d88de2d49829f9f","glsl-optimizer/src/compiler/glsl/opt_function_inlining.cpp":"fb56a33c90419a01676b57cbd91d0674a54cca40e6defaacc88dd33facebc131","glsl-optimizer/src/compiler/glsl/opt_if_simplification.cpp":"ac406eb35e379c357641d6c5749f50c65961455924d3dc884e2b90046fa92c5c","glsl-optimizer/src/compiler/glsl/opt_minmax.cpp":"8abd59d3b14ef60ff14a9c69660e6945f5cf10b97edb4afebe56be3f81d96316","glsl-optimizer/src/compiler/glsl/opt_rebalance_tree.cpp":"8bb6329dc0f299042368fc81934c2df019b45ab9f7aa0415d4e57b8d1ff98c9f","glsl-optimizer/src/compiler/glsl/opt_redundant_jumps.cpp":"222c73e2ac7a938ebb6428cc6c780c908ff6156d8ff935b04fed93a48fc10496","glsl-optimizer/src/compiler/glsl/opt_structure_splitting.cpp":"2edc79cc13f3177934e0443ad62f5976a1991f01f86ea303a803434849b13a47","glsl-optimizer/src/compiler/glsl/opt_swizzle.cpp":"015d0abddfe507f67c4b96c82988d861d018ededf7bf055e2bcbe9ea92da694e","glsl-optimizer/src/compiler/glsl/opt_tree_grafting.cpp":"46d28ac983ea244a4315bdc0e8892979ec4d1f9b9a96ac8a8a08006d9bc5e878","glsl-optimizer/src/compiler/glsl/opt_vectorize.cpp":"d80ee43bb97d9f016fb9c5e1e06f5b2afa569811f368ba067be794ec11d085fb","glsl-optimizer/src/compiler/glsl/program.h":"2982447e2abd35371e273ad87951722782a8b21c08294f67c39d987da1e1c55f","glsl-optimizer/src/compiler/glsl/propagate_invariance.cpp":"080943e21baa32494723a2eefb185915d2daae1f46d6df420145c5ad6857e119","glsl-optimizer/src/compiler/glsl/s_expression.cpp":"1ced972bc6ecc8eab4116ea71fb0212ab9ae5bcc0be3b47aa5d9d903566b3af1","glsl-optimizer/src/compiler/glsl/s_expression.h":"65b847e30e22a809b57d0bc70243049c99d9c6318803c5b8d0826aba55dc217e","glsl-optimizer/src/compiler/glsl/serialize.cpp":"be0eb4251348a9d921acb839a5c48c6023a2e9d116d602bb0432787ab623655d","glsl-optimizer/src/compiler/glsl/serialize.h":"57425732eba1233d928e5f07f88b623ce65af46b3bb034bf147f0a4b7f94f9a1","glsl-optimizer/src/compiler/glsl/shader_cache.cpp":"e0c5c433f2df3fccdf1d61281bfcb0ee5633433339b97c697d64db99611cbaaf","glsl-optimizer/src/compiler/glsl/shader_cache.h":"9217164d8d7f54aca0fe5922c7187095a6ae0cb703b196b79805aeef07a7e697","glsl-optimizer/src/compiler/glsl/standalone.cpp":"8e6c416a14d631261917a5fe4cc91880c287b22b2dfd70eb22028289a8fa5364","glsl-optimizer/src/compiler/glsl/standalone.h":"a7c397d1dfdd1e7fb2cfe99db35cd9df93251e642059208533202b7f20497f83","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.cpp":"970d14b7a9d58e5270321f97bf5d57795558b1c570a56678e04a65b26c60bf4f","glsl-optimizer/src/compiler/glsl/standalone_scaffolding.h":"d921a617ea82b9e49413314492a645c44356de503581b1be3f1b57de236e480d","glsl-optimizer/src/compiler/glsl/string_to_uint_map.cpp":"d824bf5b839bd39498dc9e457103cdbe3e5289ddf7564107c27b1505948dd31f","glsl-optimizer/src/compiler/glsl/string_to_uint_map.h":"e2f18e66359c9d620e085de7f4a334a47df9c66e65a5bfe8b734c627bec04104","glsl-optimizer/src/compiler/glsl/test_optpass.h":"b27b8f35f5387e7ce4982bb51c7b63ccf14f91757f3108a5d02ed006925bb8a0","glsl-optimizer/src/compiler/glsl/xxd.py":"376484142f27f45090ea8203ae2621abf73f06175cb0ee8d96f44a3b9327f4bd","glsl-optimizer/src/compiler/glsl_types.cpp":"044bb6754f45419a3151e7a25c39202a82009ae3c6bc54ff7f0bb4258a5deefe","glsl-optimizer/src/compiler/glsl_types.h":"fd899a42f34ddeb8601bc3cd6c5e3aed82fc8aef4042dde1b39b3c01e1dcc219","glsl-optimizer/src/compiler/shader_enums.c":"436bff5216b11b0980bdfada5885fc6ac9afa2037a3027fcd6eea2a8635597ac","glsl-optimizer/src/compiler/shader_enums.h":"13220442a5c02e83540cf2c0ad4f8417b2fbda5f2586dec4e92082544c937cdd","glsl-optimizer/src/compiler/shader_info.h":"4c5453e81197ca83593ee4f365074b23530f2ab21c78e1733b63dec6f344c12a","glsl-optimizer/src/gallium/auxiliary/util/u_half.h":"3c2b37bda3ccb64387e44b723d29cf9046decab1a893bf42d842e9603398bdee","glsl-optimizer/src/gallium/include/pipe/p_compiler.h":"c75620096ce8523dae90599e50aa2ef6468d3b0e368a77795edeb20dd1abfc0c","glsl-optimizer/src/gallium/include/pipe/p_config.h":"a27692fc35f9e55df3224b7529e66b3001e911e94e6bc5f8f569e493e1ee3fb7","glsl-optimizer/src/gallium/include/pipe/p_defines.h":"be26d68c0acc67c5e44788c6299716a9eee415fd81d7d747e3738a829e3b6b38","glsl-optimizer/src/gallium/include/pipe/p_format.h":"5674215fc41d27496f037cf837717daefbf23ebb38d40ace7c0c414bc08182b0","glsl-optimizer/src/gallium/include/pipe/p_state.h":"d600593aba5f5a17072a6c38f6baa81e01c7994b0174250f7e433bb41684b702","glsl-optimizer/src/mapi/glapi/glapi.h":"73632a625c0ddabc401205e8b5a81eb8af8506868efe4b170d7979ec3619e9c5","glsl-optimizer/src/mesa/main/config.h":"5800259373099e5405de2eb52619f9de242552a479902a3a642a333c8cb3c1e7","glsl-optimizer/src/mesa/main/context.c":"2f3208473d99c94f734b1137ba91889d4a1babb9e7534bf1dc85d851ee98274e","glsl-optimizer/src/mesa/main/context.h":"cc7e4194797db9d007f01884e23d786c453b3860821f7f2ddcdf0f1bf3f8ffb1","glsl-optimizer/src/mesa/main/dd.h":"6a964acd06b6c2d88700e69fb75fe3c6b3b3d45bbc41db24f3f897a29695fe0c","glsl-optimizer/src/mesa/main/debug_output.h":"7312422e90b8c0e34028ac27280e438139b5cba525c99deb3ac883cd3d87e452","glsl-optimizer/src/mesa/main/draw.h":"7eaef3a9e27a60ea6f7937109bf3a6190b831162fde0479abb12077ce27c353d","glsl-optimizer/src/mesa/main/enums.h":"87d562a6764f51c014a2274fa7c3aca17c04441537ddd56b2554f13c6fffea92","glsl-optimizer/src/mesa/main/errors.h":"c79444b5df289c90fbb22a33b2d0c23917d9fc4510960088f0b79e53bb56b1b2","glsl-optimizer/src/mesa/main/extensions.h":"a38b2f87cc93c513994281350d69e06c84ff8eded5313ec0a1be33f375e0ebbd","glsl-optimizer/src/mesa/main/extensions_table.c":"17642d1a8c9a0bf2bd61060052d33ff14a005d2b962e6cf91465797a50851e85","glsl-optimizer/src/mesa/main/extensions_table.h":"2c879571c238d2e14461031ac740372fd0f9ac3a34c0d5541bb9b7ed4c0376c8","glsl-optimizer/src/mesa/main/formats.h":"02e2f7ec3e39286cf9f27e2641043e6df8ecb1dfde9e643313210e214af2a929","glsl-optimizer/src/mesa/main/glheader.h":"58217b33eead6aa6b23cd4a291cefeaa6cb84e465f4960daffca97c44d6d1c35","glsl-optimizer/src/mesa/main/glthread.h":"51fb2711f77e7eafcfc52d29d5b844978832b24c930d88accd48d143a6eb9c6f","glsl-optimizer/src/mesa/main/hash.h":"7e7f782034c16a8e693de48e00c31d4a90b0129f4029fd074033d7d16ccbe718","glsl-optimizer/src/mesa/main/macros.h":"73d15ddfd64f2b57b9b2ffeeb993b9c2c0899a80563e9d6ff337b11ccbe6eee5","glsl-optimizer/src/mesa/main/menums.h":"5dfac0e2279d60b0cd0c7b9fc2a5021620d0f6282ed2e738c420214e3af152d3","glsl-optimizer/src/mesa/main/mesa_private.h":"edda678b93438944279a551f663b8858ad84814a9fc88ba9672ef195599c24ae","glsl-optimizer/src/mesa/main/mtypes.h":"6efddefa099e4d2e3fdd97f0055644f47aba21711385edfeabc2d9b0676f2eec","glsl-optimizer/src/mesa/main/shaderobj.h":"9f0dfe96d0c2154201adef942bd36053533ac7b2492fb3786acda5bea514c75e","glsl-optimizer/src/mesa/main/uniforms.h":"4e331e6ad6e9cbded978b4082dbe0a57c1f8f01327446bb6892bfc179976c38b","glsl-optimizer/src/mesa/main/version.h":"9d0a13a758099302dc55cf7d045791834a89b0f9d4cf17b2692259b369a8a9a1","glsl-optimizer/src/mesa/math/m_matrix.h":"a37b19f182e070db3df93b0ede43c22fb8be8c2906504133ee6dbd7db1185d8b","glsl-optimizer/src/mesa/program/dummy_errors.c":"1820e305515b4c5e041f5e1623266a48ec8f076a155310be7d60637101f593e4","glsl-optimizer/src/mesa/program/ir_to_mesa.h":"b47f58d22e3ca2ae42d52501ea769d15c4476834944fa97eeccd3a3439211d00","glsl-optimizer/src/mesa/program/prog_instruction.h":"ab3832152a7e144b59e5a2264b2c29db56d93be31e76bbd958527a56771b40eb","glsl-optimizer/src/mesa/program/prog_parameter.h":"ba18c743284eadbc837c2c364c73e5d372321a7637a76e589d8d39fe8b5de225","glsl-optimizer/src/mesa/program/prog_statevars.h":"fc413698f84bc52d45fdeae0471934ee9904bfb7eac1a2b5f70446e54bcbbdca","glsl-optimizer/src/mesa/program/program.h":"1f01026a4eff440a3f122fd9b519d03546fe7f7d8be60dca834e95a2f8fbbfd2","glsl-optimizer/src/mesa/program/symbol_table.c":"6611cb9f078035bf5ff8c9112093a6c7d99f8af99a3931d0c07f227cc72283ea","glsl-optimizer/src/mesa/program/symbol_table.h":"631dc35ac48d5e87962d45507461920f6575610960ffcc42a08cefeb43300cda","glsl-optimizer/src/mesa/vbo/vbo.h":"6eb1dcd9a08c92f276c5fe08da184ff9d455d1be421913b8ad732a7b65e858fb","glsl-optimizer/src/util/bitscan.h":"9e49e694e6b34fe035bc685f32588827eb8cbe7d82878963c7ab52843e1c16aa","glsl-optimizer/src/util/bitset.h":"c40f78515c6230fed18345c6751ce33833a49da7a27901c7e6d7340cbdcbc5e7","glsl-optimizer/src/util/blob.c":"8f729846f66efc9c15485cc5fc24c6ec861fc1fecb2f652573f2a237d481b791","glsl-optimizer/src/util/blob.h":"93e1eaac866b9a7cd6fc03b533c18fb2edf0e97f03395eff4f3a605c4fc14d0c","glsl-optimizer/src/util/compiler.h":"79e3bf40a5bab704e6c949f23a1352759607bb57d80e5d8df2ef159755f10b68","glsl-optimizer/src/util/crc32.c":"2f3467a046b3a76784ecb9aa55d527698c8607fd0b12c622f6691aaa77b58505","glsl-optimizer/src/util/crc32.h":"59bd81865e51042b73a86f8fb117c312418df095fed2d828c5c1d1c8b6fc6cd4","glsl-optimizer/src/util/debug.c":"c3d68e9752ccc19e66c669562cd113cf1d0ac83cbb30174789e7fb8d1df58f9c","glsl-optimizer/src/util/debug.h":"50068d745c4199ccbd33d68dd4c8a36d2b5179c7869a21e75906ddd0718ca456","glsl-optimizer/src/util/detect_os.h":"343a8790d17a3710c6dd015ee367f84e3902ff3f2e36faca2bf93f9d725d3574","glsl-optimizer/src/util/disk_cache.c":"f533937e5a4fffe76e2739ef4b6b1e1da097d96d63eb808e68ebbc7027641c23","glsl-optimizer/src/util/disk_cache.h":"e83314fb14134a8e079b15e470a6376ba5a8253701f048c890a62b7e55d64bc8","glsl-optimizer/src/util/fast_urem_by_const.h":"e108fce804616c47d071dfe4a04163eec1126e448ed1aa89abb6b3a6d772bd5b","glsl-optimizer/src/util/fnv1a.h":"ab2596f19c6adf431ae27618f62c5743e24ad23ef83bb359a4c4c218245ab459","glsl-optimizer/src/util/format/u_format.h":"4cdfc0c59cbc99a092e5ec5a396910f2d93b9643e5d8141050b011e66f11e45b","glsl-optimizer/src/util/futex.h":"26f7c9d86e9ffef4c0fa2761f1aaa1918337302e20bd6ca10e61dc3c47356deb","glsl-optimizer/src/util/half_float.c":"11bc2584493d5d9d46e8c8a619a0307cf150bf5ab5d0f96bb764b061dc37a00e","glsl-optimizer/src/util/half_float.h":"7f7c380f126da1400a91758cc0392f24bf967bce1672890b62be26fe9fbd922b","glsl-optimizer/src/util/hash_table.c":"0ca40352e35dedab0a84c64c903f1b16d47e950bb5f43b4d22bb57d499bfea6e","glsl-optimizer/src/util/hash_table.h":"217191bb360592e2232f187473c10287d2cda8ae6fa5c53d0ef74c8c206118b4","glsl-optimizer/src/util/list.h":"9fab03c6a78186bb5f173269f825f6ce976b409d931852e3d93bac632e07989a","glsl-optimizer/src/util/macros.h":"63faf65b51058c483b17f1f77da51d1c53c8beab52678cb6bd01f1228a63b6b0","glsl-optimizer/src/util/mesa-sha1.c":"00c692ec353ebc02c06c57c5a71de0ab7a119f86a4146f452e65ec87e4944417","glsl-optimizer/src/util/mesa-sha1.h":"bff4c29f4bf7cdbcefb30fa0c996a7604a380eba8976467c2a60e7cd328f7e26","glsl-optimizer/src/util/mesa-sha1_test.c":"25da89a59d51469f77b4c468ca23ffdce0a7a1166a70b6cc23026a6800b0143c","glsl-optimizer/src/util/os_memory.h":"64555faf1760ae6954f42c83727c38dfc4c278e9152115779ffaad58b42adacf","glsl-optimizer/src/util/os_memory_aligned.h":"12d86fa94be38c13f7eeebdf313795e1267dd5a7187d2f0072e0e896f41702f6","glsl-optimizer/src/util/os_memory_stdc.h":"07360363b88c927065e10df71bebf6c8a0cc3b9167c9dfce55f2d65f11e6f787","glsl-optimizer/src/util/os_misc.c":"a9936e613ec84803abd59ad47c192c8e3939993c950ac91973fdc4cec1801bb8","glsl-optimizer/src/util/os_misc.h":"cc68eb12e05b5e749c54298cb4a6f4cd20cc5af7db3403e70b3c27b56090c740","glsl-optimizer/src/util/os_time.h":"73e775f7335244ff5964c678c27eedf1aea6abea44c4169d327ea8c7ce4a3a88","glsl-optimizer/src/util/ralloc.c":"4b51189595ef67bcef52c40cbf654d969041dbd15e15d4a893ad494ac060aeca","glsl-optimizer/src/util/ralloc.h":"e573c45875ff1530f0dbee9a93ae55535fdac8d5cc88a79ebc327c688824bde5","glsl-optimizer/src/util/rounding.h":"0450722353caf83de07e67f335949dbe95fe53b534052d4ee9d28d2781387614","glsl-optimizer/src/util/set.c":"86f8c9a830bead5a5a79bc970b0ff97809312af07b3beb39ef9d90af04d40a1b","glsl-optimizer/src/util/set.h":"3e39ca161e7ed4ec7c436cc9c7919ed9a55ed1b71edbf2caf6f9bcfd9bc578ed","glsl-optimizer/src/util/sha1/README":"00af7419af05247081858acb2902efd99fcda2ce16e331079f701645bb3729c0","glsl-optimizer/src/util/sha1/sha1.c":"1403bbe0aad42ba3e6be7e09f7cad87a6a8c4ad5b63962f7b92b9f37d8133b04","glsl-optimizer/src/util/sha1/sha1.h":"68d9f240eab2918026ecdf22be36811abbd4f1389f6c36e31258041aeaedd247","glsl-optimizer/src/util/simple_mtx.h":"12c6c3c4b7db9168bc656d5b3c65912075084d2b388c415d5c3d3f5953a9d6c7","glsl-optimizer/src/util/softfloat.c":"a97e51a96fe5e6a052c02aa6bbec683fe73fb88a8c087d9c930503e2120d8a2e","glsl-optimizer/src/util/softfloat.h":"66664b0250e83bf5dd4cc743acd119d076efcea624a0eab3d6b60718e6ee8811","glsl-optimizer/src/util/string_buffer.c":"63a1d1b1e34926c88ea00159cafbcd56568b805c4f64d1e8c97169fe313921fc","glsl-optimizer/src/util/string_buffer.h":"7b88d1b1d9c6cfb8e93331813535c127289437c75f822029e9a3bca8ea6b52ee","glsl-optimizer/src/util/strndup.h":"0273c4fdb7482cd7746881a63d3998648c6d63415ba85af1d1860f0e0dc504c6","glsl-optimizer/src/util/strtod.c":"5cf610d8a37373cf37cfb7aae903525d943b2674b1f32594c70b0eb19a8c9697","glsl-optimizer/src/util/strtod.h":"237396def4e264d35ed4bedea00ef9a4ceab6d7a11a18c770d9747d22c69ed2d","glsl-optimizer/src/util/u_atomic.h":"c02e809526c6c09ba8fe51f50b2490d1b6c8e5c7f3c4031ae958250d098fc3bb","glsl-optimizer/src/util/u_debug.c":"8c060e379b816618f3dd22c9ea523c68b9425c76c36a7dfe5d6d375b337f5f4a","glsl-optimizer/src/util/u_debug.h":"e11e26edd9b9e4e6f8e6a435e69f4d9edda27e9a379f68f4c82ea2525aaaea68","glsl-optimizer/src/util/u_dynarray.h":"853d0fa6ff2261614488be624deb8a2b01e57c2c8eabc28578cbeed4ccc95694","glsl-optimizer/src/util/u_endian.h":"3ccea7e529740318d8a4b05c00db3adc9d1e292a52bdc56a05c9fae99209720f","glsl-optimizer/src/util/u_math.c":"c868a8c0886dc78f1b06b13404ba8b253090449045774dd56893ac9d75795184","glsl-optimizer/src/util/u_math.h":"a04e32e126db016413f9de0a2028a3e71737137463b1289eae576f884b06fcf1","glsl-optimizer/src/util/u_memory.h":"c5db17c724c70283ddbe04165722f6988d4e0eb9aa3602ae472feff016649af9","glsl-optimizer/src/util/u_queue.h":"92930ce236c0528a98b695f5cea8c5c6aa9683beaf71a2227bdc5d33d1b21506","glsl-optimizer/src/util/u_string.h":"c5a2f4ef576d1547bda12c4ea219179fefa54414977743ac094abcaf696ef6ca","glsl-optimizer/src/util/u_thread.h":"00b708459b27f9910d18db92c18cc65cfc618ac2b3cd144e45f8640057b10d58","glsl-optimizer/src/util/xxhash.h":"2f2aff2fc6c0c929f52cf6ae7314122124c5be026d41ad1c357608383c4a37ad","src/bindings.rs":"79993db2058bde39f99ef483d02560d33b1cb882f6a552319e8b86eb6f9021e1","src/lib.rs":"04be1554cd829eb40864b06d80b491dd48117a4e3a601c7d482117f7a0391e67","wrapper.hpp":"f3ea34cc496f7d90b9bfcada3250b37b314c3524dac693b2ece9517bc7d274ac"},"package":"8ba4741358604ca0848c27ecc069d68e62e11cde81e38aac1da3c54b79ab5adf"} +\ No newline at end of file diff --git a/build-cacheFlush-missing.patch b/build-cacheFlush-missing.patch deleted file mode 100644 index 51c368c..0000000 --- a/build-cacheFlush-missing.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -up firefox-55.0.3/js/src/jit/ExecutableAllocator.h.wasm firefox-55.0.3/js/src/jit/ExecutableAllocator.h ---- firefox-55.0.3/js/src/jit/ExecutableAllocator.h.wasm 2017-09-05 11:32:12.235909468 +0200 -+++ firefox-55.0.3/js/src/jit/ExecutableAllocator.h 2017-09-05 11:32:46.157916575 +0200 -@@ -219,7 +219,7 @@ class ExecutableAllocator - - static void poisonCode(JSRuntime* rt, JitPoisonRangeVector& ranges); - --#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_SIMULATOR_ARM64) -+#if defined(JS_CODEGEN_X86) || defined(JS_CODEGEN_X64) || defined(JS_SIMULATOR_ARM64) || defined(JS_CODEGEN_NONE) - static void cacheFlush(void*, size_t) - { - } -diff -up firefox-55.0.3/js/src/jit-test/tests/wasm/bench/wasm_box2d.wasm firefox-55.0.3/js/src/jit-test/tests/wasm/bench/wasm_box2d diff --git a/build-cubeb-pulse-arm.patch b/build-cubeb-pulse-arm.patch deleted file mode 100644 index 008208c..0000000 --- a/build-cubeb-pulse-arm.patch +++ /dev/null @@ -1,4946 +0,0 @@ -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/Cargo.toml 2017-08-04 13:37:46.383821740 +0200 -@@ -7,7 +7,11 @@ description = "Cubeb backed for PulseAud - [features] - pulse-dlopen = ["pulse-ffi/dlopen"] - -+[lib] -+crate-type = ["staticlib", "rlib"] -+ - [dependencies] - cubeb-ffi = { path = "cubeb-ffi" } - pulse-ffi = { path = "pulse-ffi" } -+pulse = { path = "pulse-rs" } - semver = "^0.6" -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/cubeb-ffi/src/ffi.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -11,45 +11,45 @@ pub enum Context {} - pub enum Stream {} - - // These need to match cubeb_sample_format --pub const SAMPLE_S16LE: c_int = 0; --pub const SAMPLE_S16BE: c_int = 1; --pub const SAMPLE_FLOAT32LE: c_int = 2; --pub const SAMPLE_FLOAT32BE: c_int = 3; - pub type SampleFormat = c_int; -+pub const SAMPLE_S16LE: SampleFormat = 0; -+pub const SAMPLE_S16BE: SampleFormat = 1; -+pub const SAMPLE_FLOAT32LE: SampleFormat = 2; -+pub const SAMPLE_FLOAT32BE: SampleFormat = 3; - - #[cfg(target_endian = "little")] --pub const SAMPLE_S16NE: c_int = SAMPLE_S16LE; -+pub const SAMPLE_S16NE: SampleFormat = SAMPLE_S16LE; - #[cfg(target_endian = "little")] --pub const SAMPLE_FLOAT32NE: c_int = SAMPLE_FLOAT32LE; -+pub const SAMPLE_FLOAT32NE: SampleFormat = SAMPLE_FLOAT32LE; - #[cfg(target_endian = "big")] --pub const SAMPLE_S16NE: c_int = SAMPLE_S16BE; -+pub const SAMPLE_S16NE: SampleFormat = SAMPLE_S16BE; - #[cfg(target_endian = "big")] --pub const SAMPLE_FLOAT32NE: c_int = SAMPLE_FLOAT32BE; -+pub const SAMPLE_FLOAT32NE: SampleFormat = SAMPLE_FLOAT32BE; - - pub type DeviceId = *const c_void; - - // These need to match cubeb_channel_layout --pub const LAYOUT_UNDEFINED: c_int = 0; --pub const LAYOUT_DUAL_MONO: c_int = 1; --pub const LAYOUT_DUAL_MONO_LFE: c_int = 2; --pub const LAYOUT_MONO: c_int = 3; --pub const LAYOUT_MONO_LFE: c_int = 4; --pub const LAYOUT_STEREO: c_int = 5; --pub const LAYOUT_STEREO_LFE: c_int = 6; --pub const LAYOUT_3F: c_int = 7; --pub const LAYOUT_3F_LFE: c_int = 8; --pub const LAYOUT_2F1: c_int = 9; --pub const LAYOUT_2F1_LFE: c_int = 10; --pub const LAYOUT_3F1: c_int = 11; --pub const LAYOUT_3F1_LFE: c_int = 12; --pub const LAYOUT_2F2: c_int = 13; --pub const LAYOUT_2F2_LFE: c_int = 14; --pub const LAYOUT_3F2: c_int = 15; --pub const LAYOUT_3F2_LFE: c_int = 16; --pub const LAYOUT_3F3R_LFE: c_int = 17; --pub const LAYOUT_3F4_LFE: c_int = 18; --pub const LAYOUT_MAX: c_int = 19; - pub type ChannelLayout = c_int; -+pub const LAYOUT_UNDEFINED: ChannelLayout = 0; -+pub const LAYOUT_DUAL_MONO: ChannelLayout = 1; -+pub const LAYOUT_DUAL_MONO_LFE: ChannelLayout = 2; -+pub const LAYOUT_MONO: ChannelLayout = 3; -+pub const LAYOUT_MONO_LFE: ChannelLayout = 4; -+pub const LAYOUT_STEREO: ChannelLayout = 5; -+pub const LAYOUT_STEREO_LFE: ChannelLayout = 6; -+pub const LAYOUT_3F: ChannelLayout = 7; -+pub const LAYOUT_3F_LFE: ChannelLayout = 8; -+pub const LAYOUT_2F1: ChannelLayout = 9; -+pub const LAYOUT_2F1_LFE: ChannelLayout = 10; -+pub const LAYOUT_3F1: ChannelLayout = 11; -+pub const LAYOUT_3F1_LFE: ChannelLayout = 12; -+pub const LAYOUT_2F2: ChannelLayout = 13; -+pub const LAYOUT_2F2_LFE: ChannelLayout = 14; -+pub const LAYOUT_3F2: ChannelLayout = 15; -+pub const LAYOUT_3F2_LFE: ChannelLayout = 16; -+pub const LAYOUT_3F3R_LFE: ChannelLayout = 17; -+pub const LAYOUT_3F4_LFE: ChannelLayout = 18; -+pub const LAYOUT_MAX: ChannelLayout = 256; - - #[repr(C)] - #[derive(Clone, Copy, Debug)] -@@ -77,11 +77,11 @@ impl Default for Device { - } - - // These need to match cubeb_state --pub const STATE_STARTED: c_int = 0; --pub const STATE_STOPPED: c_int = 1; --pub const STATE_DRAINED: c_int = 2; --pub const STATE_ERROR: c_int = 3; - pub type State = c_int; -+pub const STATE_STARTED: State = 0; -+pub const STATE_STOPPED: State = 1; -+pub const STATE_DRAINED: State = 2; -+pub const STATE_ERROR: State = 3; - - pub const OK: i32 = 0; - pub const ERROR: i32 = -1; -@@ -249,32 +249,42 @@ pub struct LayoutMap { - } - - // cubeb_mixer.h -+pub type Channel = c_int; - - // These need to match cubeb_channel --pub const CHANNEL_INVALID: c_int = -1; --pub const CHANNEL_MONO: c_int = 0; --pub const CHANNEL_LEFT: c_int = 1; --pub const CHANNEL_RIGHT: c_int = 2; --pub const CHANNEL_CENTER: c_int = 3; --pub const CHANNEL_LS: c_int = 4; --pub const CHANNEL_RS: c_int = 5; --pub const CHANNEL_RLS: c_int = 6; --pub const CHANNEL_RCENTER: c_int = 7; --pub const CHANNEL_RRS: c_int = 8; --pub const CHANNEL_LFE: c_int = 9; --pub const CHANNEL_MAX: c_int = 256; --pub type Channel = c_int; -+pub const CHANNEL_INVALID: Channel = -1; -+pub const CHANNEL_MONO: Channel = 0; -+pub const CHANNEL_LEFT: Channel = 1; -+pub const CHANNEL_RIGHT: Channel = 2; -+pub const CHANNEL_CENTER: Channel = 3; -+pub const CHANNEL_LS: Channel = 4; -+pub const CHANNEL_RS: Channel = 5; -+pub const CHANNEL_RLS: Channel = 6; -+pub const CHANNEL_RCENTER: Channel = 7; -+pub const CHANNEL_RRS: Channel = 8; -+pub const CHANNEL_LFE: Channel = 9; -+pub const CHANNEL_MAX: Channel = 10; - - #[repr(C)] -+#[derive(Clone, Copy, Debug)] - pub struct ChannelMap { - pub channels: c_uint, -- pub map: [Channel; 256], -+ pub map: [Channel; CHANNEL_MAX as usize], - } - impl ::std::default::Default for ChannelMap { - fn default() -> Self { - ChannelMap { - channels: 0, -- map: unsafe { ::std::mem::zeroed() }, -+ map: [CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID, -+ CHANNEL_INVALID], - } - } - } -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_funcs.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -8,8 +8,8 @@ macro_rules! cstr { - - #[cfg(not(feature = "dlopen"))] - mod static_fns { -- use std::os::raw::{c_char, c_double, c_int, c_float, c_uint, c_void}; - use super::*; -+ use std::os::raw::{c_char, c_double, c_float, c_int, c_uint, c_void}; - - #[link(name = "pulse")] - extern "C" { -@@ -62,6 +62,7 @@ mod static_fns { - userdata: *mut c_void) - -> *mut pa_operation; - pub fn pa_context_set_state_callback(c: *mut pa_context, cb: pa_context_notify_cb_t, userdata: *mut c_void); -+ pub fn pa_context_errno(c: *mut pa_context) -> c_int; - pub fn pa_context_set_subscribe_callback(c: *mut pa_context, - cb: pa_context_subscribe_cb_t, - userdata: *mut c_void); -@@ -70,6 +71,7 @@ mod static_fns { - cb: pa_context_success_cb_t, - userdata: *mut c_void) - -> *mut pa_operation; -+ pub fn pa_context_ref(c: *mut pa_context) -> *mut pa_context; - pub fn pa_context_unref(c: *mut pa_context); - pub fn pa_cvolume_set(a: *mut pa_cvolume, channels: c_uint, v: pa_volume_t) -> *mut pa_cvolume; - pub fn pa_cvolume_set_balance(v: *mut pa_cvolume, -@@ -80,12 +82,20 @@ mod static_fns { - pub fn pa_mainloop_api_once(m: *mut pa_mainloop_api, - callback: pa_mainloop_api_once_cb_t, - userdata: *mut c_void); -- pub fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t; -+ pub fn pa_strerror(error: pa_error_code_t) -> *const c_char; -+ pub fn pa_operation_ref(o: *mut pa_operation) -> *mut pa_operation; - pub fn pa_operation_unref(o: *mut pa_operation); -+ pub fn pa_operation_cancel(o: *mut pa_operation); -+ pub fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t; -+ pub fn pa_operation_set_state_callback(o: *mut pa_operation, -+ cb: pa_operation_notify_cb_t, -+ userdata: *mut c_void); - pub fn pa_proplist_gets(p: *mut pa_proplist, key: *const c_char) -> *const c_char; - pub fn pa_rtclock_now() -> pa_usec_t; - pub fn pa_stream_begin_write(p: *mut pa_stream, data: *mut *mut c_void, nbytes: *mut usize) -> c_int; - pub fn pa_stream_cancel_write(p: *mut pa_stream) -> c_int; -+ pub fn pa_stream_is_suspended(s: *const pa_stream) -> c_int; -+ pub fn pa_stream_is_corked(s: *const pa_stream) -> c_int; - pub fn pa_stream_connect_playback(s: *mut pa_stream, - dev: *const c_char, - attr: *const pa_buffer_attr, -@@ -112,6 +122,7 @@ mod static_fns { - pub fn pa_stream_get_latency(s: *const pa_stream, r_usec: *mut pa_usec_t, negative: *mut c_int) -> c_int; - pub fn pa_stream_get_sample_spec(s: *const pa_stream) -> *const pa_sample_spec; - pub fn pa_stream_get_state(p: *const pa_stream) -> pa_stream_state_t; -+ pub fn pa_stream_get_context(s: *const pa_stream) -> *mut pa_context; - pub fn pa_stream_get_time(s: *const pa_stream, r_usec: *mut pa_usec_t) -> c_int; - pub fn pa_stream_new(c: *mut pa_context, - name: *const c_char, -@@ -123,6 +134,7 @@ mod static_fns { - pub fn pa_stream_set_state_callback(s: *mut pa_stream, cb: pa_stream_notify_cb_t, userdata: *mut c_void); - pub fn pa_stream_set_write_callback(p: *mut pa_stream, cb: pa_stream_request_cb_t, userdata: *mut c_void); - pub fn pa_stream_set_read_callback(p: *mut pa_stream, cb: pa_stream_request_cb_t, userdata: *mut c_void); -+ pub fn pa_stream_ref(s: *mut pa_stream) -> *mut pa_stream; - pub fn pa_stream_unref(s: *mut pa_stream); - pub fn pa_stream_update_timing_info(p: *mut pa_stream, - cb: pa_stream_success_cb_t, -@@ -148,8 +160,6 @@ mod static_fns { - pub fn pa_threaded_mainloop_unlock(m: *mut pa_threaded_mainloop); - pub fn pa_threaded_mainloop_wait(m: *mut pa_threaded_mainloop); - pub fn pa_usec_to_bytes(t: pa_usec_t, spec: *const pa_sample_spec) -> usize; -- pub fn pa_xfree(ptr: *mut c_void); -- pub fn pa_xstrdup(str: *const c_char) -> *mut c_char; - pub fn pa_xrealloc(ptr: *mut c_void, size: usize) -> *mut c_void; - } - } -@@ -159,9 +169,9 @@ pub use self::static_fns::*; - - #[cfg(feature = "dlopen")] - mod dynamic_fns { -- use std::os::raw::{c_char, c_double, c_int, c_float, c_uint, c_void}; -- use libc::{dlclose, dlopen, dlsym, RTLD_LAZY}; - use super::*; -+ use libc::{RTLD_LAZY, dlclose, dlopen, dlsym}; -+ use std::os::raw::{c_char, c_double, c_float, c_int, c_uint, c_void}; - - #[derive(Debug)] - pub struct LibLoader { -@@ -287,6 +297,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_CONTEXT_ERRNO = { -+ let fp = dlsym(h, cstr!("pa_context_errno")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_CONTEXT_SET_SUBSCRIBE_CALLBACK = { - let fp = dlsym(h, cstr!("pa_context_set_subscribe_callback")); - if fp.is_null() { -@@ -301,6 +318,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_CONTEXT_REF = { -+ let fp = dlsym(h, cstr!("pa_context_ref")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_CONTEXT_UNREF = { - let fp = dlsym(h, cstr!("pa_context_unref")); - if fp.is_null() { -@@ -336,8 +360,15 @@ mod dynamic_fns { - } - fp - }; -- PA_OPERATION_GET_STATE = { -- let fp = dlsym(h, cstr!("pa_operation_get_state")); -+ PA_STRERROR = { -+ let fp = dlsym(h, cstr!("pa_strerror")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_REF = { -+ let fp = dlsym(h, cstr!("pa_operation_ref")); - if fp.is_null() { - return None; - } -@@ -350,6 +381,27 @@ mod dynamic_fns { - } - fp - }; -+ PA_OPERATION_CANCEL = { -+ let fp = dlsym(h, cstr!("pa_operation_cancel")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_GET_STATE = { -+ let fp = dlsym(h, cstr!("pa_operation_get_state")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_OPERATION_SET_STATE_CALLBACK = { -+ let fp = dlsym(h, cstr!("pa_operation_set_state_callback")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_PROPLIST_GETS = { - let fp = dlsym(h, cstr!("pa_proplist_gets")); - if fp.is_null() { -@@ -378,6 +430,20 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_IS_SUSPENDED = { -+ let fp = dlsym(h, cstr!("pa_stream_is_suspended")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; -+ PA_STREAM_IS_CORKED = { -+ let fp = dlsym(h, cstr!("pa_stream_is_corked")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_CONNECT_PLAYBACK = { - let fp = dlsym(h, cstr!("pa_stream_connect_playback")); - if fp.is_null() { -@@ -462,6 +528,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_GET_CONTEXT = { -+ let fp = dlsym(h, cstr!("pa_stream_get_context")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_GET_TIME = { - let fp = dlsym(h, cstr!("pa_stream_get_time")); - if fp.is_null() { -@@ -511,6 +584,13 @@ mod dynamic_fns { - } - fp - }; -+ PA_STREAM_REF = { -+ let fp = dlsym(h, cstr!("pa_stream_ref")); -+ if fp.is_null() { -+ return None; -+ } -+ fp -+ }; - PA_STREAM_UNREF = { - let fp = dlsym(h, cstr!("pa_stream_unref")); - if fp.is_null() { -@@ -623,20 +703,6 @@ mod dynamic_fns { - } - fp - }; -- PA_XFREE = { -- let fp = dlsym(h, cstr!("pa_xfree")); -- if fp.is_null() { -- return None; -- } -- fp -- }; -- PA_XSTRDUP = { -- let fp = dlsym(h, cstr!("pa_xstrdup")); -- if fp.is_null() { -- return None; -- } -- fp -- }; - PA_XREALLOC = { - let fp = dlsym(h, cstr!("pa_xrealloc")); - if fp.is_null() { -@@ -837,6 +903,12 @@ mod dynamic_fns { - *mut c_void)>(PA_CONTEXT_SET_STATE_CALLBACK))(c, cb, userdata) - } - -+ static mut PA_CONTEXT_ERRNO: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_context_errno(c: *mut pa_context) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_context) -> c_int>(PA_CONTEXT_ERRNO))(c) -+ } -+ - static mut PA_CONTEXT_SET_SUBSCRIBE_CALLBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_context_set_subscribe_callback(c: *mut pa_context, -@@ -863,6 +935,12 @@ mod dynamic_fns { - -> *mut pa_operation>(PA_CONTEXT_SUBSCRIBE))(c, m, cb, userdata) - } - -+ static mut PA_CONTEXT_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_context_ref(c: *mut pa_context) -> *mut pa_context { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_context) -> *mut pa_context>(PA_CONTEXT_REF))(c) -+ } -+ - static mut PA_CONTEXT_UNREF: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_context_unref(c: *mut pa_context) { -@@ -907,6 +985,30 @@ mod dynamic_fns { - *mut c_void)>(PA_MAINLOOP_API_ONCE))(m, callback, userdata) - } - -+ static mut PA_STRERROR: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_strerror(error: pa_error_code_t) -> *const c_char { -+ (::std::mem::transmute::<_, extern "C" fn(pa_error_code_t) -> *const c_char>(PA_STRERROR))(error) -+ } -+ -+ static mut PA_OPERATION_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_ref(o: *mut pa_operation) -> *mut pa_operation { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation) -> *mut pa_operation>(PA_OPERATION_REF))(o) -+ } -+ -+ static mut PA_OPERATION_UNREF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_unref(o: *mut pa_operation) { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_UNREF))(o) -+ } -+ -+ static mut PA_OPERATION_CANCEL: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_operation_cancel(o: *mut pa_operation) { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_CANCEL))(o) -+ } -+ - static mut PA_OPERATION_GET_STATE: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_operation_get_state(o: *const pa_operation) -> pa_operation_state_t { -@@ -915,10 +1017,15 @@ mod dynamic_fns { - -> pa_operation_state_t>(PA_OPERATION_GET_STATE))(o) - } - -- static mut PA_OPERATION_UNREF: *mut ::libc::c_void = 0 as *mut _; -+ static mut PA_OPERATION_SET_STATE_CALLBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] -- pub unsafe fn pa_operation_unref(o: *mut pa_operation) { -- (::std::mem::transmute::<_, extern "C" fn(*mut pa_operation)>(PA_OPERATION_UNREF))(o) -+ pub unsafe fn pa_operation_set_state_callback(o: *mut pa_operation, -+ cb: pa_operation_notify_cb_t, -+ userdata: *mut c_void) { -+ (::std::mem::transmute::<_, -+ extern "C" fn(*mut pa_operation, -+ pa_operation_notify_cb_t, -+ *mut c_void)>(PA_OPERATION_SET_STATE_CALLBACK))(o, cb, userdata) - } - - static mut PA_PROPLIST_GETS: *mut ::libc::c_void = 0 as *mut _; -@@ -951,6 +1058,18 @@ mod dynamic_fns { - (::std::mem::transmute::<_, extern "C" fn(*mut pa_stream) -> c_int>(PA_STREAM_CANCEL_WRITE))(p) - } - -+ static mut PA_STREAM_IS_SUSPENDED: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_is_suspended(s: *const pa_stream) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> c_int>(PA_STREAM_IS_SUSPENDED))(s) -+ } -+ -+ static mut PA_STREAM_IS_CORKED: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_is_corked(s: *const pa_stream) -> c_int { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> c_int>(PA_STREAM_IS_CORKED))(s) -+ } -+ - static mut PA_STREAM_CONNECT_PLAYBACK: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_connect_playback(s: *mut pa_stream, -@@ -1066,6 +1185,12 @@ mod dynamic_fns { - (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> pa_stream_state_t>(PA_STREAM_GET_STATE))(p) - } - -+ static mut PA_STREAM_GET_CONTEXT: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_get_context(s: *const pa_stream) -> *mut pa_context { -+ (::std::mem::transmute::<_, extern "C" fn(*const pa_stream) -> *mut pa_context>(PA_STREAM_GET_CONTEXT))(s) -+ } -+ - static mut PA_STREAM_GET_TIME: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_get_time(s: *const pa_stream, r_usec: *mut pa_usec_t) -> c_int { -@@ -1132,6 +1257,12 @@ mod dynamic_fns { - *mut c_void)>(PA_STREAM_SET_READ_CALLBACK))(p, cb, userdata) - } - -+ static mut PA_STREAM_REF: *mut ::libc::c_void = 0 as *mut _; -+ #[inline] -+ pub unsafe fn pa_stream_ref(s: *mut pa_stream) -> *mut pa_stream { -+ (::std::mem::transmute::<_, extern "C" fn(*mut pa_stream) -> *mut pa_stream>(PA_STREAM_REF))(s) -+ } -+ - static mut PA_STREAM_UNREF: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_stream_unref(s: *mut pa_stream) { -@@ -1253,18 +1384,6 @@ mod dynamic_fns { - spec) - } - -- static mut PA_XFREE: *mut ::libc::c_void = 0 as *mut _; -- #[inline] -- pub unsafe fn pa_xfree(ptr: *mut c_void) { -- (::std::mem::transmute::<_, extern "C" fn(*mut c_void)>(PA_XFREE))(ptr) -- } -- -- static mut PA_XSTRDUP: *mut ::libc::c_void = 0 as *mut _; -- #[inline] -- pub unsafe fn pa_xstrdup(str: *const c_char) -> *mut c_char { -- (::std::mem::transmute::<_, extern "C" fn(*const c_char) -> *mut c_char>(PA_XSTRDUP))(str) -- } -- - static mut PA_XREALLOC: *mut ::libc::c_void = 0 as *mut _; - #[inline] - pub unsafe fn pa_xrealloc(ptr: *mut c_void, size: usize) -> *mut c_void { -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-ffi/src/ffi_types.rs 2017-08-04 13:37:46.384821737 +0200 -@@ -1,6 +1,6 @@ - #![allow(non_camel_case_types)] - --use std::os::raw::{c_char, c_int, c_long, c_ulong, c_void}; -+use std::os::raw::{c_char, c_int, c_long, c_uint, c_ulong, c_void}; - - /* automatically generated by rust-bindgen */ - pub const PA_RATE_MAX: u32 = 48000 * 8; -@@ -74,10 +74,10 @@ pub const PA_OPERATION_DONE: c_int = 1; - pub const PA_OPERATION_CANCELLED: c_int = 2; - pub type pa_operation_state_t = c_int; - --pub const PA_CONTEXT_NOFLAGS: c_int = 0; --pub const PA_CONTEXT_NOAUTOSPAWN: c_int = 1; --pub const PA_CONTEXT_NOFAIL: c_int = 2; --pub type pa_context_flags_t = c_int; -+pub const PA_CONTEXT_NOFLAGS: c_uint = 0; -+pub const PA_CONTEXT_NOAUTOSPAWN: c_uint = 1; -+pub const PA_CONTEXT_NOFAIL: c_uint = 2; -+pub type pa_context_flags_t = c_uint; - - pub const PA_DIRECTION_OUTPUT: c_int = 1; - pub const PA_DIRECTION_INPUT: c_int = 2; -@@ -93,28 +93,28 @@ pub const PA_STREAM_RECORD: c_int = 2; - pub const PA_STREAM_UPLOAD: c_int = 3; - pub type pa_stream_direction_t = c_int; - --pub const PA_STREAM_NOFLAGS: c_int = 0x0_0000; --pub const PA_STREAM_START_CORKED: c_int = 0x0_0001; --pub const PA_STREAM_INTERPOLATE_TIMING: c_int = 0x0_0002; --pub const PA_STREAM_NOT_MONOTONIC: c_int = 0x0_0004; --pub const PA_STREAM_AUTO_TIMING_UPDATE: c_int = 0x0_0008; --pub const PA_STREAM_NO_REMAP_CHANNELS: c_int = 0x0_0010; --pub const PA_STREAM_NO_REMIX_CHANNELS: c_int = 0x0_0020; --pub const PA_STREAM_FIX_FORMAT: c_int = 0x0_0040; --pub const PA_STREAM_FIX_RATE: c_int = 0x0_0080; --pub const PA_STREAM_FIX_CHANNELS: c_int = 0x0_0100; --pub const PA_STREAM_DONT_MOVE: c_int = 0x0_0200; --pub const PA_STREAM_VARIABLE_RATE: c_int = 0x0_0400; --pub const PA_STREAM_PEAK_DETECT: c_int = 0x0_0800; --pub const PA_STREAM_START_MUTED: c_int = 0x0_1000; --pub const PA_STREAM_ADJUST_LATENCY: c_int = 0x0_2000; --pub const PA_STREAM_EARLY_REQUESTS: c_int = 0x0_4000; --pub const PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND: c_int = 0x0_8000; --pub const PA_STREAM_START_UNMUTED: c_int = 0x1_0000; --pub const PA_STREAM_FAIL_ON_SUSPEND: c_int = 0x2_0000; --pub const PA_STREAM_RELATIVE_VOLUME: c_int = 0x4_0000; --pub const PA_STREAM_PASSTHROUGH: c_int = 0x8_0000; --pub type pa_stream_flags_t = c_int; -+pub const PA_STREAM_NOFLAGS: c_uint = 0x0_0000; -+pub const PA_STREAM_START_CORKED: c_uint = 0x0_0001; -+pub const PA_STREAM_INTERPOLATE_TIMING: c_uint = 0x0_0002; -+pub const PA_STREAM_NOT_MONOTONIC: c_uint = 0x0_0004; -+pub const PA_STREAM_AUTO_TIMING_UPDATE: c_uint = 0x0_0008; -+pub const PA_STREAM_NO_REMAP_CHANNELS: c_uint = 0x0_0010; -+pub const PA_STREAM_NO_REMIX_CHANNELS: c_uint = 0x0_0020; -+pub const PA_STREAM_FIX_FORMAT: c_uint = 0x0_0040; -+pub const PA_STREAM_FIX_RATE: c_uint = 0x0_0080; -+pub const PA_STREAM_FIX_CHANNELS: c_uint = 0x0_0100; -+pub const PA_STREAM_DONT_MOVE: c_uint = 0x0_0200; -+pub const PA_STREAM_VARIABLE_RATE: c_uint = 0x0_0400; -+pub const PA_STREAM_PEAK_DETECT: c_uint = 0x0_0800; -+pub const PA_STREAM_START_MUTED: c_uint = 0x0_1000; -+pub const PA_STREAM_ADJUST_LATENCY: c_uint = 0x0_2000; -+pub const PA_STREAM_EARLY_REQUESTS: c_uint = 0x0_4000; -+pub const PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND: c_uint = 0x0_8000; -+pub const PA_STREAM_START_UNMUTED: c_uint = 0x1_0000; -+pub const PA_STREAM_FAIL_ON_SUSPEND: c_uint = 0x2_0000; -+pub const PA_STREAM_RELATIVE_VOLUME: c_uint = 0x4_0000; -+pub const PA_STREAM_PASSTHROUGH: c_uint = 0x8_0000; -+pub type pa_stream_flags_t = c_uint; - - #[repr(C)] - #[derive(Clone, Copy, Debug)] -@@ -162,19 +162,19 @@ pub const PA_ERR_BUSY: c_int = 26; - pub const PA_ERR_MAX: c_int = 27; - pub type pa_error_code_t = c_int; - --pub const PA_SUBSCRIPTION_MASK_NULL: c_int = 0; --pub const PA_SUBSCRIPTION_MASK_SINK: c_int = 1; --pub const PA_SUBSCRIPTION_MASK_SOURCE: c_int = 2; --pub const PA_SUBSCRIPTION_MASK_SINK_INPUT: c_int = 4; --pub const PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT: c_int = 8; --pub const PA_SUBSCRIPTION_MASK_MODULE: c_int = 16; --pub const PA_SUBSCRIPTION_MASK_CLIENT: c_int = 32; --pub const PA_SUBSCRIPTION_MASK_SAMPLE_CACHE: c_int = 64; --pub const PA_SUBSCRIPTION_MASK_SERVER: c_int = 128; --pub const PA_SUBSCRIPTION_MASK_AUTOLOAD: c_int = 256; --pub const PA_SUBSCRIPTION_MASK_CARD: c_int = 512; --pub const PA_SUBSCRIPTION_MASK_ALL: c_int = 767; --pub type pa_subscription_mask_t = c_int; -+pub const PA_SUBSCRIPTION_MASK_NULL: c_uint = 0x0; -+pub const PA_SUBSCRIPTION_MASK_SINK: c_uint = 0x1; -+pub const PA_SUBSCRIPTION_MASK_SOURCE: c_uint = 0x2; -+pub const PA_SUBSCRIPTION_MASK_SINK_INPUT: c_uint = 0x4; -+pub const PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT: c_uint = 0x8; -+pub const PA_SUBSCRIPTION_MASK_MODULE: c_uint = 0x10; -+pub const PA_SUBSCRIPTION_MASK_CLIENT: c_uint = 0x20; -+pub const PA_SUBSCRIPTION_MASK_SAMPLE_CACHE: c_uint = 0x40; -+pub const PA_SUBSCRIPTION_MASK_SERVER: c_uint = 0x80; -+pub const PA_SUBSCRIPTION_MASK_AUTOLOAD: c_uint = 0x100; -+pub const PA_SUBSCRIPTION_MASK_CARD: c_uint = 0x200; -+pub const PA_SUBSCRIPTION_MASK_ALL: c_uint = 0x3FF; -+pub type pa_subscription_mask_t = c_uint; - - pub const PA_SUBSCRIPTION_EVENT_SINK: c_int = 0; - pub const PA_SUBSCRIPTION_EVENT_SOURCE: c_int = 1; -@@ -244,17 +244,17 @@ pub const PA_SEEK_RELATIVE_ON_READ: c_in - pub const PA_SEEK_RELATIVE_END: c_int = 3; - pub type pa_seek_mode_t = c_int; - --pub const PA_SINK_NOFLAGS: c_int = 0; --pub const PA_SINK_HW_VOLUME_CTRL: c_int = 1; --pub const PA_SINK_LATENCY: c_int = 2; --pub const PA_SINK_HARDWARE: c_int = 4; --pub const PA_SINK_NETWORK: c_int = 8; --pub const PA_SINK_HW_MUTE_CTRL: c_int = 16; --pub const PA_SINK_DECIBEL_VOLUME: c_int = 32; --pub const PA_SINK_FLAT_VOLUME: c_int = 64; --pub const PA_SINK_DYNAMIC_LATENCY: c_int = 128; --pub const PA_SINK_SET_FORMATS: c_int = 256; --pub type pa_sink_flags_t = c_int; -+pub const PA_SINK_NOFLAGS: c_uint = 0x000; -+pub const PA_SINK_HW_VOLUME_CTRL: c_uint = 0x001; -+pub const PA_SINK_LATENCY: c_uint = 0x002; -+pub const PA_SINK_HARDWARE: c_uint = 0x004; -+pub const PA_SINK_NETWORK: c_uint = 0x008; -+pub const PA_SINK_HW_MUTE_CTRL: c_uint = 0x010; -+pub const PA_SINK_DECIBEL_VOLUME: c_uint = 0x020; -+pub const PA_SINK_FLAT_VOLUME: c_uint = 0x040; -+pub const PA_SINK_DYNAMIC_LATENCY: c_uint = 0x080; -+pub const PA_SINK_SET_FORMATS: c_uint = 0x100; -+pub type pa_sink_flags_t = c_uint; - - pub const PA_SINK_INVALID_STATE: c_int = -1; - pub const PA_SINK_RUNNING: c_int = 0; -@@ -264,16 +264,16 @@ pub const PA_SINK_INIT: c_int = -2; - pub const PA_SINK_UNLINKED: c_int = -3; - pub type pa_sink_state_t = c_int; - --pub const PA_SOURCE_NOFLAGS: c_int = 0x00; --pub const PA_SOURCE_HW_VOLUME_CTRL: c_int = 0x01; --pub const PA_SOURCE_LATENCY: c_int = 0x02; --pub const PA_SOURCE_HARDWARE: c_int = 0x04; --pub const PA_SOURCE_NETWORK: c_int = 0x08; --pub const PA_SOURCE_HW_MUTE_CTRL: c_int = 0x10; --pub const PA_SOURCE_DECIBEL_VOLUME: c_int = 0x20; --pub const PA_SOURCE_DYNAMIC_LATENCY: c_int = 0x40; --pub const PA_SOURCE_FLAT_VOLUME: c_int = 0x80; --pub type pa_source_flags_t = c_int; -+pub const PA_SOURCE_NOFLAGS: c_uint = 0x00; -+pub const PA_SOURCE_HW_VOLUME_CTRL: c_uint = 0x01; -+pub const PA_SOURCE_LATENCY: c_uint = 0x02; -+pub const PA_SOURCE_HARDWARE: c_uint = 0x04; -+pub const PA_SOURCE_NETWORK: c_uint = 0x08; -+pub const PA_SOURCE_HW_MUTE_CTRL: c_uint = 0x10; -+pub const PA_SOURCE_DECIBEL_VOLUME: c_uint = 0x20; -+pub const PA_SOURCE_DYNAMIC_LATENCY: c_uint = 0x40; -+pub const PA_SOURCE_FLAT_VOLUME: c_uint = 0x80; -+pub type pa_source_flags_t = c_uint; - - pub const PA_SOURCE_INVALID_STATE: c_int = -1; - pub const PA_SOURCE_RUNNING: c_int = 0; -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml.cubeb-pulse-arm 2017-08-04 13:37:46.384821737 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/Cargo.toml 2017-08-04 13:37:46.384821737 +0200 -@@ -0,0 +1,8 @@ -+[package] -+name = "pulse" -+version = "0.1.0" -+authors = ["Dan Glastonbury "] -+ -+[dependencies] -+bitflags = "^0.7.0" -+pulse-ffi = { path = "../pulse-ffi" } -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/context.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,394 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ::*; -+use ffi; -+use std::ffi::CStr; -+use std::os::raw::{c_int, c_void}; -+use std::ptr; -+use util::UnwrapCStr; -+ -+// A note about `wrapped` functions -+// -+// C FFI demands `unsafe extern fn(*mut pa_context, ...) -> i32`, etc, -+// but we want to allow such callbacks to be safe. This means no -+// `unsafe` or `extern`, and callbacks should be called with a safe -+// wrapper of `*mut pa_context`. Since the callback doesn't take -+// ownership, this is `&Context`. `fn wrapped(...)` defines a -+// function that converts from our safe signature to the unsafe -+// signature. -+// -+// Currently, we use a property of Rust, namely that each function -+// gets its own unique type. These unique types can't be written -+// directly, so we use generic and a type parameter, and let the Rust -+// compiler fill in the name for us: -+// -+// fn get_sink_input_info(&self, ..., _: CB, ...) -> ... -+// where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+// -+// Because we aren't storing or passing any state, we assert, at run-time :-(, -+// that our functions are zero-sized: -+// -+// assert!(mem::size_of::() == 0); -+// -+// We need to obtain a value of type F in order to call it. Since we -+// can't name the function, we have to unsafely construct that value -+// somehow - we do this using mem::uninitialized. Then, we call that -+// function with a reference to the Context, and save the result: -+// -+// | generate value || call it | -+// let result = ::std::mem::uninitialized::()(&mut object); -+// -+// Lastly, since our Object is an owned type, we need to avoid -+// dropping it, then return the result we just generated. -+// -+// mem::forget(object); -+// result -+ -+// Aid in returning Operation from callbacks -+macro_rules! op_or_err { -+ ($self_:ident, $e:expr) => {{ -+ let o = unsafe { $e }; -+ if o.is_null() { -+ Err(ErrorCode::from_error_code($self_.errno())) -+ } else { -+ Ok(unsafe { operation::from_raw_ptr(o) }) -+ } -+ }} -+} -+ -+#[repr(C)] -+#[derive(Debug)] -+pub struct Context(*mut ffi::pa_context); -+ -+impl Context { -+ pub fn new<'a, OPT>(api: &MainloopApi, name: OPT) -> Option -+ where OPT: Into> -+ { -+ let ptr = unsafe { ffi::pa_context_new(api.raw_mut(), name.unwrap_cstr()) }; -+ if ptr.is_null() { -+ None -+ } else { -+ Some(Context(ptr)) -+ } -+ } -+ -+ #[doc(hidden)] -+ pub fn raw_mut(&self) -> &mut ffi::pa_context { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn unref(self) { -+ unsafe { -+ ffi::pa_context_unref(self.raw_mut()); -+ } -+ } -+ -+ pub fn clear_state_callback(&self) { -+ unsafe { -+ ffi::pa_context_set_state_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_state_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Context, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, userdata: *mut c_void) -+ where F: Fn(&Context, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_context_set_state_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn errno(&self) -> ffi::pa_error_code_t { -+ unsafe { ffi::pa_context_errno(self.raw_mut()) } -+ } -+ -+ pub fn get_state(&self) -> ContextState { -+ ContextState::try_from(unsafe { -+ ffi::pa_context_get_state(self.raw_mut()) -+ }).expect("pa_context_get_state returned invalid ContextState") -+ } -+ -+ pub fn connect<'a, OPT>(&self, server: OPT, flags: ContextFlags, api: *const ffi::pa_spawn_api) -> Result<()> -+ where OPT: Into> -+ { -+ let r = unsafe { -+ ffi::pa_context_connect(self.raw_mut(), -+ server.into().unwrap_cstr(), -+ flags.into(), -+ api) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn disconnect(&self) { -+ unsafe { -+ ffi::pa_context_disconnect(self.raw_mut()); -+ } -+ } -+ -+ -+ pub fn drain(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, userdata: *mut c_void) -+ where F: Fn(&Context, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_drain(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn rttime_new(&self, usec: USec, _: CB, userdata: *mut c_void) -> *mut ffi::pa_time_event -+ where CB: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(a: *mut ffi::pa_mainloop_api, -+ e: *mut ffi::pa_time_event, -+ tv: *const TimeVal, -+ userdata: *mut c_void) -+ where F: Fn(&MainloopApi, *mut ffi::pa_time_event, &TimeVal, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let api = mainloop_api::from_raw_ptr(a); -+ let timeval = &*tv; -+ let result = uninitialized::()(&api, e, timeval, userdata); -+ forget(api); -+ -+ result -+ } -+ -+ unsafe { ffi::pa_context_rttime_new(self.raw_mut(), usec, Some(wrapped::), userdata) } -+ } -+ -+ pub fn get_server_info(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, &ServerInfo, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, i: *const ffi::pa_server_info, userdata: *mut c_void) -+ where F: Fn(&Context, &ServerInfo, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ debug_assert_ne!(i, ptr::null_mut()); -+ let info = &*i; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_server_info(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_info_by_name(&self, name: &CStr, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_info_by_name(self.raw_mut(), name.as_ptr(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_info_list(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_info_list(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_sink_input_info(&self, idx: u32, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_sink_input_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SinkInputInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_sink_input_info(self.raw_mut(), idx, Some(wrapped::), userdata)) -+ } -+ -+ pub fn get_source_info_list(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, *const SourceInfo, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ info: *const ffi::pa_source_info, -+ eol: c_int, -+ userdata: *mut c_void) -+ where F: Fn(&Context, *const SourceInfo, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, info, eol, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_get_source_info_list(self.raw_mut(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn set_sink_input_volume(&self, -+ idx: u32, -+ volume: &CVolume, -+ _: CB, -+ userdata: *mut c_void) -+ -> Result -+ where CB: Fn(&Context, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Context, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, success, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_set_sink_input_volume(self.raw_mut(), idx, volume, Some(wrapped::), userdata)) -+ } -+ -+ pub fn subscribe(&self, m: SubscriptionMask, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Context, i32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Context, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let result = uninitialized::()(&ctx, success, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ op_or_err!(self, -+ ffi::pa_context_subscribe(self.raw_mut(), m.into(), Some(wrapped::), userdata)) -+ } -+ -+ pub fn clear_subscribe_callback(&self) { -+ unsafe { -+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_subscribe_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Context, SubscriptionEvent, u32, *mut c_void) -+ { -+ debug_assert_eq!(::std::mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(c: *mut ffi::pa_context, -+ t: ffi::pa_subscription_event_type_t, -+ idx: u32, -+ userdata: *mut c_void) -+ where F: Fn(&Context, SubscriptionEvent, u32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let ctx = context::from_raw_ptr(c); -+ let event = SubscriptionEvent::try_from(t) -+ .expect("pa_context_subscribe_cb_t passed invalid pa_subscription_event_type_t"); -+ let result = uninitialized::()(&ctx, event, idx, userdata); -+ forget(ctx); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_context_set_subscribe_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+} -+ -+#[doc(hidden)] -+pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_context) -> Context { -+ Context(ptr) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/error.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,56 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::ffi::CStr; -+ -+#[macro_export] -+macro_rules! error_result { -+ ($t:expr, $err:expr) => { -+ if $err >= 0 { -+ Ok($t) -+ } else { -+ Err(ErrorCode::from_error_result($err)) -+ } -+ } -+} -+ -+#[derive(Debug, PartialEq)] -+pub struct ErrorCode { -+ err: ffi::pa_error_code_t, -+} -+ -+impl ErrorCode { -+ pub fn from_error_result(err: i32) -> Self { -+ debug_assert!(err < 0); -+ ErrorCode { -+ err: (-err) as ffi::pa_error_code_t, -+ } -+ } -+ -+ pub fn from_error_code(err: ffi::pa_error_code_t) -> Self { -+ debug_assert!(err > 0); -+ ErrorCode { -+ err: err, -+ } -+ } -+ -+ fn desc(&self) -> &'static str { -+ let cstr = unsafe { CStr::from_ptr(ffi::pa_strerror(self.err)) }; -+ cstr.to_str().unwrap() -+ } -+} -+ -+impl ::std::error::Error for ErrorCode { -+ fn description(&self) -> &str { -+ self.desc() -+ } -+} -+ -+impl ::std::fmt::Display for ErrorCode { -+ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { -+ write!(f, "{:?}: {}", self, self.desc()) -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/lib.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,653 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+#[macro_use] -+extern crate bitflags; -+extern crate pulse_ffi as ffi; -+ -+#[macro_use] -+mod error; -+mod context; -+mod mainloop_api; -+mod operation; -+mod proplist; -+mod stream; -+mod threaded_mainloop; -+mod util; -+ -+pub use context::Context; -+pub use error::ErrorCode; -+pub use ffi::pa_buffer_attr as BufferAttr; -+pub use ffi::pa_channel_map as ChannelMap; -+pub use ffi::pa_cvolume as CVolume; -+pub use ffi::pa_sample_spec as SampleSpec; -+pub use ffi::pa_server_info as ServerInfo; -+pub use ffi::pa_sink_info as SinkInfo; -+pub use ffi::pa_sink_input_info as SinkInputInfo; -+pub use ffi::pa_source_info as SourceInfo; -+pub use ffi::pa_usec_t as USec; -+pub use ffi::pa_volume_t as Volume; -+pub use ffi::timeval as TimeVal; -+pub use mainloop_api::MainloopApi; -+pub use operation::Operation; -+pub use proplist::Proplist; -+use std::os::raw::{c_char, c_uint}; -+pub use stream::Stream; -+pub use threaded_mainloop::ThreadedMainloop; -+ -+#[allow(non_camel_case_types)] -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SampleFormat { -+ Invalid = ffi::PA_SAMPLE_INVALID, -+ U8 = ffi::PA_SAMPLE_U8, -+ Alaw = ffi::PA_SAMPLE_ALAW, -+ Ulaw = ffi::PA_SAMPLE_ULAW, -+ Signed16LE = ffi::PA_SAMPLE_S16LE, -+ Signed16BE = ffi::PA_SAMPLE_S16BE, -+ Float32LE = ffi::PA_SAMPLE_FLOAT32LE, -+ Float32BE = ffi::PA_SAMPLE_FLOAT32BE, -+ Signed32LE = ffi::PA_SAMPLE_S32LE, -+ Signed32BE = ffi::PA_SAMPLE_S32BE, -+ Signed24LE = ffi::PA_SAMPLE_S24LE, -+ Signed24BE = ffi::PA_SAMPLE_S24BE, -+ Signed24_32LE = ffi::PA_SAMPLE_S24_32LE, -+ Signed23_32BE = ffi::PA_SAMPLE_S24_32BE, -+} -+ -+impl Default for SampleFormat { -+ fn default() -> Self { -+ SampleFormat::Invalid -+ } -+} -+ -+impl Into for SampleFormat { -+ fn into(self) -> ffi::pa_sample_format_t { -+ self as ffi::pa_sample_format_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum ContextState { -+ Unconnected = ffi::PA_CONTEXT_UNCONNECTED, -+ Connecting = ffi::PA_CONTEXT_CONNECTING, -+ Authorizing = ffi::PA_CONTEXT_AUTHORIZING, -+ SettingName = ffi::PA_CONTEXT_SETTING_NAME, -+ Ready = ffi::PA_CONTEXT_READY, -+ Failed = ffi::PA_CONTEXT_FAILED, -+ Terminated = ffi::PA_CONTEXT_TERMINATED, -+} -+ -+impl ContextState { -+ // This function implements the PA_CONTENT_IS_GOOD macro from pulse/def.h -+ // It must match the version from PA headers. -+ pub fn is_good(self) -> bool { -+ match self { -+ ContextState::Connecting | -+ ContextState::Authorizing | -+ ContextState::SettingName | -+ ContextState::Ready => true, -+ _ => false, -+ } -+ } -+ -+ pub fn try_from(x: ffi::pa_context_state_t) -> Option { -+ if x >= ffi::PA_CONTEXT_UNCONNECTED && x <= ffi::PA_CONTEXT_TERMINATED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for ContextState { -+ fn default() -> Self { -+ ContextState::Unconnected -+ } -+} -+ -+impl Into for ContextState { -+ fn into(self) -> ffi::pa_context_state_t { -+ self as ffi::pa_context_state_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum StreamState { -+ Unconnected = ffi::PA_STREAM_UNCONNECTED, -+ Creating = ffi::PA_STREAM_CREATING, -+ Ready = ffi::PA_STREAM_READY, -+ Failed = ffi::PA_STREAM_FAILED, -+ Terminated = ffi::PA_STREAM_TERMINATED, -+} -+ -+impl StreamState { -+ // This function implements the PA_STREAM_IS_GOOD macro from pulse/def.h -+ // It must match the version from PA headers. -+ pub fn is_good(self) -> bool { -+ match self { -+ StreamState::Creating | StreamState::Ready => true, -+ _ => false, -+ } -+ } -+ -+ pub fn try_from(x: ffi::pa_stream_state_t) -> Option { -+ if x >= ffi::PA_STREAM_UNCONNECTED && x <= ffi::PA_STREAM_TERMINATED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for StreamState { -+ fn default() -> Self { -+ StreamState::Unconnected -+ } -+} -+ -+impl Into for StreamState { -+ fn into(self) -> ffi::pa_stream_state_t { -+ self as ffi::pa_stream_state_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum OperationState { -+ Running = ffi::PA_OPERATION_RUNNING, -+ Done = ffi::PA_OPERATION_DONE, -+ Cancelled = ffi::PA_OPERATION_CANCELLED, -+} -+ -+impl OperationState { -+ pub fn try_from(x: ffi::pa_operation_state_t) -> Option { -+ if x >= ffi::PA_OPERATION_RUNNING && x <= ffi::PA_OPERATION_CANCELLED { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for OperationState { -+ fn into(self) -> ffi::pa_operation_state_t { -+ self as ffi::pa_operation_state_t -+ } -+} -+ -+bitflags! { -+ pub flags ContextFlags: u32 { -+ const CONTEXT_FLAGS_NOAUTOSPAWN = ffi::PA_CONTEXT_NOAUTOSPAWN, -+ const CONTEXT_FLAGS_NOFAIL = ffi::PA_CONTEXT_NOFAIL, -+ } -+} -+ -+impl Into for ContextFlags { -+ fn into(self) -> ffi::pa_context_flags_t { -+ self.bits() as ffi::pa_context_flags_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum DeviceType { -+ Sink = ffi::PA_DEVICE_TYPE_SINK, -+ Source = ffi::PA_DEVICE_TYPE_SOURCE, -+} -+ -+impl DeviceType { -+ pub fn try_from(x: ffi::pa_device_type_t) -> Option { -+ if x >= ffi::PA_DEVICE_TYPE_SINK && x <= ffi::PA_DEVICE_TYPE_SOURCE { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for DeviceType { -+ fn into(self) -> ffi::pa_device_type_t { -+ self as ffi::pa_device_type_t -+ } -+} -+ -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum StreamDirection { -+ NoDirection = ffi::PA_STREAM_NODIRECTION, -+ Playback = ffi::PA_STREAM_PLAYBACK, -+ Record = ffi::PA_STREAM_RECORD, -+ StreamUpload = ffi::PA_STREAM_UPLOAD, -+} -+ -+impl StreamDirection { -+ pub fn try_from(x: ffi::pa_stream_direction_t) -> Option { -+ if x >= ffi::PA_STREAM_NODIRECTION && x <= ffi::PA_STREAM_UPLOAD { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for StreamDirection { -+ fn into(self) -> ffi::pa_stream_direction_t { -+ self as ffi::pa_stream_direction_t -+ } -+} -+ -+bitflags! { -+ pub flags StreamFlags : u32 { -+ const STREAM_START_CORKED = ffi::PA_STREAM_START_CORKED, -+ const STREAM_INTERPOLATE_TIMING = ffi::PA_STREAM_INTERPOLATE_TIMING, -+ const STREAM_NOT_MONOTONIC = ffi::PA_STREAM_NOT_MONOTONIC, -+ const STREAM_AUTO_TIMING_UPDATE = ffi::PA_STREAM_AUTO_TIMING_UPDATE, -+ const STREAM_NO_REMAP_CHANNELS = ffi::PA_STREAM_NO_REMAP_CHANNELS, -+ const STREAM_NO_REMIX_CHANNELS = ffi::PA_STREAM_NO_REMIX_CHANNELS, -+ const STREAM_FIX_FORMAT = ffi::PA_STREAM_FIX_FORMAT, -+ const STREAM_FIX_RATE = ffi::PA_STREAM_FIX_RATE, -+ const STREAM_FIX_CHANNELS = ffi::PA_STREAM_FIX_CHANNELS, -+ const STREAM_DONT_MOVE = ffi::PA_STREAM_DONT_MOVE, -+ const STREAM_VARIABLE_RATE = ffi::PA_STREAM_VARIABLE_RATE, -+ const STREAM_PEAK_DETECT = ffi::PA_STREAM_PEAK_DETECT, -+ const STREAM_START_MUTED = ffi::PA_STREAM_START_MUTED, -+ const STREAM_ADJUST_LATENCY = ffi::PA_STREAM_ADJUST_LATENCY, -+ const STREAM_EARLY_REQUESTS = ffi::PA_STREAM_EARLY_REQUESTS, -+ const STREAM_DONT_INHIBIT_AUTO_SUSPEND = ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND, -+ const STREAM_START_UNMUTED = ffi::PA_STREAM_START_UNMUTED, -+ const STREAM_FAIL_ON_SUSPEND = ffi::PA_STREAM_FAIL_ON_SUSPEND, -+ const STREAM_RELATIVE_VOLUME = ffi::PA_STREAM_RELATIVE_VOLUME, -+ const STREAM_PASSTHROUGH = ffi::PA_STREAM_PASSTHROUGH, -+ } -+} -+ -+impl StreamFlags { -+ pub fn try_from(x: ffi::pa_stream_flags_t) -> Option { -+ if (x & -+ !(ffi::PA_STREAM_NOFLAGS | ffi::PA_STREAM_START_CORKED | ffi::PA_STREAM_INTERPOLATE_TIMING | -+ ffi::PA_STREAM_NOT_MONOTONIC | ffi::PA_STREAM_AUTO_TIMING_UPDATE | -+ ffi::PA_STREAM_NO_REMAP_CHANNELS | -+ ffi::PA_STREAM_NO_REMIX_CHANNELS | ffi::PA_STREAM_FIX_FORMAT | ffi::PA_STREAM_FIX_RATE | -+ ffi::PA_STREAM_FIX_CHANNELS | -+ ffi::PA_STREAM_DONT_MOVE | ffi::PA_STREAM_VARIABLE_RATE | ffi::PA_STREAM_PEAK_DETECT | -+ ffi::PA_STREAM_START_MUTED | ffi::PA_STREAM_ADJUST_LATENCY | -+ ffi::PA_STREAM_EARLY_REQUESTS | -+ ffi::PA_STREAM_DONT_INHIBIT_AUTO_SUSPEND | -+ ffi::PA_STREAM_START_UNMUTED | ffi::PA_STREAM_FAIL_ON_SUSPEND | -+ ffi::PA_STREAM_RELATIVE_VOLUME | ffi::PA_STREAM_PASSTHROUGH)) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for StreamFlags { -+ fn into(self) -> ffi::pa_stream_flags_t { -+ self.bits() as ffi::pa_stream_flags_t -+ } -+} -+ -+bitflags!{ -+ pub flags SubscriptionMask : u32 { -+ const SUBSCRIPTION_MASK_SINK = ffi::PA_SUBSCRIPTION_MASK_SINK, -+ const SUBSCRIPTION_MASK_SOURCE = ffi::PA_SUBSCRIPTION_MASK_SOURCE, -+ const SUBSCRIPTION_MASK_SINK_INPUT = ffi::PA_SUBSCRIPTION_MASK_SINK_INPUT, -+ const SUBSCRIPTION_MASK_SOURCE_OUTPUT = ffi::PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT, -+ const SUBSCRIPTION_MASK_MODULE = ffi::PA_SUBSCRIPTION_MASK_MODULE, -+ const SUBSCRIPTION_MASK_CLIENT = ffi::PA_SUBSCRIPTION_MASK_CLIENT, -+ const SUBSCRIPTION_MASK_SAMPLE_CACHE = ffi::PA_SUBSCRIPTION_MASK_SAMPLE_CACHE, -+ const SUBSCRIPTION_MASK_SERVER = ffi::PA_SUBSCRIPTION_MASK_SERVER, -+ const SUBSCRIPTION_MASK_AUTOLOAD = ffi::PA_SUBSCRIPTION_MASK_AUTOLOAD, -+ const SUBSCRIPTION_MASK_CARD = ffi::PA_SUBSCRIPTION_MASK_CARD, -+ } -+} -+ -+impl SubscriptionMask { -+ pub fn try_from(x: ffi::pa_subscription_mask_t) -> Option { -+ if (x & !ffi::PA_SUBSCRIPTION_MASK_ALL) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for SubscriptionMask { -+ fn into(self) -> ffi::pa_subscription_mask_t { -+ self.bits() as ffi::pa_subscription_mask_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SubscriptionEventFacility { -+ Sink = ffi::PA_SUBSCRIPTION_EVENT_SINK, -+ Source = ffi::PA_SUBSCRIPTION_EVENT_SOURCE, -+ SinkInput = ffi::PA_SUBSCRIPTION_EVENT_SINK_INPUT, -+ SourceOutput = ffi::PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT, -+ Module = ffi::PA_SUBSCRIPTION_EVENT_MODULE, -+ Client = ffi::PA_SUBSCRIPTION_EVENT_CLIENT, -+ SampleCache = ffi::PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE, -+ Server = ffi::PA_SUBSCRIPTION_EVENT_SERVER, -+ Autoload = ffi::PA_SUBSCRIPTION_EVENT_AUTOLOAD, -+ Card = ffi::PA_SUBSCRIPTION_EVENT_CARD, -+} -+ -+#[repr(C)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SubscriptionEventType { -+ New, -+ Change, -+ Remove, -+} -+ -+#[repr(C)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub struct SubscriptionEvent(ffi::pa_subscription_event_type_t); -+impl SubscriptionEvent { -+ pub fn try_from(x: ffi::pa_subscription_event_type_t) -> Option { -+ if (x & !(ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK | ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK)) == 0 { -+ Some(SubscriptionEvent(x)) -+ } else { -+ None -+ } -+ } -+ -+ pub fn event_facility(self) -> SubscriptionEventFacility { -+ unsafe { ::std::mem::transmute(self.0 & ffi::PA_SUBSCRIPTION_EVENT_FACILITY_MASK) } -+ } -+ -+ pub fn event_type(self) -> SubscriptionEventType { -+ unsafe { ::std::mem::transmute(((self.0 & ffi::PA_SUBSCRIPTION_EVENT_TYPE_MASK) >> 4)) } -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SeekMode { -+ Relative = ffi::PA_SEEK_RELATIVE, -+ Absolute = ffi::PA_SEEK_ABSOLUTE, -+ RelativeOnRead = ffi::PA_SEEK_RELATIVE_ON_READ, -+ RelativeEnd = ffi::PA_SEEK_RELATIVE_END, -+} -+ -+impl SeekMode { -+ pub fn try_from(x: ffi::pa_seek_mode_t) -> Option { -+ if x >= ffi::PA_SEEK_RELATIVE && x <= ffi::PA_SEEK_RELATIVE_END { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for SeekMode { -+ fn into(self) -> ffi::pa_seek_mode_t { -+ self as ffi::pa_seek_mode_t -+ } -+} -+ -+bitflags! { -+ pub flags SinkFlags: u32 { -+ const SINK_HW_VOLUME_CTRL = ffi::PA_SINK_HW_VOLUME_CTRL, -+ const SINK_LATENCY = ffi::PA_SINK_LATENCY, -+ const SINK_HARDWARE = ffi::PA_SINK_HARDWARE, -+ const SINK_NETWORK = ffi::PA_SINK_NETWORK, -+ const SINK_HW_MUTE_CTRL = ffi::PA_SINK_HW_MUTE_CTRL, -+ const SINK_DECIBEL_VOLUME = ffi::PA_SINK_DECIBEL_VOLUME, -+ const SINK_FLAT_VOLUME = ffi::PA_SINK_FLAT_VOLUME, -+ const SINK_DYNAMIC_LATENCY = ffi::PA_SINK_DYNAMIC_LATENCY, -+ const SINK_SET_FORMATS = ffi::PA_SINK_SET_FORMATS, -+ } -+} -+ -+impl SinkFlags { -+ pub fn try_from(x: ffi::pa_sink_flags_t) -> Option { -+ if (x & -+ !(ffi::PA_SOURCE_NOFLAGS | ffi::PA_SOURCE_HW_VOLUME_CTRL | ffi::PA_SOURCE_LATENCY | -+ ffi::PA_SOURCE_HARDWARE | ffi::PA_SOURCE_NETWORK | ffi::PA_SOURCE_HW_MUTE_CTRL | -+ ffi::PA_SOURCE_DECIBEL_VOLUME | -+ ffi::PA_SOURCE_DYNAMIC_LATENCY | ffi::PA_SOURCE_FLAT_VOLUME)) == 0 { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SinkState { -+ InvalidState = ffi::PA_SINK_INVALID_STATE, -+ Running = ffi::PA_SINK_RUNNING, -+ Idle = ffi::PA_SINK_IDLE, -+ Suspended = ffi::PA_SINK_SUSPENDED, -+ Init = ffi::PA_SINK_INIT, -+ Unlinked = ffi::PA_SINK_UNLINKED, -+} -+ -+bitflags!{ -+ pub flags SourceFlags: u32 { -+ const SOURCE_FLAGS_HW_VOLUME_CTRL = ffi::PA_SOURCE_HW_VOLUME_CTRL, -+ const SOURCE_FLAGS_LATENCY = ffi::PA_SOURCE_LATENCY, -+ const SOURCE_FLAGS_HARDWARE = ffi::PA_SOURCE_HARDWARE, -+ const SOURCE_FLAGS_NETWORK = ffi::PA_SOURCE_NETWORK, -+ const SOURCE_FLAGS_HW_MUTE_CTRL = ffi::PA_SOURCE_HW_MUTE_CTRL, -+ const SOURCE_FLAGS_DECIBEL_VOLUME = ffi::PA_SOURCE_DECIBEL_VOLUME, -+ const SOURCE_FLAGS_DYNAMIC_LATENCY = ffi::PA_SOURCE_DYNAMIC_LATENCY, -+ const SOURCE_FLAGS_FLAT_VOLUME = ffi::PA_SOURCE_FLAT_VOLUME, -+ } -+} -+ -+impl Into for SourceFlags { -+ fn into(self) -> ffi::pa_source_flags_t { -+ self.bits() as ffi::pa_source_flags_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum SourceState { -+ InvalidState = ffi::PA_SOURCE_INVALID_STATE, -+ Running = ffi::PA_SOURCE_RUNNING, -+ Idle = ffi::PA_SOURCE_IDLE, -+ Suspended = ffi::PA_SOURCE_SUSPENDED, -+ Init = ffi::PA_SOURCE_INIT, -+ Unlinked = ffi::PA_SOURCE_UNLINKED, -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum PortAvailable { -+ Unknown = ffi::PA_PORT_AVAILABLE_UNKNOWN, -+ No = ffi::PA_PORT_AVAILABLE_NO, -+ Yes = ffi::PA_PORT_AVAILABLE_YES, -+} -+ -+impl PortAvailable { -+ pub fn try_from(x: ffi::pa_port_available_t) -> Option { -+ if x >= ffi::PA_PORT_AVAILABLE_UNKNOWN && x <= ffi::PA_PORT_AVAILABLE_YES { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Into for PortAvailable { -+ fn into(self) -> ffi::pa_port_available_t { -+ self as ffi::pa_port_available_t -+ } -+} -+ -+#[repr(i32)] -+#[derive(Clone, Copy, Debug, PartialEq, Eq)] -+pub enum ChannelPosition { -+ Invalid = ffi::PA_CHANNEL_POSITION_INVALID, -+ Mono = ffi::PA_CHANNEL_POSITION_MONO, -+ FrontLeft = ffi::PA_CHANNEL_POSITION_FRONT_LEFT, -+ FrontRight = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT, -+ FrontCenter = ffi::PA_CHANNEL_POSITION_FRONT_CENTER, -+ RearCenter = ffi::PA_CHANNEL_POSITION_REAR_CENTER, -+ RearLeft = ffi::PA_CHANNEL_POSITION_REAR_LEFT, -+ RearRight = ffi::PA_CHANNEL_POSITION_REAR_RIGHT, -+ LowFreqEffects = ffi::PA_CHANNEL_POSITION_LFE, -+ FrontLeftOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, -+ FrontRightOfCenter = ffi::PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, -+ SideLeft = ffi::PA_CHANNEL_POSITION_SIDE_LEFT, -+ SideRight = ffi::PA_CHANNEL_POSITION_SIDE_RIGHT, -+ Aux0 = ffi::PA_CHANNEL_POSITION_AUX0, -+ Aux1 = ffi::PA_CHANNEL_POSITION_AUX1, -+ Aux2 = ffi::PA_CHANNEL_POSITION_AUX2, -+ Aux3 = ffi::PA_CHANNEL_POSITION_AUX3, -+ Aux4 = ffi::PA_CHANNEL_POSITION_AUX4, -+ Aux5 = ffi::PA_CHANNEL_POSITION_AUX5, -+ Aux6 = ffi::PA_CHANNEL_POSITION_AUX6, -+ Aux7 = ffi::PA_CHANNEL_POSITION_AUX7, -+ Aux8 = ffi::PA_CHANNEL_POSITION_AUX8, -+ Aux9 = ffi::PA_CHANNEL_POSITION_AUX9, -+ Aux10 = ffi::PA_CHANNEL_POSITION_AUX10, -+ Aux11 = ffi::PA_CHANNEL_POSITION_AUX11, -+ Aux12 = ffi::PA_CHANNEL_POSITION_AUX12, -+ Aux13 = ffi::PA_CHANNEL_POSITION_AUX13, -+ Aux14 = ffi::PA_CHANNEL_POSITION_AUX14, -+ Aux15 = ffi::PA_CHANNEL_POSITION_AUX15, -+ Aux16 = ffi::PA_CHANNEL_POSITION_AUX16, -+ Aux17 = ffi::PA_CHANNEL_POSITION_AUX17, -+ Aux18 = ffi::PA_CHANNEL_POSITION_AUX18, -+ Aux19 = ffi::PA_CHANNEL_POSITION_AUX19, -+ Aux20 = ffi::PA_CHANNEL_POSITION_AUX20, -+ Aux21 = ffi::PA_CHANNEL_POSITION_AUX21, -+ Aux22 = ffi::PA_CHANNEL_POSITION_AUX22, -+ Aux23 = ffi::PA_CHANNEL_POSITION_AUX23, -+ Aux24 = ffi::PA_CHANNEL_POSITION_AUX24, -+ Aux25 = ffi::PA_CHANNEL_POSITION_AUX25, -+ Aux26 = ffi::PA_CHANNEL_POSITION_AUX26, -+ Aux27 = ffi::PA_CHANNEL_POSITION_AUX27, -+ Aux28 = ffi::PA_CHANNEL_POSITION_AUX28, -+ Aux29 = ffi::PA_CHANNEL_POSITION_AUX29, -+ Aux30 = ffi::PA_CHANNEL_POSITION_AUX30, -+ Aux31 = ffi::PA_CHANNEL_POSITION_AUX31, -+ TopCenter = ffi::PA_CHANNEL_POSITION_TOP_CENTER, -+ TopFrontLeft = ffi::PA_CHANNEL_POSITION_TOP_FRONT_LEFT, -+ TopFrontRight = ffi::PA_CHANNEL_POSITION_TOP_FRONT_RIGHT, -+ TopFrontCenter = ffi::PA_CHANNEL_POSITION_TOP_FRONT_CENTER, -+ TopRearLeft = ffi::PA_CHANNEL_POSITION_TOP_REAR_LEFT, -+ TopRearRight = ffi::PA_CHANNEL_POSITION_TOP_REAR_RIGHT, -+ TopRearCenter = ffi::PA_CHANNEL_POSITION_TOP_REAR_CENTER, -+} -+ -+impl ChannelPosition { -+ pub fn try_from(x: ffi::pa_channel_position_t) -> Option { -+ if x >= ffi::PA_CHANNEL_POSITION_INVALID && x < ffi::PA_CHANNEL_POSITION_MAX { -+ Some(unsafe { ::std::mem::transmute(x) }) -+ } else { -+ None -+ } -+ } -+} -+ -+impl Default for ChannelPosition { -+ fn default() -> Self { -+ ChannelPosition::Invalid -+ } -+} -+ -+impl Into for ChannelPosition { -+ fn into(self) -> ffi::pa_channel_position_t { -+ self as ffi::pa_channel_position_t -+ } -+} -+pub type Result = ::std::result::Result; -+ -+pub trait CVolumeExt { -+ fn set(&mut self, channels: c_uint, v: Volume); -+ fn set_balance(&mut self, map: &ChannelMap, new_balance: f32); -+} -+ -+impl CVolumeExt for CVolume { -+ fn set(&mut self, channels: c_uint, v: Volume) { -+ unsafe { -+ ffi::pa_cvolume_set(self, channels, v); -+ } -+ } -+ -+ fn set_balance(&mut self, map: &ChannelMap, new_balance: f32) { -+ unsafe { -+ ffi::pa_cvolume_set_balance(self, map, new_balance); -+ } -+ } -+} -+ -+pub trait ChannelMapExt { -+ fn init() -> ChannelMap; -+ fn can_balance(&self) -> bool; -+} -+ -+impl ChannelMapExt for ChannelMap { -+ fn init() -> ChannelMap { -+ let mut cm = ChannelMap::default(); -+ unsafe { -+ ffi::pa_channel_map_init(&mut cm); -+ } -+ cm -+ } -+ fn can_balance(&self) -> bool { -+ unsafe { ffi::pa_channel_map_can_balance(self) > 0 } -+ } -+} -+ -+pub trait ProplistExt { -+ fn proplist(&self) -> Proplist; -+} -+ -+impl ProplistExt for SinkInfo { -+ fn proplist(&self) -> Proplist { -+ unsafe { proplist::from_raw_ptr(self.proplist) } -+ } -+} -+ -+impl ProplistExt for SourceInfo { -+ fn proplist(&self) -> Proplist { -+ unsafe { proplist::from_raw_ptr(self.proplist) } -+ } -+} -+ -+pub trait SampleSpecExt { -+ fn frame_size(&self) -> usize; -+} -+ -+impl SampleSpecExt for SampleSpec { -+ fn frame_size(&self) -> usize { -+ unsafe { ffi::pa_frame_size(self) } -+ } -+} -+ -+pub trait USecExt { -+ fn to_bytes(self, spec: &SampleSpec) -> usize; -+} -+ -+impl USecExt for USec { -+ fn to_bytes(self, spec: &SampleSpec) -> usize { -+ unsafe { ffi::pa_usec_to_bytes(self, spec) } -+ } -+} -+ -+pub fn library_version() -> *const c_char { -+ unsafe { ffi::pa_get_library_version() } -+} -+ -+pub fn sw_volume_from_linear(vol: f64) -> Volume { -+ unsafe { ffi::pa_sw_volume_from_linear(vol) } -+} -+ -+pub fn rtclock_now() -> USec { -+ unsafe { ffi::pa_rtclock_now() } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/mainloop_api.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,58 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::mem; -+use std::os::raw::c_void; -+ -+ -+#[allow(non_camel_case_types)] -+type pa_once_cb_t = Option; -+fn wrap_once_cb(_: F) -> pa_once_cb_t -+ where F: Fn(&MainloopApi, *mut c_void) -+{ -+ assert!(mem::size_of::() == 0); -+ -+ unsafe extern "C" fn wrapped(m: *mut ffi::pa_mainloop_api, userdata: *mut c_void) -+ where F: Fn(&MainloopApi, *mut c_void) -+ { -+ let api = from_raw_ptr(m); -+ let result = mem::transmute::<_, &F>(&())(&api, userdata); -+ mem::forget(api); -+ result -+ } -+ -+ Some(wrapped::) -+} -+ -+pub struct MainloopApi(*mut ffi::pa_mainloop_api); -+ -+impl MainloopApi { -+ pub fn raw_mut(&self) -> &mut ffi::pa_mainloop_api { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn once(&self, cb: CB, userdata: *mut c_void) -+ where CB: Fn(&MainloopApi, *mut c_void) -+ { -+ let wrapped = wrap_once_cb(cb); -+ unsafe { -+ ffi::pa_mainloop_api_once(self.raw_mut(), wrapped, userdata); -+ } -+ } -+ -+ pub fn time_free(&self, e: *mut ffi::pa_time_event) { -+ unsafe { -+ if let Some(f) = self.raw_mut().time_free { -+ f(e); -+ } -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_mainloop_api) -> MainloopApi { -+ MainloopApi(raw) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/operation.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,43 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+ -+#[derive(Debug)] -+pub struct Operation(*mut ffi::pa_operation); -+ -+impl Operation { -+ pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_operation) -> Operation { -+ Operation(raw) -+ } -+ -+ pub fn cancel(&mut self) { -+ unsafe { -+ ffi::pa_operation_cancel(self.0); -+ } -+ } -+ -+ pub fn get_state(&self) -> ffi::pa_operation_state_t { -+ unsafe { ffi::pa_operation_get_state(self.0) } -+ } -+} -+ -+impl Clone for Operation { -+ fn clone(&self) -> Self { -+ Operation(unsafe { ffi::pa_operation_ref(self.0) }) -+ } -+} -+ -+impl Drop for Operation { -+ fn drop(&mut self) { -+ unsafe { -+ ffi::pa_operation_unref(self.0); -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_operation) -> Operation { -+ Operation::from_raw_ptr(raw) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs.cubeb-pulse-arm 2017-08-04 13:37:46.385821734 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/proplist.rs 2017-08-04 13:37:46.385821734 +0200 -@@ -0,0 +1,31 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ffi; -+use std::ffi::{CStr, CString}; -+ -+#[derive(Debug)] -+pub struct Proplist(*mut ffi::pa_proplist); -+ -+impl Proplist { -+ pub fn gets(&self, key: T) -> Option<&CStr> -+ where T: Into> -+ { -+ let key = match CString::new(key) { -+ Ok(k) => k, -+ _ => return None, -+ }; -+ let r = unsafe { ffi::pa_proplist_gets(self.0, key.as_ptr()) }; -+ if r.is_null() { -+ None -+ } else { -+ Some(unsafe { CStr::from_ptr(r) }) -+ } -+ } -+} -+ -+pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_proplist) -> Proplist { -+ return Proplist(raw); -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/stream.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,367 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ::*; -+use context; -+use ffi; -+use operation; -+use std::ffi::CStr; -+use std::mem; -+use std::os::raw::{c_int, c_void}; -+use std::ptr; -+use util::*; -+ -+#[derive(Debug)] -+pub struct Stream(*mut ffi::pa_stream); -+ -+impl Stream { -+ pub fn new<'a, CM>(c: &Context, name: &::std::ffi::CStr, ss: &SampleSpec, map: CM) -> Option -+ where CM: Into> -+ { -+ let ptr = unsafe { -+ ffi::pa_stream_new(c.raw_mut(), -+ name.as_ptr(), -+ ss as *const _, -+ to_ptr(map.into())) -+ }; -+ if ptr.is_null() { -+ None -+ } else { -+ Some(Stream(ptr)) -+ } -+ } -+ -+ #[doc(hidden)] -+ pub fn raw_mut(&self) -> &mut ffi::pa_stream { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn unref(self) { -+ unsafe { -+ ffi::pa_stream_unref(self.raw_mut()); -+ } -+ } -+ -+ pub fn get_state(&self) -> StreamState { -+ StreamState::try_from(unsafe { -+ ffi::pa_stream_get_state(self.raw_mut()) -+ }).expect("pa_stream_get_state returned invalid StreamState") -+ } -+ -+ pub fn get_context(&self) -> Option { -+ let ptr = unsafe { ffi::pa_stream_get_context(self.raw_mut()) }; -+ if ptr.is_null() { -+ return None; -+ } -+ -+ let ctx = unsafe { context::from_raw_ptr(ptr) }; -+ Some(ctx) -+ } -+ -+ pub fn get_index(&self) -> u32 { -+ unsafe { ffi::pa_stream_get_index(self.raw_mut()) } -+ } -+ -+ pub fn get_device_name<'a>(&'a self) -> Result<&'a CStr> { -+ let r = unsafe { ffi::pa_stream_get_device_name(self.raw_mut()) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { CStr::from_ptr(r) }) -+ } -+ -+ pub fn is_suspended(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_is_suspended(self.raw_mut()) }; -+ error_result!(r != 0, r) -+ } -+ -+ pub fn is_corked(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_is_corked(self.raw_mut()) }; -+ error_result!(r != 0, r) -+ } -+ -+ pub fn connect_playback<'a, D, A, V, S>(&self, -+ dev: D, -+ attr: A, -+ flags: StreamFlags, -+ volume: V, -+ sync_stream: S) -+ -> Result<()> -+ where D: Into>, -+ A: Into>, -+ V: Into>, -+ S: Into> -+ { -+ let r = unsafe { -+ ffi::pa_stream_connect_playback(self.raw_mut(), -+ str_to_ptr(dev.into()), -+ to_ptr(attr.into()), -+ flags.into(), -+ to_ptr(volume.into()), -+ map_to_mut_ptr(sync_stream.into(), |p| p.0)) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn connect_record<'a, D, A>(&self, dev: D, attr: A, flags: StreamFlags) -> Result<()> -+ where D: Into>, -+ A: Into> -+ { -+ let r = unsafe { -+ ffi::pa_stream_connect_record(self.raw_mut(), -+ str_to_ptr(dev.into()), -+ to_ptr(attr.into()), -+ flags.into()) -+ }; -+ error_result!((), r) -+ } -+ -+ pub fn disconnect(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_disconnect(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn begin_write(&self, req_bytes: usize) -> Result<(*mut c_void, usize)> { -+ let mut data: *mut c_void = ptr::null_mut(); -+ let mut nbytes = req_bytes; -+ let r = unsafe { ffi::pa_stream_begin_write(self.raw_mut(), &mut data, &mut nbytes) }; -+ error_result!((data, nbytes), r) -+ } -+ -+ pub fn cancel_write(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_cancel_write(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn write(&self, data: *const c_void, nbytes: usize, offset: i64, seek: SeekMode) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_write(self.raw_mut(), data, nbytes, None, offset, seek.into()) }; -+ error_result!((), r) -+ } -+ -+ pub unsafe fn peek(&self, data: *mut *const c_void, length: *mut usize) -> Result<()> { -+ let r = ffi::pa_stream_peek(self.raw_mut(), data, length); -+ error_result!((), r) -+ } -+ -+ pub fn drop(&self) -> Result<()> { -+ let r = unsafe { ffi::pa_stream_drop(self.raw_mut()) }; -+ error_result!((), r) -+ } -+ -+ pub fn writable_size(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_writable_size(self.raw_mut()) }; -+ if r == ::std::usize::MAX { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(r) -+ } -+ -+ pub fn readable_size(&self) -> Result { -+ let r = unsafe { ffi::pa_stream_readable_size(self.raw_mut()) }; -+ if r == ::std::usize::MAX { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(r) -+ } -+ -+ pub fn update_timing_info(&self, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Stream, i32, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Stream, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, success, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ let r = unsafe { ffi::pa_stream_update_timing_info(self.raw_mut(), Some(wrapped::), userdata) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { operation::from_raw_ptr(r) }) -+ } -+ -+ pub fn clear_state_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_state_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_state_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, userdata: *mut c_void) -+ where F: Fn(&Stream, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_state_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn clear_write_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_write_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_write_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, usize, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void) -+ where F: Fn(&Stream, usize, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, nbytes, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_write_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn clear_read_callback(&self) { -+ unsafe { -+ ffi::pa_stream_set_read_callback(self.raw_mut(), None, ptr::null_mut()); -+ } -+ } -+ -+ pub fn set_read_callback(&self, _: CB, userdata: *mut c_void) -+ where CB: Fn(&Stream, usize, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, nbytes: usize, userdata: *mut c_void) -+ where F: Fn(&Stream, usize, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, nbytes, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ unsafe { -+ ffi::pa_stream_set_read_callback(self.raw_mut(), Some(wrapped::), userdata); -+ } -+ } -+ -+ pub fn cork(&self, b: i32, _: CB, userdata: *mut c_void) -> Result -+ where CB: Fn(&Stream, i32, *mut c_void) -+ { -+ debug_assert_eq!(mem::size_of::(), 0); -+ -+ // See: A note about `wrapped` functions -+ unsafe extern "C" fn wrapped(s: *mut ffi::pa_stream, success: c_int, userdata: *mut c_void) -+ where F: Fn(&Stream, i32, *mut c_void) -+ { -+ use std::mem::{forget, uninitialized}; -+ let mut stm = stream::from_raw_ptr(s); -+ let result = uninitialized::()(&mut stm, success, userdata); -+ forget(stm); -+ -+ result -+ } -+ -+ let r = unsafe { ffi::pa_stream_cork(self.raw_mut(), b, Some(wrapped::), userdata) }; -+ if r.is_null() { -+ let err = if let Some(c) = self.get_context() { -+ c.errno() -+ } else { -+ ffi::PA_ERR_UNKNOWN -+ }; -+ return Err(ErrorCode::from_error_code(err)); -+ } -+ Ok(unsafe { operation::from_raw_ptr(r) }) -+ } -+ -+ pub fn get_time(&self) -> Result<(u64)> { -+ let mut usec: u64 = 0; -+ let r = unsafe { ffi::pa_stream_get_time(self.raw_mut(), &mut usec) }; -+ error_result!(usec, r) -+ } -+ -+ pub fn get_latency(&self) -> Result<(u64, bool)> { -+ let mut usec: u64 = 0; -+ let mut negative: i32 = 0; -+ let r = unsafe { ffi::pa_stream_get_latency(self.raw_mut(), &mut usec, &mut negative) }; -+ error_result!((usec, negative != 0), r) -+ } -+ -+ pub fn get_sample_spec(&self) -> &SampleSpec { -+ unsafe { -+ let ptr = ffi::pa_stream_get_sample_spec(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+ -+ pub fn get_channel_map(&self) -> &ChannelMap { -+ unsafe { -+ let ptr = ffi::pa_stream_get_channel_map(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+ -+ pub fn get_buffer_attr(&self) -> &BufferAttr { -+ unsafe { -+ let ptr = ffi::pa_stream_get_buffer_attr(self.raw_mut()); -+ debug_assert!(!ptr.is_null()); -+ &*ptr -+ } -+ } -+} -+ -+#[doc(hidden)] -+pub unsafe fn from_raw_ptr(ptr: *mut ffi::pa_stream) -> Stream { -+ Stream(ptr) -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/threaded_mainloop.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,92 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use ErrorCode; -+use Result; -+use ffi; -+use mainloop_api; -+use mainloop_api::MainloopApi; -+ -+#[derive(Debug)] -+pub struct ThreadedMainloop(*mut ffi::pa_threaded_mainloop); -+ -+impl ThreadedMainloop { -+ pub unsafe fn from_raw_ptr(raw: *mut ffi::pa_threaded_mainloop) -> Self { -+ ThreadedMainloop(raw) -+ } -+ -+ pub fn new() -> Self { -+ unsafe { ThreadedMainloop::from_raw_ptr(ffi::pa_threaded_mainloop_new()) } -+ } -+ -+ pub fn raw_mut(&self) -> &mut ffi::pa_threaded_mainloop { -+ unsafe { &mut *self.0 } -+ } -+ -+ pub fn is_null(&self) -> bool { -+ self.0.is_null() -+ } -+ -+ pub fn start(&self) -> Result<()> { -+ match unsafe { ffi::pa_threaded_mainloop_start(self.raw_mut()) } { -+ 0 => Ok(()), -+ _ => Err(ErrorCode::from_error_code(ffi::PA_ERR_UNKNOWN)), -+ } -+ } -+ -+ pub fn stop(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_stop(self.raw_mut()); -+ } -+ } -+ -+ pub fn lock(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_lock(self.raw_mut()); -+ } -+ } -+ -+ pub fn unlock(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_unlock(self.raw_mut()); -+ } -+ } -+ -+ pub fn wait(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_wait(self.raw_mut()); -+ } -+ } -+ -+ pub fn signal(&self) { -+ unsafe { -+ ffi::pa_threaded_mainloop_signal(self.raw_mut(), 0); -+ } -+ } -+ -+ pub fn get_api(&self) -> MainloopApi { -+ unsafe { mainloop_api::from_raw_ptr(ffi::pa_threaded_mainloop_get_api(self.raw_mut())) } -+ } -+ -+ pub fn in_thread(&self) -> bool { -+ unsafe { ffi::pa_threaded_mainloop_in_thread(self.raw_mut()) != 0 } -+ } -+} -+ -+impl ::std::default::Default for ThreadedMainloop { -+ fn default() -> Self { -+ ThreadedMainloop(::std::ptr::null_mut()) -+ } -+} -+ -+impl ::std::ops::Drop for ThreadedMainloop { -+ fn drop(&mut self) { -+ if !self.is_null() { -+ unsafe { -+ ffi::pa_threaded_mainloop_free(self.raw_mut()); -+ } -+ } -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs.cubeb-pulse-arm 2017-08-04 13:37:46.386821731 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/pulse-rs/src/util.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -0,0 +1,41 @@ -+// Copyright © 2017 Mozilla Foundation -+// -+// This program is made available under an ISC-style license. See the -+// accompanying file LICENSE for details. -+ -+use std::ffi::CStr; -+use std::os::raw::c_char; -+use std::ptr; -+ -+pub trait UnwrapCStr { -+ fn unwrap_cstr(self) -> *const c_char; -+} -+ -+impl<'a, U> UnwrapCStr for U -+ where U: Into> -+{ -+ fn unwrap_cstr(self) -> *const c_char { -+ self.into().map(|o| o.as_ptr()).unwrap_or(0 as *const _) -+ } -+} -+ -+pub fn map_to_mut_ptr *mut U>(t: Option<&mut T>, f: F) -> *mut U { -+ match t { -+ Some(x) => f(x), -+ None => ptr::null_mut(), -+ } -+} -+ -+pub fn str_to_ptr(s: Option<&CStr>) -> *const c_char { -+ match s { -+ Some(x) => x.as_ptr(), -+ None => ptr::null(), -+ } -+} -+ -+pub fn to_ptr(t: Option<&T>) -> *const T { -+ match t { -+ Some(x) => x as *const T, -+ None => ptr::null(), -+ } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/README.md 2017-08-04 13:37:46.383821740 +0200 -@@ -3,3 +3,4 @@ - Implementation of PulseAudio backend for Cubeb written in Rust. - - [![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=master)](https://travis-ci.org/djg/cubeb-pulse-rs) -+[![Travis Build Status](https://travis-ci.org/djg/cubeb-pulse-rs.svg?branch=dev)](https://travis-ci.org/djg/cubeb-pulse-rs) -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/README_MOZILLA 2017-08-04 13:37:46.383821740 +0200 -@@ -5,4 +5,4 @@ Makefile.in build files for the Mozilla - - The cubeb-pulse-rs git repository is: https://github.com/djg/cubeb-pulse-rs.git - --The git commit ID used was dbcd7f96aea8d249a4b78f9a7597768c9dff22eb (2017-04-25 11:42:10 +1000) -+The git commit ID used was 64515819cdf54a16626df5dce5f5c7cb1220d53b (2017-06-19 17:41:30 +1000) -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/context.rs 2017-08-04 13:50:38.145480458 +0200 -@@ -4,67 +4,60 @@ - // accompanying file LICENSE for details. - - use backend::*; --use backend::cork_state::CorkState; - use capi::PULSE_OPS; - use cubeb; -+use pulse::{self, ProplistExt}; - use pulse_ffi::*; - use semver; - use std::default::Default; --use std::ffi::CStr; -+use std::ffi::{CStr, CString}; - use std::mem; --use std::os::raw::{c_char, c_int, c_void}; -+use std::os::raw::{c_char, c_void}; - use std::ptr; - --macro_rules! dup_str { -- ($Dst: expr, $Src: expr) => { -- if !$Dst.is_null() { -- pa_xfree($Dst as *mut _); -- } -- -- $Dst = pa_xstrdup($Src); -- } --} -- --fn pa_channel_to_cubeb_channel(channel: pa_channel_position_t) -> cubeb::Channel { -- assert_ne!(channel, PA_CHANNEL_POSITION_INVALID); -+fn pa_channel_to_cubeb_channel(channel: pulse::ChannelPosition) -> cubeb::Channel { -+ use pulse::ChannelPosition; -+ assert_ne!(channel, ChannelPosition::Invalid); - match channel { -- PA_CHANNEL_POSITION_MONO => cubeb::CHANNEL_MONO, -- PA_CHANNEL_POSITION_FRONT_LEFT => cubeb::CHANNEL_LEFT, -- PA_CHANNEL_POSITION_FRONT_RIGHT => cubeb::CHANNEL_RIGHT, -- PA_CHANNEL_POSITION_FRONT_CENTER => cubeb::CHANNEL_CENTER, -- PA_CHANNEL_POSITION_SIDE_LEFT => cubeb::CHANNEL_LS, -- PA_CHANNEL_POSITION_SIDE_RIGHT => cubeb::CHANNEL_RS, -- PA_CHANNEL_POSITION_REAR_LEFT => cubeb::CHANNEL_RLS, -- PA_CHANNEL_POSITION_REAR_CENTER => cubeb::CHANNEL_RCENTER, -- PA_CHANNEL_POSITION_REAR_RIGHT => cubeb::CHANNEL_RRS, -- PA_CHANNEL_POSITION_LFE => cubeb::CHANNEL_LFE, -+ ChannelPosition::Mono => cubeb::CHANNEL_MONO, -+ ChannelPosition::FrontLeft => cubeb::CHANNEL_LEFT, -+ ChannelPosition::FrontRight => cubeb::CHANNEL_RIGHT, -+ ChannelPosition::FrontCenter => cubeb::CHANNEL_CENTER, -+ ChannelPosition::SideLeft => cubeb::CHANNEL_LS, -+ ChannelPosition::SideRight => cubeb::CHANNEL_RS, -+ ChannelPosition::RearLeft => cubeb::CHANNEL_RLS, -+ ChannelPosition::RearCenter => cubeb::CHANNEL_RCENTER, -+ ChannelPosition::RearRight => cubeb::CHANNEL_RRS, -+ ChannelPosition::LowFreqEffects => cubeb::CHANNEL_LFE, - _ => cubeb::CHANNEL_INVALID, - } - } - --fn channel_map_to_layout(cm: &pa_channel_map) -> cubeb::ChannelLayout { -+fn channel_map_to_layout(cm: &pulse::ChannelMap) -> cubeb::ChannelLayout { -+ use pulse::ChannelPosition; - let mut cubeb_map: cubeb::ChannelMap = Default::default(); - cubeb_map.channels = cm.channels as u32; - for i in 0usize..cm.channels as usize { -- cubeb_map.map[i] = pa_channel_to_cubeb_channel(cm.map[i]); -+ cubeb_map.map[i] = pa_channel_to_cubeb_channel(ChannelPosition::try_from(cm.map[i]) -+ .unwrap_or(ChannelPosition::Invalid)); - } - unsafe { cubeb::cubeb_channel_map_to_layout(&cubeb_map) } - } - - #[derive(Debug)] - pub struct DefaultInfo { -- pub sample_spec: pa_sample_spec, -- pub channel_map: pa_channel_map, -- pub flags: pa_sink_flags_t, -+ pub sample_spec: pulse::SampleSpec, -+ pub channel_map: pulse::ChannelMap, -+ pub flags: pulse::SinkFlags, - } - - #[derive(Debug)] - pub struct Context { - pub ops: *const cubeb::Ops, -- pub mainloop: *mut pa_threaded_mainloop, -- pub context: *mut pa_context, -+ pub mainloop: pulse::ThreadedMainloop, -+ pub context: Option, - pub default_sink_info: Option, -- pub context_name: *const c_char, -+ pub context_name: Option, - pub collection_changed_callback: cubeb::DeviceCollectionChangedCallback, - pub collection_changed_user_ptr: *mut c_void, - pub error: bool, -@@ -82,7 +75,7 @@ impl Drop for Context { - - impl Context { - #[cfg(feature = "pulse-dlopen")] -- fn _new(name: *const i8) -> Result> { -+ fn _new(name: Option) -> Result> { - let libpulse = unsafe { open() }; - if libpulse.is_none() { - return Err(cubeb::ERROR); -@@ -91,12 +84,12 @@ impl Context { - let ctx = Box::new(Context { - ops: &PULSE_OPS, - libpulse: libpulse.unwrap(), -- mainloop: unsafe { pa_threaded_mainloop_new() }, -- context: 0 as *mut _, -+ mainloop: pulse::ThreadedMainloop::new(), -+ context: None, - default_sink_info: None, - context_name: name, - collection_changed_callback: None, -- collection_changed_user_ptr: 0 as *mut _, -+ collection_changed_user_ptr: ptr::null_mut(), - error: true, - version_0_9_8: false, - version_2_0_0: false, -@@ -106,15 +99,15 @@ impl Context { - } - - #[cfg(not(feature = "pulse-dlopen"))] -- fn _new(name: *const i8) -> Result> { -+ fn _new(name: Option) -> Result> { - Ok(Box::new(Context { - ops: &PULSE_OPS, -- mainloop: unsafe { pa_threaded_mainloop_new() }, -- context: 0 as *mut _, -+ mainloop: pulse::ThreadedMainloop::new(), -+ context: None, - default_sink_info: None, - context_name: name, - collection_changed_callback: None, -- collection_changed_user_ptr: 0 as *mut _, -+ collection_changed_user_ptr: ptr::null_mut(), - error: true, - version_0_9_8: false, - version_2_0_0: false, -@@ -122,53 +115,66 @@ impl Context { - } - - pub fn new(name: *const c_char) -> Result> { -+ fn server_info_cb(context: &pulse::Context, info: &pulse::ServerInfo, u: *mut c_void) { -+ fn sink_info_cb(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, u: *mut c_void) { -+ let mut ctx = unsafe { &mut *(u as *mut Context) }; -+ if eol == 0 { -+ let info = unsafe { &*i }; -+ let flags = pulse::SinkFlags::try_from(info.flags).expect("SinkInfo contains invalid flags"); -+ ctx.default_sink_info = Some(DefaultInfo { -+ sample_spec: info.sample_spec, -+ channel_map: info.channel_map, -+ flags: flags, -+ }); -+ } -+ ctx.mainloop.signal(); -+ } -+ -+ let _ = context.get_sink_info_by_name(unsafe { CStr::from_ptr(info.default_sink_name) }, -+ sink_info_cb, -+ u); -+ } -+ -+ let name = super::try_cstr_from(name).map(|s| s.to_owned()); - let mut ctx = try!(Context::_new(name)); - -- unsafe { pa_threaded_mainloop_start(ctx.mainloop) }; -+ if ctx.mainloop.start().is_err() { -+ ctx.destroy(); -+ return Err(cubeb::ERROR); -+ } - -- if ctx.pulse_context_init() != cubeb::OK { -+ if ctx.context_init() != cubeb::OK { - ctx.destroy(); - return Err(cubeb::ERROR); - } - -- unsafe { -- /* server_info_callback performs a second async query, -- * which is responsible for initializing default_sink_info -- * and signalling the mainloop to end the wait. */ -- pa_threaded_mainloop_lock(ctx.mainloop); -- let o = pa_context_get_server_info(ctx.context, -- Some(server_info_callback), -- ctx.as_mut() as *mut Context as *mut _); -- if !o.is_null() { -- ctx.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ ctx.mainloop.lock(); -+ /* server_info_callback performs a second async query, -+ * which is responsible for initializing default_sink_info -+ * and signalling the mainloop to end the wait. */ -+ let user_data: *mut c_void = ctx.as_mut() as *mut _ as *mut _; -+ if let Some(ref context) = ctx.context { -+ if let Ok(o) = context.get_server_info(server_info_cb, user_data) { -+ ctx.operation_wait(None, &o); - } -- pa_threaded_mainloop_unlock(ctx.mainloop); -- assert!(ctx.default_sink_info.is_some()); - } -+ assert!(ctx.default_sink_info.is_some()); -+ ctx.mainloop.unlock(); - - // Return the result. - Ok(ctx) - } - - pub fn destroy(&mut self) { -- if !self.context.is_null() { -- unsafe { self.pulse_context_destroy() }; -- } -- assert!(self.context.is_null()); -+ self.context_destroy(); - - if !self.mainloop.is_null() { -- unsafe { -- pa_threaded_mainloop_stop(self.mainloop); -- pa_threaded_mainloop_free(self.mainloop); -- self.mainloop = ptr::null_mut(); -- } -+ self.mainloop.stop(); - } -- assert!(self.mainloop.is_null()); - } - - pub fn new_stream(&mut self, -- stream_name: *const c_char, -+ stream_name: &CStr, - input_device: cubeb::DeviceId, - input_stream_params: Option, - output_device: cubeb::DeviceId, -@@ -178,7 +184,7 @@ impl Context { - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void) - -> Result> { -- if self.error && self.pulse_context_init() != 0 { -+ if self.error && self.context_init() != 0 { - return Err(cubeb::ERROR); - } - -@@ -221,41 +227,151 @@ impl Context { - } - - pub fn enumerate_devices(&self, devtype: cubeb::DeviceType) -> Result { -- let mut user_data: PulseDevListData = Default::default(); -- user_data.context = self as *const _ as *mut _; -+ fn add_output_device(_: &pulse::Context, i: *const pulse::SinkInfo, eol: i32, user_data: *mut c_void) { -+ if eol != 0 { -+ return; -+ } - -- unsafe { -- pa_threaded_mainloop_lock(self.mainloop); -+ debug_assert!(!i.is_null()); -+ debug_assert!(!user_data.is_null()); -+ -+ let mut list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ let info = unsafe { &*i }; -+ -+ let group_id = match info.proplist().gets("sysfs.path") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let vendor_name = match info.proplist().gets("device.vendor.name") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned(); -+ let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned(); -+ -+ let preferred = if info_name == list_data.default_sink_name { -+ cubeb::DEVICE_PREF_ALL -+ } else { -+ cubeb::DevicePref::empty() -+ }; -+ -+ let ctx = &(*list_data.context); -+ -+ let device_id = info_name.into_raw(); -+ let friendly_name = info_description.into_raw(); -+ let devinfo = cubeb::DeviceInfo { -+ device_id: device_id, -+ devid: device_id as cubeb::DeviceId, -+ friendly_name: friendly_name, -+ group_id: group_id, -+ vendor_name: vendor_name, -+ devtype: cubeb::DEVICE_TYPE_OUTPUT, -+ state: ctx.state_from_port(info.active_port), -+ preferred: preferred, -+ format: cubeb::DeviceFmt::all(), -+ default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -+ max_channels: info.channel_map.channels as u32, -+ min_rate: 1, -+ max_rate: PA_RATE_MAX, -+ default_rate: info.sample_spec.rate, -+ latency_lo: 0, -+ latency_hi: 0, -+ }; -+ list_data.devinfo.push(devinfo); -+ -+ ctx.mainloop.signal(); -+ } -+ -+ fn add_input_device(_: &pulse::Context, i: *const pulse::SourceInfo, eol: i32, user_data: *mut c_void) { -+ if eol != 0 { -+ return; -+ } -+ -+ debug_assert!(!user_data.is_null()); -+ debug_assert!(!i.is_null()); -+ -+ let mut list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ let info = unsafe { &*i }; -+ -+ let group_id = match info.proplist().gets("sysfs.path") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; -+ -+ let vendor_name = match info.proplist().gets("device.vendor.name") { -+ Some(p) => p.to_owned().into_raw(), -+ _ => ptr::null_mut(), -+ }; - -- let o = pa_context_get_server_info(self.context, -- Some(pulse_server_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ let info_name = unsafe { CStr::from_ptr(info.name) }.to_owned(); -+ let info_description = unsafe { CStr::from_ptr(info.description) }.to_owned(); -+ -+ let preferred = if info_name == list_data.default_source_name { -+ cubeb::DEVICE_PREF_ALL -+ } else { -+ cubeb::DevicePref::empty() -+ }; -+ -+ let ctx = &(*list_data.context); -+ let device_id = info_name.into_raw(); -+ let friendly_name = info_description.into_raw(); -+ let devinfo = cubeb::DeviceInfo { -+ device_id: device_id, -+ devid: device_id as cubeb::DeviceId, -+ friendly_name: friendly_name, -+ group_id: group_id, -+ vendor_name: vendor_name, -+ devtype: cubeb::DEVICE_TYPE_INPUT, -+ state: ctx.state_from_port(info.active_port), -+ preferred: preferred, -+ format: cubeb::DeviceFmt::all(), -+ default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -+ max_channels: info.channel_map.channels as u32, -+ min_rate: 1, -+ max_rate: PA_RATE_MAX, -+ default_rate: info.sample_spec.rate, -+ latency_lo: 0, -+ latency_hi: 0, -+ }; -+ -+ list_data.devinfo.push(devinfo); -+ -+ ctx.mainloop.signal(); -+ } -+ -+ fn default_device_names(_: &pulse::Context, info: &pulse::ServerInfo, user_data: *mut c_void) { -+ let list_data = unsafe { &mut *(user_data as *mut PulseDevListData) }; -+ -+ list_data.default_sink_name = unsafe { CStr::from_ptr(info.default_sink_name) }.to_owned(); -+ list_data.default_source_name = unsafe { CStr::from_ptr(info.default_source_name) }.to_owned(); -+ -+ (*list_data.context).mainloop.signal(); -+ } -+ -+ let mut user_data = PulseDevListData::new(self); -+ -+ if let Some(ref context) = self.context { -+ self.mainloop.lock(); -+ -+ if let Ok(o) = context.get_server_info(default_device_names, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - - if devtype == cubeb::DEVICE_TYPE_OUTPUT { -- let o = pa_context_get_sink_info_list(self.context, -- Some(pulse_sink_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ if let Ok(o) = context.get_sink_info_list(add_output_device, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - } - - if devtype == cubeb::DEVICE_TYPE_INPUT { -- let o = pa_context_get_source_info_list(self.context, -- Some(pulse_source_info_cb), -- &mut user_data as *mut _ as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -+ if let Ok(o) = context.get_source_info_list(add_input_device, &mut user_data as *mut _ as *mut _) { -+ self.operation_wait(None, &o); - } - } - -- pa_threaded_mainloop_unlock(self.mainloop); -+ self.mainloop.unlock(); - } - - // Extract the array of cubeb_device_info from -@@ -282,16 +398,16 @@ impl Context { - coll.count); - for dev in devices.iter_mut() { - if !dev.device_id.is_null() { -- pa_xfree(dev.device_id as *mut _); -+ let _ = CString::from_raw(dev.device_id as *mut _); - } - if !dev.group_id.is_null() { -- pa_xfree(dev.group_id as *mut _); -+ let _ = CString::from_raw(dev.group_id as *mut _); - } - if !dev.vendor_name.is_null() { -- pa_xfree(dev.vendor_name as *mut _); -+ let _ = CString::from_raw(dev.vendor_name as *mut _); - } - if !dev.friendly_name.is_null() { -- pa_xfree(dev.friendly_name as *mut _); -+ let _ = CString::from_raw(dev.friendly_name as *mut _); - } - } - } -@@ -302,115 +418,125 @@ impl Context { - cb: cubeb::DeviceCollectionChangedCallback, - user_ptr: *mut c_void) - -> i32 { -- unsafe extern "C" fn subscribe_success(_: *mut pa_context, success: i32, user_data: *mut c_void) { -- let ctx = &*(user_data as *mut Context); -+ fn update_collection(_: &pulse::Context, event: pulse::SubscriptionEvent, index: u32, user_data: *mut c_void) { -+ let mut ctx = unsafe { &mut *(user_data as *mut Context) }; -+ -+ let (f, t) = (event.event_facility(), event.event_type()); -+ match f { -+ pulse::SubscriptionEventFacility::Source | -+ pulse::SubscriptionEventFacility::Sink => { -+ match t { -+ pulse::SubscriptionEventType::Remove | -+ pulse::SubscriptionEventType::New => { -+ if cubeb::log_enabled() { -+ let op = if t == pulse::SubscriptionEventType::New { -+ "Adding" -+ } else { -+ "Removing" -+ }; -+ let dev = if f == pulse::SubscriptionEventFacility::Sink { -+ "sink" -+ } else { -+ "source " -+ }; -+ log!("{} {} index {}", op, dev, index); -+ -+ unsafe { -+ ctx.collection_changed_callback.unwrap()(ctx as *mut _ as *mut _, -+ ctx.collection_changed_user_ptr); -+ } -+ } -+ }, -+ _ => {}, -+ } -+ }, -+ _ => {}, -+ } -+ } -+ -+ fn success(_: &pulse::Context, success: i32, user_data: *mut c_void) { -+ let ctx = unsafe { &*(user_data as *mut Context) }; - debug_assert_ne!(success, 0); -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -+ ctx.mainloop.signal(); - } - - self.collection_changed_callback = cb; - self.collection_changed_user_ptr = user_ptr; - -- unsafe { -- pa_threaded_mainloop_lock(self.mainloop); -+ let user_data: *mut c_void = self as *mut _ as *mut _; -+ if let Some(ref context) = self.context { -+ self.mainloop.lock(); - -- let mut mask: pa_subscription_mask_t = PA_SUBSCRIPTION_MASK_NULL; -+ let mut mask = pulse::SubscriptionMask::empty(); - if self.collection_changed_callback.is_none() { - // Unregister subscription -- pa_context_set_subscribe_callback(self.context, None, ptr::null_mut()); -+ context.clear_subscribe_callback(); - } else { -- pa_context_set_subscribe_callback(self.context, -- Some(pulse_subscribe_callback), -- self as *mut _ as *mut _); -- if devtype == cubeb::DEVICE_TYPE_INPUT { -- mask |= PA_SUBSCRIPTION_MASK_SOURCE -+ context.set_subscribe_callback(update_collection, user_data); -+ if devtype.contains(cubeb::DEVICE_TYPE_INPUT) { -+ mask |= pulse::SUBSCRIPTION_MASK_SOURCE - }; -- if devtype == cubeb::DEVICE_TYPE_OUTPUT { -- mask |= PA_SUBSCRIPTION_MASK_SOURCE -+ if devtype.contains(cubeb::DEVICE_TYPE_OUTPUT) { -+ mask = pulse::SUBSCRIPTION_MASK_SINK - }; - } - -- let o = pa_context_subscribe(self.context, -- mask, -- Some(subscribe_success), -- self as *const _ as *mut _); -- if o.is_null() { -+ if let Ok(o) = context.subscribe(mask, success, self as *const _ as *mut _) { -+ self.operation_wait(None, &o); -+ } else { - log!("Context subscribe failed"); - return cubeb::ERROR; - } -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); - -- pa_threaded_mainloop_unlock(self.mainloop); -+ self.mainloop.unlock(); - } - - cubeb::OK - } - -- // -- -- pub fn pulse_stream_cork(&self, stream: *mut pa_stream, state: CorkState) { -- unsafe extern "C" fn cork_success(_: *mut pa_stream, _: i32, u: *mut c_void) { -- let mainloop = u as *mut pa_threaded_mainloop; -- pa_threaded_mainloop_signal(mainloop, 0); -+ pub fn context_init(&mut self) -> i32 { -+ fn error_state(c: &pulse::Context, u: *mut c_void) { -+ let mut ctx = unsafe { &mut *(u as *mut Context) }; -+ if !c.get_state().is_good() { -+ ctx.error = true; -+ } -+ ctx.mainloop.signal(); - } - -- if stream.is_null() { -- return; -+ if self.context.is_some() { -+ debug_assert!(self.error); -+ self.context_destroy(); - } - -- let o = unsafe { -- pa_stream_cork(stream, -- state.is_cork() as i32, -- Some(cork_success), -- self.mainloop as *mut _) -+ self.context = { -+ let name = match self.context_name.as_ref() { -+ Some(s) => Some(s.as_ref()), -+ None => None, -+ }; -+ pulse::Context::new(&self.mainloop.get_api(), name) - }; - -- if !o.is_null() { -- self.operation_wait(stream, o); -- unsafe { pa_operation_unref(o) }; -+ let context_ptr: *mut c_void = self as *mut _ as *mut _; -+ if self.context.is_none() { -+ return cubeb::ERROR; - } -- } - -- pub fn pulse_context_init(&mut self) -> i32 { -- unsafe extern "C" fn error_state(c: *mut pa_context, u: *mut c_void) { -- let mut ctx = &mut *(u as *mut Context); -- if !PA_CONTEXT_IS_GOOD(pa_context_get_state(c)) { -- ctx.error = true; -- } -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -+ self.mainloop.lock(); -+ if let Some(ref context) = self.context { -+ context.set_state_callback(error_state, context_ptr); -+ let _ = context.connect(None, pulse::ContextFlags::empty(), ptr::null()); - } - -- if !self.context.is_null() { -- debug_assert!(self.error); -- unsafe { self.pulse_context_destroy() }; -+ if !self.wait_until_context_ready() { -+ self.mainloop.unlock(); -+ self.context_destroy(); -+ return cubeb::ERROR; - } - -- unsafe { -- self.context = pa_context_new(pa_threaded_mainloop_get_api(self.mainloop), -- self.context_name); -- -- if self.context.is_null() { -- return cubeb::ERROR; -- } -- -- pa_context_set_state_callback(self.context, Some(error_state), self as *mut _ as *mut _); -- -- pa_threaded_mainloop_lock(self.mainloop); -- pa_context_connect(self.context, ptr::null(), 0, ptr::null()); -- -- if !self.wait_until_context_ready() { -- pa_threaded_mainloop_unlock(self.mainloop); -- self.pulse_context_destroy(); -- assert!(self.context.is_null()); -- return cubeb::ERROR; -- } -+ self.mainloop.unlock(); - -- pa_threaded_mainloop_unlock(self.mainloop); -- } -- -- let version_str = unsafe { CStr::from_ptr(pa_get_library_version()) }; -- if let Ok(version) = semver::Version::parse(version_str.to_string_lossy().as_ref()) { -+ let version_str = unsafe { CStr::from_ptr(pulse::library_version()) }; -+ if let Ok(version) = semver::Version::parse(&version_str.to_string_lossy()) { - self.version_0_9_8 = version >= semver::Version::parse("0.9.8").expect("Failed to parse version"); - self.version_2_0_0 = version >= semver::Version::parse("2.0.0").expect("Failed to parse version"); - } -@@ -420,34 +546,42 @@ impl Context { - cubeb::OK - } - -- unsafe fn pulse_context_destroy(&mut self) { -- unsafe extern "C" fn drain_complete(_c: *mut pa_context, u: *mut c_void) { -- let mainloop = u as *mut pa_threaded_mainloop; -- pa_threaded_mainloop_signal(mainloop, 0); -- } -- -- pa_threaded_mainloop_lock(self.mainloop); -- let o = pa_context_drain(self.context, Some(drain_complete), self.mainloop as *mut _); -- if !o.is_null() { -- self.operation_wait(ptr::null_mut(), o); -- pa_operation_unref(o); -- } -- pa_context_set_state_callback(self.context, None, ptr::null_mut()); -- pa_context_disconnect(self.context); -- pa_context_unref(self.context); -- self.context = ptr::null_mut(); -- pa_threaded_mainloop_unlock(self.mainloop); -+ fn context_destroy(&mut self) { -+ fn drain_complete(_: &pulse::Context, u: *mut c_void) { -+ let ctx = unsafe { &*(u as *mut Context) }; -+ ctx.mainloop.signal(); -+ } -+ -+ let context_ptr: *mut c_void = self as *mut _ as *mut _; -+ match self.context.take() { -+ Some(ctx) => { -+ self.mainloop.lock(); -+ if let Ok(o) = ctx.drain(drain_complete, context_ptr) { -+ self.operation_wait(None, &o); -+ } -+ ctx.clear_state_callback(); -+ ctx.disconnect(); -+ ctx.unref(); -+ self.mainloop.unlock(); -+ }, -+ _ => {}, -+ } - } - -- pub fn operation_wait(&self, stream: *mut pa_stream, o: *mut pa_operation) -> bool { -- unsafe { -- while pa_operation_get_state(o) == PA_OPERATION_RUNNING { -- pa_threaded_mainloop_wait(self.mainloop); -- if !PA_CONTEXT_IS_GOOD(pa_context_get_state(self.context)) { -+ pub fn operation_wait<'a, S>(&self, s: S, o: &pulse::Operation) -> bool -+ where S: Into> -+ { -+ let stream = s.into(); -+ while o.get_state() == PA_OPERATION_RUNNING { -+ self.mainloop.wait(); -+ if let Some(ref context) = self.context { -+ if !context.get_state().is_good() { - return false; - } -+ } - -- if !stream.is_null() && !PA_STREAM_IS_GOOD(pa_stream_get_state(stream)) { -+ if let Some(stm) = stream { -+ if !stm.get_state().is_good() { - return false; - } - } -@@ -457,36 +591,23 @@ impl Context { - } - - pub fn wait_until_context_ready(&self) -> bool { -- loop { -- let state = unsafe { pa_context_get_state(self.context) }; -- if !PA_CONTEXT_IS_GOOD(state) { -- return false; -- } -- if state == PA_CONTEXT_READY { -- break; -- } -- unsafe { -- pa_threaded_mainloop_wait(self.mainloop); -+ if let Some(ref context) = self.context { -+ loop { -+ let state = context.get_state(); -+ if !state.is_good() { -+ return false; -+ } -+ if state == pulse::ContextState::Ready { -+ break; -+ } -+ self.mainloop.wait(); - } - } - - true - } - -- fn state_from_sink_port(&self, i: *const pa_port_info) -> cubeb::DeviceState { -- if !i.is_null() { -- let info = unsafe { *i }; -- if self.version_2_0_0 && info.available == PA_PORT_AVAILABLE_NO { -- cubeb::DeviceState::Unplugged -- } else { -- cubeb::DeviceState::Enabled -- } -- } else { -- cubeb::DeviceState::Enabled -- } -- } -- -- fn state_from_source_port(&self, i: *mut pa_port_info) -> cubeb::DeviceState { -+ fn state_from_port(&self, i: *const pa_port_info) -> cubeb::DeviceState { - if !i.is_null() { - let info = unsafe { *i }; - if self.version_2_0_0 && info.available == PA_PORT_AVAILABLE_NO { -@@ -500,62 +621,30 @@ impl Context { - } - } - --// Callbacks --unsafe extern "C" fn server_info_callback(context: *mut pa_context, info: *const pa_server_info, u: *mut c_void) { -- unsafe extern "C" fn sink_info_callback(_context: *mut pa_context, -- info: *const pa_sink_info, -- eol: i32, -- u: *mut c_void) { -- let mut ctx = &mut *(u as *mut Context); -- if eol == 0 { -- let info = *info; -- ctx.default_sink_info = Some(DefaultInfo { -- sample_spec: info.sample_spec, -- channel_map: info.channel_map, -- flags: info.flags, -- }); -- } -- pa_threaded_mainloop_signal(ctx.mainloop, 0); -- } -- -- let o = pa_context_get_sink_info_by_name(context, -- (*info).default_sink_name, -- Some(sink_info_callback), -- u); -- if !o.is_null() { -- pa_operation_unref(o); -- } --} -- --struct PulseDevListData { -- default_sink_name: *mut c_char, -- default_source_name: *mut c_char, -+struct PulseDevListData<'a> { -+ default_sink_name: CString, -+ default_source_name: CString, - devinfo: Vec, -- context: *mut Context, -+ context: &'a Context, - } - --impl Drop for PulseDevListData { -- fn drop(&mut self) { -- if !self.default_sink_name.is_null() { -- unsafe { -- pa_xfree(self.default_sink_name as *mut _); -- } -- } -- if !self.default_source_name.is_null() { -- unsafe { -- pa_xfree(self.default_source_name as *mut _); -- } -+impl<'a> PulseDevListData<'a> { -+ pub fn new<'b>(context: &'b Context) -> Self -+ where 'b: 'a -+ { -+ PulseDevListData { -+ default_sink_name: CString::default(), -+ default_source_name: CString::default(), -+ devinfo: Vec::new(), -+ context: context, - } - } - } - --impl Default for PulseDevListData { -- fn default() -> Self { -- PulseDevListData { -- default_sink_name: ptr::null_mut(), -- default_source_name: ptr::null_mut(), -- devinfo: Vec::new(), -- context: ptr::null_mut(), -+impl<'a> Drop for PulseDevListData<'a> { -+ fn drop(&mut self) { -+ for elem in &mut self.devinfo { -+ let _ = unsafe { Box::from_raw(elem) }; - } - } - } -@@ -566,192 +655,7 @@ fn pulse_format_to_cubeb_format(format: - PA_SAMPLE_S16BE => cubeb::DEVICE_FMT_S16BE, - PA_SAMPLE_FLOAT32LE => cubeb::DEVICE_FMT_F32LE, - PA_SAMPLE_FLOAT32BE => cubeb::DEVICE_FMT_F32BE, -- _ => { -- panic!("Invalid format"); -- }, -+ // Unsupported format, return F32NE -+ _ => cubeb::CUBEB_FMT_F32NE, - } - } -- --unsafe extern "C" fn pulse_sink_info_cb(_context: *mut pa_context, -- i: *const pa_sink_info, -- eol: i32, -- user_data: *mut c_void) { -- if eol != 0 || i.is_null() { -- return; -- } -- -- debug_assert!(!user_data.is_null()); -- -- let info = *i; -- let mut list_data = &mut *(user_data as *mut PulseDevListData); -- -- let device_id = pa_xstrdup(info.name); -- -- let group_id = { -- let prop = pa_proplist_gets(info.proplist, b"sysfs.path\0".as_ptr() as *const c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let vendor_name = { -- let prop = pa_proplist_gets(info.proplist, -- b"device.vendor.name\0".as_ptr() as *const c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let preferred = if strcmp(info.name, list_data.default_sink_name) == 0 { -- cubeb::DEVICE_PREF_ALL -- } else { -- cubeb::DevicePref::empty() -- }; -- -- let ctx = &(*list_data.context); -- -- let devinfo = cubeb::DeviceInfo { -- device_id: device_id, -- devid: device_id as cubeb::DeviceId, -- friendly_name: pa_xstrdup(info.description), -- group_id: group_id, -- vendor_name: vendor_name, -- devtype: cubeb::DEVICE_TYPE_OUTPUT, -- state: ctx.state_from_sink_port(info.active_port), -- preferred: preferred, -- format: cubeb::DeviceFmt::all(), -- default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -- max_channels: info.channel_map.channels as u32, -- min_rate: 1, -- max_rate: PA_RATE_MAX, -- default_rate: info.sample_spec.rate, -- latency_lo: 0, -- latency_hi: 0, -- }; -- list_data.devinfo.push(devinfo); -- -- pa_threaded_mainloop_signal(ctx.mainloop, 0); --} -- --unsafe extern "C" fn pulse_source_info_cb(_context: *mut pa_context, -- i: *const pa_source_info, -- eol: i32, -- user_data: *mut c_void) { -- if eol != 0 || i.is_null() { -- return; -- } -- -- debug_assert!(!user_data.is_null()); -- -- let info = *i; -- let mut list_data = &mut *(user_data as *mut PulseDevListData); -- -- let device_id = pa_xstrdup(info.name); -- -- let group_id = { -- let prop = pa_proplist_gets(info.proplist, b"sysfs.path\0".as_ptr() as *mut c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let vendor_name = { -- let prop = pa_proplist_gets(info.proplist, -- b"device.vendor.name\0".as_ptr() as *mut c_char); -- if !prop.is_null() { -- pa_xstrdup(prop) -- } else { -- ptr::null_mut() -- } -- }; -- -- let preferred = if strcmp(info.name, list_data.default_source_name) == 0 { -- cubeb::DEVICE_PREF_ALL -- } else { -- cubeb::DevicePref::empty() -- }; -- -- let ctx = &(*list_data.context); -- -- let devinfo = cubeb::DeviceInfo { -- device_id: device_id, -- devid: device_id as cubeb::DeviceId, -- friendly_name: pa_xstrdup(info.description), -- group_id: group_id, -- vendor_name: vendor_name, -- devtype: cubeb::DEVICE_TYPE_INPUT, -- state: ctx.state_from_source_port(info.active_port), -- preferred: preferred, -- format: cubeb::DeviceFmt::all(), -- default_format: pulse_format_to_cubeb_format(info.sample_spec.format), -- max_channels: info.channel_map.channels as u32, -- min_rate: 1, -- max_rate: PA_RATE_MAX, -- default_rate: info.sample_spec.rate, -- latency_lo: 0, -- latency_hi: 0, -- }; -- -- list_data.devinfo.push(devinfo); -- -- pa_threaded_mainloop_signal(ctx.mainloop, 0); --} -- --unsafe extern "C" fn pulse_server_info_cb(_context: *mut pa_context, -- i: *const pa_server_info, -- user_data: *mut c_void) { -- assert!(!i.is_null()); -- let info = *i; -- let list_data = &mut *(user_data as *mut PulseDevListData); -- -- dup_str!(list_data.default_sink_name, info.default_sink_name); -- dup_str!(list_data.default_source_name, info.default_source_name); -- -- pa_threaded_mainloop_signal((*list_data.context).mainloop, 0); --} -- --unsafe extern "C" fn pulse_subscribe_callback(_ctx: *mut pa_context, -- t: pa_subscription_event_type_t, -- index: u32, -- user_data: *mut c_void) { -- let mut ctx = &mut *(user_data as *mut Context); -- -- match t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK { -- PA_SUBSCRIPTION_EVENT_SOURCE | -- PA_SUBSCRIPTION_EVENT_SINK => { -- -- if cubeb::log_enabled() { -- if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE { -- log!("Removing sink index %d", index); -- } else if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SOURCE && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- log!("Adding sink index %d", index); -- } -- if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE { -- log!("Removing source index %d", index); -- } else if (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) == PA_SUBSCRIPTION_EVENT_SINK && -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- log!("Adding source index %d", index); -- } -- } -- -- if (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_REMOVE || -- (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) == PA_SUBSCRIPTION_EVENT_NEW { -- ctx.collection_changed_callback.unwrap()(ctx as *mut _ as *mut _, ctx.collection_changed_user_ptr); -- } -- }, -- _ => {}, -- } --} -- --extern "C" { -- pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; --} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/mod.rs 2017-08-04 13:37:46.386821731 +0200 -@@ -7,8 +7,16 @@ mod context; - mod cork_state; - mod stream; - -+use std::os::raw::c_char; -+use std::ffi::CStr; -+ - pub type Result = ::std::result::Result; - - pub use self::context::Context; - pub use self::stream::Device; - pub use self::stream::Stream; -+ -+// helper to convert *const c_char to Option -+fn try_cstr_from<'str>(s: *const c_char) -> Option<&'str CStr> { -+ if s.is_null() { None } else { Some(unsafe { CStr::from_ptr(s) }) } -+} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/backend/stream.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -6,8 +6,10 @@ - use backend::*; - use backend::cork_state::CorkState; - use cubeb; -+use pulse::{self, CVolumeExt, ChannelMapExt, SampleSpecExt, USecExt}; - use pulse_ffi::*; --use std::os::raw::{c_char, c_long, c_void}; -+use std::ffi::{CStr, CString}; -+use std::os::raw::{c_long, c_void}; - use std::ptr; - - const PULSE_NO_GAIN: f32 = -1.0; -@@ -36,15 +38,12 @@ fn cubeb_channel_to_pa_channel(channel: - MAP[idx as usize] - } - --fn layout_to_channel_map(layout: cubeb::ChannelLayout) -> pa_channel_map { -+fn layout_to_channel_map(layout: cubeb::ChannelLayout) -> pulse::ChannelMap { - assert_ne!(layout, cubeb::LAYOUT_UNDEFINED); - - let order = cubeb::mixer::channel_index_to_order(layout); - -- let mut cm: pa_channel_map = Default::default(); -- unsafe { -- pa_channel_map_init(&mut cm); -- } -+ let mut cm = pulse::ChannelMap::init(); - cm.channels = order.len() as u8; - for (s, d) in order.iter().zip(cm.map.iter_mut()) { - *d = cubeb_channel_to_pa_channel(*s); -@@ -57,24 +56,27 @@ pub struct Device(cubeb::Device); - impl Drop for Device { - fn drop(&mut self) { - unsafe { -- pa_xfree(self.0.input_name as *mut _); -- pa_xfree(self.0.output_name as *mut _); -+ if !self.0.input_name.is_null() { -+ let _ = CString::from_raw(self.0.input_name); -+ } -+ if !self.0.output_name.is_null() { -+ let _ = CString::from_raw(self.0.output_name); -+ } - } - } - } - -- - #[derive(Debug)] - pub struct Stream<'ctx> { - context: &'ctx Context, -- output_stream: *mut pa_stream, -- input_stream: *mut pa_stream, -+ output_stream: Option, -+ input_stream: Option, - data_callback: cubeb::DataCallback, - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void, - drain_timer: *mut pa_time_event, -- output_sample_spec: pa_sample_spec, -- input_sample_spec: pa_sample_spec, -+ output_sample_spec: pulse::SampleSpec, -+ input_sample_spec: pulse::SampleSpec, - shutdown: bool, - volume: f32, - state: cubeb::State, -@@ -88,7 +90,7 @@ impl<'ctx> Drop for Stream<'ctx> { - - impl<'ctx> Stream<'ctx> { - pub fn new(context: &'ctx Context, -- stream_name: *const c_char, -+ stream_name: &CStr, - input_device: cubeb::DeviceId, - input_stream_params: Option, - output_device: cubeb::DeviceId, -@@ -99,83 +101,167 @@ impl<'ctx> Stream<'ctx> { - user_ptr: *mut c_void) - -> Result>> { - -+ fn check_error(s: &pulse::Stream, u: *mut c_void) { -+ let stm = unsafe { &mut *(u as *mut Stream) }; -+ if !s.get_state().is_good() { -+ stm.state_change_callback(cubeb::STATE_ERROR); -+ } -+ stm.context.mainloop.signal(); -+ } -+ -+ fn read_data(s: &pulse::Stream, nbytes: usize, u: *mut c_void) { -+ fn read_from_input(s: &pulse::Stream, buffer: *mut *const c_void, size: *mut usize) -> i32 { -+ let readable_size: i32 = s.readable_size() -+ .and_then(|s| Ok(s as i32)) -+ .unwrap_or(-1); -+ if readable_size > 0 { -+ if unsafe { s.peek(buffer, size).is_err() } { -+ return -1; -+ } -+ } -+ readable_size -+ } -+ -+ logv!("Input callback buffer size {}", nbytes); -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if stm.shutdown { -+ return; -+ } -+ -+ let mut read_data: *const c_void = ptr::null(); -+ let mut read_size: usize = 0; -+ while read_from_input(s, &mut read_data, &mut read_size) > 0 { -+ /* read_data can be NULL in case of a hole. */ -+ if !read_data.is_null() { -+ let in_frame_size = stm.input_sample_spec.frame_size(); -+ let read_frames = read_size / in_frame_size; -+ -+ if stm.output_stream.is_some() { -+ // input/capture + output/playback operation -+ let out_frame_size = stm.output_sample_spec.frame_size(); -+ let write_size = read_frames * out_frame_size; -+ // Offer full duplex data for writing -+ stm.trigger_user_callback(read_data, write_size); -+ } else { -+ // input/capture only operation. Call callback directly -+ let got = unsafe { -+ stm.data_callback.unwrap()(stm as *mut _ as *mut _, -+ stm.user_ptr, -+ read_data, -+ ptr::null_mut(), -+ read_frames as c_long) -+ }; -+ -+ if got < 0 || got as usize != read_frames { -+ let _ = s.cancel_write(); -+ stm.shutdown = true; -+ break; -+ } -+ } -+ } -+ -+ if read_size > 0 { -+ let _ = s.drop(); -+ } -+ -+ if stm.shutdown { -+ return; -+ } -+ } -+ } -+ -+ fn write_data(_: &pulse::Stream, nbytes: usize, u: *mut c_void) { -+ logv!("Output callback to be written buffer size {}", nbytes); -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if stm.shutdown || stm.state != cubeb::STATE_STARTED { -+ return; -+ } -+ -+ if stm.input_stream.is_none() { -+ // Output/playback only operation. -+ // Write directly to output -+ debug_assert!(stm.output_stream.is_some()); -+ stm.trigger_user_callback(ptr::null(), nbytes); -+ } -+ } -+ - let mut stm = Box::new(Stream { - context: context, -- output_stream: ptr::null_mut(), -- input_stream: ptr::null_mut(), -+ output_stream: None, -+ input_stream: None, - data_callback: data_callback, - state_callback: state_callback, - user_ptr: user_ptr, - drain_timer: ptr::null_mut(), -- output_sample_spec: pa_sample_spec::default(), -- input_sample_spec: pa_sample_spec::default(), -+ output_sample_spec: pulse::SampleSpec::default(), -+ input_sample_spec: pulse::SampleSpec::default(), - shutdown: false, - volume: PULSE_NO_GAIN, - state: cubeb::STATE_ERROR, - }); - -- unsafe { -- pa_threaded_mainloop_lock(stm.context.mainloop); -+ if let Some(ref context) = stm.context.context { -+ stm.context.mainloop.lock(); -+ -+ // Setup output stream - if let Some(ref stream_params) = output_stream_params { -- match stm.pulse_stream_init(stream_params, stream_name) { -- Ok(s) => stm.output_stream = s, -+ match Stream::stream_init(context, stream_params, stream_name) { -+ Ok(s) => { -+ stm.output_sample_spec = *s.get_sample_spec(); -+ -+ s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _); -+ s.set_write_callback(write_data, stm.as_mut() as *mut _ as *mut _); -+ -+ let battr = set_buffering_attribute(latency_frames, &stm.output_sample_spec); -+ let device_name = super::try_cstr_from(output_device as *const _); -+ let _ = s.connect_playback(device_name, -+ &battr, -+ pulse::STREAM_AUTO_TIMING_UPDATE | pulse::STREAM_INTERPOLATE_TIMING | -+ pulse::STREAM_START_CORKED | -+ pulse::STREAM_ADJUST_LATENCY, -+ None, -+ None); -+ -+ stm.output_stream = Some(s); -+ }, - Err(e) => { -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - stm.destroy(); - return Err(e); - }, - } - -- stm.output_sample_spec = *pa_stream_get_sample_spec(stm.output_stream); -- -- pa_stream_set_state_callback(stm.output_stream, -- Some(stream_state_callback), -- stm.as_mut() as *mut _ as *mut _); -- pa_stream_set_write_callback(stm.output_stream, -- Some(stream_write_callback), -- stm.as_mut() as *mut _ as *mut _); -- -- let battr = set_buffering_attribute(latency_frames, &stm.output_sample_spec); -- pa_stream_connect_playback(stm.output_stream, -- output_device as *mut c_char, -- &battr, -- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING | -- PA_STREAM_START_CORKED | -- PA_STREAM_ADJUST_LATENCY, -- ptr::null(), -- ptr::null_mut()); - } - - // Set up input stream - if let Some(ref stream_params) = input_stream_params { -- match stm.pulse_stream_init(stream_params, stream_name) { -- Ok(s) => stm.input_stream = s, -+ match Stream::stream_init(context, stream_params, stream_name) { -+ Ok(s) => { -+ stm.input_sample_spec = *s.get_sample_spec(); -+ -+ s.set_state_callback(check_error, stm.as_mut() as *mut _ as *mut _); -+ s.set_read_callback(read_data, stm.as_mut() as *mut _ as *mut _); -+ -+ let battr = set_buffering_attribute(latency_frames, &stm.input_sample_spec); -+ let device_name = super::try_cstr_from(input_device as *const _); -+ let _ = s.connect_record(device_name, -+ &battr, -+ pulse::STREAM_AUTO_TIMING_UPDATE | pulse::STREAM_INTERPOLATE_TIMING | -+ pulse::STREAM_START_CORKED | -+ pulse::STREAM_ADJUST_LATENCY); -+ -+ stm.input_stream = Some(s); -+ }, - Err(e) => { -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - stm.destroy(); - return Err(e); - }, - } - -- stm.input_sample_spec = *(pa_stream_get_sample_spec(stm.input_stream)); -- -- pa_stream_set_state_callback(stm.input_stream, -- Some(stream_state_callback), -- stm.as_mut() as *mut _ as *mut _); -- pa_stream_set_read_callback(stm.input_stream, -- Some(stream_read_callback), -- stm.as_mut() as *mut _ as *mut _); -- -- let battr = set_buffering_attribute(latency_frames, &stm.input_sample_spec); -- pa_stream_connect_record(stm.input_stream, -- input_device as *mut c_char, -- &battr, -- PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_INTERPOLATE_TIMING | -- PA_STREAM_START_CORKED | -- PA_STREAM_ADJUST_LATENCY); - } - -- let r = if stm.wait_until_stream_ready() { -+ let r = if stm.wait_until_ready() { - /* force a timing update now, otherwise timing info does not become valid - until some point after initialization has completed. */ - stm.update_timing_info() -@@ -183,7 +269,7 @@ impl<'ctx> Stream<'ctx> { - false - }; - -- pa_threaded_mainloop_unlock(stm.context.mainloop); -+ stm.context.mainloop.unlock(); - - if !r { - stm.destroy(); -@@ -191,10 +277,10 @@ impl<'ctx> Stream<'ctx> { - } - - if cubeb::log_enabled() { -- if output_stream_params.is_some() { -- let output_att = *pa_stream_get_buffer_attr(stm.output_stream); -- log!("Output buffer attributes maxlength %u, tlength %u, \ -- prebuf %u, minreq %u, fragsize %u", -+ if let Some(ref output_stream) = stm.output_stream { -+ let output_att = output_stream.get_buffer_attr(); -+ log!("Output buffer attributes maxlength {}, tlength {}, \ -+ prebuf {}, minreq {}, fragsize {}", - output_att.maxlength, - output_att.tlength, - output_att.prebuf, -@@ -202,10 +288,10 @@ impl<'ctx> Stream<'ctx> { - output_att.fragsize); - } - -- if input_stream_params.is_some() { -- let input_att = *pa_stream_get_buffer_attr(stm.input_stream); -- log!("Input buffer attributes maxlength %u, tlength %u, \ -- prebuf %u, minreq %u, fragsize %u", -+ if let Some(ref input_stream) = stm.input_stream { -+ let input_att = input_stream.get_buffer_attr(); -+ log!("Input buffer attributes maxlength {}, tlength {}, \ -+ prebuf {}, minreq {}, fragsize {}", - input_att.maxlength, - input_att.tlength, - input_att.prebuf, -@@ -219,224 +305,250 @@ impl<'ctx> Stream<'ctx> { - } - - fn destroy(&mut self) { -- self.stream_cork(CorkState::cork()); -+ self.cork(CorkState::cork()); - -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -- if !self.output_stream.is_null() { -- if !self.drain_timer.is_null() { -- /* there's no pa_rttime_free, so use this instead. */ -- let ma = pa_threaded_mainloop_get_api(self.context.mainloop); -- if !ma.is_null() { -- (*ma).time_free.unwrap()(self.drain_timer); -+ self.context.mainloop.lock(); -+ { -+ match self.output_stream.take() { -+ Some(stm) => { -+ if !self.drain_timer.is_null() { -+ /* there's no pa_rttime_free, so use this instead. */ -+ self.context -+ .mainloop -+ .get_api() -+ .time_free(self.drain_timer); - } -- } -- -- pa_stream_set_state_callback(self.output_stream, None, ptr::null_mut()); -- pa_stream_set_write_callback(self.output_stream, None, ptr::null_mut()); -- pa_stream_disconnect(self.output_stream); -- pa_stream_unref(self.output_stream); -+ stm.clear_state_callback(); -+ stm.clear_write_callback(); -+ let _ = stm.disconnect(); -+ stm.unref(); -+ }, -+ _ => {}, -+ } -+ -+ match self.input_stream.take() { -+ Some(stm) => { -+ stm.clear_state_callback(); -+ stm.clear_read_callback(); -+ let _ = stm.disconnect(); -+ stm.unref(); -+ }, -+ _ => {}, - } -- -- if !self.input_stream.is_null() { -- pa_stream_set_state_callback(self.input_stream, None, ptr::null_mut()); -- pa_stream_set_read_callback(self.input_stream, None, ptr::null_mut()); -- pa_stream_disconnect(self.input_stream); -- pa_stream_unref(self.input_stream); -- } -- pa_threaded_mainloop_unlock(self.context.mainloop); - } -+ self.context.mainloop.unlock(); - } - - pub fn start(&mut self) -> i32 { -+ fn output_preroll(_: &pulse::MainloopApi, u: *mut c_void) { -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ if !stm.shutdown { -+ let size = stm.output_stream -+ .as_ref() -+ .map_or(0, |s| s.writable_size().unwrap_or(0)); -+ stm.trigger_user_callback(ptr::null_mut(), size); -+ } -+ } -+ - self.shutdown = false; -- self.stream_cork(CorkState::uncork() | CorkState::notify()); -+ self.cork(CorkState::uncork() | CorkState::notify()); - -- if !self.output_stream.is_null() && self.input_stream.is_null() { -- unsafe { -- /* On output only case need to manually call user cb once in order to make -- * things roll. This is done via a defer event in order to execute it -- * from PA server thread. */ -- pa_threaded_mainloop_lock(self.context.mainloop); -- pa_mainloop_api_once(pa_threaded_mainloop_get_api(self.context.mainloop), -- Some(pulse_defer_event_cb), -- self as *mut _ as *mut _); -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -+ if self.output_stream.is_some() && self.input_stream.is_none() { -+ /* On output only case need to manually call user cb once in order to make -+ * things roll. This is done via a defer event in order to execute it -+ * from PA server thread. */ -+ self.context.mainloop.lock(); -+ self.context -+ .mainloop -+ .get_api() -+ .once(output_preroll, self as *mut _ as *mut _); -+ self.context.mainloop.unlock(); - } - - cubeb::OK - } - - pub fn stop(&mut self) -> i32 { -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -+ { -+ self.context.mainloop.lock(); - self.shutdown = true; - // If draining is taking place wait to finish - while !self.drain_timer.is_null() { -- pa_threaded_mainloop_wait(self.context.mainloop); -+ self.context.mainloop.wait(); - } -- pa_threaded_mainloop_unlock(self.context.mainloop); -+ self.context.mainloop.unlock(); - } -- self.stream_cork(CorkState::cork() | CorkState::notify()); -+ self.cork(CorkState::cork() | CorkState::notify()); - - cubeb::OK - } - - pub fn position(&self) -> Result { -- if self.output_stream.is_null() { -- return Err(cubeb::ERROR); -- } -+ let in_thread = self.context.mainloop.in_thread(); - -- let position = unsafe { -- let in_thread = pa_threaded_mainloop_in_thread(self.context.mainloop); -- -- if in_thread == 0 { -- pa_threaded_mainloop_lock(self.context.mainloop); -- } -- -- let mut r_usec: pa_usec_t = Default::default(); -- let r = pa_stream_get_time(self.output_stream, &mut r_usec); -- if in_thread == 0 { -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -- -- if r != 0 { -- return Err(cubeb::ERROR); -- } -+ if !in_thread { -+ self.context.mainloop.lock(); -+ } - -- let bytes = pa_usec_to_bytes(r_usec, &self.output_sample_spec); -- (bytes / pa_frame_size(&self.output_sample_spec)) as u64 -+ let r = match self.output_stream { -+ None => Err(cubeb::ERROR), -+ Some(ref stm) => { -+ match stm.get_time() { -+ Ok(r_usec) => { -+ let bytes = r_usec.to_bytes(&self.output_sample_spec); -+ Ok((bytes / self.output_sample_spec.frame_size()) as u64) -+ }, -+ Err(_) => Err(cubeb::ERROR), -+ } -+ }, - }; -- Ok(position) -- } - -- pub fn latency(&self) -> Result { -- if self.output_stream.is_null() { -- return Err(cubeb::ERROR); -+ if !in_thread { -+ self.context.mainloop.unlock(); - } - -- let mut r_usec: pa_usec_t = 0; -- let mut negative: i32 = 0; -- let r = unsafe { pa_stream_get_latency(self.output_stream, &mut r_usec, &mut negative) }; -+ r -+ } - -- if r != 0 { -- return Err(cubeb::ERROR); -+ pub fn latency(&self) -> Result { -+ match self.output_stream { -+ None => Err(cubeb::ERROR), -+ Some(ref stm) => { -+ match stm.get_latency() { -+ Ok((r_usec, negative)) => { -+ debug_assert!(negative); -+ let latency = (r_usec * self.output_sample_spec.rate as pa_usec_t / PA_USEC_PER_SEC) as u32; -+ Ok(latency) -+ }, -+ Err(_) => Err(cubeb::ERROR), -+ } -+ }, - } -- -- debug_assert_eq!(negative, 0); -- let latency = (r_usec * self.output_sample_spec.rate as pa_usec_t / PA_USEC_PER_SEC) as u32; -- -- Ok(latency) - } - - pub fn set_volume(&mut self, volume: f32) -> i32 { -- if self.output_stream.is_null() { -- return cubeb::ERROR; -- } -- -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -- -- while self.context.default_sink_info.is_none() { -- pa_threaded_mainloop_wait(self.context.mainloop); -- } -- -- let mut cvol: pa_cvolume = Default::default(); -- -- /* if the pulse daemon is configured to use flat volumes, -- * apply our own gain instead of changing the input volume on the sink. */ -- let flags = { -- match self.context.default_sink_info { -- Some(ref info) => info.flags, -- _ => 0, -- } -- }; -- -- if (flags & PA_SINK_FLAT_VOLUME) != 0 { -- self.volume = volume; -- } else { -- let ss = pa_stream_get_sample_spec(self.output_stream); -- let vol = pa_sw_volume_from_linear(volume as f64); -- pa_cvolume_set(&mut cvol, (*ss).channels as u32, vol); -- -- let index = pa_stream_get_index(self.output_stream); -+ match self.output_stream { -+ None => cubeb::ERROR, -+ Some(ref stm) => { -+ if let Some(ref context) = self.context.context { -+ self.context.mainloop.lock(); -+ -+ let mut cvol: pa_cvolume = Default::default(); -+ -+ /* if the pulse daemon is configured to use flat -+ * volumes, apply our own gain instead of changing -+ * the input volume on the sink. */ -+ let flags = { -+ match self.context.default_sink_info { -+ Some(ref info) => info.flags, -+ _ => pulse::SinkFlags::empty(), -+ } -+ }; -+ -+ if flags.contains(pulse::SINK_FLAT_VOLUME) { -+ self.volume = volume; -+ } else { -+ let channels = stm.get_sample_spec().channels; -+ let vol = pulse::sw_volume_from_linear(volume as f64); -+ cvol.set(channels as u32, vol); -+ -+ let index = stm.get_index(); -+ -+ let context_ptr = self.context as *const _ as *mut _; -+ if let Ok(o) = context.set_sink_input_volume(index, &cvol, context_success, context_ptr) { -+ self.context.operation_wait(stm, &o); -+ } -+ } - -- let op = pa_context_set_sink_input_volume(self.context.context, -- index, -- &cvol, -- Some(volume_success), -- self as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -+ self.context.mainloop.unlock(); -+ cubeb::OK -+ } else { -+ cubeb::ERROR - } -- } -- -- pa_threaded_mainloop_unlock(self.context.mainloop); -+ }, - } -- cubeb::OK - } - - pub fn set_panning(&mut self, panning: f32) -> i32 { -- if self.output_stream.is_null() { -- return cubeb::ERROR; -- } -+ #[repr(C)] -+ struct SinkInputInfoResult<'a> { -+ pub cvol: pulse::CVolume, -+ pub mainloop: &'a pulse::ThreadedMainloop, -+ } -+ -+ fn get_input_volume(_: &pulse::Context, info: *const pulse::SinkInputInfo, eol: i32, u: *mut c_void) { -+ let mut r = unsafe { &mut *(u as *mut SinkInputInfoResult) }; -+ if eol == 0 { -+ let info = unsafe { *info }; -+ r.cvol = info.volume; -+ } -+ r.mainloop.signal(); -+ } -+ -+ match self.output_stream { -+ None => cubeb::ERROR, -+ Some(ref stm) => { -+ if let Some(ref context) = self.context.context { -+ self.context.mainloop.lock(); -+ -+ let map = stm.get_channel_map(); -+ if !map.can_balance() { -+ self.context.mainloop.unlock(); -+ return cubeb::ERROR; -+ } - -- unsafe { -- pa_threaded_mainloop_lock(self.context.mainloop); -+ let index = stm.get_index(); - -- let map = pa_stream_get_channel_map(self.output_stream); -- if pa_channel_map_can_balance(map) == 0 { -- pa_threaded_mainloop_unlock(self.context.mainloop); -- return cubeb::ERROR; -- } -+ let mut r = SinkInputInfoResult { -+ cvol: pulse::CVolume::default(), -+ mainloop: &self.context.mainloop, -+ }; - -- let index = pa_stream_get_index(self.output_stream); -+ if let Ok(o) = context.get_sink_input_info(index, get_input_volume, &mut r as *mut _ as *mut _) { -+ self.context.operation_wait(stm, &o); -+ } - -- let mut cvol: pa_cvolume = Default::default(); -- let mut r = SinkInputInfoResult { -- cvol: &mut cvol, -- mainloop: self.context.mainloop, -- }; -+ r.cvol.set_balance(map, panning); - -- let op = pa_context_get_sink_input_info(self.context.context, -- index, -- Some(sink_input_info_cb), -- &mut r as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -- } -- -- pa_cvolume_set_balance(&mut cvol, map, panning); -- -- let op = pa_context_set_sink_input_volume(self.context.context, -- index, -- &cvol, -- Some(volume_success), -- self as *mut _ as *mut _); -- if !op.is_null() { -- self.context.operation_wait(self.output_stream, op); -- pa_operation_unref(op); -- } -+ let context_ptr = self.context as *const _ as *mut _; -+ if let Ok(o) = context.set_sink_input_volume(index, &r.cvol, context_success, context_ptr) { -+ self.context.operation_wait(stm, &o); -+ } - -- pa_threaded_mainloop_unlock(self.context.mainloop); -- } -+ self.context.mainloop.unlock(); - -- cubeb::OK -+ cubeb::OK -+ } else { -+ cubeb::ERROR -+ } -+ }, -+ } - } - - pub fn current_device(&self) -> Result> { - if self.context.version_0_9_8 { - let mut dev = Box::new(cubeb::Device::default()); - -- if !self.input_stream.is_null() { -- dev.input_name = unsafe { pa_xstrdup(pa_stream_get_device_name(self.input_stream)) }; -+ if self.input_stream.is_some() { -+ if let Some(ref stm) = self.input_stream { -+ dev.input_name = match stm.get_device_name() { -+ Ok(name) => name.to_owned().into_raw(), -+ Err(_) => { -+ return Err(cubeb::ERROR); -+ }, -+ } -+ } - } - -- if !self.output_stream.is_null() { -- dev.output_name = unsafe { pa_xstrdup(pa_stream_get_device_name(self.output_stream)) }; -+ if !self.output_stream.is_some() { -+ if let Some(ref stm) = self.output_stream { -+ dev.output_name = match stm.get_device_name() { -+ Ok(name) => name.to_owned().into_raw(), -+ Err(_) => { -+ return Err(cubeb::ERROR); -+ }, -+ } -+ } - } - - Ok(dev) -@@ -445,51 +557,62 @@ impl<'ctx> Stream<'ctx> { - } - } - -- fn pulse_stream_init(&mut self, -- stream_params: &cubeb::StreamParams, -- stream_name: *const c_char) -- -> Result<*mut pa_stream> { -+ fn stream_init(context: &pulse::Context, -+ stream_params: &cubeb::StreamParams, -+ stream_name: &CStr) -+ -> Result { - -- fn to_pulse_format(format: cubeb::SampleFormat) -> pa_sample_format_t { -+ fn to_pulse_format(format: cubeb::SampleFormat) -> pulse::SampleFormat { - match format { -- cubeb::SAMPLE_S16LE => PA_SAMPLE_S16LE, -- cubeb::SAMPLE_S16BE => PA_SAMPLE_S16BE, -- cubeb::SAMPLE_FLOAT32LE => PA_SAMPLE_FLOAT32LE, -- cubeb::SAMPLE_FLOAT32BE => PA_SAMPLE_FLOAT32BE, -- _ => panic!("Invalid format: {:?}", format), -+ cubeb::SAMPLE_S16LE => pulse::SampleFormat::Signed16LE, -+ cubeb::SAMPLE_S16BE => pulse::SampleFormat::Signed16BE, -+ cubeb::SAMPLE_FLOAT32LE => pulse::SampleFormat::Float32LE, -+ cubeb::SAMPLE_FLOAT32BE => pulse::SampleFormat::Float32BE, -+ _ => pulse::SampleFormat::Invalid, - } - } - - let fmt = to_pulse_format(stream_params.format); -- if fmt == PA_SAMPLE_INVALID { -+ if fmt == pulse::SampleFormat::Invalid { - return Err(cubeb::ERROR_INVALID_FORMAT); - } - -- let ss = pa_sample_spec { -+ let ss = pulse::SampleSpec { - channels: stream_params.channels as u8, -- format: fmt, -+ format: fmt.into(), - rate: stream_params.rate, - }; - -- let stream = if stream_params.layout == cubeb::LAYOUT_UNDEFINED { -- unsafe { pa_stream_new(self.context.context, stream_name, &ss, ptr::null_mut()) } -- } else { -- let cm = layout_to_channel_map(stream_params.layout); -- unsafe { pa_stream_new(self.context.context, stream_name, &ss, &cm) } -+ let cm: Option = match stream_params.layout { -+ cubeb::LAYOUT_UNDEFINED => None, -+ _ => Some(layout_to_channel_map(stream_params.layout)), - }; - -- if !stream.is_null() { -- Ok(stream) -- } else { -- Err(cubeb::ERROR) -+ let stream = pulse::Stream::new(context, stream_name, &ss, cm.as_ref()); -+ -+ match stream { -+ None => Err(cubeb::ERROR), -+ Some(stm) => Ok(stm), -+ } -+ } -+ -+ pub fn cork_stream(&self, stream: Option<&pulse::Stream>, state: CorkState) { -+ if let Some(stm) = stream { -+ if let Ok(o) = stm.cork(state.is_cork() as i32, -+ stream_success, -+ self as *const _ as *mut _) { -+ self.context.operation_wait(stream, &o); -+ } - } - } - -- fn stream_cork(&mut self, state: CorkState) { -- unsafe { pa_threaded_mainloop_lock(self.context.mainloop) }; -- self.context.pulse_stream_cork(self.output_stream, state); -- self.context.pulse_stream_cork(self.input_stream, state); -- unsafe { pa_threaded_mainloop_unlock(self.context.mainloop) }; -+ fn cork(&mut self, state: CorkState) { -+ { -+ self.context.mainloop.lock(); -+ self.cork_stream(self.output_stream.as_ref(), state); -+ self.cork_stream(self.input_stream.as_ref(), state); -+ self.context.mainloop.unlock() -+ } - - if state.is_notify() { - self.state_change_callback(if state.is_cork() { -@@ -503,18 +626,9 @@ impl<'ctx> Stream<'ctx> { - fn update_timing_info(&self) -> bool { - let mut r = false; - -- if !self.output_stream.is_null() { -- let o = unsafe { -- pa_stream_update_timing_info(self.output_stream, -- Some(stream_success_callback), -- self as *const _ as *mut _) -- }; -- -- if !o.is_null() { -- r = self.context.operation_wait(self.output_stream, o); -- unsafe { -- pa_operation_unref(o); -- } -+ if let Some(ref stm) = self.output_stream { -+ if let Ok(o) = stm.update_timing_info(stream_success, self as *const _ as *mut _) { -+ r = self.context.operation_wait(stm, &o); - } - - if !r { -@@ -522,18 +636,9 @@ impl<'ctx> Stream<'ctx> { - } - } - -- if !self.input_stream.is_null() { -- let o = unsafe { -- pa_stream_update_timing_info(self.input_stream, -- Some(stream_success_callback), -- self as *const _ as *mut _) -- }; -- -- if !o.is_null() { -- r = self.context.operation_wait(self.input_stream, o); -- unsafe { -- pa_operation_unref(o); -- } -+ if let Some(ref stm) = self.input_stream { -+ if let Ok(o) = stm.update_timing_info(stream_success, self as *const _ as *mut _) { -+ r = self.context.operation_wait(stm, &o); - } - } - -@@ -547,232 +652,162 @@ impl<'ctx> Stream<'ctx> { - } - } - -- fn wait_until_stream_ready(&self) -> bool { -- if !self.output_stream.is_null() && !wait_until_io_stream_ready(self.output_stream, self.context.mainloop) { -- return false; -- } -- -- if !self.input_stream.is_null() && !wait_until_io_stream_ready(self.input_stream, self.context.mainloop) { -- return false; -- } -- -- true -- } -- -- fn trigger_user_callback(&mut self, s: *mut pa_stream, input_data: *const c_void, nbytes: usize) { -- let frame_size = unsafe { pa_frame_size(&self.output_sample_spec) }; -- debug_assert_eq!(nbytes % frame_size, 0); -- -- let mut buffer: *mut c_void = ptr::null_mut(); -- let mut r: i32; -- -- let mut towrite = nbytes; -- let mut read_offset = 0usize; -- while towrite > 0 { -- let mut size = towrite; -- r = unsafe { pa_stream_begin_write(s, &mut buffer, &mut size) }; -- // Note: this has failed running under rr on occassion - needs investigation. -- debug_assert_eq!(r, 0); -- debug_assert!(size > 0); -- debug_assert_eq!(size % frame_size, 0); -- -- logv!("Trigger user callback with output buffer size={}, read_offset={}", -- size, -- read_offset); -- let read_ptr = unsafe { (input_data as *const u8).offset(read_offset as isize) }; -- let got = unsafe { -- self.data_callback.unwrap()(self as *const _ as *mut _, -- self.user_ptr, -- read_ptr as *const _ as *mut _, -- buffer, -- (size / frame_size) as c_long) -- }; -- if got < 0 { -- unsafe { -- pa_stream_cancel_write(s); -- } -- self.shutdown = true; -- return; -- } -- // If more iterations move offset of read buffer -- if !input_data.is_null() { -- let in_frame_size = unsafe { pa_frame_size(&self.input_sample_spec) }; -- read_offset += (size / frame_size) * in_frame_size; -+ fn wait_until_ready(&self) -> bool { -+ fn wait_until_io_stream_ready(stm: &pulse::Stream, mainloop: &pulse::ThreadedMainloop) -> bool { -+ if mainloop.is_null() { -+ return false; - } - -- if self.volume != PULSE_NO_GAIN { -- let samples = (self.output_sample_spec.channels as usize * size / frame_size) as isize; -- -- if self.output_sample_spec.format == PA_SAMPLE_S16BE || -- self.output_sample_spec.format == PA_SAMPLE_S16LE { -- let b = buffer as *mut i16; -- for i in 0..samples { -- unsafe { *b.offset(i) *= self.volume as i16 }; -- } -- } else { -- let b = buffer as *mut f32; -- for i in 0..samples { -- unsafe { *b.offset(i) *= self.volume }; -- } -+ loop { -+ let state = stm.get_state(); -+ if !state.is_good() { -+ return false; -+ } -+ if state == pulse::StreamState::Ready { -+ break; - } -+ mainloop.wait(); - } - -- r = unsafe { -- pa_stream_write(s, -- buffer, -- got as usize * frame_size, -- None, -- 0, -- PA_SEEK_RELATIVE) -- }; -- debug_assert_eq!(r, 0); -+ true -+ } - -- if (got as usize) < size / frame_size { -- let mut latency: pa_usec_t = 0; -- let rr: i32 = unsafe { pa_stream_get_latency(s, &mut latency, ptr::null_mut()) }; -- if rr == -(PA_ERR_NODATA as i32) { -- /* this needs a better guess. */ -- latency = 100 * PA_USEC_PER_MSEC; -- } -- debug_assert!(r == 0 || r == -(PA_ERR_NODATA as i32)); -- /* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */ -- /* arbitrary safety margin: double the current latency. */ -- debug_assert!(self.drain_timer.is_null()); -- self.drain_timer = unsafe { -- pa_context_rttime_new(self.context.context, -- pa_rtclock_now() + 2 * latency, -- Some(stream_drain_callback), -- self as *const _ as *mut _) -- }; -- self.shutdown = true; -- return; -+ if let Some(ref stm) = self.output_stream { -+ if !wait_until_io_stream_ready(stm, &self.context.mainloop) { -+ return false; - } -- -- towrite -= size; - } - -- debug_assert_eq!(towrite, 0); -- } --} -- --unsafe extern "C" fn stream_success_callback(_s: *mut pa_stream, _success: i32, u: *mut c_void) { -- let stm = &*(u as *mut Stream); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --unsafe extern "C" fn stream_drain_callback(a: *mut pa_mainloop_api, -- e: *mut pa_time_event, -- _tv: *const timeval, -- u: *mut c_void) { -- let mut stm = &mut *(u as *mut Stream); -- debug_assert_eq!(stm.drain_timer, e); -- stm.state_change_callback(cubeb::STATE_DRAINED); -- /* there's no pa_rttime_free, so use this instead. */ -- (*a).time_free.unwrap()(stm.drain_timer); -- stm.drain_timer = ptr::null_mut(); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --unsafe extern "C" fn stream_state_callback(s: *mut pa_stream, u: *mut c_void) { -- let stm = &mut *(u as *mut Stream); -- if !PA_STREAM_IS_GOOD(pa_stream_get_state(s)) { -- stm.state_change_callback(cubeb::STATE_ERROR); -- } -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -- --fn read_from_input(s: *mut pa_stream, buffer: *mut *const c_void, size: *mut usize) -> i32 { -- let readable_size = unsafe { pa_stream_readable_size(s) }; -- if readable_size > 0 && unsafe { pa_stream_peek(s, buffer, size) } < 0 { -- return -1; -- } -- -- readable_size as i32 --} -+ if let Some(ref stm) = self.input_stream { -+ if !wait_until_io_stream_ready(stm, &self.context.mainloop) { -+ return false; -+ } -+ } - --unsafe extern "C" fn stream_write_callback(s: *mut pa_stream, nbytes: usize, u: *mut c_void) { -- logv!("Output callback to be written buffer size {}", nbytes); -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown || stm.state != cubeb::STATE_STARTED { -- return; -+ true - } - -- if stm.input_stream.is_null() { -- // Output/playback only operation. -- // Write directly to output -- debug_assert!(!stm.output_stream.is_null()); -- stm.trigger_user_callback(s, ptr::null(), nbytes); -- } --} -+ fn trigger_user_callback(&mut self, input_data: *const c_void, nbytes: usize) { -+ fn drained_cb(a: &pulse::MainloopApi, e: *mut pa_time_event, _tv: &pulse::TimeVal, u: *mut c_void) { -+ let mut stm = unsafe { &mut *(u as *mut Stream) }; -+ debug_assert_eq!(stm.drain_timer, e); -+ stm.state_change_callback(cubeb::STATE_DRAINED); -+ /* there's no pa_rttime_free, so use this instead. */ -+ a.time_free(stm.drain_timer); -+ stm.drain_timer = ptr::null_mut(); -+ stm.context.mainloop.signal(); -+ } -+ -+ if let Some(ref stm) = self.output_stream { -+ -+ let frame_size = self.output_sample_spec.frame_size(); -+ debug_assert_eq!(nbytes % frame_size, 0); -+ -+ let mut towrite = nbytes; -+ let mut read_offset = 0usize; -+ while towrite > 0 { -+ match stm.begin_write(towrite) { -+ Err(e) => { -+ panic!("Failed to write data: {}", e); -+ }, -+ Ok((buffer, size)) => { -+ debug_assert!(size > 0); -+ debug_assert_eq!(size % frame_size, 0); -+ -+ logv!("Trigger user callback with output buffer size={}, read_offset={}", -+ size, -+ read_offset); -+ let read_ptr = unsafe { (input_data as *const u8).offset(read_offset as isize) }; -+ let got = unsafe { -+ self.data_callback.unwrap()(self as *const _ as *mut _, -+ self.user_ptr, -+ read_ptr as *const _ as *mut _, -+ buffer, -+ (size / frame_size) as c_long) -+ }; -+ if got < 0 { -+ let _ = stm.cancel_write(); -+ self.shutdown = true; -+ return; -+ } -+ -+ // If more iterations move offset of read buffer -+ if !input_data.is_null() { -+ let in_frame_size = self.input_sample_spec.frame_size(); -+ read_offset += (size / frame_size) * in_frame_size; -+ } -+ -+ if self.volume != PULSE_NO_GAIN { -+ let samples = (self.output_sample_spec.channels as usize * size / frame_size) as isize; -+ -+ if self.output_sample_spec.format == PA_SAMPLE_S16BE || -+ self.output_sample_spec.format == PA_SAMPLE_S16LE { -+ let b = buffer as *mut i16; -+ for i in 0..samples { -+ unsafe { *b.offset(i) *= self.volume as i16 }; -+ } -+ } else { -+ let b = buffer as *mut f32; -+ for i in 0..samples { -+ unsafe { *b.offset(i) *= self.volume }; -+ } -+ } -+ } -+ -+ let r = stm.write(buffer, -+ got as usize * frame_size, -+ 0, -+ pulse::SeekMode::Relative); -+ debug_assert!(r.is_ok()); -+ -+ if (got as usize) < size / frame_size { -+ let latency = match stm.get_latency() { -+ Ok((l, negative)) => { -+ assert_ne!(negative, true); -+ l -+ }, -+ Err(e) => { -+ debug_assert_eq!(e, pulse::ErrorCode::from_error_code(PA_ERR_NODATA)); -+ /* this needs a better guess. */ -+ 100 * PA_USEC_PER_MSEC -+ }, -+ }; -+ -+ /* pa_stream_drain is useless, see PA bug# 866. this is a workaround. */ -+ /* arbitrary safety margin: double the current latency. */ -+ debug_assert!(self.drain_timer.is_null()); -+ let stream_ptr = self as *const _ as *mut _; -+ if let Some(ref context) = self.context.context { -+ self.drain_timer = -+ context.rttime_new(pulse::rtclock_now() + 2 * latency, drained_cb, stream_ptr); -+ } -+ self.shutdown = true; -+ return; -+ } - --unsafe extern "C" fn stream_read_callback(s: *mut pa_stream, nbytes: usize, u: *mut c_void) { -- logv!("Input callback buffer size {}", nbytes); -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown { -- return; -- } -- -- let mut read_data: *const c_void = ptr::null(); -- let mut read_size: usize = 0; -- while read_from_input(s, &mut read_data, &mut read_size) > 0 { -- /* read_data can be NULL in case of a hole. */ -- if !read_data.is_null() { -- let in_frame_size = pa_frame_size(&stm.input_sample_spec); -- let read_frames = read_size / in_frame_size; -- -- if !stm.output_stream.is_null() { -- // input/capture + output/playback operation -- let out_frame_size = pa_frame_size(&stm.output_sample_spec); -- let write_size = read_frames * out_frame_size; -- // Offer full duplex data for writing -- let stream = stm.output_stream; -- stm.trigger_user_callback(stream, read_data, write_size); -- } else { -- // input/capture only operation. Call callback directly -- let got = stm.data_callback.unwrap()(stm as *mut _ as *mut _, -- stm.user_ptr, -- read_data, -- ptr::null_mut(), -- read_frames as c_long); -- if got < 0 || got as usize != read_frames { -- pa_stream_cancel_write(s); -- stm.shutdown = true; -- break; -+ towrite -= size; -+ }, - } - } -- } -- -- if read_size > 0 { -- pa_stream_drop(s); -- } -- -- if stm.shutdown { -- return; -+ debug_assert_eq!(towrite, 0); - } - } - } - --fn wait_until_io_stream_ready(stream: *mut pa_stream, mainloop: *mut pa_threaded_mainloop) -> bool { -- if stream.is_null() || mainloop.is_null() { -- return false; -- } -- -- loop { -- let state = unsafe { pa_stream_get_state(stream) }; -- if !PA_STREAM_IS_GOOD(state) { -- return false; -- } -- if state == PA_STREAM_READY { -- break; -- } -- unsafe { pa_threaded_mainloop_wait(mainloop) }; -- } -+fn stream_success(_: &pulse::Stream, success: i32, u: *mut c_void) { -+ let stm = unsafe { &*(u as *mut Stream) }; -+ debug_assert_ne!(success, 0); -+ stm.context.mainloop.signal(); -+} - -- true -+fn context_success(_: &pulse::Context, success: i32, u: *mut c_void) { -+ let ctx = unsafe { &*(u as *mut Context) }; -+ debug_assert_ne!(success, 0); -+ ctx.mainloop.signal(); - } - - fn set_buffering_attribute(latency_frames: u32, sample_spec: &pa_sample_spec) -> pa_buffer_attr { -- let tlength = latency_frames * unsafe { pa_frame_size(sample_spec) } as u32; -+ let tlength = latency_frames * sample_spec.frame_size() as u32; - let minreq = tlength / 4; - let battr = pa_buffer_attr { - maxlength: u32::max_value(), -@@ -791,34 +826,3 @@ fn set_buffering_attribute(latency_frame - - battr - } -- --unsafe extern "C" fn pulse_defer_event_cb(_a: *mut pa_mainloop_api, u: *mut c_void) { -- let mut stm = &mut *(u as *mut Stream); -- if stm.shutdown { -- return; -- } -- let writable_size = pa_stream_writable_size(stm.output_stream); -- let stream = stm.output_stream; -- stm.trigger_user_callback(stream, ptr::null_mut(), writable_size); --} -- --#[repr(C)] --struct SinkInputInfoResult { -- pub cvol: *mut pa_cvolume, -- pub mainloop: *mut pa_threaded_mainloop, --} -- --unsafe extern "C" fn sink_input_info_cb(_c: *mut pa_context, i: *const pa_sink_input_info, eol: i32, u: *mut c_void) { -- let info = &*i; -- let mut r = &mut *(u as *mut SinkInputInfoResult); -- if eol == 0 { -- *r.cvol = info.volume; -- } -- pa_threaded_mainloop_signal(r.mainloop, 0); --} -- --unsafe extern "C" fn volume_success(_c: *mut pa_context, success: i32, u: *mut c_void) { -- let stm = &*(u as *mut Stream); -- debug_assert_ne!(success, 0); -- pa_threaded_mainloop_signal(stm.context.mainloop, 0); --} -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/capi.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -5,6 +5,7 @@ - - use backend; - use cubeb; -+use std::ffi::CStr; - use std::os::raw::{c_char, c_void}; - - unsafe extern "C" fn capi_init(c: *mut *mut cubeb::Context, context_name: *const c_char) -> i32 { -@@ -114,21 +115,18 @@ unsafe extern "C" fn capi_stream_init(c: - state_callback: cubeb::StateCallback, - user_ptr: *mut c_void) - -> i32 { -+ fn try_stream_params_from(sp: *mut cubeb::StreamParams) -> Option { -+ if sp.is_null() { None } else { Some(unsafe { *sp }) } -+ } -+ - let mut ctx = &mut *(c as *mut backend::Context); -+ let stream_name = CStr::from_ptr(stream_name); - - match ctx.new_stream(stream_name, - input_device, -- if input_stream_params.is_null() { -- None -- } else { -- Some(*input_stream_params) -- }, -+ try_stream_params_from(input_stream_params), - output_device, -- if output_stream_params.is_null() { -- None -- } else { -- Some(*output_stream_params) -- }, -+ try_stream_params_from(output_stream_params), - latency_frames, - data_callback, - state_callback, -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/src/lib.rs 2017-08-04 13:37:46.387821728 +0200 -@@ -8,6 +8,7 @@ - #[macro_use] - extern crate cubeb_ffi as cubeb; - extern crate pulse_ffi; -+extern crate pulse; - extern crate semver; - - mod capi; -diff -up firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh.cubeb-pulse-arm firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh ---- firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh.cubeb-pulse-arm 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/media/libcubeb/cubeb-pulse-rs/update.sh 2017-08-04 13:37:46.383821740 +0200 -@@ -13,6 +13,9 @@ cp -pr $1/cubeb-ffi/src/* cubeb-ffi/src/ - test -d pulse-ffi/src || mkdir -p pulse-ffi/src - cp -pr $1/pulse-ffi/Cargo.toml pulse-ffi/ - cp -pr $1/pulse-ffi/src/* pulse-ffi/src/ -+test -d pulse-rs/src || mkdir -p pulse-rs/src -+cp -pr $1/pulse-rs/Cargo.toml pulse-rs/ -+cp -pr $1/pulse-rs/src/* pulse-rs/src/ - - if [ -d $1/.git ]; then - rev=$(cd $1 && git rev-parse --verify HEAD) -diff -up firefox-55.0/toolkit/library/gtest/rust/Cargo.lock.cubeb-pulse-arm firefox-55.0/toolkit/library/gtest/rust/Cargo.lock ---- firefox-55.0/toolkit/library/gtest/rust/Cargo.lock.cubeb-pulse-arm 2017-08-04 13:37:46.388821725 +0200 -+++ firefox-55.0/toolkit/library/gtest/rust/Cargo.lock 2017-08-04 13:59:15.592940994 +0200 -@@ -252,6 +252,7 @@ name = "cubeb-pulse" - version = "0.0.1" - dependencies = [ - "cubeb-ffi 0.0.1", -+ "pulse 0.1.0", - "pulse-ffi 0.1.0", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - ] -@@ -660,6 +661,14 @@ version = "0.1.1" - source = "registry+https://github.com/rust-lang/crates.io-index" - - [[package]] -+name = "pulse" -+version = "0.1.0" -+dependencies = [ -+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pulse-ffi 0.1.0", -+] -+ -+[[package]] - name = "pulse-ffi" - version = "0.1.0" - dependencies = [ -diff -up firefox-55.0/toolkit/library/rust/Cargo.lock.cubeb-pulse-arm firefox-55.0/toolkit/library/rust/Cargo.lock ---- firefox-55.0/toolkit/library/rust/Cargo.lock.cubeb-pulse-arm 2017-08-04 13:37:46.388821725 +0200 -+++ firefox-55.0/toolkit/library/rust/Cargo.lock 2017-08-04 13:52:24.551163669 +0200 -@@ -250,6 +250,7 @@ name = "cubeb-pulse" - version = "0.0.1" - dependencies = [ - "cubeb-ffi 0.0.1", -+ "pulse 0.1.0", - "pulse-ffi 0.1.0", - "semver 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - ] -@@ -647,6 +648,14 @@ version = "0.1.1" - source = "registry+https://github.com/rust-lang/crates.io-index" - - [[package]] -+name = "pulse" -+version = "0.1.0" -+dependencies = [ -+ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -+ "pulse-ffi 0.1.0", -+] -+ -+[[package]] - name = "pulse-ffi" - version = "0.1.0" - dependencies = [ diff --git a/build-disable-elfhack.patch b/build-disable-elfhack.patch deleted file mode 100644 index a80c551..0000000 --- a/build-disable-elfhack.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-65.0/toolkit/moz.configure.disable-elfhack firefox-65.0/toolkit/moz.configure ---- firefox-65.0/toolkit/moz.configure.disable-elfhack 2019-01-28 14:16:48.530345132 +0100 -+++ firefox-65.0/toolkit/moz.configure 2019-01-28 14:18:03.231029682 +0100 -@@ -1036,7 +1036,7 @@ with only_when('--enable-compile-environ - help='{Enable|Disable} elf hacks') - - set_config('USE_ELF_HACK', -- depends_if('--enable-elf-hack')(lambda _: True)) -+ depends_if('--enable-elf-hack')(lambda _: False)) - - - @depends(check_build_environment) diff --git a/build-ppc-jit.patch b/build-ppc-jit.patch deleted file mode 100644 index a9dc6d1..0000000 --- a/build-ppc-jit.patch +++ /dev/null @@ -1,51 +0,0 @@ -diff -up firefox-55.0/js/src/jit/MIR.h.old firefox-55.0/js/src/jit/MIR.h ---- firefox-55.0/js/src/jit/MIR.h.old 2017-08-08 14:04:44.528460099 +0200 -+++ firefox-55.0/js/src/jit/MIR.h 2017-08-08 14:05:11.045364831 +0200 -@@ -12434,7 +12434,7 @@ class MNearbyInt - TRIVIAL_NEW_WRAPPERS - - static bool HasAssemblerSupport(RoundingMode mode) { -- return Assembler::HasRoundInstruction(mode); -+ return false; - } - - RoundingMode roundingMode() const { return roundingMode_; } -diff -up firefox-55.0/js/src/jit/ExecutableAllocator.h.old firefox-55.0/js/src/jit/ExecutableAllocator.h ---- firefox-55.0/js/src/jit/ExecutableAllocator.h.old 2017-08-09 09:24:18.784983505 +0200 -+++ firefox-55.0/js/src/jit/ExecutableAllocator.h 2017-08-09 09:28:01.471100075 +0200 -@@ -307,6 +307,10 @@ class ExecutableAllocator - { - sync_instruction_memory((caddr_t)code, size); - } -+#else -+ static void cacheFlush(void*, size_t) -+ { -+ } - #endif - - private: -diff -up firefox-55.0/js/src/wasm/WasmBuiltins.cpp.old firefox-55.0/js/src/wasm/WasmBuiltins.cpp ---- firefox-55.0/js/src/wasm/WasmBuiltins.cpp.old 2017-08-09 12:50:46.877450765 +0200 -+++ firefox-55.0/js/src/wasm/WasmBuiltins.cpp 2017-08-09 12:50:59.725406974 +0200 -@@ -881,7 +881,6 @@ wasm::EnsureBuiltinThunksInitialized() - MOZ_ASSERT(!masm.numSymbolicAccesses()); - #endif - -- ExecutableAllocator::cacheFlush(thunks->codeBase, thunks->codeSize); - if (!ExecutableAllocator::makeExecutable(thunks->codeBase, thunks->codeSize)) - return false; - -diff -up firefox-55.0/js/src/wasm/WasmCode.cpp.old firefox-55.0/js/src/wasm/WasmCode.cpp ---- firefox-55.0/js/src/wasm/WasmCode.cpp.old 2017-08-09 12:50:37.205483731 +0200 -+++ firefox-55.0/js/src/wasm/WasmCode.cpp 2017-08-09 12:51:10.365370708 +0200 -@@ -287,8 +287,6 @@ CodeSegment::initialize(Tier tier, - if (!StaticallyLink(*this, linkData)) - return false; - -- ExecutableAllocator::cacheFlush(bytes_.get(), RoundupCodeLength(codeLength)); -- - // Reprotect the whole region to avoid having separate RW and RX mappings. - if (!ExecutableAllocator::makeExecutable(bytes_.get(), RoundupCodeLength(codeLength))) - return false; -diff -up firefox-55.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium.old firefox-55.0/media/libyuv/libyuv/tools_libyuv/autoroller/unittests/testdata/DEPS.chromium -diff -up firefox-55.0/media/webrtc/trunk/Makefile.old firefox-55.0/media/webrtc/trunk/Makefile diff --git a/build-rust-ppc64le.patch b/build-rust-ppc64le.patch deleted file mode 100644 index 2474c35..0000000 --- a/build-rust-ppc64le.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff -up firefox-55.0/build/moz.configure/rust.configure.rust-ppc64le firefox-55.0/build/moz.configure/rust.configure ---- firefox-55.0/build/moz.configure/rust.configure.rust-ppc64le 2017-07-31 18:20:49.000000000 +0200 -+++ firefox-55.0/build/moz.configure/rust.configure 2017-08-02 10:19:03.254220003 +0200 -@@ -151,6 +151,9 @@ def rust_triple_alias(host_or_target): - ('sparc64', 'Linux'): 'sparc64-unknown-linux-gnu', - ('x86', 'Linux'): 'i686-unknown-linux-gnu', - ('x86_64', 'Linux'): 'x86_64-unknown-linux-gnu', -+ ('ppc64le', 'Linux'): 'powerpc64le-unknown-linux-gnu', -+ ('ppc64', 'Linux'): 'powerpc64-unknown-linux-gnu', -+ ('s390x', 'Linux'): 's390x-unknown-linux-gnu', - # OS X - ('x86', 'OSX'): 'i686-apple-darwin', - ('x86_64', 'OSX'): 'x86_64-apple-darwin', -@@ -174,8 +177,10 @@ def rust_triple_alias(host_or_target): - ('sparc64', 'SunOS'): 'sparcv9-sun-solaris', - }.get((host_or_target.cpu, os_or_kernel), None) - -+ if (rustc_target == 'powerpc64-unknown-linux-gnu' and host_or_target.endianness == 'little'): -+ rustc_target = 'powerpc64le-unknown-linux-gnu' - if rustc_target is None: -- die("Don't know how to translate {} for rustc".format(host_or_target.alias)) -+ die("Don't know how to translate {} for rustc, cpu: {}, os: {}".format(target.alias, target.cpu, os_or_kernel)) - - # Check to see whether our rustc has a reasonably functional stdlib - # for our chosen target. diff --git a/build-seccomp.patch b/build-seccomp.patch new file mode 100644 index 0000000..b57f65a --- /dev/null +++ b/build-seccomp.patch @@ -0,0 +1,11 @@ +diff -up thunderbird-145.0/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h.seccomp thunderbird-145.0/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h +--- thunderbird-145.0/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h.seccomp 2025-12-09 13:42:31.378958842 +0100 ++++ thunderbird-145.0/security/sandbox/chromium/sandbox/linux/system_headers/linux_seccomp.h 2025-12-09 13:42:37.886937626 +0100 +@@ -6,6 +6,7 @@ + #define SANDBOX_LINUX_SYSTEM_HEADERS_LINUX_SECCOMP_H_ + + #include ++#include + #include + + #include "build/build_config.h" diff --git a/disable-openh264-download.patch b/disable-openh264-download.patch index 028b730..0631850 100644 --- a/disable-openh264-download.patch +++ b/disable-openh264-download.patch @@ -1,32 +1,30 @@ -diff -up firefox-81.0/toolkit/modules/GMPInstallManager.jsm.old firefox-81.0/toolkit/modules/GMPInstallManager.jsm ---- firefox-81.0/toolkit/modules/GMPInstallManager.jsm.old 2020-09-25 10:39:04.769458703 +0200 -+++ firefox-81.0/toolkit/modules/GMPInstallManager.jsm 2020-09-25 10:39:22.038504747 +0200 -@@ -54,10 +54,6 @@ function getScopedLogger(prefix) { - - const LOCAL_GMP_SOURCES = [ - { -- id: "gmp-gmpopenh264", -- src: "chrome://global/content/gmp-sources/openh264.json", -- }, -- { - id: "gmp-widevinecdm", - src: "chrome://global/content/gmp-sources/widevinecdm.json", - }, -diff --git a/toolkit/content/jar.mn b/toolkit/content/jar.mn ---- a/toolkit/content/jar.mn -+++ b/toolkit/content/jar.mn -@@ -108,7 +108,6 @@ toolkit.jar: +diff -up firefox-121.0/toolkit/content/jar.mn.disable-openh264-download firefox-121.0/toolkit/content/jar.mn +--- firefox-121.0/toolkit/content/jar.mn.disable-openh264-download 2023-12-18 20:15:04.352014249 +0100 ++++ firefox-121.0/toolkit/content/jar.mn 2023-12-18 20:19:26.857929200 +0100 +@@ -130,7 +130,6 @@ toolkit.jar: #ifdef XP_MACOSX content/global/macWindowMenu.js #endif - content/global/gmp-sources/openh264.json (gmp-sources/openh264.json) content/global/gmp-sources/widevinecdm.json (gmp-sources/widevinecdm.json) + content/global/gmp-sources/widevinecdm_l1.json (gmp-sources/widevinecdm_l1.json) - # Third party files -diff --git a/toolkit/modules/GMPInstallManager.jsm b/toolkit/modules/GMPInstallManager.jsm ---- a/toolkit/modules/GMPInstallManager.jsm -+++ b/toolkit/modules/GMPInstallManager.jsm -@@ -238,6 +234,9 @@ GMPInstallManager.prototype = { +diff -up firefox-121.0/toolkit/modules/GMPInstallManager.sys.mjs.disable-openh264-download firefox-121.0/toolkit/modules/GMPInstallManager.sys.mjs +--- firefox-121.0/toolkit/modules/GMPInstallManager.sys.mjs.disable-openh264-download 2023-12-11 21:42:21.000000000 +0100 ++++ firefox-121.0/toolkit/modules/GMPInstallManager.sys.mjs 2023-12-18 20:18:52.665768579 +0100 +@@ -35,11 +35,6 @@ function getScopedLogger(prefix) { + + const LOCAL_GMP_SOURCES = [ + { +- id: "gmp-gmpopenh264", +- src: "chrome://global/content/gmp-sources/openh264.json", +- installByDefault: true, +- }, +- { + id: "gmp-widevinecdm", + src: "chrome://global/content/gmp-sources/widevinecdm.json", + installByDefault: true, +@@ -421,6 +416,9 @@ GMPInstallManager.prototype = { * downloaderr, verifyerr or previouserrorencountered */ installAddon(gmpAddon) { @@ -36,4 +34,3 @@ diff --git a/toolkit/modules/GMPInstallManager.jsm b/toolkit/modules/GMPInstallM if (this._deferred) { let log = getScopedLogger("GMPInstallManager.installAddon"); log.error("previous error encountered"); - diff --git a/distribution.ini b/distribution.ini deleted file mode 100644 index 11f1f96..0000000 --- a/distribution.ini +++ /dev/null @@ -1,9 +0,0 @@ -[Global] -id=fedora -version=1.0 -about=Mozilla Firefox for Fedora - -[Preferences] -app.distributor=fedora -app.distributor.channel=fedora -app.partner.fedora=fedora diff --git a/distribution.ini.in b/distribution.ini.in new file mode 100644 index 0000000..0eaacc7 --- /dev/null +++ b/distribution.ini.in @@ -0,0 +1,9 @@ +[Global] +id=__ID__ +version=1.0 +about=Mozilla Firefox for __NAME__ + +[Preferences] +app.distributor=__ID__ +app.distributor.channel=__ID__ +app.partner.fedora=__ID__ 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/fedora-customization.patch b/fedora-customization.patch new file mode 100644 index 0000000..395f48d --- /dev/null +++ b/fedora-customization.patch @@ -0,0 +1,17 @@ +diff -up firefox-124.0/toolkit/xre/nsAppRunner.cpp.fedora-customization firefox-124.0/toolkit/xre/nsAppRunner.cpp +diff -up firefox-124.0/widget/gtk/nsWindow.cpp.fedora-customization firefox-124.0/widget/gtk/nsWindow.cpp +--- firefox-124.0/widget/gtk/nsWindow.cpp.fedora-customization 2024-03-13 12:35:57.098591719 +0100 ++++ firefox-124.0/widget/gtk/nsWindow.cpp 2024-03-13 12:43:17.375928494 +0100 +@@ -3459,6 +3459,12 @@ nsresult nsWindow::SetTitle(const nsAStr + return NS_OK; + } + ++ const char* appTitle = getenv("MOZ_APP_TITLE"); ++ if (appTitle) { ++ gtk_window_set_title(GTK_WINDOW(mShell), appTitle); ++ return NS_OK; ++ } ++ + // convert the string into utf8 and set the title. + #define UTF8_FOLLOWBYTE(ch) (((ch) & 0xC0) == 0x80) + NS_ConvertUTF16toUTF8 titleUTF8(aTitle); diff --git a/fedora-shebang-build.patch b/fedora-shebang-build.patch deleted file mode 100644 index 9ade86c..0000000 --- a/fedora-shebang-build.patch +++ /dev/null @@ -1,9 +0,0 @@ -diff -up firefox-73.0/build/unix/run-mozilla.sh.old firefox-73.0/build/unix/run-mozilla.sh ---- firefox-73.0/build/unix/run-mozilla.sh.old 2020-02-12 09:58:00.150895904 +0100 -+++ firefox-73.0/build/unix/run-mozilla.sh 2020-02-12 09:58:06.505860696 +0100 -@@ -1,4 +1,4 @@ --#!/bin/sh -+#!/usr/bin/sh - # - # This Source Code Form is subject to the terms of the Mozilla Public - # License, v. 2.0. If a copy of the MPL was not distributed with this diff --git a/firefox-disable-ffvpx-with-vapi.patch b/firefox-disable-ffvpx-with-vapi.patch deleted file mode 100644 index dfe6dd8..0000000 --- a/firefox-disable-ffvpx-with-vapi.patch +++ /dev/null @@ -1,29 +0,0 @@ -diff -up firefox-81.0/dom/media/platforms/PDMFactory.cpp.firefox-disable-ffvpx-with-vapi firefox-81.0/dom/media/platforms/PDMFactory.cpp ---- firefox-81.0/dom/media/platforms/PDMFactory.cpp.firefox-disable-ffvpx-with-vapi 2020-09-17 02:32:43.000000000 +0200 -+++ firefox-81.0/dom/media/platforms/PDMFactory.cpp 2020-09-21 10:30:29.393903183 +0200 -@@ -371,12 +371,6 @@ void PDMFactory::CreatePDMs() { - StartupPDM(m); - } - #endif --#ifdef MOZ_FFVPX -- if (StaticPrefs::media_ffvpx_enabled()) { -- m = FFVPXRuntimeLinker::CreateDecoderModule(); -- StartupPDM(m); -- } --#endif - #ifdef MOZ_FFMPEG - if (StaticPrefs::media_ffmpeg_enabled()) { - m = FFmpegRuntimeLinker::CreateDecoderModule(); -@@ -385,6 +379,12 @@ void PDMFactory::CreatePDMs() { - mFFmpegFailedToLoad = false; - } - #endif -+#ifdef MOZ_FFVPX -+ if (StaticPrefs::media_ffvpx_enabled()) { -+ m = FFVPXRuntimeLinker::CreateDecoderModule(); -+ StartupPDM(m); -+ } -+#endif - #ifdef MOZ_WIDGET_ANDROID - if (StaticPrefs::media_android_media_codec_enabled()) { - m = new AndroidDecoderModule(); diff --git a/firefox-enable-addons.patch b/firefox-enable-addons.patch index 15d0707..75e1403 100644 --- a/firefox-enable-addons.patch +++ b/firefox-enable-addons.patch @@ -1,10 +1,10 @@ -diff -up firefox-55.0/browser/app/profile/firefox.js.addons firefox-55.0/browser/app/profile/firefox.js ---- firefox-55.0/browser/app/profile/firefox.js.addons 2017-08-02 10:58:30.566363833 +0200 -+++ firefox-55.0/browser/app/profile/firefox.js 2017-08-02 10:59:15.377216959 +0200 -@@ -65,7 +65,8 @@ pref("extensions.systemAddon.update.url" +diff -up firefox-125.0/browser/app/profile/firefox.js.addons firefox-125.0/browser/app/profile/firefox.js +--- firefox-125.0/browser/app/profile/firefox.js.addons 2024-04-09 10:34:30.728405003 +0200 ++++ firefox-125.0/browser/app/profile/firefox.js 2024-04-09 10:36:01.444584632 +0200 +@@ -58,7 +58,8 @@ pref("extensions.systemAddon.update.enab // Disable add-ons that are not installed by the user in all scopes by default. - // See the SCOPE constants in AddonManager.jsm for values to use here. + // See the SCOPE constants in AddonManager.sys.mjs for values to use here. -pref("extensions.autoDisableScopes", 15); +pref("extensions.autoDisableScopes", 0); +pref("extensions.showMismatchUI", false); diff --git a/firefox-fedora-ua.patch b/firefox-fedora-ua.patch deleted file mode 100644 index 7f1f554..0000000 --- a/firefox-fedora-ua.patch +++ /dev/null @@ -1,19 +0,0 @@ -diff -up firefox-65.0/netwerk/protocol/http/nsHttpHandler.cpp.fedora-ua firefox-65.0/netwerk/protocol/http/nsHttpHandler.cpp ---- firefox-65.0/netwerk/protocol/http/nsHttpHandler.cpp.fedora-ua 2019-01-28 14:28:35.806375063 +0100 -+++ firefox-65.0/netwerk/protocol/http/nsHttpHandler.cpp 2019-01-28 14:30:25.886917219 +0100 -@@ -873,6 +873,7 @@ void nsHttpHandler::BuildUserAgent() { - mUserAgent.SetCapacity(mLegacyAppName.Length() + mLegacyAppVersion.Length() + - #ifndef UA_SPARE_PLATFORM - mPlatform.Length() + -+ mPlatform.Length() + 8 + - #endif - mOscpu.Length() + mMisc.Length() + mProduct.Length() + - mProductSub.Length() + mAppName.Length() + -@@ -891,6 +892,7 @@ void nsHttpHandler::BuildUserAgent() { - if (!mPlatform.IsEmpty()) { - mUserAgent += mPlatform; - mUserAgent.AppendLiteral("; "); -+ mUserAgent.AppendLiteral("Fedora; "); - } - #endif - if (!mCompatDevice.IsEmpty()) { diff --git a/firefox-gcc-13-build.patch b/firefox-gcc-13-build.patch new file mode 100644 index 0000000..8512b76 --- /dev/null +++ b/firefox-gcc-13-build.patch @@ -0,0 +1,24 @@ +--- firefox-109.0.1/gfx/2d/Rect.h.old 2023-02-07 09:44:24.946279843 +0100 ++++ firefox-109.0.1/gfx/2d/Rect.h 2023-02-07 09:44:47.969032049 +0100 +@@ -324,8 +324,8 @@ IntRectTyped RoundedToInt(const R + + template + bool RectIsInt32Safe(const RectTyped& aRect) { +- float min = (float)std::numeric_limits::min(); +- float max = (float)std::numeric_limits::max(); ++ float min = (float)std::numeric_limits::min(); ++ float max = (float)std::numeric_limits::max(); + return aRect.x > min && aRect.y > min && aRect.width < max && + aRect.height < max && aRect.XMost() < max && aRect.YMost() < max; + } +diff -up firefox-109.0.1/toolkit/components/telemetry/pingsender/pingsender.cpp.old firefox-109.0.1/toolkit/components/telemetry/pingsender/pingsender.cpp +--- firefox-109.0.1/toolkit/components/telemetry/pingsender/pingsender.cpp.old 2023-02-07 11:03:41.788720090 +0100 ++++ firefox-109.0.1/toolkit/components/telemetry/pingsender/pingsender.cpp 2023-02-07 11:04:29.195345659 +0100 +@@ -10,6 +10,7 @@ + #include + #include + #include ++#include + + #include + diff --git a/firefox-gcc-15.0-s390.patch b/firefox-gcc-15.0-s390.patch new file mode 100644 index 0000000..9cf82fc --- /dev/null +++ b/firefox-gcc-15.0-s390.patch @@ -0,0 +1,19 @@ +diff -up firefox-137.0.2/toolkit/components/protobuf/src/google/protobuf/port_def.inc.s390 firefox-137.0.2/toolkit/components/protobuf/src/google/protobuf/port_def.inc +--- firefox-137.0.2/toolkit/components/protobuf/src/google/protobuf/port_def.inc.s390 2025-04-22 11:42:00.650759505 +0200 ++++ firefox-137.0.2/toolkit/components/protobuf/src/google/protobuf/port_def.inc 2025-04-22 11:46:02.522031338 +0200 +@@ -257,12 +257,14 @@ + #if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \ + !defined(_ARCH_PPC) && !defined(__wasm__) && \ + !(defined(_MSC_VER) && defined(_M_IX86)) && \ +- !(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24) ++ !(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24) && \ ++ !defined(__s390__) + # ifndef PROTO2_OPENSOURCE + // Compilation fails on ARM32: b/195943306 + // Compilation fails on powerpc64le: b/187985113 + // Compilation fails on X86 Windows: + // https://github.com/llvm/llvm-project/issues/53271 ++// Compilation fails on S390 for calls with more than 4 arguments + # endif + #define PROTOBUF_MUSTTAIL [[clang::musttail]] + #define PROTOBUF_TAILCALL true diff --git a/firefox-gcc-always-inline.patch b/firefox-gcc-always-inline.patch new file mode 100644 index 0000000..d7af60f --- /dev/null +++ b/firefox-gcc-always-inline.patch @@ -0,0 +1,14 @@ +diff -up firefox-114.0.2/gfx/wr/swgl/src/gl.cc.inline firefox-114.0.2/gfx/wr/swgl/src/gl.cc +--- firefox-114.0.2/gfx/wr/swgl/src/gl.cc.inline 2023-06-22 11:08:53.294593327 +0200 ++++ firefox-114.0.2/gfx/wr/swgl/src/gl.cc 2023-06-22 11:12:43.663486734 +0200 +@@ -58,9 +58,7 @@ WINBASEAPI BOOL WINAPI QueryPerformanceF + } + + #else +-// 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) ++# if defined(__clang__) || defined (__GNUC__) || defined(NDEBUG) + # define ALWAYS_INLINE __attribute__((always_inline)) inline + # else + # define ALWAYS_INLINE inline diff --git a/firefox-i686-build.patch b/firefox-i686-build.patch new file mode 100644 index 0000000..320199f --- /dev/null +++ b/firefox-i686-build.patch @@ -0,0 +1,12 @@ +diff -up firefox-105.0/mozglue/misc/SIMD_avx2.cpp.old firefox-105.0/mozglue/misc/SIMD_avx2.cpp +--- firefox-105.0/mozglue/misc/SIMD_avx2.cpp.old 2022-09-22 21:35:07.006221995 +0200 ++++ firefox-105.0/mozglue/misc/SIMD_avx2.cpp 2022-09-22 21:36:12.972480517 +0200 +@@ -55,7 +55,7 @@ __m256i CmpEq256(__m256i a, __m256i b) { + return _mm256_cmpeq_epi64(a, b); + } + +-# if defined(__GNUC__) && !defined(__clang__) ++# if 0 + + // See the comment in SIMD.cpp over Load32BitsIntoXMM. This is just adapted + // from that workaround. Testing this, it also yields the correct instructions diff --git a/firefox-locale-debug.patch b/firefox-locale-debug.patch deleted file mode 100644 index 35de02f..0000000 --- a/firefox-locale-debug.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-75.0/intl/locale/LocaleService.cpp.locale-debug firefox-75.0/intl/locale/LocaleService.cpp ---- firefox-75.0/intl/locale/LocaleService.cpp.locale-debug 2020-04-06 22:42:20.196799809 +0200 -+++ firefox-75.0/intl/locale/LocaleService.cpp 2020-04-06 22:43:02.522530317 +0200 -@@ -372,8 +372,6 @@ LocaleService::GetDefaultLocale(nsACStri - // just use our hard-coded default below. - GetGREFileContents("update.locale", &locale); - locale.Trim(" \t\n\r"); -- // This should never be empty. -- MOZ_ASSERT(!locale.IsEmpty()); - if (CanonicalizeLanguageId(locale)) { - mDefaultLocale.Assign(locale); - } diff --git a/firefox-mozconfig b/firefox-mozconfig index 0528687..2736abc 100644 --- a/firefox-mozconfig +++ b/firefox-mozconfig @@ -2,7 +2,6 @@ ac_add_options --with-system-zlib ac_add_options --disable-strip -#ac_add_options --enable-libnotify ac_add_options --enable-necko-wifi ac_add_options --disable-updater ac_add_options --enable-chrome-format=omni @@ -11,11 +10,11 @@ ac_add_options --enable-av1 ac_add_options --without-system-icu ac_add_options --enable-release ac_add_options --update-channel=release -# Workaround for mozbz#1341234 -ac_add_options BINDGEN_CFLAGS="$(pkg-config nspr pixman-1 --cflags)" ac_add_options --allow-addon-sideload ac_add_options --with-system-fdk-aac ac_add_options --enable-js-shell +ac_add_options --with-unsigned-addon-scopes=app,system +ac_add_options --disable-bootstrap export BUILD_OFFICIAL=1 export MOZILLA_OFFICIAL=1 diff --git a/firefox-nss-addon-hack.patch b/firefox-nss-addon-hack.patch new file mode 100644 index 0000000..0322707 --- /dev/null +++ b/firefox-nss-addon-hack.patch @@ -0,0 +1,19 @@ +diff -up firefox-84.0.2/security/certverifier/NSSCertDBTrustDomain.cpp.nss-hack firefox-84.0.2/security/certverifier/NSSCertDBTrustDomain.cpp +--- firefox-84.0.2/security/certverifier/NSSCertDBTrustDomain.cpp.nss-hack 2021-01-11 12:12:02.585514543 +0100 ++++ firefox-84.0.2/security/certverifier/NSSCertDBTrustDomain.cpp 2021-01-11 12:47:50.345984582 +0100 +@@ -1619,6 +1619,15 @@ SECStatus InitializeNSS(const nsACString + return srv; + } + ++ /* Sets the NSS_USE_ALG_IN_ANY_SIGNATURE bit. ++ * does not change NSS_USE_ALG_IN_CERT_SIGNATURE, ++ * so policy will still disable use of sha1 in ++ * certificate related signature processing. */ ++ srv = NSS_SetAlgorithmPolicy(SEC_OID_SHA1, NSS_USE_ALG_IN_ANY_SIGNATURE, 0); ++ if (srv != SECSuccess) { ++ NS_WARNING("Unable to use SHA1 for Add-ons, expect broken/disabled Add-ons. See https://bugzilla.redhat.com/show_bug.cgi?id=1908018 for details."); ++ } ++ + if (nssDbConfig == NSSDBConfig::ReadWrite) { + UniquePK11SlotInfo slot(PK11_GetInternalKeySlot()); + if (!slot) { diff --git a/firefox-nss-version.patch b/firefox-nss-version.patch deleted file mode 100644 index fee93bb..0000000 --- a/firefox-nss-version.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-78.0/toolkit/moz.configure.nss-version firefox-78.0/toolkit/moz.configure ---- firefox-78.0/toolkit/moz.configure.nss-version 2020-06-30 08:47:09.657501414 +0200 -+++ firefox-78.0/toolkit/moz.configure 2020-06-30 08:47:12.652510169 +0200 -@@ -2089,7 +2089,7 @@ option('--with-system-nss', help='Use sy - - imply_option('--with-system-nspr', True, when='--with-system-nss') - --nss_pkg = pkg_check_modules('NSS', 'nss >= 3.53.1', when='--with-system-nss', config=False) -+nss_pkg = pkg_check_modules('NSS', 'nss >= 3.53.0', when='--with-system-nss', config=False) - - set_config('MOZ_SYSTEM_NSS', True, when='--with-system-nss') - diff --git a/firefox-redhat-default-prefs.js b/firefox-redhat-default-prefs.js index 89afe2c..979f21b 100644 --- a/firefox-redhat-default-prefs.js +++ b/firefox-redhat-default-prefs.js @@ -2,13 +2,11 @@ pref("app.update.auto", false); pref("app.update.enabled", false); pref("app.update.autoInstallEnabled", false); pref("general.smoothScroll", true); -pref("intl.locale.matchOS", true); pref("intl.locale.requested", ""); pref("toolkit.storage.synchronous", 0); pref("toolkit.networkmanager.disable", false); pref("offline.autoDetect", true); pref("browser.backspace_action", 2); -pref("browser.display.use_system_colors", true); pref("browser.download.folderList", 1); pref("browser.link.open_external", 3); pref("browser.shell.checkDefaultBrowser", false); @@ -18,20 +16,18 @@ pref("ui.SpellCheckerUnderlineStyle", 1); pref("startup.homepage_override_url", ""); pref("browser.startup.homepage", "data:text/plain,browser.startup.homepage=https://start.fedoraproject.org/"); pref("browser.newtabpage.pinned", '[{"url":"https://start.fedoraproject.org/","title":"Fedora Project - Start Page"}]'); -pref("geo.wifi.uri", "https://location.services.mozilla.com/v1/geolocate?key=%MOZILLA_API_KEY%"); pref("media.gmp-gmpopenh264.provider.enabled",false); pref("media.gmp-gmpopenh264.autoupdate",false); pref("media.gmp-gmpopenh264.enabled",false); pref("media.gmp.decoder.enabled", true); pref("plugins.notifyMissingFlash", false); -/* See https://bugzilla.redhat.com/show_bug.cgi?id=1226489 */ -pref("browser.display.use_system_colors", false); -pref("layers.use-image-offscreen-surfaces", false); /* Allow sending credetials to all https:// sites */ pref("network.negotiate-auth.trusted-uris", "https://"); -pref("spellchecker.dictionary_path","/usr/share/myspell"); +pref("spellchecker.dictionary_path","/usr/share/hunspell"); /* Disable DoH by default */ pref("network.trr.mode", 5); /* Enable per-user policy dir, see mozbz#1583466 */ pref("browser.policies.perUserDir", true); -pref("browser.gnome-search-provider.enabled",true); \ No newline at end of file +pref("browser.gnome-search-provider.enabled",true); +/* Enable ffvpx playback for WebRTC */ +pref("media.navigator.mediadatadecoder_vpx_enabled", true); diff --git a/firefox-search-provider.ini b/firefox-search-provider.ini deleted file mode 100644 index 3868e3d..0000000 --- a/firefox-search-provider.ini +++ /dev/null @@ -1,5 +0,0 @@ -[Shell Search Provider] -DesktopId=firefox.desktop -BusName=org.mozilla.Firefox.SearchProvider -ObjectPath=/org/mozilla/Firefox/SearchProvider -Version=2 diff --git a/firefox-symbolic.svg b/firefox-symbolic.svg index 2078eea..8ecd135 100644 --- a/firefox-symbolic.svg +++ b/firefox-symbolic.svg @@ -1,64 +1,3 @@ - - - - - - image/svg+xml - - Gnome Symbolic Icon Theme - - - - - - - - Gnome Symbolic Icon Theme - + + diff --git a/firefox-testing.patch b/firefox-testing.patch deleted file mode 100644 index 04ef0f3..0000000 --- a/firefox-testing.patch +++ /dev/null @@ -1,60 +0,0 @@ -diff -up firefox-83.0/docshell/base/crashtests/crashtests.list.test firefox-83.0/docshell/base/crashtests/crashtests.list ---- firefox-83.0/docshell/base/crashtests/crashtests.list.test 2020-11-12 19:04:36.000000000 +0100 -+++ firefox-83.0/docshell/base/crashtests/crashtests.list 2020-11-19 10:30:26.127468382 +0100 -@@ -13,7 +13,6 @@ load 614499-1.html - load 678872-1.html - skip-if(Android) pref(dom.disable_open_during_load,false) load 914521.html # Android bug 1584562 - pref(browser.send_pings,true) asserts(0-2) load 1257730-1.html # bug 566159 --load 1331295.html - load 1341657.html - load 1584467.html - load 1614211-1.html ---- firefox-83.0/dom/media/tests/crashtests/crashtests.list.test 2020-11-19 10:42:04.960128784 +0100 -+++ firefox-83.0/dom/media/tests/crashtests/crashtests.list 2020-11-19 10:42:21.508182030 +0100 -@@ -24,7 +24,7 @@ asserts-if(Android,0-1) pref(browser.lin - asserts-if(Android,0-1) pref(browser.link.open_newwindow,2) load 1429507_2.html # window.open() in tab doesn't work for crashtest in e10s, this opens a new window instead - asserts-if(Android,0-2) load 1453030.html - load 1468451.html --skip-if(Android) load 1490700.html # No screenshare on Android -+#skip-if(Android) load 1490700.html # No screenshare on Android and Wayland - load 1505957.html - load 1509442.html - load 1511130.html -diff -up firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.old firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py ---- firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py.old 2020-11-19 11:15:59.150990819 +0100 -+++ firefox-83.0/testing/marionette/harness/marionette_harness/tests/unit/test_marionette.py 2020-11-19 11:17:53.390337862 +0100 -@@ -62,16 +62,9 @@ class TestMarionette(MarionetteTestCase) - - def test_application_update_disabled(self): - # Updates of the application should always be disabled by default -- with self.marionette.using_context("chrome"): -- update_allowed = self.marionette.execute_script(""" -- let aus = Cc['@mozilla.org/updates/update-service;1'] -- .getService(Ci.nsIApplicationUpdateService); -- return aus.canCheckForUpdates; -- """) -- -+ update_allowed = False - self.assertFalse(update_allowed) - -- - class TestContext(MarionetteTestCase): - - def setUp(self): -diff -up firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py.old firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py ---- firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py.old 2020-11-19 11:37:03.591683420 +0100 -+++ firefox-83.0/testing/web-platform/tests/tools/manifest/vcs.py 2020-11-19 11:37:18.730715053 +0100 -@@ -9,11 +9,8 @@ from six.moves.collections_abc import Mu - - from .utils import git - --try: -- from ..gitignore import gitignore --except ValueError: -- # relative import beyond toplevel throws *ValueError*! -- from gitignore import gitignore # type: ignore -+# relative import beyond toplevel throws *ValueError*! -+from gitignore import gitignore # type: ignore - - - MYPY = False diff --git a/firefox-vaapi-extra-frames.patch b/firefox-vaapi-extra-frames.patch deleted file mode 100644 index e26158a..0000000 --- a/firefox-vaapi-extra-frames.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.old firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp ---- firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp.old 2020-05-13 14:28:26.556800474 +0200 -+++ firefox-76.0.1/dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp 2020-05-13 14:28:31.562768959 +0200 -@@ -43,7 +43,7 @@ typedef int VAStatus; - #endif - - // Use some extra HW frames for potential rendering lags. --#define EXTRA_HW_FRAMES 6 -+#define EXTRA_HW_FRAMES 20 - - typedef mozilla::layers::Image Image; - typedef mozilla::layers::PlanarYCbCrImage PlanarYCbCrImage; diff --git a/firefox.1 b/firefox.1 index 556cf07..318f2af 100644 --- a/firefox.1 +++ b/firefox.1 @@ -1,4 +1,4 @@ -.TH FIREFOX 1 "November 30, 2017" firefox "Linux User's Manual" +.TH FIREFOX 1 "July 10, 2019" firefox "Linux User's Manual" .SH NAME firefox \- a Web browser for X11 derived from the Mozilla browser @@ -6,17 +6,10 @@ firefox \- a Web browser for X11 derived from the Mozilla browser .B firefox [\fIOPTIONS\fR ...] [\fIURL\fR] -.B firefox-bin -[\fIOPTIONS\fR] [\fIURL\fR] - .SH DESCRIPTION \fBMozilla Firefox\fR is an open-source web browser, designed for standards compliance, performance and portability. -.SH USAGE -\fBfirefox\fR is a simple shell script that will set up the -environment for the actual executable, \fBfirefox-bin\fR. - .SH OPTIONS A summary of the options supported by \fBfirefox\fR is included below. @@ -33,10 +26,10 @@ Make all warnings fatal .SS "Firefox options" .TP -.B \-h, \-help +.B \-h, \--help Show summary of options. .TP -.B \-v, \-version +.B \-v, \--version Print Firefox version. .TP \fB\-P\fR \fIprofile\fR @@ -63,11 +56,22 @@ Start with \fIlocale\fR resources as UI Locale. \fB\-\-safe\-mode\fR Disables extensions and themes for this session. .TP +\fB\--allow-downgrade\fR +Allows downgrading a profile. +.TP +\fB\--MOZ_LOG\fR=\fImodules\fR +Treated as \fBMOZ_LOG\fR=\fImodules\fR environment variable, overrides it. +.TP +\fB\--MOZ_LOG_FILE\fR=\fIfile\fR +Treated as \fBMOZ_LOG_FILE\fR=\fIfile\fR environment variable, overrides it. If +MOZ_LOG_FILE is not specified as an argument or as an environment variable, +logging will be written to stdout. +.TP \fB\-\-headless\fR Run without a GUI. .TP -\fB\-\-marionette\fR -Enable remote control server. +\fB\-\-save-recordings\fR +Save recordings for all content processes to a directory. .TP \fB\-\-browser\fR Open a browser window. @@ -93,8 +97,9 @@ Width and optionally height of screenshot. \fB\-\-search\fR \fIterm\fR Search \fIterm\fR with your default search engine. .TP - - +\fB\-\-setDefaultBrowser\fR +Set this app as the default browser. +.TP \fB\-\-jsconsole\fR Open the Browser Console. .TP @@ -115,19 +120,16 @@ Record drawing for a given URL. .TP \fB\-\-recording-output\fR \fIfile\fR Specify destination file for a drawing recording. -.TP -\fB\-\-setDefaultBrowser\fR -Set this app as the default browser. .SH FILES \fI/usr/bin/firefox\fR - shell script wrapping \fBfirefox\fR .br -\fI/usr/lib64/firefox/firefox-bin\fR - \fBfirefox\fR +\fI/usr/lib64/firefox/firefox\fR - \fBfirefox\fR executable .SH VERSION -57.0 +68.0 .SH BUGS To report a bug, please visit \fIhttp://bugzilla.mozilla.org/\fR diff --git a/firefox.desktop b/firefox.desktop index 35c2c48..bd09aa8 100644 --- a/firefox.desktop +++ b/firefox.desktop @@ -1,47 +1,520 @@ [Desktop Entry] Version=1.0 Name=Firefox -GenericName=Web Browser -GenericName[ca]=Navegador web -GenericName[cs]=Webový prohlížeč -GenericName[es]=Navegador web -GenericName[fa]=مرورگر اینترنتی -GenericName[fi]=WWW-selain -GenericName[fr]=Navigateur Web -GenericName[hu]=Webböngésző -GenericName[it]=Browser Web -GenericName[ja]=ウェブ・ブラウザ -GenericName[ko]=웹 브라우저 -GenericName[nb]=Nettleser -GenericName[nl]=Webbrowser -GenericName[nn]=Nettlesar -GenericName[no]=Nettleser -GenericName[pl]=Przeglądarka WWW -GenericName[pt]=Navegador Web -GenericName[pt_BR]=Navegador Web -GenericName[sk]=Internetový prehliadač -GenericName[sv]=Webbläsare -Comment=Browse the Web -Comment[ca]=Navegueu per el web +Name[ach]=Firefox +Name[af]=Firefox +Name[an]=Firefox +Name[ar]=Firefox +Name[ast]=Firefox +Name[az]=Firefox +Name[be]=Firefox +Name[bg]=Firefox +Name[bn]=Firefox +Name[br]=Firefox +Name[bs]=Firefox +Name[ca]=Firefox +Name[ca_valencia]=Firefox +Name[cak]=Firefox +Name[cs]=Firefox +Name[cy]=Firefox +Name[da]=Firefox +Name[de]=Firefox +Name[dsb]=Firefox +Name[el]=Firefox +Name[en_CA]=Firefox +Name[en_GB]=Firefox +Name[eo]=Firefox +Name[es_AR]=Firefox +Name[es_CL]=Firefox +Name[es_ES]=Firefox +Name[es_MX]=Firefox +Name[et]=Firefox +Name[eu]=Firefox +Name[fa]=Firefox +Name[ff]=Firefox +Name[fi]=Firefox +Name[fr]=Firefox +Name[fur]=Firefox +Name[fy_NL]=Firefox +Name[ga_IE]=Firefox +Name[gd]=Firefox +Name[gl]=Firefox +Name[gn]=Firefox +Name[gu_IN]=Firefox +Name[he]=Firefox +Name[hi_IN]=Firefox +Name[hr]=Firefox +Name[hsb]=Firefox +Name[hu]=Firefox +Name[hy_AM]=Firefox +Name[ia]=Firefox +Name[id]=Firefox +Name[is]=Firefox +Name[it]=Firefox +Name[ja]=Firefox +Name[ka]=Firefox +Name[kab]=Firefox +Name[kk]=Firefox +Name[km]=Firefox +Name[kn]=Firefox +Name[ko]=Firefox +Name[lij]=Firefox +Name[lt]=Firefox +Name[lv]=Firefox +Name[mk]=Firefox +Name[mr]=Firefox +Name[ms]=Firefox +Name[my]=Firefox +Name[nb_NO]=Firefox +Name[ne_NP]=Firefox +Name[nl]=Firefox +Name[nn_NO]=Firefox +Name[oc]=Firefox +Name[pa_IN]=Firefox +Name[pl]=Firefox +Name[pt_BR]=Firefox +Name[pt_PT]=Firefox +Name[rm]=Firefox +Name[ro]=Firefox +Name[ru]=Firefox +Name[sat]=Firefox +Name[sc]=Firefox +Name[sco]=Firefox +Name[si]=Firefox +Name[sk]=Firefox +Name[skr]=Firefox +Name[sl]=Firefox +Name[son]=Firefox +Name[sq]=Firefox +Name[sr]=Firefox +Name[sv_SE]=Firefox +Name[szl]=Firefox +Name[ta]=Firefox +Name[te]=Firefox +Name[tg]=Firefox +Name[th]=Firefox +Name[tl]=Firefox +Name[tr]=Firefox +Name[trs]=Firefox +Name[uk]=Firefox +Name[ur]=Firefox +Name[uz]=Firefox +Name[vi]=Firefox +Name[xh]=Firefox +Name[zh_CN]=Firefox +Name[zh_TW]=Firefox +Comment=Browse the World Wide Web +Comment[ach]=Browse the World Wide Web +Comment[af]=Browse the World Wide Web +Comment[an]=Browse the World Wide Web +Comment[ar]=تصفح شبكة الوِب العالمية +Comment[ast]=Browse the World Wide Web +Comment[az]=Browse the World Wide Web +Comment[be]=Аглядайце Сеціва +Comment[bg]=Разгледайте световната мрежа +Comment[bn]=ওয়ার্ল্ড ওয়াইড ওয়েব ব্রাউজ করুন +Comment[br]=Ergerzhout ar World Wide Web +Comment[bs]=Pretražujte World Wide Web +Comment[ca]=Navegeu pel Web +Comment[ca_valencia]=Browse the World Wide Web +Comment[cak]=Tok chupam Word Wide Web Comment[cs]=Prohlížení stránek World Wide Webu +Comment[cy]=Pori'r We Fyd Eang +Comment[da]=Brug internettet Comment[de]=Im Internet surfen -Comment[es]=Navegue por la web -Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید -Comment[fi]=Selaa Internetin WWW-sivuja -Comment[fr]=Navigue sur Internet -Comment[hu]=A világháló böngészése -Comment[it]=Esplora il web -Comment[ja]=ウェブを閲覧します -Comment[ko]=웹을 돌아 다닙니다 -Comment[nb]=Surf på nettet -Comment[nl]=Verken het internet -Comment[nn]=Surf på nettet -Comment[no]=Surf på nettet -Comment[pl]=Przeglądanie stron WWW -Comment[pt]=Navegue na Internet -Comment[pt_BR]=Navegue na Internet -Comment[sk]=Prehliadanie internetu -Comment[sv]=Surfa på webben +Comment[dsb]=Pśeglědajśo World Wide Web +Comment[el]=Περιηγηθείτε στον παγκόσμιο ιστό +Comment[en_CA]=Browse the World Wide Web +Comment[en_GB]=Browse the World Wide Web +Comment[eo]=Retumi en la reto +Comment[es_AR]=Navegar la World Wide Web +Comment[es_CL]=Navegar por la World Wide Web +Comment[es_ES]=Navegar por la web +Comment[es_MX]=Navegar por la web +Comment[et]=Browse the World Wide Web +Comment[eu]=Arakatu World Wide Web-a +Comment[fa]=Browse the World Wide Web +Comment[ff]=Browse the World Wide Web +Comment[fi]=Selaa Internetiä +Comment[fr]=Naviguer sur le Web +Comment[fur]=Navighe sul Web +Comment[fy_NL]=Navigearje op it wrâldwide web +Comment[ga_IE]=Browse the World Wide Web +Comment[gd]=Rùraich lìon na cruinne +Comment[gl]=Navegar pola World Wide Web +Comment[gn]=Eikundaha World Wide Web rupi +Comment[gu_IN]=Browse the World Wide Web +Comment[he]=גלישה באינטרנט +Comment[hi_IN]=Browse the World Wide Web +Comment[hr]=Pregledaj World Wide Web +Comment[hsb]=Přehladajće World Wide Web +Comment[hu]=Böngésszen a világhálón +Comment[hy_AM]=Զննի՛ր համաշխարհային սարդոստայնը +Comment[ia]=Navigar sur le Web +Comment[id]=Jelajahi World Wide Web +Comment[is]=Vafraðu um veraldarvefinn +Comment[it]=Naviga sul Web +Comment[ja]=World Wide Web をブラウジング +Comment[ka]=მსოფლიო ქსელთან წვდომა +Comment[kab]=Inig deg Web +Comment[kk]=Ғаламторды шолу +Comment[km]=Browse the World Wide Web +Comment[kn]=Browse the World Wide Web +Comment[ko]=월드 와이드 웹 탐색 +Comment[lij]=Browse the World Wide Web +Comment[lt]=Browse the World Wide Web +Comment[lv]=Pārlūkojiet globālo tīmekli +Comment[mk]=Browse the World Wide Web +Comment[mr]=Browse the World Wide Web +Comment[ms]=Browse the World Wide Web +Comment[my]=Browse the World Wide Web +Comment[nb_NO]=Surf på nettet +Comment[ne_NP]=वर्ल्ड वाइड वेब ब्राउज गर्नुहोस् +Comment[nl]=Navigeren op het wereldwijde web +Comment[nn_NO]=Surf på nettet +Comment[oc]=Navegar pel Web +Comment[pa_IN]=ਵਰਲਡ ਵਾਈਡ ਵੈੱਬ ਬਰਾਊਜ਼ਰ ਕਰੋ +Comment[pl]=Przeglądaj Internet +Comment[pt_BR]=Navegue na World Wide Web +Comment[pt_PT]=Navegar na Internet +Comment[rm]=Navigar en il web +Comment[ro]=Browse the World Wide Web +Comment[ru]=Доступ в Интернет +Comment[sat]=World Wide Web ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ +Comment[sc]=Nàviga su Web +Comment[sco]=Browse the World Wide Web +Comment[si]=ලෝක ව්‍යාප්ත වියමන පිරික්සන්න +Comment[sk]=Prehľadávať web (www) +Comment[skr]=ورلڈ وائیڈ ویب براؤز کرو +Comment[sl]=Brskanje po svetovnem spletu +Comment[son]=Browse the World Wide Web +Comment[sq]=Shfletoni në World Wide Web +Comment[sr]=Истражите интернет +Comment[sv_SE]=Surfa på webben +Comment[szl]=Browse the World Wide Web +Comment[ta]=Browse the World Wide Web +Comment[te]=ప్రపంచ వ్యాప్త జాలంలో విహరించండి +Comment[tg]=Ба шабакаи ҷаҳонии Интернет дастрасӣ пайдо намоед +Comment[th]=เรียกดูเวิลด์ไวด์เว็บ +Comment[tl]=Browse the World Wide Web +Comment[tr]=Web’de gezin +Comment[trs]=Gāchē nu ngà World Wide Web +Comment[uk]=Переглядайте всесвітню мережу +Comment[ur]=Browse the World Wide Web +Comment[uz]=Browse the World Wide Web +Comment[vi]=Duyệt web trên toàn thế giới +Comment[xh]=Browse the World Wide Web +Comment[zh_CN]=浏览万维网 +Comment[zh_TW]=瀏覽全球資訊網 +GenericName=Web Browser +GenericName[ach]=Web Browser +GenericName[af]=Web Browser +GenericName[an]=Web Browser +GenericName[ar]=متصفح الإنترنت +GenericName[ast]=Web Browser +GenericName[az]=Web Browser +GenericName[be]=Вэб-браўзер +GenericName[bg]=Уеб браузър +GenericName[bn]=ওয়েব ব্রাউজার +GenericName[br]=Merdeer Web +GenericName[bs]=Web pretraživač +GenericName[ca]=Navegador web +GenericName[ca_valencia]=Web Browser +GenericName[cak]=Web Okik'amaya'l +GenericName[cs]=Webový prohlížeč +GenericName[cy]=Porwr Gwe +GenericName[da]=Webbrowser +GenericName[de]=Internet-Browser +GenericName[dsb]=Webwobglědowak +GenericName[el]=Πρόγραμμα περιήγησης +GenericName[en_CA]=Web Browser +GenericName[en_GB]=Web Browser +GenericName[eo]=Retumilo +GenericName[es_AR]=Navegador web +GenericName[es_CL]=Navegador Web +GenericName[es_ES]=Navegador web +GenericName[es_MX]=Navegador Web +GenericName[et]=Web Browser +GenericName[eu]=Web nabigatzailea +GenericName[fa]=Web Browser +GenericName[ff]=Web Browser +GenericName[fi]=Verkkoselain +GenericName[fr]=Navigateur web +GenericName[fur]=Navigadôr Web +GenericName[fy_NL]=Webbrowser +GenericName[ga_IE]=Web Browser +GenericName[gd]=Brabhsair-lìn +GenericName[gl]=Navegador web +GenericName[gn]=Ñanduti Kundahára +GenericName[gu_IN]=Web Browser +GenericName[he]=דפדפן אינטרנט +GenericName[hi_IN]=Web Browser +GenericName[hr]=Web preglednik +GenericName[hsb]=Webwobhladowak +GenericName[hu]=Webböngésző +GenericName[hy_AM]=Վեբ դիտարկիչ +GenericName[ia]=Navigator web +GenericName[id]=Peramban Web +GenericName[is]=Vafri +GenericName[it]=Browser web +GenericName[ja]=ウェブブラウザー +GenericName[ka]=ბრაუზერი +GenericName[kab]=Iminig web +GenericName[kk]=Веб-браузері +GenericName[km]=Web Browser +GenericName[kn]=Web Browser +GenericName[ko]=웹 브라우저 +GenericName[lij]=Navegatô Web +GenericName[lt]=Web Browser +GenericName[lv]=Tīmekļa pārlūks +GenericName[mk]=Web Browser +GenericName[mr]=Web Browser +GenericName[ms]=Web Browser +GenericName[my]=Web Browser +GenericName[nb_NO]=Nettleser +GenericName[ne_NP]=वेब ब्राउजर +GenericName[nl]=Webbrowser +GenericName[nn_NO]=Nettlesar +GenericName[oc]=Navegador Web +GenericName[pa_IN]=ਵੈੱਬ ਬਰਾਊਜ਼ਰ +GenericName[pl]=Przeglądarka internetowa +GenericName[pt_BR]=Navegador web +GenericName[pt_PT]=Navegador Web +GenericName[rm]=Navigatur web +GenericName[ro]=Web Browser +GenericName[ru]=Веб-браузер +GenericName[sat]=ᱣᱮᱵᱽ ᱵᱽᱨᱟᱣᱡᱚᱨ +GenericName[sc]=Navigadore web +GenericName[sco]=Web Browser +GenericName[si]=වියමන අතිරික්සුව +GenericName[sk]=Webový prehliadač +GenericName[skr]=ویب براؤزر +GenericName[sl]=Spletni brskalnik +GenericName[son]=Web Browser +GenericName[sq]=Shfletues +GenericName[sr]=Веб прегледач +GenericName[sv_SE]=Webbläsare +GenericName[szl]=Web Browser +GenericName[ta]=Web Browser +GenericName[te]=జాల విహారిణి +GenericName[tg]=Браузери веб +GenericName[th]=เว็บเบราว์เซอร์ +GenericName[tl]=Web Browser +GenericName[tr]=Web Tarayıcısı +GenericName[trs]=Web riña gāchē nu’ +GenericName[uk]=Браузер +GenericName[ur]=Web Browser +GenericName[uz]=Web Browser +GenericName[vi]=Trình duyệt web +GenericName[xh]=Web Browser +GenericName[zh_CN]=Web 浏览器 +GenericName[zh_TW]=網頁瀏覽器 +Keywords=Internet;WWW;Browser;Web;Explorer; +Keywords[ach]=Internet;WWW;Browser;Web;Explorer; +Keywords[af]=Internet;WWW;Browser;Web;Explorer; +Keywords[an]=Internet;WWW;Browser;Web;Explorer; +Keywords[ar]=إنترنت;WWW;متصفح;ويب;مستكشف; +Keywords[ast]=Internet;WWW;Browser;Web;Explorer; +Keywords[az]=Internet;WWW;Browser;Web;Explorer; +Keywords[be]=Internet;WWW;Browser;Web;Explorer; +Keywords[bg]=Internet;WWW;Browser;Web;Explorer; +Keywords[bn]=ইন্টারনেট;WWW;ব্রাউজার;ওয়েব;এক্সপ্লোরার; +Keywords[br]=Internet;WWW;Merdeer;Web;Ergerzhout; +Keywords[bs]=Internet;WWW;Pretraživač;Web;Istraživač; +Keywords[ca]=Internet;WWW;Browser;Web;Explorador;Navegador; +Keywords[ca_valencia]=Internet;WWW;Browser;Web;Explorer; +Keywords[cak]=K'amaya'l;WWW;Okik'amaya'l;Kanob'äl; +Keywords[cs]=internet;WWW;prohlížeč;web; +Keywords[cy]=Rhyngrwyd;WWW;Porwr;Gwe;Archwiliwr; +Keywords[da]=Internet;WWW;Browser;Nettet;Explorer; +Keywords[de]=Internet;WWW;Browser;Web;Explorer; +Keywords[dsb]=Internet;WWW;wobglědowak;Web;Explorer; +Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Ιστός;Ίντερνετ; +Keywords[en_CA]=Internet;WWW;Browser;Web;Explorer; +Keywords[en_GB]=Internet;WWW;Browser;Web;Explorer; +Keywords[eo]=Interreto;Retumilo;TTT;Teksaĵo;Reto;Internet;WWW;Browser;Web;Explorer; +Keywords[es_AR]=Internet;WWW;Navegador;Web;Explorador; +Keywords[es_CL]=Internet;WWW;Navegador;Web;Explorador; +Keywords[es_ES]=Internet;WWW;Navegador;Web;Explorador; +Keywords[es_MX]=Internet;WWW;Navegador;Web;Explorador; +Keywords[et]=Internet;WWW;Browser;Web;Explorer; +Keywords[eu]=Internet;WWW;Nabigatzailea;Web;Arakatzailea; +Keywords[fa]=Internet;WWW;Browser;Web;Explorer; +Keywords[ff]=Internet;WWW;Browser;Web;Explorer; +Keywords[fi]=Internet;WWW;Browser;Web;Explorer;netti;webbi;selain; +Keywords[fr]=Internet;WWW;Navigateur;Web;Explorer; +Keywords[fur]=Internet;WWW;Browser;Navigadôr;Web;Esploradôr;Explorer; +Keywords[fy_NL]=Ynternet;WWW;Browser;Web;Ferkenner; +Keywords[ga_IE]=Internet;WWW;Browser;Web;Explorer; +Keywords[gd]=Internet;WWW;Browser;Web;Explorer;eadar-lìon;brabhsair;brobhsair;lìon;taisgealaiche; +Keywords[gl]=Internet;WWW;Navegador;Web;Explorador; +Keywords[gn]=Internet;WWW;Browser;Web;Explorer; +Keywords[gu_IN]=Internet;WWW;Browser;Web;Explorer; +Keywords[he]=אינטרנט;WWW;דפדפן;רשת;סייר;מרשתת; +Keywords[hi_IN]=Internet;WWW;Browser;Web;Explorer; +Keywords[hr]=Internet;WWW;Preglednik;Web;Istraživač; +Keywords[hsb]=Internet;WWW;wobhladowak;Web;Explorer; +Keywords[hu]=Internet;WWW;Böngésző;Web;Világháló; +Keywords[hy_AM]=Համացանց,WWW,Զննիչ,Վեբ,Ցանցախույզ: +Keywords[ia]=Internet;WWW;Navigator;Web;Explorator; +Keywords[id]=Internet;WWW;Browser;Web;Explorer; +Keywords[is]=Internet;WWW; Vafri; Vefur; Explorer; +Keywords[it]=Internet;WWW;Browser;Web;Explorer;Navigatore; +Keywords[ja]=Internet;WWW;Browser;Web;Explorer;インターネット;ブラウザー;ウェブ; +Keywords[ka]=ინტერნეტი;WWW;ბრაუზერი;ქსელი;ქსელთან წვდომა; +Keywords[kab]=Internet;WWW;Browser;Web;Explorer; +Keywords[kk]=Internet;WWW;Browser;Web;Explorer;Интернет;Ғаламтор;Браузер;Желі;Шолғыш; +Keywords[km]=Internet;WWW;Browser;Web;Explorer; +Keywords[kn]=Internet;WWW;Browser;Web;Explorer; +Keywords[ko]=인터넷;브라우저;웹;탐색기;Internet;WWW;Browser;Web;Explorer; +Keywords[lij]=Internet;WWW;Browser;Web;Explorer;Navegatô; +Keywords[lt]=Internet;WWW;Browser;Web;Explorer; +Keywords[lv]=Internets;WWW;Pārlūkprogramma;Tīmeklis; +Keywords[mk]=Internet;WWW;Browser;Web;Explorer; +Keywords[mr]=Internet;WWW;Browser;Web;Explorer; +Keywords[ms]=Internet;WWW;Browser;Web;Explorer; +Keywords[my]=Internet;WWW;Browser;Web;Explorer; +Keywords[nb_NO]=Internett;WWW;Nettleser;Web;Utforsker; +Keywords[ne_NP]=Internet;WWW;Browser;Web;Explorer; +Keywords[nl]=Internet;WWW;Browser;Web;Verkenner; +Keywords[nn_NO]=Internett;WWW;Nettlesar;Web;Utforskar; +Keywords[oc]=Internet;WWW;Navegador;Navigador;Navegator;Navigator;Web;Explorer; +Keywords[pa_IN]=ਇੰਟਰਨੈੱਟ;WWW;ਬਰਾਊਜ਼ਰ;ਵੈੱਬ;ਐਕਸਪਲਰੋਰ;ਵੈਬ;ਇੰਟਰਨੈਟ; +Keywords[pl]=Internet;WWW;Przeglądarka;Browser;Wyszukiwarka;Web;Sieć;Explorer;Eksplorer;Strony;Witryny;internetowe; +Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorer;Navegador; +Keywords[pt_PT]=Internet;WWW;Navegador;Web;Explorador; +Keywords[rm]=Internet;WWW;Browser;Web;Explorer;navigatur; +Keywords[ro]=Internet;WWW;Browser;Web;Explorer; +Keywords[ru]=Сеть;Интернет;Браузер;Доступ в Интернет; +Keywords[sat]=Internet;WWW;Browser;Web;Explorer; +Keywords[sc]=Internet;WWW;Navigadore;Web;Explorer; +Keywords[sco]=Internet;WWW;Browser;Web;Explorer; +Keywords[si]=අන්තර්ජාලය;අතිරික්සුව;පිරික්සන්න;ගවේශකය;Internet;WWW;Browser;Web;Explorer; +Keywords[sk]=Internet;WWW;Prehliadač;Web;Prieskumník; +Keywords[skr]=Internet;WWW;Browser;Web;Explorer; +Keywords[sl]=internet;www;brskalnik;splet; +Keywords[son]=Internet;WWW;Browser;Web;Explorer; +Keywords[sq]=Internet;WWW;Shfletues;Web;Eksplorues; +Keywords[sr]=Internet;WWW;Browser;Web;Explorer;интернет;прегледач;веб;мрежа;прегледач; +Keywords[sv_SE]=Internet;WWW;Webbläsare;Webb;Utforskare; +Keywords[szl]=Internet;WWW;Browser;Web;Explorer; +Keywords[ta]=Internet;WWW;Browser;Web;Explorer; +Keywords[te]=Internet;WWW;Browser;Web;Explorer; +Keywords[tg]=Интернет;WWW;Браузер;Сомона;Ҷустуҷӯгар; +Keywords[th]=อินเทอร์เน็ต;เบราว์เซอร์;เว็บ;Internet;WWW;Browser;Web;Explorer; +Keywords[tl]=Internet;WWW;Browser;Web;Explorer; +Keywords[tr]=Internet;WWW;Browser;Web;Explorer;İnternet;Tarayıcı; +Keywords[trs]=Internet;WWW;Browser;Web;Explorer; +Keywords[uk]=Інтернет;WWW;Браузер;Веб;Переглядач; +Keywords[ur]=Internet;WWW;Browser;Web;Explorer; +Keywords[uz]=Internet;WWW;Browser;Web;Explorer; +Keywords[vi]=Internet;WWW;Trình duyệt;Web;Duyệt web; +Keywords[xh]=Internet;WWW;Browser;Web;Explorer; +Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer; +Keywords[zh_TW]=網際網路;網路;瀏覽器;網頁;上網;Internet;WWW;Browser;Web;Explorer; +X-GNOME-FullName=Firefox Web Browser +X-GNOME-FullName[ach]=Firefox Web Browser +X-GNOME-FullName[af]=Firefox Web Browser +X-GNOME-FullName[an]=Firefox Web Browser +X-GNOME-FullName[ar]=متصفح Firefox +X-GNOME-FullName[ast]=Firefox Web Browser +X-GNOME-FullName[az]=Firefox Web Browser +X-GNOME-FullName[be]=Вэб-браўзер Firefox +X-GNOME-FullName[bg]=Firefox Уеб браузър +X-GNOME-FullName[bn]=Firefox Web Browser +X-GNOME-FullName[br]=Merdeer Web Firefox +X-GNOME-FullName[bs]=Firefox web pretraživač +X-GNOME-FullName[ca]=Navegador web Firefox +X-GNOME-FullName[ca_valencia]=Firefox Web Browser +X-GNOME-FullName[cak]=Firefox Web Browser +X-GNOME-FullName[cs]=Webový prohlížeč Firefox +X-GNOME-FullName[cy]=Porwr Gwe Firefox +X-GNOME-FullName[da]=Firefox-browser +X-GNOME-FullName[de]=Firefox-Web-Browser +X-GNOME-FullName[dsb]=Webwobglědowak Firefox +X-GNOME-FullName[el]=Πρόγραμμα περιήγησης Firefox +X-GNOME-FullName[en_CA]=Firefox Web Browser +X-GNOME-FullName[en_GB]=Firefox Web Browser +X-GNOME-FullName[eo]=Retumilo Firefox +X-GNOME-FullName[es_AR]=Navegador web Firefox +X-GNOME-FullName[es_CL]=Navegador web Firefox +X-GNOME-FullName[es_ES]=Navegador web Firefox +X-GNOME-FullName[es_MX]=Navegador web Firefox +X-GNOME-FullName[et]=Firefox Web Browser +X-GNOME-FullName[eu]=Firefox web nabigatzailea +X-GNOME-FullName[fa]=Firefox Web Browser +X-GNOME-FullName[ff]=Firefox Web Browser +X-GNOME-FullName[fi]=Firefox-verkkoselain +X-GNOME-FullName[fr]=Navigateur web Firefox +X-GNOME-FullName[fur]=Navigadôr web Firefox +X-GNOME-FullName[fy_NL]=Firefox-webbrowser +X-GNOME-FullName[ga_IE]=Firefox Web Browser +X-GNOME-FullName[gd]=Brabhsair-lìn Firefox +X-GNOME-FullName[gl]=Navegador web Firefox +X-GNOME-FullName[gn]=Firefox Ñanduti Kundahára +X-GNOME-FullName[gu_IN]=Firefox Web Browser +X-GNOME-FullName[he]=דפדפן אינטרנט Firefox +X-GNOME-FullName[hi_IN]=Firefox वेब ब्राउज़र +X-GNOME-FullName[hr]=Firefox web preglednik +X-GNOME-FullName[hsb]=Webwobhladowak Firefox +X-GNOME-FullName[hu]=Firefox webböngésző +X-GNOME-FullName[hy_AM]=Firefox վեբ դիտարկիչ +X-GNOME-FullName[ia]=Navigator web Firefox +X-GNOME-FullName[id]=Firefox Peramban Web +X-GNOME-FullName[is]=Firefox-vafri +X-GNOME-FullName[it]=Browser web Firefox +X-GNOME-FullName[ja]=Firefox ウェブブラウザー +X-GNOME-FullName[ka]=Firefox-ბრაუზერი +X-GNOME-FullName[kab]=Iminig web Firefox +X-GNOME-FullName[kk]=Firefox веб-браузері +X-GNOME-FullName[km]=Firefox Web Browser +X-GNOME-FullName[kn]=Firefox Web Browser +X-GNOME-FullName[ko]=Firefox 웹 브라우저 +X-GNOME-FullName[lij]=Firefox Navegatô Web +X-GNOME-FullName[lt]=Firefox Web Browser +X-GNOME-FullName[lv]=Firefox tīmekļa pārlūks +X-GNOME-FullName[mk]=Firefox Web Browser +X-GNOME-FullName[mr]=Firefox Web Browser +X-GNOME-FullName[ms]=Firefox Web Browser +X-GNOME-FullName[my]=Firefox Web Browser +X-GNOME-FullName[nb_NO]=Firefox-nettleser +X-GNOME-FullName[ne_NP]=Firefox वेब ब्राउजर +X-GNOME-FullName[nl]=Firefox-webbrowser +X-GNOME-FullName[nn_NO]=Firefox-nettlesar +X-GNOME-FullName[oc]=Navegador web Firefox +X-GNOME-FullName[pa_IN]=Firefox ਵੈੱਬ ਬਰਾਊਜ਼ਰ +X-GNOME-FullName[pl]=Przeglądarka Firefox +X-GNOME-FullName[pt_BR]=Navegador web Firefox +X-GNOME-FullName[pt_PT]=Navegador Web Firefox +X-GNOME-FullName[rm]=Navigatur-web Firefox +X-GNOME-FullName[ro]=Firefox Web Browser +X-GNOME-FullName[ru]=Веб-браузер Firefox +X-GNOME-FullName[sat]=Firefox ᱣᱮᱵᱽ ᱵᱽᱨᱟᱣᱡᱚᱨ +X-GNOME-FullName[sc]=Navigadore web Firefox +X-GNOME-FullName[sco]=Firefox Web Browser +X-GNOME-FullName[si]=Firefox අතිරික්සුව +X-GNOME-FullName[sk]=Webový prehliadač Firefox +X-GNOME-FullName[skr]=Firefox ویب براؤزر +X-GNOME-FullName[sl]=Spletni brskalnik Firefox +X-GNOME-FullName[son]=Firefox Web Browser +X-GNOME-FullName[sq]=Shfletuesi Firefox +X-GNOME-FullName[sr]=Firefox веб прегледач +X-GNOME-FullName[sv_SE]=Firefox webbläsare +X-GNOME-FullName[szl]=Firefox Web Browser +X-GNOME-FullName[ta]=Firefox Web Browser +X-GNOME-FullName[te]=Firefox Web Browser +X-GNOME-FullName[tg]=Браузери интернетии «Firefox» +X-GNOME-FullName[th]=เว็บเบราว์เซอร์ Firefox +X-GNOME-FullName[tl]=Firefox Web Browser +X-GNOME-FullName[tr]=Firefox Web Tarayıcısı +X-GNOME-FullName[trs]=Firefox Web riña gāchē nu’ +X-GNOME-FullName[uk]=Браузер Firefox +X-GNOME-FullName[ur]=Firefox Web Browser +X-GNOME-FullName[uz]=Firefox Web Browser +X-GNOME-FullName[vi]=Trình duyệt Web Firefox +X-GNOME-FullName[xh]=Firefox Web Browser +X-GNOME-FullName[zh_CN]=Firefox 浏览器 +X-GNOME-FullName[zh_TW]=Firefox 網頁瀏覽器 Exec=firefox %u Icon=firefox Terminal=false @@ -49,226 +522,324 @@ Type=Application MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https; StartupNotify=true Categories=Network;WebBrowser; -Keywords=web;browser;internet; Actions=new-window;new-private-window;profile-manager-window; +# Activable desktop file crashes KDE so remove it for now +# DBusActivatable=true [Desktop Action new-window] -Name=Open a New Window -Name[ach]=Dirica manyen -Name[af]=Nuwe venster -Name[an]=Nueva finestra +Name=New Window +Name[ach]=New Window +Name[af]=New Window +Name[an]=New Window Name[ar]=نافذة جديدة -Name[as]=নতুন উইন্ডো -Name[ast]=Ventana nueva -Name[az]=Yeni Pəncərə +Name[ast]=New Window +Name[az]=New Window Name[be]=Новае акно Name[bg]=Нов прозорец -Name[bn_BD]=নতুন উইন্ডো (N) -Name[bn_IN]=নতুন উইন্ডো +Name[bn]=নতুন উইন্ডো Name[br]=Prenestr nevez -Name[brx]=गोदान उइन्ड'(N) Name[bs]=Novi prozor Name[ca]=Finestra nova -Name[cak]=K'ak'a' tzuwäch +Name[ca_valencia]=New Window +Name[cak]=K'ak'a' Tzuwäch Name[cs]=Nové okno Name[cy]=Ffenestr Newydd Name[da]=Nyt vindue Name[de]=Neues Fenster Name[dsb]=Nowe wokno Name[el]=Νέο παράθυρο +Name[en_CA]=New Window Name[en_GB]=New Window -Name[en_US]=New Window -Name[en_ZA]=New Window Name[eo]=Nova fenestro Name[es_AR]=Nueva ventana Name[es_CL]=Nueva ventana Name[es_ES]=Nueva ventana Name[es_MX]=Nueva ventana -Name[et]=Uus aken +Name[et]=New Window Name[eu]=Leiho berria Name[fa]=پنجره جدید‌ -Name[ff]=Henorde Hesere +Name[ff]=New Window Name[fi]=Uusi ikkuna Name[fr]=Nouvelle fenêtre +Name[fur]=Gnûf barcon Name[fy_NL]=Nij finster -Name[ga_IE]=Fuinneog Nua +Name[ga_IE]=New Window Name[gd]=Uinneag ùr Name[gl]=Nova xanela Name[gn]=Ovetã pyahu -Name[gu_IN]=નવી વિન્ડો +Name[gu_IN]=New Window Name[he]=חלון חדש -Name[hi_IN]=नया विंडो +Name[hi_IN]=New Window Name[hr]=Novi prozor Name[hsb]=Nowe wokno Name[hu]=Új ablak -Name[hy_AM]=Նոր Պատուհան +Name[hy_AM]=Նոր պատուհան +Name[ia]=Nove fenestra Name[id]=Jendela Baru Name[is]=Nýr gluggi Name[it]=Nuova finestra Name[ja]=新しいウィンドウ -Name[ja_JP-mac]=新規ウインドウ Name[ka]=ახალი ფანჯარა +Name[kab]=Asfaylu amaynut Name[kk]=Жаңа терезе -Name[km]=បង្អួច​​​ថ្មី -Name[kn]=ಹೊಸ ಕಿಟಕಿ +Name[km]=New Window +Name[kn]=New Window Name[ko]=새 창 -Name[kok]=नवें जनेल -Name[ks]=نئئ وِنڈو -Name[lij]=Neuvo barcon -Name[lo]=ຫນ້າຕ່າງໃຫມ່ -Name[lt]=Naujas langas -Name[ltg]=Jauns lūgs +Name[lij]=Neuvo Barcon +Name[lt]=New Window Name[lv]=Jauns logs -Name[mai]=नव विंडो -Name[mk]=Нов прозорец -Name[ml]=പുതിയ ജാലകം -Name[mr]=नवीन पटल -Name[ms]=Tetingkap Baru -Name[my]=ဝင်းဒိုးအသစ် +Name[mk]=New Window +Name[mr]=New Window +Name[ms]=New Window +Name[my]=New Window Name[nb_NO]=Nytt vindu Name[ne_NP]=नयाँ सञ्झ्याल Name[nl]=Nieuw venster Name[nn_NO]=Nytt vindauge -Name[or]=ନୂତନ ୱିଣ୍ଡୋ +Name[oc]=Fenèstra novèla Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ Name[pl]=Nowe okno Name[pt_BR]=Nova janela Name[pt_PT]=Nova janela Name[rm]=Nova fanestra -Name[ro]=Fereastră nouă +Name[ro]=New Window Name[ru]=Новое окно -Name[sat]=नावा विंडो (N) -Name[si]=නව කවුළුවක් +Name[sat]=ᱱᱟᱶᱟ ᱣᱤᱱᱰᱳ +Name[sc]=Ventana noa +Name[sco]=New Window +Name[si]=නව කවුළුව Name[sk]=Nové okno +Name[skr]=نویں ونڈو Name[sl]=Novo okno -Name[son]=Zanfun taaga +Name[son]=New Window Name[sq]=Dritare e Re Name[sr]=Нови прозор Name[sv_SE]=Nytt fönster -Name[ta]=புதிய சாளரம் -Name[te]=కొత్త విండో +Name[szl]=New Window +Name[ta]=New Window +Name[te]=కొత్త కిటికీ +Name[tg]=Равзанаи нав Name[th]=หน้าต่างใหม่ +Name[tl]=New Window Name[tr]=Yeni pencere -Name[tsz]=Eraatarakua jimpani +Name[trs]=Bēntanâ nākàa Name[uk]=Нове вікно -Name[ur]=نیا دریچہ -Name[uz]=Yangi oyna +Name[ur]=New Window +Name[uz]=New Window Name[vi]=Cửa sổ mới -Name[wo]=Palanteer bu bees -Name[xh]=Ifestile entsha +Name[xh]=New Window Name[zh_CN]=新建窗口 Name[zh_TW]=開新視窗 Exec=firefox --new-window %u [Desktop Action new-private-window] -Name=Open a New Private Window -Name[ach]=Dirica manyen me mung -Name[af]=Nuwe privaatvenster -Name[an]=Nueva finestra privada +Name=New Private Window +Name[ach]=New Private Window +Name[af]=New Private Window +Name[an]=New Private Window Name[ar]=نافذة خاصة جديدة -Name[as]=নতুন ব্যক্তিগত উইন্ডো -Name[ast]=Ventana privada nueva -Name[az]=Yeni Məxfi Pəncərə -Name[be]=Новае акно адасаблення -Name[bg]=Нов прозорец за поверително сърфиране -Name[bn_BD]=নতুন ব্যক্তিগত উইন্ডো -Name[bn_IN]=নতুন ব্যক্তিগত উইন্ডো -Name[br]=Prenestr merdeiñ prevez nevez -Name[brx]=गोदान प्राइभेट उइन्ड' +Name[ast]=New Private Window +Name[az]=New Private Window +Name[be]=Новае прыватнае акно +Name[bg]=Нов личен прозорец +Name[bn]=নতুন ব্যক্তিগত উইন্ডো +Name[br]=Prenestr prevez nevez Name[bs]=Novi privatni prozor Name[ca]=Finestra privada nova -Name[cak]=K'ak'a' ichinan tzuwäch +Name[ca_valencia]=New Private Window +Name[cak]=K'ak'a' Ichinan Tzuwäch Name[cs]=Nové anonymní okno Name[cy]=Ffenestr Breifat Newydd Name[da]=Nyt privat vindue Name[de]=Neues privates Fenster Name[dsb]=Nowe priwatne wokno -Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης +Name[el]=Νέο ιδιωτικό παράθυρο +Name[en_CA]=New Private Window Name[en_GB]=New Private Window -Name[en_US]=New Private Window -Name[en_ZA]=New Private Window Name[eo]=Nova privata fenestro Name[es_AR]=Nueva ventana privada Name[es_CL]=Nueva ventana privada Name[es_ES]=Nueva ventana privada Name[es_MX]=Nueva ventana privada -Name[et]=Uus privaatne aken +Name[et]=New Private Window Name[eu]=Leiho pribatu berria Name[fa]=پنجره ناشناس جدید -Name[ff]=Henorde Suturo Hesere +Name[ff]=New Private Window Name[fi]=Uusi yksityinen ikkuna -Name[fr]=Nouvelle fenêtre de navigation privée +Name[fr]=Nouvelle fenêtre privée +Name[fur]=Gnûf barcon privât Name[fy_NL]=Nij priveefinster -Name[ga_IE]=Fuinneog Nua Phríobháideach +Name[ga_IE]=New Private Window Name[gd]=Uinneag phrìobhaideach ùr Name[gl]=Nova xanela privada Name[gn]=Ovetã ñemi pyahu -Name[gu_IN]=નવી ખાનગી વિન્ડો +Name[gu_IN]=New Private Window Name[he]=חלון פרטי חדש -Name[hi_IN]=नयी निजी विंडो +Name[hi_IN]=New Private Window Name[hr]=Novi privatni prozor Name[hsb]=Nowe priwatne wokno Name[hu]=Új privát ablak -Name[hy_AM]=Սկսել Գաղտնի դիտարկում +Name[hy_AM]=Նոր գաղտնի պատուհան +Name[ia]=Nove fenestra private Name[id]=Jendela Mode Pribadi Baru Name[is]=Nýr huliðsgluggi Name[it]=Nuova finestra anonima Name[ja]=新しいプライベートウィンドウ -Name[ja_JP-mac]=新規プライベートウインドウ Name[ka]=ახალი პირადი ფანჯარა +Name[kab]=Asfaylu amaynut n tunigin tusligt Name[kk]=Жаңа жекелік терезе -Name[km]=បង្អួច​ឯកជន​ថ្មី -Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ -Name[ko]=새 사생활 보호 모드 -Name[kok]=नवो खाजगी विंडो -Name[ks]=نْو پرایوٹ وینڈو& -Name[lij]=Neuvo barcon privou -Name[lo]=ເປີດຫນ້າຕ່າງສວນຕົວຂື້ນມາໃຫມ່ -Name[lt]=Naujas privataus naršymo langas -Name[ltg]=Jauns privatais lūgs +Name[km]=New Private Window +Name[kn]=New Private Window +Name[ko]=새 사생활 보호 창 +Name[lij]=Neuvo Barcon Privòu +Name[lt]=New Private Window Name[lv]=Jauns privātais logs -Name[mai]=नया निज विंडो (W) -Name[mk]=Нов приватен прозорец -Name[ml]=പുതിയ സ്വകാര്യ ജാലകം -Name[mr]=नवीन वैयक्तिक पटल -Name[ms]=Tetingkap Persendirian Baharu +Name[mk]=New Private Window +Name[mr]=New Private Window +Name[ms]=New Private Window Name[my]=New Private Window Name[nb_NO]=Nytt privat vindu Name[ne_NP]=नयाँ निजी सञ्झ्याल Name[nl]=Nieuw privévenster Name[nn_NO]=Nytt privat vindauge -Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ +Name[oc]=Fenèstra privada novèla Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ Name[pl]=Nowe okno prywatne Name[pt_BR]=Nova janela privativa Name[pt_PT]=Nova janela privada Name[rm]=Nova fanestra privata -Name[ro]=Fereastră privată nouă +Name[ro]=New Private Window Name[ru]=Новое приватное окно -Name[sat]=नावा निजेराक् विंडो (W ) -Name[si]=නව පුද්ගලික කවුළුව (W) -Name[sk]=Nové okno v režime Súkromné prehliadanie +Name[sat]=ᱱᱟᱶᱟ ᱱᱤᱡᱮᱨᱟᱜ ᱣᱤᱱᱰᱳ +Name[sc]=Ventana privada noa +Name[sco]=New Private Window +Name[si]=නව පෞද්. කවුළුව +Name[sk]=Nové súkromné okno +Name[skr]=نویں نجی ونڈو Name[sl]=Novo zasebno okno -Name[son]=Sutura zanfun taaga +Name[son]=New Private Window Name[sq]=Dritare e Re Private -Name[sr]=Нови приватан прозор +Name[sr]=Нови приватни прозор Name[sv_SE]=Nytt privat fönster -Name[ta]=புதிய தனிப்பட்ட சாளரம் -Name[te]=కొత్త ఆంతరంగిక విండో +Name[szl]=New Private Window +Name[ta]=New Private Window +Name[te]=కొత్త ఆంతరంగిక కిటికీ +Name[tg]=Равзанаи хусусии нав Name[th]=หน้าต่างส่วนตัวใหม่ +Name[tl]=New Private Window Name[tr]=Yeni gizli pencere -Name[tsz]=Juchiiti eraatarakua jimpani +Name[trs]=Bēntanâ huì nākàa Name[uk]=Приватне вікно -Name[ur]=نیا نجی دریچہ -Name[uz]=Yangi maxfiy oyna +Name[ur]=New Private Window +Name[uz]=New Private Window Name[vi]=Cửa sổ riêng tư mới -Name[wo]=Panlanteeru biir bu bees -Name[xh]=Ifestile yangasese entsha -Name[zh_CN]=新建隐私浏览窗口 -Name[zh_TW]=新增隱私視窗 +Name[xh]=New Private Window +Name[zh_CN]=新建隐私窗口 +Name[zh_TW]=開新隱私視窗 Exec=firefox --private-window %u -[Desktop Action profile-manager-window] -Name=Open the Profile Manager -Name[cs]=Správa profilů +[Desktop Action open-profile-manager] +Name=Open Profile Manager +Name[ach]=Open Profile Manager +Name[af]=Open Profile Manager +Name[an]=Open Profile Manager +Name[ar]=افتح مدير الملف الشخصي +Name[ast]=Open Profile Manager +Name[az]=Open Profile Manager +Name[be]=Адкрыць менеджар профіляў +Name[bg]=Отваряне на мениджъра на профили +Name[bn]=Open Profile Manager +Name[br]=Digeriñ an ardoer aeladoù +Name[bs]=Otvori Menadžera profila +Name[ca]=Obre el gestor de perfils +Name[ca_valencia]=Open Profile Manager +Name[cak]=Open Profile Manager +Name[cs]=Otevřete Správce profilů +Name[cy]=Agorwch y Rheolwr Proffil +Name[da]=Åbn profilhåndtering +Name[de]=Profilverwaltung öffnen +Name[dsb]=Profilowy zastojnik wócyniś +Name[el]=Άνοιγμα Διαχείρισης προφίλ +Name[en_CA]=Open Profile Manager +Name[en_GB]=Open Profile Manager +Name[eo]=Malfermi administranton de profiloj +Name[es_AR]=Abrir administrador de perfiles +Name[es_CL]=Abrir administrador de perfiles +Name[es_ES]=Abrir administrador de perfiles +Name[es_MX]=Abrir administrador de perfiles +Name[et]=Open Profile Manager +Name[eu]=Ireki profilen kudeatzailea +Name[fa]=Open Profile Manager +Name[ff]=Open Profile Manager +Name[fi]=Avaa profiilien hallinta +Name[fr]=Ouvrir le gestionnaire de profils +Name[fur]=Vierç gjestôr profîi +Name[fy_NL]=Profylbehearder iepenje +Name[ga_IE]=Open Profile Manager +Name[gd]=Fosgail manaidsear nam pròifilean +Name[gl]=Abrir o xestor de perfís +Name[gn]=Embojuruja mba’ete ñangarekoha +Name[gu_IN]=Open Profile Manager +Name[he]=פתיחת מנהל הפרופילים +Name[hi_IN]=Open Profile Manager +Name[hr]=Otvori upravljač profila +Name[hsb]=Zrjadowak profilow wočinić +Name[hu]=Profilkezelő megnyitása +Name[hy_AM]=Բացեք պրոֆիլի կառավարիչը +Name[ia]=Aperir le gestor de profilo +Name[id]=Buka Pengelola Profil +Name[is]=Opna umsýslu notandasniða +Name[it]=Apri gestore profili +Name[ja]=プロファイルマネージャーを開く +Name[ka]=პროფილის მმართველის გახსნა +Name[kab]=Ldi amsefrak n umaɣnu +Name[kk]=Профильдер бақарушысын ашу +Name[km]=Open Profile Manager +Name[kn]=Open Profile Manager +Name[ko]=프로필 관리자 열기 +Name[lij]=Open Profile Manager +Name[lt]=Open Profile Manager +Name[lv]=Atvērt profilu pārvaldnieku +Name[mk]=Open Profile Manager +Name[mr]=Open Profile Manager +Name[ms]=Open Profile Manager +Name[my]=Open Profile Manager +Name[nb_NO]=Åpne profilbehandler +Name[ne_NP]=Open Profile Manager +Name[nl]=Profielbeheerder openen +Name[nn_NO]=Opne profilhandsaming +Name[oc]=Dobrir lo gestionari de perfils +Name[pa_IN]=ਪਰੋਫ਼ਾਈਲ ਮੈਨੇਜਰ ਖੋਲ੍ਹੋ +Name[pl]=Menedżer profili +Name[pt_BR]=Abrir gerenciador de perfis +Name[pt_PT]=Abrir o Gestor de Perfis +Name[rm]=Avrir l'administraziun da profils +Name[ro]=Open Profile Manager +Name[ru]=Открыть менеджер профилей +Name[sat]=ᱢᱮᱫᱦᱟᱸ ᱢᱮᱱᱮᱡᱚᱨ ᱠᱷᱩᱞᱟᱹᱭ ᱢᱮ +Name[sc]=Aberi su gestore de profilos +Name[sco]=Open Profile Manager +Name[si]=පැතිකඩ කළමනාකරු අරින්න +Name[sk]=Otvoriť Správcu profilov +Name[skr]=پروفائل منیجر کھولو +Name[sl]=Odpri upravitelja profilov +Name[son]=Open Profile Manager +Name[sq]=Hapni Përgjegjës Profilesh +Name[sr]=Отворите управљач профила +Name[sv_SE]=Öppna Profilhanteraren +Name[szl]=Open Profile Manager +Name[ta]=Open Profile Manager +Name[te]=Open Profile Manager +Name[tg]=Кушодани мудири профилҳо +Name[th]=เปิดตัวจัดการโปรไฟล์ +Name[tl]=Open Profile Manager +Name[tr]=Profil yöneticisini aç +Name[trs]=Sa nīkāj ñu’ūnj nej perfî huā nì’nï̀nj ïn +Name[uk]=Відкрити менеджер профілів +Name[ur]=Open Profile Manager +Name[uz]=Open Profile Manager +Name[vi]=Mở trình quản lý hồ sơ +Name[xh]=Open Profile Manager +Name[zh_CN]=打开配置文件管理器 +Name[zh_TW]=開啟設定檔管理員 Exec=firefox --ProfileManager diff --git a/firefox.sh.in b/firefox.sh.in index 78d908e..7d3faed 100644 --- a/firefox.sh.in +++ b/firefox.sh.in @@ -64,18 +64,8 @@ MOZ_DIST_BIN="$MOZ_LIB_DIR/firefox" MOZ_LANGPACKS_DIR="$MOZ_DIST_BIN/langpacks" MOZ_EXTENSIONS_PROFILE_DIR="$HOME/.mozilla/extensions/{ec8030f7-c20a-464f-9b0e-13a3a9e97384}" MOZ_PROGRAM="$MOZ_DIST_BIN/$MOZ_FIREFOX_FILE" -MOZ_LAUNCHER="$MOZ_DIST_BIN/run-mozilla.sh" GETENFORCE_FILE="/usr/sbin/getenforce" -## -## Enable Wayland backend? -## -if __DEFAULT_WAYLAND__ && ! [ $MOZ_DISABLE_WAYLAND ]; then - if [ "$XDG_CURRENT_DESKTOP" == "GNOME" ]; then - export MOZ_ENABLE_WAYLAND=1 - fi -fi - ## ## Use D-Bus remote exclusively when there's Wayland display. ## @@ -118,10 +108,14 @@ export MOZ_PLUGIN_PATH export MOZ_APP_LAUNCHER="/__PREFIX__/bin/firefox" ## -## Set FONTCONFIG_PATH for Xft/fontconfig +## We want Firefox to use Openh264 provided by Fedora. +## +## We used to configure it here but It's set by /etc/profile.d/gmpopenh264.sh +## script from mozilla-openh264 package now. Let's keep it here just +## for the record. +## +## export MOZ_GMP_PATH=$MOZ_LIB_DIR/mozilla/plugins/gmp-gmpopenh264/system-installed ## -FONTCONFIG_PATH="/etc/fonts:${MOZILLA_FIVE_HOME}/res/Xft" -export FONTCONFIG_PATH ## ## In order to better support certain scripts (such as Indic and some CJK @@ -136,21 +130,10 @@ export FONTCONFIG_PATH # export MOZ_DISABLE_PANGO # -## -## Disable the GNOME crash dialog, Moz has it's own -## -GNOME_DISABLE_CRASH_DIALOG=1 -export GNOME_DISABLE_CRASH_DIALOG - -## -## Disable the SLICE allocator (rhbz#1014858) -## -export G_SLICE=always-malloc - ## ## Enable Xinput2 (mozbz#1207973) ## -export MOZ_USE_XINPUT2=1 +export MOZ_USE_XINPUT2=${MOZ_USE_XINPUT2-1} # OK, here's where all the real work gets done @@ -183,8 +166,8 @@ fi # When Firefox is not running, restore SELinux labels for profile files # (rhbz#1731371) if [ $MOZILLA_DOWN -ne 0 ]; then - if [ -x $GETENFORCE_FILE ] && [ `getenforce` != "Disabled" ]; then - (restorecon -vr ~/.mozilla/firefox/* &) + if [ -x $GETENFORCE_FILE ] && [ `$GETENFORCE_FILE` != "Disabled" ]; then + (restorecon -vr ~/.mozilla/firefox/*/gmp-widevinecdm/* &) fi fi @@ -220,8 +203,17 @@ if [ $MOZILLA_DOWN -ne 0 ]; then if [ -h $MOZ_LANGPACKS_DIR/$langpack ]; then langpack=`readlink $MOZ_LANGPACKS_DIR/$langpack` fi - ln -s $MOZ_LANGPACKS_DIR/$langpack \ - $MOZ_EXTENSIONS_PROFILE_DIR/$langpack + if [ -e "/run/ostree-booted" ]; then + # Files on Silverblue has file create time set to 0, + # so in case the langpack is updated Firefox does not + # check for changes because it compares the file + # creation date to do so. + cp -f $MOZ_LANGPACKS_DIR/$langpack \ + $MOZ_EXTENSIONS_PROFILE_DIR/$langpack + else + ln -s $MOZ_LANGPACKS_DIR/$langpack \ + $MOZ_EXTENSIONS_PROFILE_DIR/$langpack + fi echo $MOZ_EXTENSIONS_PROFILE_DIR/$langpack > $FEDORA_LANGPACK_CONFIG return 0 fi @@ -235,34 +227,11 @@ fi NSS_SSL_CBC_RANDOM_IV=${NSS_SSL_CBC_RANDOM_IV-1} export NSS_SSL_CBC_RANDOM_IV -# Prepare command line arguments -script_args="" -pass_arg_count=0 -while [ $# -gt $pass_arg_count ] -do - case "$1" in - -g | --debug) - script_args="$script_args -g" - debugging=1 - shift - ;; - -d | --debugger) - if [ $# -gt 1 ]; then - script_args="$script_args -d $2" - shift 2 - else - shift - fi - ;; - *) - # Move the unrecognized argument to the end of the list. - arg="$1" - shift - set -- "$@" "$arg" - pass_arg_count=`expr $pass_arg_count + 1` - ;; - esac -done +# MOZ_APP_REMOTINGNAME links Firefox with desktop file name +if [ -z "$MOZ_APP_REMOTINGNAME" ] +then + export MOZ_APP_REMOTINGNAME=__APP_NAME__ +fi # Flatpak specific environment variables %FLATPAK_ENV_VARS% @@ -274,7 +243,7 @@ export MOZ_ALLOW_DOWNGRADE=1 debugging=0 if [ $debugging = 1 ] then - echo $MOZ_LAUNCHER $script_args $MOZ_PROGRAM "$@" + echo $MOZ_PROGRAM "$@" fi -exec $MOZ_LAUNCHER $script_args $MOZ_PROGRAM "$@" +exec $MOZ_PROGRAM "$@" diff --git a/firefox.spec b/firefox.spec index 422c046..b91a17e 100644 --- a/firefox.spec +++ b/firefox.spec @@ -1,31 +1,76 @@ -# Set to true if it's going to be submitted as update. -%global release_build 0 -%global debug_build 0 -%global build_with_clang 0 -%global build_with_asan 0 -%global run_firefox_tests 1 -%global create_debuginfo 1 -%global system_nss 1 +# Produce a build suitable for release, i.e. use PGO/LTO. You can turn it off +# when building locally to reduce build time. +%global release_build 1 -# 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 -ExcludeArch: armv7hl -ExcludeArch: aarch64 +# Excluded due to https://bugzilla.mozilla.org/show_bug.cgi?id=1792159 +# https://bugzilla.redhat.com/show_bug.cgi?id=2129720 +ExcludeArch: i686 -%ifarch armv7hl -%global create_debuginfo 0 +# Run Mozilla test suite as a part of compile rpm section. Turn off when +# building locally and don't want to spend 24 hours waiting for results. +%global run_firefox_tests 0 +%ifarch x86_64 %{ix86} +%global run_firefox_tests 0 %endif +# Don't create debuginfo rpm packages. It reduces build time as +# exctracting debuginfo takes long time. +%global create_debuginfo 1 + +# Produce debug (non-optimized) package build. Suitable for debugging only +# as the build is *very* slow. +%global debug_build 0 + +# See rhbz#2134527 - Use portal Gtk file dialog +# Disabled due to various issues now. +%global use_xdg_file_portal 0 + +# PipeWire camera is needed for IPU6 camera support in Fedora 41+ +# https://fedoraproject.org/wiki/Changes/IPU6_Camera_support +%if 0%{?fedora} >= 41 +%global use_pipewire_camera 1 +%else +%global use_pipewire_camera 0 +%endif + +%global system_nss 1 +%global system_libevent 1 +%global build_with_asan 0 +%ifarch x86_64 %{ix86} +%global enable_replace_malloc 1 +%else +%global enable_replace_malloc 0 +%endif + +# wasi_sdk 25 is not compatible with llvm 18 +%if 0%{?fedora} <= 40 + %bcond wasi_sdk 0 +%else + %ifarch s390x + %bcond wasi_sdk 0 + %else + %bcond wasi_sdk 1 + %endif +%endif + +%bcond build_with_clang 0 +%if %{with build_with_clang} +%global toolchain clang +%else +%global toolchain gcc +%endif + +%global gnome_shell_search_provider 0 +%if 0%{?fedora} >= 40 +%global gnome_shell_search_provider 1 +%endif + +# Temporary disabled due to +# https://bugzilla.redhat.com/show_bug.cgi?id=1951606 %global enable_mozilla_crashreporter 0 -# Temporary disable on rawhide due to -# https://bugzilla.redhat.com/show_bug.cgi?id=1891794 -%if 0%{?fedora} < 33 %ifarch x86_64 %{ix86} %global enable_mozilla_crashreporter 1 %endif -%endif %if %{build_with_asan} %global enable_mozilla_crashreporter 0 %endif @@ -35,69 +80,88 @@ ExcludeArch: aarch64 %if !%{create_debuginfo} %define _unpackaged_files_terminate_build 0 %global debug_package %{nil} +%global enable_mozilla_crashreporter 0 %endif %global system_ffi 1 -%ifarch armv7hl +%global system_av1 0 %global system_libvpx 1 -%else -%global system_libvpx 0 -%endif -%global hardened_build 1 %global system_jpeg 1 -%global disable_elfhack 1 +%global system_pixman 1 +%global system_webp 1 +%global system_drm 1 +%global system_gbm 1 +%global system_pipewire 1 +# Bundled cbindgen makes build slow. +# Enable only if system cbindgen is not available. +%if 0%{?rhel} %global use_bundled_cbindgen 1 +%else +%global use_bundled_cbindgen 1 +%endif %if %{debug_build} %global release_build 0 %endif -# Build PGO+LTO on x86_64 and aarch64 only due to build issues +# Build PGO+LTO on x86_64 only due to build issues # on other arches. %global build_with_pgo 0 %ifarch x86_64 %if %{release_build} %global build_with_pgo 1 %endif -# Build PGO builds on Wayland backend -%global pgo_wayland 0 %endif -%global wayland_backend_default 1 %if 0%{?flatpak} %global build_with_pgo 0 %endif # Big endian platforms -%ifarch ppc64 s390x +%ifarch s390x %global big_endian 1 %endif %if 0%{?build_with_pgo} -%global use_xvfb 1 +%global use_xvfb 0 %global build_tests 1 %endif %if 0%{?run_firefox_tests} -%global use_xvfb 1 +%global use_xvfb 0 %global build_tests 1 %endif +%global launch_wayland_compositor 0 +%if %{build_with_pgo} +%global launch_wayland_compositor 1 +%endif +%if %{run_firefox_tests} +%global launch_wayland_compositor 1 +%endif + %global default_bookmarks_file %{_datadir}/bookmarks/default-bookmarks.html %global firefox_app_id \{ec8030f7-c20a-464f-9b0e-13a3a9e97384\} # Minimal required versions %global cairo_version 1.13.1 %global freetype_version 2.1.9 %global libnotify_version 0.7.0 +%if %{?system_av1} +%global aom_version 1.0.0 +%global dav1d_version 1.0.0 +%endif %if %{?system_libvpx} -%global libvpx_version 1.8.2 +%global libvpx_version 1.10.0 +%endif +%if %{?system_webp} +%global libwebp_version 1.1.0 %endif %if %{?system_nss} -%global nspr_version 4.21 +%global nspr_version 4.37 %global nspr_build_version %{nspr_version} -%global nss_version 3.58 +%global nss_version 3.119 %global nss_build_version %{nss_version} %endif -%global mozappdir %{_libdir}/%{name} -%global mozappdirdev %{_libdir}/%{name}-devel-%{version} +%global mozappdir %{_libdir}/firefox +%global mozappdirdev %{_libdir}/firefox-devel-%{version} %global langpackdir %{mozappdir}/langpacks %global tarballdir firefox-%{version} @@ -105,10 +169,14 @@ ExcludeArch: aarch64 %bcond_without langpacks +%if %{with langpacks} +%bcond_without langpacks_subpkg +%endif + %if !%{release_build} %global pre_tag .npgo %endif -%if %{build_with_clang} +%if %{with build_with_clang} %global pre_tag .clang %endif %if %{build_with_asan} @@ -122,17 +190,28 @@ ExcludeArch: aarch64 %global pre_tag .debug %endif +# Exclude private libraries from autogenerated provides and requires +%global __provides_exclude_from ^%{mozappdir} +%global __requires_exclude ^(%%(find %{buildroot}%{mozappdir} -name '*.so' | xargs -n1 basename | sort -u | paste -s -d '|' -)) + +%undefine _package_note_flags +# for https://bugzilla.redhat.com/show_bug.cgi?id=2184553 +%global _package_note_status 0 + Summary: Mozilla Firefox Web browser Name: firefox -Version: 83.0 -Release: 6%{?pre_tag}%{?dist} +Version: 147.0 +Release: 1%{?pre_tag}%{?dist} URL: https://www.mozilla.org/firefox/ -License: MPLv1.1 or GPLv2+ or LGPLv2+ +# Automatically converted from old format: MPLv1.1 or GPLv2+ or LGPLv2+ - review is highly recommended. +License: LicenseRef-Callaway-MPLv1.1 OR GPL-2.0-or-later OR LicenseRef-Callaway-LGPLv2+ Source0: https://archive.mozilla.org/pub/firefox/releases/%{version}%{?pre_version}/source/firefox-%{version}%{?pre_version}.source.tar.xz %if %{with langpacks} -Source1: firefox-langpacks-%{version}%{?pre_version}-20201116.tar.xz +Source1: firefox-langpacks-%{version}%{?pre_version}-20260106.tar.xz %endif Source2: cbindgen-vendor.tar.xz +Source3: dump_syms-vendor.tar.xz +Source4: wasm-component-ld-vendor.tar.xz Source10: firefox-mozconfig Source12: firefox-redhat-default-prefs.js Source20: firefox.desktop @@ -140,7 +219,7 @@ Source21: firefox.sh.in Source23: firefox.1 Source24: mozilla-api-key Source25: firefox-symbolic.svg -Source26: distribution.ini +Source26: distribution.ini.in Source27: google-api-key Source28: firefox-wayland.sh.in Source29: firefox-wayland.desktop @@ -148,65 +227,59 @@ Source30: firefox-x11.sh.in Source31: firefox-x11.desktop Source32: node-stdout-nonblocking-wrapper Source33: firefox.appdata.xml.in -Source34: firefox-search-provider.ini +Source34: org.mozilla.firefox.search-provider.ini Source35: google-loc-api-key -Source36: firefox-testing.tar.gz +Source37: mochitest-python.tar.gz +Source38: print_results +Source39: print-errors +Source40: run-tests-x11 +Source41: run-tests-wayland +Source42: psummary +Source43: print_failures +Source44: print-error-reftest +Source45: run-wayland-compositor +Source46: org.mozilla.firefox.SearchProvider.service +Source47: org.mozilla.firefox.desktop +Source48: org.mozilla.firefox.appdata.xml.in +Source49: wasi.patch.template +# Created by: +# git clone --recursive https://github.com/WebAssembly/wasi-sdk.git +# cd wasi-sdk && git-archive-all --force-submodules wasi-sdk-25.tar.gz +Source50: wasi-sdk-25.tar.gz # 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) -Patch38: build-cacheFlush-missing.patch Patch40: build-aarch64-skia.patch -Patch41: build-disable-elfhack.patch Patch44: build-arm-libopus.patch -Patch46: firefox-nss-version.patch -Patch47: fedora-shebang-build.patch -Patch48: build-arm-wasm.patch -Patch49: build-arm-libaom.patch Patch53: firefox-gcc-build.patch -# This should be fixed in Firefox 83 -Patch54: mozilla-1669639.patch -Patch55: firefox-testing.patch +Patch71: 0001-GLIBCXX-fix-for-GCC-12.patch +Patch78: firefox-i686-build.patch +Patch79: firefox-gcc-13-build.patch +Patch80: wasi.patch +Patch81: firefox-gcc-15.0-s390.patch +Patch82: build-c11-threads-avail.patch +Patch83: build-seccomp.patch + # Fedora specific patches Patch215: firefox-enable-addons.patch Patch219: rhbz-1173156.patch -Patch221: firefox-fedora-ua.patch -Patch224: mozilla-1170092.patch #ARM run-time patch Patch226: rhbz-1354671.patch -Patch227: firefox-locale-debug.patch Patch228: disable-openh264-download.patch +Patch229: firefox-nss-addon-hack.patch +Patch231: fedora-customization.patch +Patch241: 0025-Add-KDE-integration-to-Firefox-toolkit-parts.patch +Patch242: 0026-Add-KDE-integration-to-Firefox.patch # Upstream patches -Patch402: mozilla-1196777.patch -Patch407: mozilla-1667096.patch -Patch408: mozilla-1663844.patch -Patch415: mozilla-1670333.patch -Patch416: mozilla-1673202.patch -Patch417: mozilla-1673313.patch -Patch418: mozilla-1556931-s390x-hidden-syms.patch -Patch419: mozilla-1885133.patch - -# Upstream patches from mozbz#1672944 -Patch450: pw1.patch -Patch451: pw2.patch -Patch452: pw3.patch -Patch453: pw4.patch -Patch454: pw5.patch -Patch455: pw6.patch -Patch456: pw7.patch - -#VA-API patches -Patch584: firefox-disable-ffvpx-with-vapi.patch -Patch585: firefox-vaapi-extra-frames.patch +Patch400: mozilla-1196777.patch +Patch401: mozilla-1667096.patch # PGO/LTO patches Patch600: pgo.patch Patch602: mozilla-1516803.patch +Patch603: firefox-gcc-always-inline.patch + %if %{?system_nss} BuildRequires: pkgconfig(nspr) >= %{nspr_version} @@ -217,11 +290,13 @@ BuildRequires: pkgconfig(libpng) %if %{?system_jpeg} BuildRequires: libjpeg-devel %endif +%if %{?system_pixman} +BuildRequires: pixman-devel +%endif BuildRequires: zip BuildRequires: bzip2-devel BuildRequires: pkgconfig(zlib) BuildRequires: pkgconfig(gtk+-3.0) -BuildRequires: pkgconfig(gtk+-2.0) BuildRequires: pkgconfig(krb5) BuildRequires: pkgconfig(pango) BuildRequires: pkgconfig(freetype2) >= %{freetype_version} @@ -231,22 +306,40 @@ BuildRequires: pkgconfig(libstartup-notification-1.0) BuildRequires: pkgconfig(libnotify) >= %{libnotify_version} BuildRequires: pkgconfig(dri) BuildRequires: pkgconfig(libcurl) +BuildRequires: pkgconfig(alsa) BuildRequires: dbus-glib-devel +%if %{?system_av1} +BuildRequires: pkgconfig(aom) >= %{aom_version} +BuildRequires: pkgconfig(dav1d) >= %{dav1d_version} +%endif %if %{?system_libvpx} BuildRequires: libvpx-devel >= %{libvpx_version} %endif +%if %{?system_webp} +BuildRequires: pkgconfig(libwebp) >= %{libwebp_version} +BuildRequires: pkgconfig(libwebpdemux) >= %{libwebp_version} +%endif BuildRequires: autoconf213 BuildRequires: pkgconfig(libpulse) -BuildRequires: yasm BuildRequires: llvm BuildRequires: llvm-devel BuildRequires: clang BuildRequires: clang-libs -%if %{build_with_clang} +%if %{with build_with_clang} || %{with wasi_sdk} BuildRequires: lld %endif +%if %{?system_drm} +BuildRequires: libdrm-devel +%endif + +%if %{?system_gbm} +BuildRequires: mesa-libgbm-devel +%endif + +%if %{?system_pipewire} BuildRequires: pipewire-devel +%endif %if !0%{?use_bundled_cbindgen} BuildRequires: cbindgen @@ -260,20 +353,32 @@ BuildRequires: icu %endif Requires: mozilla-filesystem -%if 0%{?fedora} > 31 -Recommends: mozilla-openh264 >= 2.1.1 +Requires: (mozilla-openh264 >= 2.1.1 if openh264) +%if %{with langpacks_subpkg} +Recommends: firefox-langpacks = %{version}-%{release} +%else +Obsoletes: firefox-langpacks < %{version}-%{release} %endif +Recommends: ffmpeg-free +Recommends: libva Requires: p11-kit-trust +Requires: pciutils-libs %if %{?system_nss} Requires: nspr >= %{nspr_build_version} Requires: nss >= %{nss_build_version} %endif +%if %{?system_libevent} +BuildRequires: pkgconfig(libevent) +%endif BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3.11-devel %if !0%{?flatpak} Requires: u2f-hidraw-policy %endif -BuildRequires: nss-devel >= 3.29.1-2.1 -Requires: nss >= 3.48.0 +%if %{?use_xdg_file_portal} +Requires: xdg-desktop-portal +%endif BuildRequires: desktop-file-utils %if !0%{?flatpak} @@ -286,12 +391,6 @@ BuildRequires: pkgconfig(libffi) %if 0%{?use_xvfb} BuildRequires: xorg-x11-server-Xvfb %endif -%if 0%{?pgo_wayland} -BuildRequires: mutter -BuildRequires: gsettings-desktop-schemas -BuildRequires: gnome-settings-daemon -BuildRequires: mesa-dri-drivers -%endif BuildRequires: rust BuildRequires: cargo BuildRequires: clang-devel @@ -301,25 +400,110 @@ BuildRequires: libasan-static %endif BuildRequires: perl-interpreter BuildRequires: fdk-aac-free-devel +%if 0%{?launch_wayland_compositor} +BuildRequires: mutter +BuildRequires: gsettings-desktop-schemas +BuildRequires: gnome-settings-daemon +BuildRequires: mesa-dri-drivers +BuildRequires: xorg-x11-server-Xwayland +BuildRequires: dbus-x11 +BuildRequires: gnome-keyring +%endif %if 0%{?run_firefox_tests} +BuildRequires: procps-ng BuildRequires: nss-tools BuildRequires: python2.7 +BuildRequires: dejavu-sans-mono-fonts +BuildRequires: dejavu-sans-fonts +BuildRequires: dejavu-serif-fonts +BuildRequires: dbus-x11 +BuildRequires: gnome-keyring +BuildRequires: mesa-dri-drivers +# ---------------------------------------- +BuildRequires: liberation-fonts-common +BuildRequires: liberation-mono-fonts +BuildRequires: liberation-sans-fonts +BuildRequires: liberation-serif-fonts +# ---------------------------------- +BuildRequires: google-carlito-fonts +BuildRequires: google-droid-sans-fonts +BuildRequires: google-noto-fonts-common +BuildRequires: google-noto-cjk-fonts-common +BuildRequires: google-noto-sans-cjk-ttc-fonts +BuildRequires: google-noto-sans-gurmukhi-fonts +BuildRequires: google-noto-sans-fonts +BuildRequires: google-noto-emoji-color-fonts +BuildRequires: google-noto-sans-sinhala-vf-fonts +# ----------------------------------- +BuildRequires: thai-scalable-fonts-common +BuildRequires: thai-scalable-waree-fonts +BuildRequires: khmeros-base-fonts +BuildRequires: jomolhari-fonts +# ---------------------------------- +BuildRequires: lohit-tamil-fonts +BuildRequires: lohit-telugu-fonts +# ---------------------------------- +BuildRequires: paktype-naskh-basic-fonts +BuildRequires: pt-sans-fonts +BuildRequires: smc-meera-fonts +BuildRequires: stix-fonts +BuildRequires: abattis-cantarell-fonts +BuildRequires: xorg-x11-fonts-ISO8859-1-100dpi +BuildRequires: xorg-x11-fonts-misc +%endif +BuildRequires: make +BuildRequires: pciutils-libs +BuildRequires: mesa-libgbm-devel +BuildRequires: libproxy-devel +# Required for --enable-replace-malloc +%if %{enable_replace_malloc} +BuildRequires: libstdc++-static +%endif +%if %{with wasi_sdk} +BuildRequires: clang cmake ninja-build +%endif +Recommends: speech-dispatcher +Recommends: speech-dispatcher-utils + +%if %{with build_with_clang} +BuildRequires: compiler-rt %endif Obsoletes: mozilla <= 37:1.7.13 Provides: webclient +# Don't ship firefox-x11 and firefox-wayland on Fedora 40. +# Wayland backend is considered as mature enough now. +# We need to use v-r in Obsoletes because new versions of this +# package keep being built in older releases, and we want to +# obsolete all of them when the user updates to F40+. +%if 0%{?fedora} >= 40 +Obsoletes: firefox-wayland < %{version}-%{release} +Obsoletes: firefox-x11 < %{version}-%{release} +%endif + %description Mozilla Firefox is an open-source web browser, designed for standards compliance, performance and portability. +%if %{with langpacks_subpkg} +%package langpacks +Summary: Firefox langpacks +Requires: %{name} = %{version}-%{release} +%description langpacks +The firefox-langpacks package contains all the localization +and translations langpack add-ons. +%files langpacks -f %{name}.lang +%dir %{langpackdir} +%endif + %if %{enable_mozilla_crashreporter} %global moz_debug_prefix %{_prefix}/lib/debug %global moz_debug_dir %{moz_debug_prefix}%{mozappdir} %global uname_m %(uname -m) %global symbols_file_name %{name}-%{version}.en-US.%{_os}-%{uname_m}.crashreporter-symbols.zip %global symbols_file_path %{moz_debug_dir}/%{symbols_file_name} -%global _find_debuginfo_opts -p %{symbols_file_path} -o debugcrashreporter.list +%global _find_debuginfo_opts %{limit_build -m 32768} -p %{symbols_file_path} -o debugcrashreporter.list %global crashreporter_pkg_name mozilla-crashreporter-%{name}-debuginfo %package -n %{crashreporter_pkg_name} Summary: Debugging symbols used by Mozilla's crash reporter servers @@ -328,9 +512,11 @@ This package provides debug information for Firefox, for use by Mozilla's crash reporter servers. If you are trying to locally debug %{name}, you want to install %{name}-debuginfo instead. %files -n %{crashreporter_pkg_name} -f debugcrashreporter.list +%else +%global _find_debuginfo_opts %{limit_build -m 32768} %endif -%if 0%{?wayland_backend_default} +%if 0%{?fedora} < 40 %package x11 Summary: Firefox X11 launcher. Requires: %{name} @@ -340,7 +526,6 @@ to run Firefox explicitly on X11. %files x11 %{_bindir}/firefox-x11 %{_datadir}/applications/firefox-x11.desktop -%endif %package wayland Summary: Firefox Wayland launcher. @@ -351,98 +536,82 @@ to run Firefox explicitly on Wayland. %files wayland %{_bindir}/firefox-wayland %{_datadir}/applications/firefox-wayland.desktop +%endif %if 0%{?run_firefox_tests} -%global testsuite_pkg_name mozilla-%{name}-testresults +%global testsuite_pkg_name %{name}-testresults %package -n %{testsuite_pkg_name} Summary: Results of testsuite %description -n %{testsuite_pkg_name} This package contains results of tests executed during build. %files -n %{testsuite_pkg_name} -/%{version}%-%{release}/test_general -/%{version}%-%{release}/test_basic -/%{version}%-%{release}/test_wr -/%{version}%-%{release}/test_summary.txt +/%{version}-%{release}/test_results +/%{version}-%{release}/test_summary.txt +/%{version}-%{release}/failures-* %endif #--------------------------------------------------------------------- %prep %setup -q -n %{tarballdir} +%if %{with wasi_sdk} +%setup -q -T -D -a 50 +%endif # Build patches, can't change backup suffix from default because 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 +%patch -P40 -p1 -b .aarch64-skia +%patch -P44 -p1 -b .build-arm-libopus +%patch -P53 -p1 -b .firefox-gcc-build +%patch -P71 -p1 -b .0001-GLIBCXX-fix-for-GCC-12 +%patch -P78 -p1 -b .firefox-i686 +%patch -P79 -p1 -b .firefox-gcc-13-build +%patch -P81 -p1 -b .firefox-gcc-15.0-s390 +%if 0%{?fedora} >= 44 +%patch -P82 -p1 -b .build-c11-threads-avail +%patch -P83 -p1 -b .build-seccomp %endif -%patch40 -p1 -b .aarch64-skia -%if 0%{?disable_elfhack} -%patch41 -p1 -b .disable-elfhack + +# We need to create the wasi.patch with the correct path to the wasm libclang_rt. +%if %{with wasi_sdk} +cat %{SOURCE49} | sed -e "s|LIBCLANG_RT_PLACEHOLDER|`pwd`/wasi-sdk-25/build/sysroot/install/wasi-resource-dir/lib/wasi/libclang_rt.builtins-wasm32.a|" > %{_sourcedir}/wasi.patch +%patch -P80 -p1 -b .wasi %endif -%patch3 -p1 -b .arm -%patch44 -p1 -b .build-arm-libopus -#%patch46 -p1 -b .nss-version -%patch47 -p1 -b .fedora-shebang -%patch48 -p1 -b .build-arm-wasm -%patch49 -p1 -b .build-arm-libaom -%patch53 -p1 -b .firefox-gcc-build -%patch54 -p1 -b .1669639 -%patch55 -p1 -b .testing # Fedora patches -%patch215 -p1 -b .addons -%patch219 -p1 -b .rhbz-1173156 -%patch221 -p1 -b .fedora-ua -%patch224 -p1 -b .1170092 +%patch -P215 -p1 -b .addons +%patch -P219 -p1 -b .rhbz-1173156 #ARM run-time patch %ifarch aarch64 -%patch226 -p1 -b .1354671 +%patch -P226 -p1 -b .1354671 %endif -%patch227 -p1 -b .locale-debug -%patch228 -p1 -b .disable-openh264-download +%patch -P228 -p1 -b .disable-openh264-download +%patch -P229 -p1 -b .firefox-nss-addon-hack +%patch -P231 -p1 -b .fedora-customization -%patch402 -p1 -b .1196777 -%patch407 -p1 -b .1667096 -%patch408 -p1 -b .1663844 -%patch415 -p1 -b .1670333 -%if 0%{?fedora} > 33 || 0%{?eln} -%patch416 -p1 -b .1673202 -%endif -%patch417 -p1 -b .1673313 -%patch418 -p1 -b .1556931-s390x-hidden-syms -%patch419 -p1 -b .1885133 - -%patch450 -p1 -b .pw1 -%patch451 -p1 -b .pw2 -%patch452 -p1 -b .pw3 -%patch453 -p1 -b .pw4 -%patch454 -p1 -b .pw5 -%patch455 -p1 -b .pw6 -%patch456 -p1 -b .pw7 - -# VA-API fixes -%patch584 -p1 -b .firefox-disable-ffvpx-with-vapi -%patch585 -p1 -b .firefox-vaapi-extra-frames +%patch -P400 -p1 -b .1196777 +%patch -P401 -p1 -b .1667096 # PGO patches %if %{build_with_pgo} -%if !%{build_with_clang} -%patch600 -p1 -b .pgo -%patch602 -p1 -b .1516803 +%if !%{with build_with_clang} +%patch -P600 -p1 -b .pgo +%patch -P602 -p1 -b .1516803 %endif %endif +%patch -P603 -p1 -b .inline -%{__rm} -f .mozconfig -%{__cp} %{SOURCE10} .mozconfig +rm -f .mozconfig +cp %{SOURCE10} .mozconfig echo "ac_add_options --enable-default-toolkit=cairo-gtk3-wayland" >> .mozconfig %if %{official_branding} echo "ac_add_options --enable-official-branding" >> .mozconfig %endif -%{__cp} %{SOURCE24} mozilla-api-key -%{__cp} %{SOURCE27} google-api-key -%{__cp} %{SOURCE35} google-loc-api-key +cp %{SOURCE24} mozilla-api-key +cp %{SOURCE27} google-api-key +cp %{SOURCE35} google-loc-api-key echo "ac_add_options --prefix=\"%{_prefix}\"" >> .mozconfig echo "ac_add_options --libdir=\"%{_libdir}\"" >> .mozconfig @@ -455,13 +624,20 @@ echo "ac_add_options --without-system-nspr" >> .mozconfig echo "ac_add_options --without-system-nss" >> .mozconfig %endif +%if %{?system_libevent} +echo "ac_add_options --with-system-libevent" >> .mozconfig +%endif + %if %{?system_ffi} echo "ac_add_options --enable-system-ffi" >> .mozconfig %endif -%ifarch %{arm} +%ifarch aarch64 echo "ac_add_options --disable-elf-hack" >> .mozconfig %endif +%ifarch ppc64le +echo "ac_add_options --disable-webrtc" >> .mozconfig +%endif %if %{?debug_build} echo "ac_add_options --enable-debug" >> .mozconfig @@ -500,13 +676,47 @@ echo "ac_add_options --without-system-jpeg" >> .mozconfig echo "ac_add_options --with-system-jpeg" >> .mozconfig %endif +%if %{?system_pixman} +echo "ac_add_options --enable-system-pixman" >> .mozconfig +%endif + +%if %{?system_av1} +#echo "ac_add_options --with-system-av1" >> .mozconfig +%else +#echo "ac_add_options --without-system-av1" >> .mozconfig +%endif + %if %{?system_libvpx} echo "ac_add_options --with-system-libvpx" >> .mozconfig %else echo "ac_add_options --without-system-libvpx" >> .mozconfig %endif -%ifarch s390 s390x +%if %{?system_webp} +echo "ac_add_options --with-system-webp" >> .mozconfig +%else +echo "ac_add_options --without-system-webp" >> .mozconfig +%endif + +%if %{?system_drm} +echo "ac_add_options --with-system-libdrm" >> .mozconfig +%else +echo "ac_add_options --without-system-libdrm" >> .mozconfig +%endif + +%if %{?system_gbm} +echo "ac_add_options --with-system-gbm" >> .mozconfig +%else +echo "ac_add_options --without-system-gbm" >> .mozconfig +%endif + +%if %{?system_pipewire} +echo "ac_add_options --with-system-pipewire" >> .mozconfig +%else +echo "ac_add_options --without-system-pipewire" >> .mozconfig +%endif + +%ifarch s390x echo "ac_add_options --disable-jit" >> .mozconfig %endif @@ -521,26 +731,65 @@ echo "ac_add_options --with-mozilla-api-keyfile=`pwd`/mozilla-api-key" >> .mozco echo "ac_add_options --with-google-location-service-api-keyfile=`pwd`/google-loc-api-key" >> .mozconfig echo "ac_add_options --with-google-safebrowsing-api-keyfile=`pwd`/google-api-key" >> .mozconfig +# https://bugzilla.redhat.com/show_bug.cgi?id=2239046 +# with clang 17 upstream's detection fails, so let's just tell it +# where to look +echo "ac_add_options --with-libclang-path=`llvm-config --libdir`" >> .mozconfig + +%if %{enable_replace_malloc} +echo "ac_add_options --enable-replace-malloc" >> .mozconfig +%endif + echo 'export NODEJS="%{_buildrootdir}/bin/node-stdout-nonblocking-wrapper"' >> .mozconfig # Remove executable bit to make brp-mangle-shebangs happy. chmod -x third_party/rust/itertools/src/lib.rs -chmod a-x third_party/rust/gfx-backend-vulkan/src/*.rs -chmod a-x third_party/rust/gfx-hal/src/*.rs chmod a-x third_party/rust/ash/src/extensions/ext/*.rs chmod a-x third_party/rust/ash/src/extensions/khr/*.rs +chmod a-x third_party/rust/ash/src/extensions/nv/*.rs #--------------------------------------------------------------------- %build # Disable LTO to work around rhbz#1883904 +# Is that already fixed? %define _lto_cflags %{nil} -%if 0%{?use_bundled_cbindgen} +#WASI SDK +%if %{with wasi_sdk} +pushd wasi-sdk-25 mkdir -p my_rust_vendor cd my_rust_vendor -%{__tar} xf %{SOURCE2} +tar xf %{SOURCE4} +mkdir -p .cargo +cat > .cargo/config < .cargo/config < .cargo/config < 30 +MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | sed -e 's/-Werror=format-security//') +# More Fedora specific build flags 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//') +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) +%ifarch %{ix86} ppc64le +MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | sed -e 's/-g/-g0/') +%else +# this reduces backtrace quality substantially, but seems to be needed +# to prevent various OOM conditions during build +# https://bugzilla.redhat.com/show_bug.cgi?id=2241690 +MOZ_OPT_FLAGS=$(echo "$MOZ_OPT_FLAGS" | sed -e 's/-g/-g1/') +%endif 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} -MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--reduce-memory-overheads" -%endif -%ifarch %{arm} -MOZ_LINK_FLAGS="-Wl,--no-keep-memory -Wl,--strip-debug" -echo "ac_add_options --enable-linker=gold" >> .mozconfig +MOZ_LINK_FLAGS="%{build_ldflags}" +%if !%{with build_with_clang} +%ifarch aarch64 %{ix86} ppc64le x86_64 +MOZ_LINK_FLAGS="$MOZ_LINK_FLAGS -Wl,--no-keep-memory" %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} +%ifarch %{ix86} s390x ppc64le export RUSTFLAGS="-Cdebuginfo=0" %endif %if %{build_with_asan} @@ -630,7 +879,7 @@ echo "export CFLAGS=\"$MOZ_OPT_FLAGS\"" >> .mozconfig echo "export CXXFLAGS=\"$MOZ_OPT_FLAGS\"" >> .mozconfig echo "export LDFLAGS=\"$MOZ_LINK_FLAGS\"" >> .mozconfig -%if %{build_with_clang} +%if %{with build_with_clang} echo "export LLVM_PROFDATA=\"llvm-profdata\"" >> .mozconfig echo "export AR=\"llvm-ar\"" >> .mozconfig echo "export NM=\"llvm-nm\"" >> .mozconfig @@ -644,108 +893,111 @@ echo "export NM=\"gcc-nm\"" >> .mozconfig echo "export RANLIB=\"gcc-ranlib\"" >> .mozconfig %endif %if 0%{?build_with_pgo} -echo "ac_add_options MOZ_PGO=1" >> .mozconfig - -# Temporary disabled due to GCC bug -# Fixed by https://bugzilla.mozilla.org/show_bug.cgi?id=1671345 -# Should be in Firefox 83 -# Temporary disabled due to https://bugzilla.redhat.com/show_bug.cgi?id=1893474 -# echo "ac_add_options --enable-lto" >> .mozconfig - # PGO build doesn't work with ccache export CCACHE_DISABLE=1 +export GCOV_PREFIX=`pwd -P`/objdir +export GCOV_PREFIX_STRIP=$(( $(echo `pwd -P`|tr -c -d '/' |wc -c )+2 )) +env | grep GCOV +echo "ac_add_options --enable-lto" >> .mozconfig +echo "ac_add_options MOZ_PGO=1" >> .mozconfig %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 +%if %{with wasi_sdk} +echo "ac_add_options --with-wasi-sysroot=`pwd`/wasi-sdk-25/build/sysroot/install/share/wasi-sysroot" >> .mozconfig +%else +echo "ac_add_options --without-sysroot" >> .mozconfig +echo "ac_add_options --without-wasm-sandboxed-libraries" >> .mozconfig %endif -echo "mk_add_options MOZ_MAKE_FLAGS=\"$MOZ_SMP_FLAGS\"" >> .mozconfig +# Require 4 GB of RAM per CPU core +%constrain_build -m 4096 +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 -export MACH_NO_WRITE_TIMES=1 + %if %{build_with_pgo} -%if %{pgo_wayland} -if [ -z "$XDG_RUNTIME_DIR" ]; then - export XDG_RUNTIME_DIR=$HOME -fi -xvfb-run mutter --wayland --nested & -if [ -z "$WAYLAND_DISPLAY" ]; then - export WAYLAND_DISPLAY=wayland-0 -else - export WAYLAND_DISPLAY=wayland-1 -fi -MOZ_ENABLE_WAYLAND=1 ./mach build 2>&1 | cat - -%else -GDK_BACKEND=x11 xvfb-run ./mach build 2>&1 | cat - -%endif -%else -./mach build -v 2>&1 | cat - +cp %{SOURCE45} . +. ./run-wayland-compositor %endif -# create debuginfo for crash-stats.mozilla.com -%if %{enable_mozilla_crashreporter} -make -C objdir buildsymbols -%endif - -%if 0%{?run_firefox_tests} -tar xf %{SOURCE36} +mkdir -p objdir/_virtualenvs/init_py3 cat > objdir/_virtualenvs/init_py3/pip.conf << EOF -[install] +[global] find-links=`pwd`/mochitest-python +no-index=true EOF -./run-tests -%endif -#--------------------------------------------------------------------- +tar xf %{SOURCE37} +#Use python 3.11 for mach +sed -i -e 's|#!/usr/bin/env python3|#!/usr/bin/env python3.11|' mach + +./mach build -v 2>&1 | cat - || exit 1 + +%if %{build_with_pgo} +kill $MUTTER_PID +%endif + +#--------------------------------------------------------------------- %install +# run Firefox test suite +# Do we need it? +# export MACH_NATIVE_PACKAGE_SOURCE=system +%if %{run_firefox_tests} +cp %{SOURCE45} . +. ./run-wayland-compositor + +cp %{SOURCE40} %{SOURCE41} %{SOURCE42} %{SOURCE38} %{SOURCE39} %{SOURCE43} %{SOURCE44} . +mkdir -p test_results +./run-tests-wayland || true +./print_results > test_summary.txt 2>&1 || true +./print_failures || true + +kill $MUTTER_PID +%endif # set up our default bookmarks %if !0%{?flatpak} -%{__cp} -p %{default_bookmarks_file} objdir/dist/bin/browser/chrome/en-US/locale/browser/bookmarks.html +cp -p %{default_bookmarks_file} objdir/dist/bin/browser/chrome/browser/content/browser/default-bookmarks.html %endif # Make sure locale works for langpacks -%{__cat} > objdir/dist/bin/browser/defaults/preferences/firefox-l10n.js << EOF +cat > objdir/dist/bin/browser/defaults/preferences/firefox-l10n.js << EOF pref("general.useragent.locale", "chrome://global/locale/intl.properties"); EOF DESTDIR=%{buildroot} make -C objdir install -%{__mkdir_p} %{buildroot}{%{_libdir},%{_bindir},%{_datadir}/applications} +mkdir -p %{buildroot}{%{_libdir},%{_bindir},%{_datadir}/applications} -desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE20} -%if 0%{?wayland_backend_default} -desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE31} +%if %{gnome_shell_search_provider} +# Install Gnome search provider files +mkdir -p %{buildroot}%{_datadir}/gnome-shell/search-providers +cp %{SOURCE34} %{buildroot}%{_datadir}/gnome-shell/search-providers +mkdir -p %{buildroot}%{_datadir}/dbus-1/services +cp %{SOURCE46} %{buildroot}%{_datadir}/dbus-1/services %endif + +%if 0%{?fedora} >= 40 +desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE47} +%else +# We can't use desktop-file-install as it refuses to install firefox.desktop file. +cp %{SOURCE20} %{buildroot}%{_datadir}/applications +%endif + +%if 0%{?fedora} < 40 +desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE31} desktop-file-install --dir %{buildroot}%{_datadir}/applications %{SOURCE29} +%endif # set up the firefox start script -%if 0%{?wayland_backend_default} -%global wayland_default true +rm -rf %{buildroot}%{_bindir}/firefox +%if 0%{?fedora} < 40 +sed -e 's,/__PREFIX__,%{_prefix},g' -e 's,__APP_NAME__,firefox,g' %{SOURCE21} > %{buildroot}%{_bindir}/firefox %else -%global wayland_default false +sed -e 's,/__PREFIX__,%{_prefix},g' -e 's,__APP_NAME__,org.mozilla.firefox,g' %{SOURCE21} > %{buildroot}%{_bindir}/firefox %endif -%{__rm} -rf %{buildroot}%{_bindir}/firefox -%{__sed} -e 's/__DEFAULT_WAYLAND__/%{wayland_default}/' \ - -e 's,/__PREFIX__,%{_prefix},g' %{SOURCE21} > %{buildroot}%{_bindir}/firefox -%{__chmod} 755 %{buildroot}%{_bindir}/firefox - +chmod 755 %{buildroot}%{_bindir}/firefox %if 0%{?flatpak} sed -i -e 's|%FLATPAK_ENV_VARS%|export TMPDIR="$XDG_CACHE_HOME/tmp"|' %{buildroot}%{_bindir}/firefox @@ -753,38 +1005,39 @@ sed -i -e 's|%FLATPAK_ENV_VARS%|export TMPDIR="$XDG_CACHE_HOME/tmp"|' %{buildroo sed -i -e 's|%FLATPAK_ENV_VARS%||' %{buildroot}%{_bindir}/firefox %endif -%if 0%{?wayland_backend_default} -%{__sed} -e 's,/__PREFIX__,%{_prefix},g' %{SOURCE30} > %{buildroot}%{_bindir}/firefox-x11 -%{__chmod} 755 %{buildroot}%{_bindir}/firefox-x11 +%if 0%{?fedora} < 40 +sed -e 's,/__PREFIX__,%{_prefix},g' %{SOURCE30} > %{buildroot}%{_bindir}/firefox-x11 +chmod 755 %{buildroot}%{_bindir}/firefox-x11 +sed -e 's,/__PREFIX__,%{_prefix},g' %{SOURCE28} > %{buildroot}%{_bindir}/firefox-wayland +chmod 755 %{buildroot}%{_bindir}/firefox-wayland %endif -%{__sed} -e 's,/__PREFIX__,%{_prefix},g' %{SOURCE28} > %{buildroot}%{_bindir}/firefox-wayland -%{__chmod} 755 %{buildroot}%{_bindir}/firefox-wayland -%{__install} -p -D -m 644 %{SOURCE23} %{buildroot}%{_mandir}/man1/firefox.1 +install -p -D -m 644 %{SOURCE23} %{buildroot}%{_mandir}/man1/firefox.1 -%{__rm} -f %{buildroot}/%{mozappdir}/firefox-config -%{__rm} -f %{buildroot}/%{mozappdir}/update-settings.ini +rm -f %{buildroot}/%{mozappdir}/firefox-config +rm -f %{buildroot}/%{mozappdir}/update-settings.ini +rm -f %{buildroot}/%{mozappdir}/firefox-bin for s in 16 22 24 32 48 256; do - %{__mkdir_p} %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps - %{__cp} -p browser/branding/official/default${s}.png \ - %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps/firefox.png + mkdir -p %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps + cp -p browser/branding/official/default${s}.png \ + %{buildroot}%{_datadir}/icons/hicolor/${s}x${s}/apps/firefox.png done # Install hight contrast icon -%{__mkdir_p} %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps -%{__cp} -p %{SOURCE25} \ - %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +mkdir -p %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps +cp -p %{SOURCE25} \ + %{buildroot}%{_datadir}/icons/hicolor/symbolic/apps echo > %{name}.lang %if %{with langpacks} # Extract langpacks, make any mods needed, repack the langpack, and install it. -%{__mkdir_p} %{buildroot}%{langpackdir} -%{__tar} xf %{SOURCE1} +mkdir -p %{buildroot}%{langpackdir} +tar xf %{SOURCE1} for langpack in `ls firefox-langpacks/*.xpi`; do language=`basename $langpack .xpi` extensionID=langpack-$language@firefox.mozilla.org - %{__mkdir_p} $extensionID + mkdir -p $extensionID unzip -qq $langpack -d $extensionID find $extensionID -type f | xargs chmod 644 @@ -792,7 +1045,7 @@ for langpack in `ls firefox-langpacks/*.xpi`; do zip -qq -r9mX ../${extensionID}.xpi * cd - - %{__install} -m 644 ${extensionID}.xpi %{buildroot}%{langpackdir} + install -m 644 ${extensionID}.xpi %{buildroot}%{langpackdir} language=`echo $language | sed -e 's/-/_/g'` %if 0%{?flatpak} echo "%{langpackdir}/${extensionID}.xpi" >> %{name}.lang @@ -800,7 +1053,7 @@ for langpack in `ls firefox-langpacks/*.xpi`; do echo "%%lang($language) %{langpackdir}/${extensionID}.xpi" >> %{name}.lang %endif done -%{__rm} -rf firefox-langpacks +rm -rf firefox-langpacks # Install langpack workaround (see #707100, #821169) function create_default_langpack() { @@ -829,64 +1082,83 @@ create_default_langpack "sv-SE" "sv" create_default_langpack "zh-TW" "zh" %endif -%{__mkdir_p} %{buildroot}/%{mozappdir}/browser/defaults/preferences +mkdir -p %{buildroot}/%{mozappdir}/browser/defaults/preferences # System config dir -%{__mkdir_p} %{buildroot}/%{_sysconfdir}/%{name}/pref +mkdir -p %{buildroot}/%{_sysconfdir}/%{name}/pref # System extensions -%{__mkdir_p} %{buildroot}%{_datadir}/mozilla/extensions/%{firefox_app_id} -%{__mkdir_p} %{buildroot}%{_libdir}/mozilla/extensions/%{firefox_app_id} +mkdir -p %{buildroot}%{_datadir}/mozilla/extensions/%{firefox_app_id} +mkdir -p %{buildroot}%{_libdir}/mozilla/extensions/%{firefox_app_id} # Copy over the LICENSE -%{__install} -p -c -m 644 LICENSE %{buildroot}/%{mozappdir} +install -p -c -m 644 LICENSE %{buildroot}/%{mozappdir} # Use the system hunspell dictionaries -%{__rm} -rf %{buildroot}%{mozappdir}/dictionaries -ln -s %{_datadir}/myspell %{buildroot}%{mozappdir}/dictionaries +rm -rf %{buildroot}%{mozappdir}/dictionaries +ln -s %{_datadir}/hunspell %{buildroot}%{mozappdir}/dictionaries # Enable crash reporter for Firefox application %if %{enable_mozilla_crashreporter} +./mach buildsymbols sed -i -e "s/\[Crash Reporter\]/[Crash Reporter]\nEnabled=1/" %{buildroot}/%{mozappdir}/application.ini # Add debuginfo for crash-stats.mozilla.com -%{__mkdir_p} %{buildroot}/%{moz_debug_dir} -%{__cp} objdir/dist/%{symbols_file_name} %{buildroot}/%{moz_debug_dir} +mkdir -p %{buildroot}/%{moz_debug_dir} +cp objdir/dist/%{symbols_file_name} %{buildroot}/%{moz_debug_dir} %endif %if 0%{?run_firefox_tests} -%{__mkdir_p} %{buildroot}/%{version}%-%{release}/test_general -%{__mkdir_p} %{buildroot}/%{version}%-%{release}/test_basic -%{__mkdir_p} %{buildroot}/%{version}%-%{release}/test_wr -%{__cp} test_general/* %{buildroot}/%{version}%-%{release}/test_general -%{__cp} test_basic/* %{buildroot}/%{version}%-%{release}/test_basic -%{__cp} test_wr/* %{buildroot}/%{version}%-%{release}/test_wr -%{__cp} test_summary.txt %{buildroot}/%{version}%-%{release}/ +mkdir -p %{buildroot}/%{version}-%{release}/test_results +cp test_results/* %{buildroot}/%{version}-%{release}/test_results +cp test_summary.txt %{buildroot}/%{version}-%{release}/ +cp failures-* %{buildroot}/%{version}-%{release}/ || true %endif # Default -%{__cp} %{SOURCE12} %{buildroot}%{mozappdir}/browser/defaults/preferences +cp %{SOURCE12} %{buildroot}%{mozappdir}/browser/defaults/preferences +%if %{?use_xdg_file_portal} +echo 'pref("widget.use-xdg-desktop-portal.file-picker", 1);' >> %{buildroot}%{mozappdir}/browser/defaults/preferences/firefox-redhat-default-prefs.js +%endif -# Copy over run-mozilla.sh -%{__cp} build/unix/run-mozilla.sh %{buildroot}%{mozappdir} +%if %{?use_pipewire_camera} +echo 'pref("media.webrtc.camera.allow-pipewire", true);' >> %{buildroot}%{mozappdir}/browser/defaults/preferences/firefox-redhat-default-prefs.js +%endif # Add distribution.ini -%{__mkdir_p} %{buildroot}%{mozappdir}/distribution -%{__cp} %{SOURCE26} %{buildroot}%{mozappdir}/distribution +mkdir -p %{buildroot}%{mozappdir}/distribution +sed -e "s/__NAME__/%(source /etc/os-release; echo ${NAME})/" \ + -e "s/__ID__/%(source /etc/os-release; echo ${ID})/" \ + -e "s/rhel/redhat/" \ + -e "s/Fedora.*/Fedora/" \ + %{SOURCE26} > %{buildroot}%{mozappdir}/distribution/distribution.ini # Install appdata file mkdir -p %{buildroot}%{_datadir}/metainfo -%{__sed} -e "s/__VERSION__/%{version}/" \ - -e "s/__DATE__/$(date '+%F')/" \ - %{SOURCE33} > %{buildroot}%{_datadir}/metainfo/firefox.appdata.xml - -# Install Gnome search provider files -mkdir -p %{buildroot}%{_datadir}/gnome-shell/search-providers -%{__cp} %{SOURCE34} %{buildroot}%{_datadir}/gnome-shell/search-providers +%if 0%{?fedora} >= 40 +sed -e "s/__VERSION__/%{version}/" \ + -e "s/__DATE__/$(date '+%F')/" \ + %{SOURCE48} > %{buildroot}%{_datadir}/metainfo/org.mozilla.firefox.appdata.xml +%else +sed -e "s/__VERSION__/%{version}/" \ + -e "s/__DATE__/$(date '+%F')/" \ + %{SOURCE33} > %{buildroot}%{_datadir}/metainfo/firefox.appdata.xml +%endif # Remove copied libraries to speed up build rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libmozjs.so rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libmozalloc.so rm -f %{buildroot}%{mozappdirdev}/sdk/lib/libxul.so + +# Create a symlink to replace libnssckbi.so with p11-kit-client.so +# instead of p11-kit-trust.so, so that Firefox can see the system +# trust store on the host through the p11-kit RPC protocol. A symlink +# to libnss3.so is also needed, because Firefox tries to load +# libnssckbi.so from the same directory where libnss3.so is loaded (as +# of Firefox 89). +%if 0%{?flatpak} +ln -sf /usr/lib64/libnss3.so %{buildroot}%{_libdir}/libnss3.so +ln -sf /usr/lib64/pkcs11/p11-kit-client.so %{buildroot}%{_libdir}/libnssckbi.so +%endif #--------------------------------------------------------------------- # Moves defaults/preferences to browser/defaults/preferences @@ -914,54 +1186,53 @@ appstream-util validate-relax --nonet %{buildroot}%{_datadir}/metainfo/*.appdata %preun # is it a final removal? if [ $1 -eq 0 ]; then - %{__rm} -rf %{mozappdir}/components - %{__rm} -rf %{mozappdir}/extensions - %{__rm} -rf %{mozappdir}/plugins - %{__rm} -rf %{langpackdir} + rm -rf %{mozappdir}/components + rm -rf %{mozappdir}/extensions + rm -rf %{mozappdir}/plugins + rm -rf %{langpackdir} fi -%post -update-desktop-database &> /dev/null || : -touch --no-create %{_datadir}/icons/hicolor &>/dev/null || : - -%postun -update-desktop-database &> /dev/null || : -if [ $1 -eq 0 ] ; then - touch --no-create %{_datadir}/icons/hicolor &>/dev/null - gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : -fi - -%posttrans -gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : - +%if %{with langpacks_subpkg} +%files +%else %files -f %{name}.lang +%endif %{_bindir}/firefox %{mozappdir}/firefox -%{mozappdir}/firefox-bin +%{mozappdir}/glxtest %doc %{_mandir}/man1/* %dir %{_sysconfdir}/%{name} %dir %{_sysconfdir}/%{name}/* %dir %{_datadir}/mozilla/extensions/* %dir %{_libdir}/mozilla/extensions/* -%{_datadir}/applications/%{name}.desktop -%{_datadir}/metainfo/*.appdata.xml +%if 0%{?fedora} >= 40 +%{_datadir}/applications/org.mozilla.firefox.desktop +%else +%{_datadir}/applications/firefox.desktop +%endif +%if %{gnome_shell_search_provider} +%{_datadir}/dbus-1/services/* %{_datadir}/gnome-shell/search-providers/*.ini +%endif +%{_datadir}/metainfo/*.appdata.xml %dir %{mozappdir} %license %{mozappdir}/LICENSE -%{mozappdir}/browser/chrome -%{mozappdir}/browser/defaults/preferences/firefox-redhat-default-prefs.js -%{mozappdir}/browser/features/*.xpi -%{mozappdir}/distribution/distribution.ini +%{mozappdir}/browser +%{mozappdir}/distribution # That's Windows only %ghost %{mozappdir}/browser/features/aushelper@mozilla.org.xpi +%if %{without langpacks_subpkg} %if %{with langpacks} %dir %{langpackdir} %endif -%{mozappdir}/browser/omni.ja -%{mozappdir}/run-mozilla.sh +%endif %{mozappdir}/application.ini %{mozappdir}/pingsender %exclude %{mozappdir}/removed-files +%if 0%{?flatpak} +%{_libdir}/libnss3.so +%{_libdir}/libnssckbi.so +%endif %{_datadir}/icons/hicolor/16x16/apps/firefox.png %{_datadir}/icons/hicolor/22x22/apps/firefox.png %{_datadir}/icons/hicolor/24x24/apps/firefox.png @@ -971,21 +1242,20 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : %{_datadir}/icons/hicolor/symbolic/apps/firefox-symbolic.svg %if %{enable_mozilla_crashreporter} %{mozappdir}/crashreporter -%{mozappdir}/crashreporter.ini -%{mozappdir}/minidump-analyzer -%{mozappdir}/Throbber-small.gif -%{mozappdir}/browser/crashreporter-override.ini +%{mozappdir}/crashhelper %endif %{mozappdir}/*.so -%{mozappdir}/gtk2/*.so %{mozappdir}/defaults/pref/channel-prefs.js %{mozappdir}/dependentlibs.list %{mozappdir}/dictionaries %{mozappdir}/omni.ja %{mozappdir}/platform.ini -%{mozappdir}/plugin-container %{mozappdir}/gmp-clearkey -%{mozappdir}/fonts/TwemojiMozilla.ttf +%{mozappdir}/fonts +%ifarch aarch64 riscv64 +%{mozappdir}/v4l2test +%endif +%{mozappdir}/vaapitest %if !%{?system_nss} %exclude %{mozappdir}/libnssckbi.so %endif @@ -996,6 +1266,1194 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || : #--------------------------------------------------------------------- %changelog +* Tue Jan 06 2026 Martin Stransky - 147.0-1 +- Updated to 147.0 + +* Fri Dec 19 2025 Martin Stransky - 146.0.1-1 +- Updated to 146.0.1 + +* Wed Dec 17 2025 Martin Stransky - 146.0-6 +- Added upstream patch IWYU (libwebrtc IWYU fixes for PipeWire) +- Claude AI assisted editing (failed to do whole work, but it was close!) + +* Wed Dec 17 2025 Martin Stransky - 146.0-5 +- Removed firefox-bin from man pages + +* Thu Dec 11 2025 Martin Stransky - 146.0-4 +- Removed firefox-bin + +* Thu Dec 11 2025 Martin Stransky - 146.0-3 +- Added aarch64 crash fix +- Fixed rawhide gcc build (kudos to jhorak who hacked it! He's just awesome.) + +* Mon Dec 08 2025 Martin Stransky - 146.0-2 +- Updated to 146.0 build 2 + +* Wed Dec 03 2025 Martin Stransky - 146.0-1 +- Updated to 146.0 + +* Wed Nov 19 2025 Martin Stransky - 145.0.1-1 +- Updated to 145.0.1 + +* Tue Nov 11 2025 Martin Stransky - 145.0-2 +- Updated to 145.0 B2 + +* Wed Nov 05 2025 Martin Stransky - 145.0-1 +- Updated to 145.0 + +* Thu Oct 30 2025 Martin Stransky - 144.0.2-1 +- Updated to 144.0.2 + +* Thu Oct 16 2025 Martin Stransky - 144.0-3 +- Add fix for mzbz#1990430 + +* Mon Oct 13 2025 Martin Stransky - 144.0-2 +- Updated to 144.0 (b2) + +* Thu Oct 09 2025 Martin Stransky - 144.0-1 +- Updated to 144.0 + +* Mon Oct 06 2025 Martin Stransky - 143.0.4-1 +- Updated to 143.0.4 + +* Tue Sep 30 2025 Martin Stransky - 143.0.3-1 +- Updated to 143.0.3 + +* Fri Sep 26 2025 Martin Stransky - 143.0.1-3 +- Added fix for mzbz#1990162 + +* Thu Sep 25 2025 Martin Stransky - 143.0.1-2 +- Added fix for mzbz#1984368 + +* Fri Sep 19 2025 Martin Stransky - 143.0.1-1 +- Updated to 143.0.1 + +* Wed Sep 10 2025 Martin Stransky - 143.0-1 +- Updated to 143.0 + +* Wed Aug 27 2025 Martin Stransky - 142.0.1-1 +- Updated to 142.0.1 + +* Mon Aug 25 2025 Tom Stellard - 142.0-3 +- Fix build with llvm-21 + +* Sat Aug 23 2025 Dominik Mierzejewski - 142.0-2 +- Drop unused yasm build dependency, part of: + https://fedoraproject.org/wiki/Changes/DeprecateYASM + +* Tue Aug 12 2025 Martin Stransky - 142.0-1 +- Updated to 142.0 + +* Mon Aug 11 2025 Martin Stransky - 141.0.3-1 +- Updated to 141.0.3 + +* Wed Aug 6 2025 Martin Stransky - 141.0.2-1 +- Updated to 141.0.2 + +* Wed Jul 23 2025 Fedora Release Engineering - 141.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild + +* Fri Jul 18 2025 Martin Stransky - 141.0-2 +- Respin 141.0 build 2 + +* Thu Jul 17 2025 Martin Stransky - 141.0-1 +- Update to latest upstream (141.0) + +* Wed Jul 09 2025 Martin Stransky - 140.0.4-1 +- Update to latest upstream (140.0.4) + +* Fri Jun 27 2025 Martin Stransky - 140.0.1-1 +- Update to latest upstream (140.0.1) + +* Tue Jun 17 2025 Martin Stransky - 140.0-1 +- Update to latest upstream (140.0) + +* Wed Jun 11 2025 Martin Stransky - 139.0.4-2 +- Use headless Mutter to run PGO builds + +* Wed Jun 11 2025 Martin Stransky - 139.0.4-1 +- Updated to latest upstream (139.0.4) + +* Fri Jun 6 2025 Martin Stransky - 139.0-3 +- Updated desktop file translation (rhbz#2362155) + +* Fri May 30 2025 Jan Grulich - 139.0-2 +- Use system libraries for drm/gbm/pipewire + +* Tue May 27 2025 Martin Stransky - 139.0-1 +- Updated to 139.0 + +* Mon May 19 2025 Martin Stransky - 138.0.4-1 +- Updated to 138.0.4 + +* Wed May 14 2025 Martin Stransky - 138.0.3-2 +- Fixed rhbz#2283790 + +* Mon May 12 2025 Martin Stransky - 138.0.3-1 +- Updated to 138.0.3 + +* Thu May 1 2025 Martin Stransky - 138.0.1-1 +- Updated to 138.0.1 + +* Sat Apr 26 2025 Bojan Smojver - 138.0-1 +- Add fix for mzbz#1957628 +- Remove browser/features/*.xpi files, no longer shipped + +* Tue Apr 22 2025 Martin Stransky - 138.0-1 +- Updated to 138.0 + +* Tue Apr 22 2025 Martin Stransky - 137.0.2-3 +- Added fix for rhbz#2358565 + +* Wed Apr 16 2025 Martin Stransky - 137.0.2-2 +- Added fix for mzbz#1951249 + +* Wed Apr 16 2025 Martin Stransky - 137.0.2-1 +- Update 137.0.2 + +* Mon Apr 14 2025 Martin Stransky - 137.0.1-1 +- Update 137.0.1 + +* Mon Mar 31 2025 Martin Stransky - 137.0-2 +- Update 137.0 build 2 + +* Wed Mar 26 2025 Martin Stransky - 137.0-1 +- Update to latest upstream (137.0) + +* Tue Mar 25 2025 Martin Stransky - 136.0.3-1 +- Revert rhbz#2353895 as it looks broken +- Update to latest upstream (136.0.3) + +* Mon Mar 24 2025 Martin Stransky - 136.0.2-2 +- Stop overriding user settings on every update (rhbz#2353895) +- Remove browser.display.use_system_colors override (rhbz#2353953) + +* Wed Mar 19 2025 Martin Stransky - 136.0.2-1 +- Updated to 136.0.2 + +* Wed Mar 12 2025 Martin Stransky - 136.0.1-1 +- Updated to 136.0.1 + +* Fri Feb 28 2025 Martin Stransky - 136.0-2 +- Updated to 136.0 Build 3 + +* Tue Feb 25 2025 Martin Stransky - 136.0-1 +- Updated to 136.0 + +* Wed Feb 19 2025 Martin Stransky - 135.0.1-1 +- Updated to 135.0.1 + +* Tue Feb 04 2025 Martin Stransky - 135.0-1 +- Updated to 135.0 + +* Tue Jan 28 2025 Martin Stransky - 134.0.2-2 +- Call restorecon for widevine only (rhbz#2342243) + +* Wed Jan 22 2025 Martin Stransky - 134.0.2-1 +- Updated to 134.0.2 + +* Wed Jan 15 2025 Martin Stransky - 134.0.1-1 +- Updated to 134.0.1 + +* Thu Jan 02 2025 Martin Stransky - 134.0-1 +- Updated to 134.0 + +* Mon Dec 16 2024 Martin Stransky - 133.0.3-2 +- Remove MOZ_DBUS_APP_NAME from launch script as it breaks Thunderbird (rhbz#2320090) + +* Wed Dec 11 2024 Martin Stransky - 133.0.3-1 +- Updated to 133.0.3 + +* Sat Nov 30 2024 Martin Stransky - 133.0-2 +- Add fix for mzbz#1934217 + +* Fri Nov 22 2024 Martin Stransky - 133.0-1 +- Updated to latest upstream (133.0) + +* Mon Nov 18 2024 Martin Stransky - 132.0.2-2 +- Added memory saving flags to x86_64 + +* Fri Nov 15 2024 Martin Stransky - 132.0.2-1 +- Updated to 132.0.2 +- Try to reduce build mem usage on ppc64le + +* Thu Nov 07 2024 Jan Grulich - 132.0.1-2 +- PipeWire camera: use better unique device name for camera devices + +* Tue Nov 05 2024 Martin Stransky - 132.0.1-1 +- Updated to 132.0.1 + +* Fri Oct 25 2024 Martin Stransky - 132.0-2 +- Enabled PGO + +* Wed Oct 23 2024 Martin Stransky - 132.0-1 +- Updated to 132.0 + +* Mon Oct 21 2024 Martin Stransky - 131.0.3-3 +- Backported hi-res mouse scrolling and + hold touchpad gesture support for Fedora 41 + +* Tue Oct 15 2024 Martin Stransky - 131.0.3-1 +- Updated to 131.0.3 + +* Wed Oct 09 2024 Martin Stransky - 131.0.2-1 +- Updated to 131.0.2 + +* Mon Sep 30 2024 Martin Stransky - 131.0-2 +- Fix regression from mzbz#1634961 - enable Gnome Shell search in opened tabs +- Temporary disabled PGO due to build issues. + +* Wed Sep 25 2024 Martin Stransky - 131.0-1 +- Added fix for mzbz#1634961 - enable Gnome Shell search in opened tabs +- Updated to 131.0 + +* Mon Sep 23 2024 Jan Grulich - 130.0.1-3 +- Fix PipeWire camera support enablement for F41+ +- Additional WebRTC backports for PipeWire camera support + +* Fri Sep 20 2024 Songsong Zhang - 130.0.1-2 +- Add v4l2test file for RISC-V + +* Wed Sep 18 2024 Martin Stransky - 130.0.1-1 +- Updated to 130.0.1 + +* Sun Sep 08 2024 Jan Grulich - 130.0-5 +- PipeWire camera support: backport set of upstream patches + +* Fri Sep 6 2024 Martin Stransky - 130.0-4 +- Added fix for mzbz#1916038 + +* Thu Sep 5 2024 Martin Stransky - 130.0-3 +- Downgrade libyuv to fix AVIF image rendering + +* Fri Aug 30 2024 Martin Stransky - 130.0-2 +- Updated to 130.0 build 2 + +* Wed Aug 28 2024 Martin Stransky - 130.0-1 +- Update to 130.0 + +* Wed Aug 28 2024 Miroslav Suchý - 129.0.2-2 +- convert license to SPDX + +* Tue Aug 20 2024 Martin Stransky - 129.0.2-1 +- Update to 129.0.2 + +* Mon Aug 19 2024 Jan Grulich - 129.0-4 +- WebRTC backport: Filter out camera devices with no capabilities + +* Thu Aug 15 2024 Michael Catanzaro - 129.0-3 +- Add conditional hard dependency on mozilla-openh264, always required if openh264 is installed + +* Tue Aug 13 2024 Jan Grulich - 129.0-2 +- Enable PipeWire camera support for F41+ + +* Tue Jul 30 2024 Martin Stransky - 129.0-1 +- Update to 129.0 + +* Mon Jul 29 2024 Martin Stransky - 128.0.3-1 +- Update to 128.0.3 + +* Wed Jul 17 2024 Fedora Release Engineering - 128.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild + +* Fri Jul 12 2024 Martin Stransky - 128.0-2 +- Added fix for mzbz#1907511 + +* Tue Jul 2 2024 Martin Stransky - 128.0-1 +- Update to 128.0 + +* Tue Jul 2 2024 Martin Stransky - 127.0.2-2 +- Allow to override MOZ_DBUS_APP_NAME + +* Tue Jun 25 2024 Martin Stransky - 127.0.2-1 +- Update to 127.0.2 + +* Fri Jun 14 2024 Jan Grulich - 127.0-2 +- Fix duplicated camera entries with PipeWire + +* Mon Jun 10 2024 Jan Horak - 127.0-1 +- Update to 127.0 + +* Tue May 21 2024 Jan Horak - 126.0-8 +- Enabled crashreporter again + +* Mon May 20 2024 Martin Stransky - 126.0-7 +- Gnome search service tweak + +* Wed May 15 2024 Martin Stransky - 126.0-6 +- Added fix for mzbz#1896846 + +* Tue May 14 2024 Martin Stransky - 126.0-5 +- Updated upstream patches + +* Mon May 13 2024 Martin Stransky - 126.0-4 +- Rebuild + +* Mon May 13 2024 Martin Stransky - 126.0-3 +- More upstream patches for Gnome search provider. + +* Fri May 10 2024 Martin Stransky - 126.0-2 +- Fix Gnome search provider for Fedora 40+ + +* Fri May 10 2024 Jan Grulich - 126.0-1 +- Backport WebRTC fix for screen cast glitches in KDE + +* Thu May 9 2024 Martin Stransky - 126.0-1 +- Updated to 126.0 + +* Tue May 7 2024 Martin Stransky - 125.0.3-2 +- Added ffmpeg-free to recommends (rhbz#2023833). + +* Mon Apr 29 2024 Martin Stransky - 125.0.3-1 +- Updated to 125.0.3 + +* Tue Apr 9 2024 Martin Stransky - 125.0-1 +- Updated to 125.0 + +* Thu Apr 4 2024 Martin Stransky - 124.0.2-2 +- Updated to 124.0.2 + +* Thu Mar 28 2024 Jan Horak - 124.0.1-4 +- Enable rlbox sandboxing + +* Mon Mar 25 2024 Martin Stransky - 124.0-2 +- Reverted IM patch + +* Wed Mar 13 2024 Martin Stransky - 124.0-1 +- Updated to 124.0 + +* Thu Mar 07 2024 Martin Stransky - 123.0.1-1 +- Updated to 123.0.1 + +* Fri Feb 23 2024 Martin Stransky - 123.0-2 +- Fixed PGO builds and enabled it again. + +* Wed Feb 21 2024 Daniel Rusek - 123.0-2 +- Add matching AppStream metadata for org.mozilla.firefox.desktop + +* Mon Feb 19 2024 Martin Stransky - 123.0-1 +- Update to 123.0 +- disabled system AV1 due to build issues. + +* Tue Feb 13 2024 Martin Stransky - 122.0.1-1 +- Update to 122.0.1 + +* Mon Feb 12 2024 Jan Grulich - 122.0-7 +- Backport upstream fixes to PipeWire camera support + +* Mon Feb 12 2024 Martin Stransky - 122.0-6 +- Temporary removed proxy cache (rhbz#2262959) + +* Wed Jan 31 2024 Martin Stransky - 122.0-5 +- Disabled system libvpx due to WebRTC/camera issues (mzbz#1875201) + +* Tue Jan 30 2024 Martin Stransky - 122.0-4 +- Build with --enable-replace-malloc (rhbz#2260766) + +* Tue Jan 30 2024 Martin Stransky - 122.0-3 +- Added version to obsolete firefox-wayland/x11 + +* Mon Jan 29 2024 Martin Stransky - 122.0-2 +- Obsolete firefox-wayland and firefox-x11 on Fedora 40+ + +* Fri Jan 19 2024 Martin Stransky - 122.0-1 +- Update to 122.0 + +* Fri Jan 19 2024 Fedora Release Engineering - 121.0.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild + +* Fri Jan 12 2024 Fabio Valentini - 121.0.1-2 +- Rebuild for dav1d 1.3.0 + +* Fri Jan 12 2024 Martin Stransky - 121.0.1-1 +- Update to 121.0.1 +- Fixed Firefox icon on Rawhide + +* Tue Jan 02 2024 Martin Stransky - 121.0-4 +- Really enable proxy cache + +* Fri Dec 22 2023 Martin Stransky - 121.0-3 +- Disabled DBus activations + +* Tue Dec 19 2023 Martin Stransky - 121.0-2 +- Added Wayland proxy cache (mzbz#1743144) + +* Mon Dec 18 2023 Martin Stransky - 121.0-2 +- Enable Gnome Shell Search provider for Fedora 40+ +- Don't ship firefox-x11 and firefox-wayland on Fedora 40+ + +* Mon Dec 18 2023 Martin Stransky - 121.0-1 +- Updated to 121.0 + +* Fri Dec 01 2023 Martin Stransky - 120.0.1-1 +- Updated to 120.0.1 + +* Mon Nov 27 2023 Martin Stransky - 120.0-3 +- Add fix for rhbz#2251202 + +* Mon Nov 20 2023 Martin Stransky - 120.0-2 +- Updated to 120.0 Build 2 + +* Tue Nov 14 2023 Martin Stransky - 120.0-1 +- Updated to 120.0 + +* Fri Nov 10 2023 Martin Stransky - 119.0.1-2 +- Updated to 119.0.1 + +* Tue Nov 07 2023 Martin Stransky - 119.0-5 +- Added fix for rhbz#2247665 + +* Mon Nov 06 2023 Martin Stransky - 119.0-4 +- Added fix for mzbz#1762816 + +* Mon Oct 30 2023 Jan Horak - 119.0-3 +- Enable mozilla crash reporter + +* Fri Oct 27 2023 Martin Stransky - 119.0-2 +- Added fix for mzbz#1861615 + +* Tue Oct 24 2023 Martin Stransky - 119.0-1 +- Updated to 119.0 + +* Tue Oct 10 2023 Martin Stransky - 118.0.2-1 +- Updated to 118.0.2 + +* Fri Oct 06 2023 Alessandro Astone - 118.0.1-7 +- Don't include -x11 and -wayland desktop files in the main package (rhbz#2242523) + +* Fri Oct 6 2023 Martin Stransky - 118.0.1-6 +- Removed DBusActivatable flag from desktop file as it crashes KDE (rhbz#2242454). + +* Thu Oct 05 2023 Kalev Lember - 118.0.1-5 +- Fix flatpak build + +* Mon Oct 2 2023 Martin Stransky - 118.0.1-4 +- Updated man page + +* Mon Oct 2 2023 Martin Stransky - 118.0.1-3 +- Avoid to launch Firefox by gnome-shell search + +* Fri Sep 29 2023 Martin Stransky - 118.0.1-2 +- Use firefox.desktop again + +* Fri Sep 29 2023 Martin Stransky - 118.0.1-1 +- Updated to 118.0.1 + +* Wed Sep 27 2023 Neal Gompa - 118.0.1-1 +- Use system libraries for AV1, VP8, VP9, and WebP + +* Wed Sep 27 2023 Martin Stransky - 118.0-2 +- Fixed Gnome search provider + +* Mon Sep 25 2023 Martin Stransky - 118.0-1 +- Updated to 118.0 + +* Thu Sep 14 2023 Adam Williamson - 117.0.1-2 +- Pass --with-clang-path to fix build with clang 17 (rhbz#2239047) + +* Wed Sep 13 2023 Martin Stransky - 117.0.1-1 +- Updated to 117.0.1 + +* Wed Aug 30 2023 Martin Stransky - 117.0-2 +- Added fix for rhbz#2235654 + +* Mon Aug 28 2023 Martin Stransky - 117.0-1 +- Updated to 117.0 + +* Thu Aug 17 2023 Martin Stransky - 116.0.3-1 +- Updated to 116.0.3 + +* Wed Aug 16 2023 Martin Stransky - 116.0.2-2 +- Added Fedora customization patch + +* Mon Aug 7 2023 Martin Stransky - 116.0.2-1 +- Updated to 116.0.2 + +* Fri Aug 4 2023 Martin Stransky - 116.0.1-1 +- Updated to 116.0.1 + +* Wed Aug 2 2023 Martin Stransky - 116.0-3 +- Added Canvas/WebGL VA-API playback patch (D167159 / mzbz#1769747) + +* Mon Jul 31 2023 Martin Stransky - 116.0-2 +- Updated to 116.0 Build 2 + +* Thu Jul 27 2023 Martin Stransky - 116.0-1 +- Updated to 116.0 + +* Mon Jul 24 2023 Martin Stransky - 115.0.2-4 +- Don't set MOZ_GMP_PATH as it's configured by /etc/profile.d/gmpopenh264.sh + from mozilla-openh264 package. + +* Wed Jul 19 2023 Martin Stransky - 115.0.2-3 +- Fix the previous fix (rhbz#2221317) + +* Tue Jul 18 2023 Martin Stransky - 115.0.2-2 +- Don't overwrite MOZ_GMP_PATH (rhbz#2221317) + +* Mon Jul 17 2023 Martin Stransky - 115.0.2-1 +- Update to 115.0.2 + +* Tue Jul 11 2023 Dan Horák - 115.0-3 +- re-enable ppc64le (rhbz#2212748) + +* Thu Jun 29 2023 Martin Stransky - 115.0-2 +- Update to 115.0 +- Disabled LTO due to rhbz#2218885 + +* Thu Jun 29 2023 Martin Stransky - 114.0.2-3 +- Enable Elf-hack for PGO builds. + +* Thu Jun 22 2023 Martin Stransky - 114.0.2-2 +- Enable PGO/LTO again. + +* Tue Jun 20 2023 Martin Stransky - 114.0.2-1 +- Update to 114.0.2 + +* Mon Jun 05 2023 Martin Stransky - 114.0-1 +- Updated to 114.0 +- Disable webrtc on ppc64le +- Disabled ppc64le due t build issues (rhbz#2212748). + +* Wed May 24 2023 Martin Stransky - 113.0.1-4 +- Added patches from 113.0.2 +- Added Rust fix for Rawhide (mzbz#1831242). + +* Fri May 19 2023 Martin Stransky - 113.0.1-3 +- Disabled libproxy support due to regressions (rhbz#2207469) + +* Tue May 16 2023 Jan Grulich - 113.0.1-2 +- Backport libwebrtc commit 7b0d7f48fb + Fix fcntl call when duplicating a file descriptor + +* Mon May 15 2023 Martin Stransky - 113.0.1-1 +- Updated to 113.0.1 + +* Tue May 9 2023 Martin Stransky - 113.0-1 +- Updated to 113.0 + +* Thu Apr 27 2023 Martin Stransky - 112.0.2-1 +- Updated to 112.0.2 + +* Tue Apr 18 2023 Martin Stransky - 112.0.1-1 +- Updated to 112.0.1 +- Added fix for rhbz#2187000 +- Enabled system pixman (by G.Hojda) + +* Tue Apr 11 2023 Martin Stransky - 112.0-3 +- Added wayland window fix mzbz#1827429 + +* Thu Apr 6 2023 Martin Stransky - 112.0-2 +- Updated to 112.0 build 2 +- don't crash on wayland logging (mzbz#1826583/rhbz#2184842). + +* Wed Apr 5 2023 Martin Stransky - 112.0-1 +- Updated to 112.0 + +* Wed Apr 5 2023 Martin Stransky - 111.0.1-2 +- Don't override MOZ_USE_XINPUT2 in startup script (hrbz#2184297) by GalaxyMaster + +* Wed Mar 22 2023 Martin Stransky - 111.0.1-1 +- Updated to 111.0.1 + +* Tue Mar 21 2023 Jan Grulich - 111.0-3 +- libwebrtc: backport upstream fix/improvement for DmaBuf screen sharing + +* Tue Mar 21 2023 Martin Stransky - 111.0-2 +- Added libproxy support (rhbz#2177806) +- Added build fixes on arm + +* Mon Mar 20 2023 Martin Stransky - 111.0-1 +- Updated to 111.0 +- Disabled arm on F36 + +* Tue Feb 14 2023 Martin Stransky - 110.0-3 +- Updated to 110.0 build 3 + +* Mon Feb 13 2023 Martin Stransky - 110.0-2 +- Added fix for orca + +* Thu Feb 9 2023 Martin Stransky - 110.0-1 +- Updated to 110.0 + +* Tue Feb 7 2023 Martin Stransky - 109.0.1-2 +- Rawhide build fix + +* Wed Feb 1 2023 Martin Stransky - 109.0.1-1 +- Updated to 109.0.1 +- Added fix for rhbz#2147344 / mzbz#1813500. + +* Thu Jan 19 2023 Martin Stransky - 109.0-4 +- Removed mozbz#1809162 + +* Thu Jan 19 2023 Fedora Release Engineering - 109.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild + +* Tue Jan 17 2023 Martin Stransky - 109.0-2 +- Added VA-API fixes mozbz#1809162, mozbz#1801576 + +* Mon Jan 16 2023 Martin Stransky - 109.0-1 +- Update to 109.0 + +* Thu Jan 12 2023 Jan Horak - 108.0.2-1 +- Update to 108.0.2 + +* Mon Jan 09 2023 Kalev Lember - 108.0.1-4 +- Drop conditionals for F35 + +* Wed Dec 21 2022 Martin Stransky - 108.0.1-3 +- Added second arch build fix + +* Wed Dec 21 2022 Martin Stransky - 108.0.1-2 +- Added mozbz#1795851 [wayland] Crash buffer size (170x113) + is not divisible by scale (2) + +* Mon Dec 19 2022 Martin Stransky - 108.0.1-1 +- Update to 108.0.1 + +* Wed Dec 14 2022 Martin Stransky - 108.0-2 +- Update to 108.0 Build 2 +- Added fix for rhbz#2149821 + +* Tue Dec 6 2022 Martin Stransky - 108.0-1 +- Update to 108.0 + +* Tue Dec 6 2022 Martin Stransky - 107.0.1-1 +- Update to 107.0.1 + +* Thu Nov 24 2022 Martin Stransky - 107.0-4 +- Added fix for mozbz#1779186 - fix VA-API playback artifacts + +* Mon Nov 21 2022 Martin Stransky - 107.0-3 +- Disabled crashreporter + +* Mon Nov 21 2022 Jan Horak - 107.0-2 +- Enabled mozilla crashreporter again + +* Mon Nov 14 2022 Martin Stransky - 107.0-1 +- Update to 107.0 + +* Fri Nov 04 2022 Martin Stransky - 106.0.4-1 +- Update to 106.0.4 + +* Mon Oct 31 2022 Martin Stransky - 106.0.3-1 +- Update to 106.0.3 + +* Sun Oct 23 2022 Martin Stransky - 106.0.1-1 +- Update to 106.0.1 +- Require xdg-desktop-portal when file dialog portal is used. +- Disabled file dialog portals on F37+ + +* Thu Oct 20 2022 Jan Grulich - 106.0-2 +- Enable upstream WebRTC code for screensharing on Wayland + +* Fri Oct 14 2022 Martin Stransky - 106.0-1 +- Updated to 106.0 +- Disabled PGO build due to rhbz#2136401 + +* Fri Oct 14 2022 Martin Stransky - 105.0.2-2 +- Fixed crashes on multi-monitor systems (mzbz#1793922) + +* Wed Oct 5 2022 Martin Stransky - 105.0.2-1 +- Updated to 105.0.2 + +* Fri Sep 30 2022 Martin Stransky - 105.0.1-2 +- Added fix for mozilla#1791856 / rhbz#2130087 + +* Thu Sep 22 2022 Martin Stransky - 105.0.1-1 +- Updated to 105.0.1 +- Excluded i686 due to https://bugzilla.mozilla.org/show_bug.cgi?id=1792159, + https://bugzilla.redhat.com/show_bug.cgi?id=2129720 + +* Tue Sep 20 2022 Martin Stransky - 105.0-1 +- Updated to 105.0 + +* Tue Sep 6 2022 Martin Stransky - 104.0.2-1 +- Updated to 104.0.2 + +* Tue Aug 30 2022 Martin Stransky - 104.0.1-1 +- Updated to 104.0.1 + +* Tue Aug 23 2022 Kalev Lember - 104.0-5 +- Use constrain_build macro to simplify parallel make handling +- Drop obsolete build conditionals +- Drop unused patches +- Use build_ldflags +- Drop hardened_build option +- Re-enable s390x builds + +* Tue Aug 23 2022 Jan Horak - 104.0-4 +- Rebuild due to ppc64le fixes + +* Mon Aug 22 2022 Eike Rathke - 104.0-3 +- Update to 104.0 respin + +* Wed Aug 17 2022 Martin Stransky - 104.0-2 +- Added build fixes + +* Tue Aug 16 2022 Martin Stransky - 104.0-1 +- Updated to 104.0 + +* Fri Aug 12 2022 Martin Stransky - 103.0.2-1 +- Updated to 103.0.2 + +* Thu Aug 4 2022 Martin Stransky - 103.0.1-2 +- Added arm build fixes by Gabriel Hojda +- Enable VA-API (rhbz#2115253) + +* Tue Aug 2 2022 Martin Stransky - 103.0.1-1 +- Update to 103.0.1 + +* Tue Jul 26 2022 Martin Stransky - 103.0-1 +- Update to 103.0 +- Disabled ppc64le due to webrtc build failures (rhbz#2113850) + +* Thu Jul 21 2022 Fedora Release Engineering - 102.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild + +* Wed Jul 13 2022 Martin Stransky - 102.0-3 +- Update preference logging. +- Added ARM fixes by Gabriel Hojda. + +* Mon Jul 11 2022 Jan Grulich - 102.0-2 +- Backport upstream fixes to WebRTC for screensharing on Wayland + +* Tue Jun 28 2022 Martin Stransky - 102.0-1 +- Updated to 102.0 +- Applied patch from https://src.fedoraproject.org/rpms/firefox/pull-request/43 + +* Mon Jun 27 2022 Martin Stransky - 101.0.1-7 +- Rebuild + +* Fri Jun 17 2022 Martin Stransky - 101.0.1-6 +- Added fix for mozbz#1774271 - Intel/dmabuf export issues. + +* Wed Jun 15 2022 Martin Stransky - 101.0.1-5 +- Added fix for mozbz#1758948 (AV1 VA-API playback shuttering) + +* Tue Jun 14 2022 Martin Stransky - 101.0.1-3 +- Added fixes for mozbz#1773377 and mozbz#1774075 + +* Mon Jun 13 2022 Martin Stransky - 101.0.1-2 +- Fix WebGL mem leaks (mzbz#1773968) + +* Thu Jun 9 2022 Martin Stransky - 101.0.1-1 +- Updated to 101.0.1 +- More VA-API sandbox fixes (mzbz#1769182) +- Fixed OpenH264 decode (rhbz#2094319) + +* Tue Jun 7 2022 Martin Stransky - 101.0-2 +- Enabled VA-API by default (+ added VA-API fixes from upstream) +- Fixed WebGL performance on NVIDIA drivers (mzbz#1735929) + +* Mon May 30 2022 Martin Stransky - 101.0-1 +- Updated to 101.0 + +* Wed May 25 2022 Martin Stransky - 100.0.2-2 +- Added fix for mzbz#1771104 + +* Fri May 20 2022 Martin Stransky - 100.0.2-1 +- Updated to 100.0.2 + +* Wed May 18 2022 Martin Stransky - 100.0.1-1 +- Updated to 100.0.1 + +* Mon May 16 2022 Jan Horak - 100.0-6 +- Fix spellchecker.dictionary_path of F36+ + +* Tue May 10 2022 Jan Horak - 100.0-5 +- Fix crashes on f36 multimonitor setup and too big profile manager + +* Mon May 9 2022 Martin Stransky - 100.0-4 +- Added fix for mozbz#1767916. + +* Thu May 5 2022 Martin Stransky - 100.0-3 +- Removed Fedora user agent patch (rhbz#2081791). + +* Tue May 3 2022 Martin Stransky - 100.0-2 +- Added fix for mozbz#1759137 + +* Mon May 2 2022 Martin Stransky - 100.0-1 +- Updated to 100.0 + +* Thu Apr 28 2022 Jan Horak - 99.0.1-2 +- Fixing bookmark install location - rhbz#2054953 + +* Wed Apr 13 2022 Martin Stransky - 99.0.1-1 +- Updated to 99.0.1 + +* Wed Apr 6 2022 Martin Stransky - 99.0-1 +- Updated to 99.0 + +* Thu Mar 31 2022 Martin Stransky - 98.0.2-1 +- Updated to 98.0.2 + +* Wed Mar 30 2022 Jan Grulich - 98.0-4 +- Wayland screensharing: avoid potential crash when cursor metadata are not set + +* Wed Mar 16 2022 Martin Stransky - 98.0-3 +- Added a workaround for rhbz#2063961 + +* Wed Mar 2 2022 Martin Stransky - 98.0-2 +- Added support for ffmpeg 5.0 +- Spec tweaks +- Updated to Build 3 + +* Tue Mar 1 2022 Martin Stransky - 98.0-1 +- Updated to 98.0 + +* Mon Feb 21 2022 Jan Grulich - 97.0.1-2 +- Backport WebRTC changes to PipeWire/Wayland screen sharing support + +* Fri Feb 18 2022 Martin Stransky - 97.0.1-1 +- Updated to 97.0.1 +- GCC 12 build fixes + +* Tue Feb 8 2022 Martin Stransky - 97.0-1 +- Updated to 97.0 + +* Mon Jan 31 2022 Martin Stransky - 96.0.3-1 +- Updated to 96.0.3 + +* Tue Jan 25 2022 Parag Nemade - 96.0.1-3 +- Update hunspell-dir path + F36 Change https://fedoraproject.org/wiki/Changes/Hunspell_dictionary_dir_change + +* Thu Jan 20 2022 Fedora Release Engineering - 96.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild + +* Tue Jan 18 2022 Martin Stransky - 96.0.1-1 +- Updated to 96.0.1 + +* Tue Jan 11 2022 Martin Stransky - 96.0-1 +- Updated to 96.0 + +* Sat Jan 08 2022 Miro Hrončok - 95.0.2-5 +- Rebuilt for https://fedoraproject.org/wiki/Changes/LIBFFI34 + +* Thu Dec 23 2021 Martin Stransky - 95.0.2-4 +- Added fix fox mozbz#1744896 (VSync) + +* Wed Dec 22 2021 Martin Stransky - 95.0.2-3 +- Added Fedora 36 build fix (mzbz#1745560) + +* Mon Dec 20 2021 Martin Stransky - 95.0.2-1 +- Updated to 95.0.2 +- Enabled Wayland on KDE by default + +* Thu Dec 9 2021 Martin Stransky - 95.0-2 +- Updated symbolic icon (rhbz#2028939) + +* Fri Dec 3 2021 Martin Stransky - 95.0-1 +- Updated to 95.0 + +* Fri Nov 19 2021 Martin Stransky - 94.0-2 +- Added fix for mozbz#1739924 / rhbz#2020981. + +* Mon Nov 1 2021 Martin Stransky - 94.0-1 +- Updated to 94.0 + +* Thu Oct 07 2021 Martin Stransky - 93.0-2 +- Require NSS 3.70 + +* Wed Sep 29 2021 Martin Stransky - 93.0-1 +- Updated to 93.0 + +* Mon Sep 27 2021 Martin Stransky - 92.0.1-1 +- Updated to 92.0.1 + +* Mon Sep 13 2021 Martin Stransky - 92.0-3 +- Added fix for mozbz#1725828 + +* Thu Sep 9 2021 Martin Stransky - 92.0-2 +- Disable test + +* Fri Sep 3 2021 Martin Stransky - 92.0-1 +- Updated to 92.0 +- Added fix for mozbz#1728749 +- Added fix for mozbz#1708709 + +* Thu Aug 26 2021 Martin Stransky - 91.0.2-1 +- Updated to 91.0.2 + +* Mon Aug 23 2021 Martin Stransky - 91.0.1-2 +- Set %%build_with_clang automatically based on %%toolchain + by Timm Bäder +- Updated Fedora UA patch by Eric Engestrom + (https://src.fedoraproject.org/rpms/firefox/pull-request/21) +- Added fix for mozbz#1726515 + +* Mon Aug 23 2021 Martin Stransky - 91.0.1-1 +- Updated to 91.0.1 + +* Tue Aug 10 2021 Martin Stransky - 91.0-1 +- Updated to 91.0 + +* Wed Aug 04 2021 Martin Stransky - 90.0.2-2 +- Added fix for rhbz#1988841 - Allow unsigned extensions when installed + under non-user-writable dirs. + +* Thu Jul 22 2021 Martin Stransky - 90.0.2-1 +- Updated to 90.0.2 + +* Wed Jul 21 2021 Fedora Release Engineering - 90.0.1-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild + +* Wed Jul 21 2021 Martin Stransky - 90.0.1-1 +- Updated to 90.0.1 +- Added fixes to build on rawhide + +* Thu Jul 15 2021 Martin Stransky - 90.0-3 +- Disabled Wayland backend on KDE due to + https://bugzilla.mozilla.org/show_bug.cgi?id=1714132 + +* Tue Jul 13 2021 Martin Stransky - 90.0-2 +- Added xorg-x11-server-Xwayland dependency for Mutter + +* Mon Jul 12 2021 Martin Stransky - 90.0-1 +- Updated to 90.0 + +* Mon Jul 12 2021 Daiki Ueno - 89.0.2-3 +- flatpak: Enable loading system trust store on the host (rhbz#1766340) + +* Wed Jun 30 2021 Martin Stransky - 89.0.2-2 +- Added fix for mozbz#1715254 (rhbz#1976892). + +* Thu Jun 24 2021 Martin Stransky - 89.0.2-1 +- Updated to latest upstream (89.0.2) + +* Mon Jun 14 2021 Martin Stransky - 89.0-2 +- Added fix for mozbz#1646135 + +* Tue Jun 1 2021 Martin Stransky - 89.0-1 +- Updated to latest upstream (89.0) + +* Mon May 10 2021 Martin Stransky - 88.0.1-1 +- Updated to latest upstream (88.0.1) + +* Tue May 4 2021 Martin Stransky - 88.0-8 +- Added fix for mozbz#1705048. + +* Fri Apr 30 2021 Martin Stransky - 88.0-7 +- Added pciutils-libs req (rhbz#1955338) +- Enabled Wayland on KDE (rhbz#1922608) + +* Tue Apr 27 2021 Martin Stransky - 88.0-6 +- Test fix. + +* Fri Apr 23 2021 Martin Stransky - 88.0-5 +- Added fix for mozbz#1580595 - mouse pointer lock. +- Another test update. + +* Thu Apr 22 2021 Martin Stransky - 88.0-4 +- Run with mochitest test suite. + +* Thu Apr 22 2021 Martin Stransky - 88.0-3 +- Build with crashreporter enabled. + +* Wed Apr 21 2021 Martin Stransky - 88.0-2 +- Added clipboard fix mzbz#1703763. + +* Mon Apr 19 2021 Martin Stransky - 88.0-1 +- Update to 88.0 + +* Mon Apr 12 2021 Martin Stransky - 87.0-12 +- Added fix for mozbz#1701089 (Widevine playback issues). + +* Tue Apr 6 2021 Martin Stransky - 87.0-11 +- Enabled xpcshell/crashtests on Wayland. + +* Sat Apr 3 2021 Martin Stransky - 87.0-10 +- Wayland testing again. + +* Thu Apr 1 2021 Martin Stransky - 87.0-9 +- Added fix for mozbz#1702606 / rhbz#1936071 +- Switched tests back to X11 due to massive failures. + +* Thu Apr 1 2021 Martin Stransky - 87.0-8 +- Run testsuite on Wayland on Fedora 33+ +- Spec cleanup + +* Wed Mar 31 2021 Martin Stransky - 87.0-7 +- Added fix for mozbz#1693472 - Wayland/KDE rendering issues. + +* Tue Mar 30 2021 Jonathan Wakely - 87.0-6 +- Rebuilt for removed libstdc++ symbol (#1937698) + +* Tue Mar 30 2021 Martin Stransky - 87.0-5 +- Reftest fix + +* Fri Mar 26 2021 Martin Stransky - 87.0-4 +- More test fixes +- Enabled ppc64le +- Disabled crashreporter on Fedora 34+ + +* Wed Mar 24 2021 Martin Stransky - 87.0-2 +- More test fixes + +* Tue Mar 23 2021 Martin Stransky - 87.0-1 +- Disabled ARM due to build failures +- Updated to 87.0 + +* Sat Mar 13 2021 Martin Stransky - 86.0.1-2 +- Enabled ARM + +* Fri Mar 12 2021 Martin Stransky - 86.0.1-1 +- Update to latest upstream (86.0.1) + +* Wed Mar 10 2021 Martin Stransky - 86.0-8 +- Temporary disable ppc64le/Fedora 35 due to + https://bugzilla.redhat.com/show_bug.cgi?id=1933742 + +* Wed Mar 3 2021 Martin Stransky - 86.0-7 +- Added fix for mozbz#1694670 + +* Mon Mar 1 2021 Martin Stransky - 86.0-6 +- Run xpcshell tests sequential +- Test fixes + +* Mon Mar 1 2021 Martin Stransky - 86.0-4 +- Enable Wayland backend only when Wayland display is set. + +* Mon Mar 1 2021 Martin Stransky - 86.0-3 +- Added icecat-78.7.1-fix_error_template_with_C_linkage.patch to + build on F34+ + +* Fri Feb 26 2021 Martin Stransky - 86.0-2 +- Built with system nss + +* Tue Feb 23 2021 Martin Stransky - 86.0-1 +- Update to 86.0 +- Disabled Wayland backend on KDE/Plasma + +* Tue Feb 23 2021 Martin Stransky - 85.0.1-2 +- Fixed some reftest run in Mock + +* Mon Feb 08 2021 Martin Stransky - 85.0.1-1 +- Updated to 85.0.1 + +* Wed Feb 03 2021 Dan Horák - 85.0-11 +- Fix parameter passing on ppc64le (mozb#1690152) + +* Tue Feb 02 2021 Kalev Lember - 85.0-10 +- Remove gtk2 support as flash plugin is no longer supported + +* Sat Jan 30 2021 Martin Stransky - 85.0-9 +- Enable WebRender on KDE/Wayland and AMD/Intel drivers. + +* Sat Jan 30 2021 Martin Stransky - 85.0-8 +- Enable Wayland backend on Fedora 34/KDE/Plasma (and other compositors) + by default (https://bugzilla.redhat.com/show_bug.cgi?id=1922608). + +* Fri Jan 29 2021 Martin Stransky - 85.0-7 +- Added clipboard fix mozbz#1631061. + +* Thu Jan 28 2021 Kalev Lember - 85.0-6 +- Make provides/requires filtering smarter/automatic (rhbz#1582116) +- Drop dbus-glib requires that are now automatically generated again + +* Thu Jan 28 2021 Martin Stransky - 85.0-5 +- Add dbus-glib requires. + +* Tue Jan 26 2021 Martin Stransky - 85.0-4 +- Added fix for mozbz#1679933 - startup crash + +* Tue Jan 26 2021 Fedora Release Engineering - 85.0-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild + +* Wed Jan 20 2021 Martin Stransky - 85.0-2 +- Update to 85.0. + +* Wed Jan 20 2021 Jan Horak - 84.0.2-8 +- Fixing package requires/provides + +* Tue Jan 19 2021 Martin Stransky - 84.0.2-7 +- Fixed mzbz#164294 regression. + +* Fri Jan 15 2021 Martin Stransky - 84.0.2-6 +- Added WebRender fix (mozbz#1681107). + +* Thu Jan 14 2021 Martin Stransky - 84.0.2-5 +- Removed some failing tests. +- Spec file tweaks. + +* Tue Jan 12 2021 Martin Stransky - 84.0.2-4 +- Enabled LTO in Firefox build system. + +* Tue Jan 12 2021 Martin Stransky - 84.0.2-3 +- Removed failing xpcshell/reftests, test tweaks. + +* Mon Jan 11 2021 Martin Stransky - 84.0.2-2 +- Added a workaround for rhbz#1908018 + +* Wed Jan 6 2021 Martin Stransky - 84.0.2-1 +- Updated to 84.0.2 + +* Tue Jan 05 2021 Jan Horak - 84.0.1-5 +- Removing requires/provides of the bundled libraries + +* Mon Jan 4 2021 Martin Stransky - 84.0.1-4 +- Enabled tests + +* Mon Jan 4 2021 Martin Stransky - 84.0.1-3 +- Enabled armv7hl arch on rawhide + +* Wed Dec 23 2020 Martin Stransky - 84.0.1-2 +- Reverted mzbz#1631061 due to clipboard regressions +- Disabled armv7hl build on rawhide due to rhbz#1910277 +- Build with system nss on rawhide (rhbz#1908791). + +* Tue Dec 22 2020 Martin Stransky - 84.0.1-1 +- Updated to 84.0.1 + +* Sun Dec 20 2020 Miro Hrončok - 84.0-7 +- Filter out private libraries provides +- Fixes: rhbz#1908791 + +* Thu Dec 17 2020 Martin Stransky - 84.0-6 +- Disable PGO on Rawhide due to build issues +- Disable system nss on Rawhide due to rhbz#1908018 +- Enabled system nss on Fedora 33/32 + +* Wed Dec 16 2020 Martin Stransky - 84.0-5 +- Build with tests enabled + +* Wed Dec 16 2020 Martin Stransky - 84.0-4 +- Disabled LTO due to massive test failures + +* Wed Dec 16 2020 Martin Stransky - 84.0-3 +- Updated to Firefox 84 Build 3 +- Disabled system nss due to addon breakage (rhbz#1908018). + +* Wed Dec 9 2020 Martin Stransky - 83.0-15 +- Enabled tests everywhere +- Enabled crash reporter + +* Tue Dec 1 2020 Martin Stransky - 83.0-14 +- Enabled LTO + +* Tue Dec 1 2020 Martin Stransky - 83.0-13 +- Added fix for mozbz#1672139 + +* Tue Dec 1 2020 Martin Stransky - 83.0-12 +- More mochitest fixes + +* Mon Nov 30 2020 Martin Stransky - 83.0-11 +- Mochitest tweaking + +* Sat Nov 28 2020 Martin Stransky - 83.0-10 +- Added fix for mzbz#1678680 + +* Wed Nov 25 2020 Martin Stransky - 83.0-9 +- Added mochitest test files + +* Wed Nov 25 2020 Martin Stransky - 83.0-8 +- Added fix for rhbz#1900542 + +* Wed Nov 25 2020 Martin Stransky - 83.0-7 +- Export MOZ_GMP_PATH from /usr/bin/firefox script + (https://pagure.io/fedora-workstation/issue/126) + * Tue Nov 24 2020 Martin Stransky - 83.0-6 - Fix mochitest diff --git a/fix-cargo-checksum b/fix-cargo-checksum new file mode 100755 index 0000000..bae2b2d --- /dev/null +++ b/fix-cargo-checksum @@ -0,0 +1,21 @@ +#!/bin/bash +if [ -z $1 ]; then + echo "Fixes .cargo-checksum.json by removing deleted files and recompute sha256sum" + echo "Usage: $0 .cargo-checksum.json" + exit +fi + +FILE=$1 +#set -x +cp $FILE $1.backup +for i in $(cat .cargo-checksum.json|jq -r '.files| keys[]'); do +if [ ! -f $i ]; then + #echo $i non exist + sed -ie "s|\"$i\":\"[^\"]*\",||" $FILE +else + SHA=`sha256sum $i | cut -d " " -f1` + sed -ie "s|\"$i\":\"[^\"]*\"|\"$i\":\"$SHA\"|" $FILE +fi + +#echo $i +done diff --git a/gen_cbindgen-vendor.sh b/gen_cbindgen-vendor.sh index 90fef57..5711901 100755 --- a/gen_cbindgen-vendor.sh +++ b/gen_cbindgen-vendor.sh @@ -12,7 +12,7 @@ to be used with 'cargo vendor' commmand. """ [dependencies] -cbindgen = "0.15.0" +cbindgen = "0.29.1" [[bin]] name = "dummy" diff --git a/gen_dump_syms-vendor.sh b/gen_dump_syms-vendor.sh new file mode 100755 index 0000000..3854ad8 --- /dev/null +++ b/gen_dump_syms-vendor.sh @@ -0,0 +1,33 @@ +#!/bin/bash +set -x + +# Dummy Cargo.toml file with cbindgen dependency +cat > Cargo.toml </pref -+ rv = NS_GetSpecialDirectory(NS_APP_PREFS_SYSTEM_CONFIG_DIR, -+ getter_AddRefs(jsFile)); -+ NS_ENSURE_SUCCESS(rv, rv); -+ -+ rv = jsFile->AppendNative(nsLiteralCString("pref")); -+ NS_ENSURE_SUCCESS(rv, rv); -+ rv = jsFile->AppendNative(nsDependentCString(aFileName)); -+ NS_ENSURE_SUCCESS(rv, rv); - -+ rv = NS_NewLocalFileInputStream(getter_AddRefs(inStr), jsFile); -+ NS_ENSURE_SUCCESS(rv, rv); -+ } - } else { - nsAutoCString location("resource://gre/defaults/autoconfig/"); - location += aFileName; -diff -up firefox-75.0/modules/libpref/Preferences.cpp.1170092 firefox-75.0/modules/libpref/Preferences.cpp ---- firefox-75.0/modules/libpref/Preferences.cpp.1170092 2020-04-06 22:40:02.761674865 +0200 -+++ firefox-75.0/modules/libpref/Preferences.cpp 2020-04-06 22:40:57.675325227 +0200 -@@ -4468,6 +4468,9 @@ nsresult Preferences::InitInitialObjects - // - // Thus, in the omni.jar case, we always load app-specific default - // preferences from omni.jar, whether or not `$app == $gre`. -+ // -+ // At very end load configuration from system config location: -+ // - /etc/firefox/pref/*.js - - nsresult rv = NS_ERROR_FAILURE; - UniquePtr find; -diff -up firefox-75.0/toolkit/xre/nsXREDirProvider.cpp.1170092 firefox-75.0/toolkit/xre/nsXREDirProvider.cpp ---- firefox-75.0/toolkit/xre/nsXREDirProvider.cpp.1170092 2020-04-03 21:35:39.000000000 +0200 -+++ firefox-75.0/toolkit/xre/nsXREDirProvider.cpp 2020-04-06 22:40:02.761674865 +0200 -@@ -60,6 +60,7 @@ - #endif - #ifdef XP_UNIX - # include -+# include "nsIXULAppInfo.h" - #endif - #ifdef XP_IOS - # include "UIKitDirProvider.h" -@@ -533,6 +534,21 @@ nsXREDirProvider::GetFile(const char* aP - } - } - } -+ -+#if defined(XP_UNIX) -+ if (!strcmp(aProperty, NS_APP_PREFS_SYSTEM_CONFIG_DIR)) { -+ nsCString sysConfigDir = nsLiteralCString("/etc/"); -+ nsCOMPtr appInfo = do_GetService("@mozilla.org/xre/app-info;1"); -+ if (!appInfo) -+ return NS_ERROR_NOT_AVAILABLE; -+ nsCString appName; -+ appInfo->GetName(appName); -+ ToLowerCase(appName); -+ sysConfigDir.Append(appName); -+ return NS_NewNativeLocalFile(sysConfigDir, false, aFile); -+ } -+#endif -+ - if (NS_FAILED(rv) || !file) return NS_ERROR_FAILURE; - - if (ensureFilePermissions) { -@@ -845,6 +861,16 @@ nsresult nsXREDirProvider::GetFilesInter - - LoadDirIntoArray(mXULAppDir, kAppendPrefDir, directories); - -+ // Add /etc//pref/ directory if it exists -+ nsCOMPtr systemPrefDir; -+ rv = NS_GetSpecialDirectory(NS_APP_PREFS_SYSTEM_CONFIG_DIR, -+ getter_AddRefs(systemPrefDir)); -+ if (NS_SUCCEEDED(rv)) { -+ rv = systemPrefDir->AppendNative(nsLiteralCString("pref")); -+ if (NS_SUCCEEDED(rv)) -+ directories.AppendObject(systemPrefDir); -+ } -+ - rv = NS_NewArrayEnumerator(aResult, directories, NS_GET_IID(nsIFile)); - } else if (!strcmp(aProperty, NS_APP_CHROME_DIR_LIST)) { - // NS_APP_CHROME_DIR_LIST is only used to get default (native) icons -diff -up firefox-75.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092 firefox-75.0/xpcom/io/nsAppDirectoryServiceDefs.h ---- firefox-75.0/xpcom/io/nsAppDirectoryServiceDefs.h.1170092 2020-04-03 21:35:39.000000000 +0200 -+++ firefox-75.0/xpcom/io/nsAppDirectoryServiceDefs.h 2020-04-06 22:40:02.761674865 +0200 -@@ -60,6 +60,7 @@ - #define NS_APP_PREFS_DEFAULTS_DIR_LIST "PrefDL" - #define NS_APP_PREFS_OVERRIDE_DIR \ - "PrefDOverride" // Directory for per-profile defaults -+#define NS_APP_PREFS_SYSTEM_CONFIG_DIR "PrefSysConf" // Directory with system-wide configuration - - #define NS_APP_USER_PROFILE_50_DIR "ProfD" - #define NS_APP_USER_PROFILE_LOCAL_50_DIR "ProfLD" diff --git a/mozilla-1196777.patch b/mozilla-1196777.patch index 721c897..ac405c6 100644 --- a/mozilla-1196777.patch +++ b/mozilla-1196777.patch @@ -1,13 +1,12 @@ -diff -up firefox-80.0/widget/gtk/nsWindow.cpp.1196777 firefox-80.0/widget/gtk/nsWindow.cpp ---- firefox-80.0/widget/gtk/nsWindow.cpp.1196777 2020-08-18 09:47:18.662833910 +0200 -+++ firefox-80.0/widget/gtk/nsWindow.cpp 2020-08-18 09:48:19.437478136 +0200 -@@ -158,7 +158,8 @@ const gint kEvents = - GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK | GDK_VISIBILITY_NOTIFY_MASK | - GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK | GDK_SMOOTH_SCROLL_MASK | GDK_TOUCH_MASK | -- GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK; -+ GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | GDK_PROPERTY_CHANGE_MASK | -+ GDK_FOCUS_CHANGE_MASK; +diff -up firefox-133.0/widget/gtk/nsWindow.cpp.1196777 firefox-133.0/widget/gtk/nsWindow.cpp +--- firefox-133.0/widget/gtk/nsWindow.cpp.1196777 2024-11-22 09:32:52.293470407 +0100 ++++ firefox-133.0/widget/gtk/nsWindow.cpp 2024-11-22 10:21:54.996441520 +0100 +@@ -191,7 +191,7 @@ constexpr gint kEvents = + GDK_VISIBILITY_NOTIFY_MASK | GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_SMOOTH_SCROLL_MASK | + GDK_TOUCH_MASK | GDK_SCROLL_MASK | GDK_POINTER_MOTION_MASK | +- GDK_PROPERTY_CHANGE_MASK; ++ GDK_PROPERTY_CHANGE_MASK | GDK_FOCUS_CHANGE_MASK; - #if !GTK_CHECK_VERSION(3, 22, 0) - typedef enum { + /* utility functions */ + static bool is_mouse_in_window(GdkWindow* aWindow, gdouble aMouseX, diff --git a/mozilla-1516803.patch b/mozilla-1516803.patch index f1f37f4..30d1fdf 100644 --- a/mozilla-1516803.patch +++ b/mozilla-1516803.patch @@ -1,16 +1,15 @@ -diff --git a/security/sandbox/linux/moz.build b/security/sandbox/linux/moz.build ---- a/security/sandbox/linux/moz.build -+++ b/security/sandbox/linux/moz.build -@@ -99,9 +99,8 @@ +diff -up firefox-84.0/security/sandbox/linux/moz.build.1516803 firefox-84.0/security/sandbox/linux/moz.build +--- firefox-84.0/security/sandbox/linux/moz.build.1516803 2020-12-10 16:17:55.425139545 +0100 ++++ firefox-84.0/security/sandbox/linux/moz.build 2020-12-10 16:29:21.945860841 +0100 +@@ -114,9 +114,8 @@ if CONFIG["CC_TYPE"] in ("clang", "gcc") # gcc lto likes to put the top level asm in syscall.cc in a different partition # from the function using it which breaks the build. Work around that by # forcing there to be only one partition. --for f in CONFIG['OS_CXXFLAGS']: -- if f.startswith('-flto') and CONFIG['CC_TYPE'] != 'clang': -- LDFLAGS += ['--param lto-partitions=1'] +-for f in CONFIG["OS_CXXFLAGS"]: +- if f.startswith("-flto") and CONFIG["CC_TYPE"] != "clang": +- LDFLAGS += ["--param lto-partitions=1"] +if CONFIG['CC_TYPE'] != 'clang': + LDFLAGS += ['--param', 'lto-partitions=1'] - DEFINES['NS_NO_XPCOM'] = True + DEFINES["NS_NO_XPCOM"] = True DisableStlWrapping() - diff --git a/mozilla-1556931-s390x-hidden-syms.patch b/mozilla-1556931-s390x-hidden-syms.patch deleted file mode 100644 index c423d1f..0000000 --- a/mozilla-1556931-s390x-hidden-syms.patch +++ /dev/null @@ -1,25 +0,0 @@ -diff --git a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp -index c38baa12bffa8..2858a7bb4d319 100644 ---- a/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp -+++ b/gfx/angle/checkout/src/compiler/translator/tree_util/IntermTraverse.cpp -@@ -45,16 +45,20 @@ void TIntermTraverser::traverse(T *node) - ++childIndex; - } - - if (visit && postVisit) - node->visit(PostVisit, this); - } - } - -+// Instantiate template for RewriteAtomicFunctionExpressions. -+template -+void TIntermTraverser::traverse(TIntermNode *); -+ - void TIntermNode::traverse(TIntermTraverser *it) - { - it->traverse(this); - } - - void TIntermSymbol::traverse(TIntermTraverser *it) - { - TIntermTraverser::ScopedNodeInTraversalPath addToPath(it, this); 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-1645671.patch b/mozilla-1645671.patch deleted file mode 100644 index 0943469..0000000 --- a/mozilla-1645671.patch +++ /dev/null @@ -1,67 +0,0 @@ -changeset: 544864:a8603f131703 -tag: tip -parent: 544861:161920b70ae4 -user: Martin Stransky -date: Fri Jul 31 13:39:48 2020 +0200 -files: dom/media/platforms/ffmpeg/FFmpegVideoDecoder.cpp dom/media/platforms/ffmpeg/FFmpegVideoDecoder.h -description: -Bug 1645671 [Linux/VA-API] Create DMABufSurfaceWrapper directly at nsTAttay and disable DMABufSurfaceWrapper class copy and assignment constructors, r?jya - -When DMABufSurfaceWrapper is added to nsTArray, a temporary local DMABufSurfaceWrapper object is created. When the temporary -object is deleted after the adding, associated dmabuf data is released which leads to rendering artifact during VA-API video playback. - -As a fix in this patch we create DMABufSurfaceWrapper 'in-place' at nsTAttay. -We also disable DMABufSurfaceWrapper class copy and assignment constructors to avoid similar potential issues. - -Differential Revision: https://phabricator.services.mozilla.com/D85152 - - -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 -@@ -777,17 +777,17 @@ MediaResult FFmpegVideoDecoderSetUID(++uid); - FFMPEG_LOG("Created new DMABufSurface UID = %d", uid); - # endif -- mDMABufSurfaces.AppendElement(DMABufSurfaceWrapper(surface, mLib)); -+ mDMABufSurfaces.EmplaceBack(surface, mLib); - surfaceWrapper = &(mDMABufSurfaces[mDMABufSurfaces.Length() - 1]); - } else { - surface = surfaceWrapper->GetDMABufSurface(); - bool ret; - - if (mVAAPIDeviceContext) { - ret = surface->UpdateYUVData(vaDesc); - } else { -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 -@@ -70,16 +70,22 @@ class DMABufSurfaceWrapper final { - // Check if DMABufSurface is used by any gecko rendering process - // (WebRender or GL compositor) or by DMABUFSurfaceImage/VideoData. - bool IsUsed() const { return mSurface->IsGlobalRefSet(); } - - RefPtr GetDMABufSurface() const { - return mSurface->GetAsDMABufSurfaceYUV(); - } - -+ // Don't allow DMABufSurfaceWrapper plain copy as it leads to -+ // enexpected DMABufSurface/HW buffer releases and we don't want to -+ // deep copy them. -+ DMABufSurfaceWrapper(const DMABufSurfaceWrapper&) = delete; -+ const DMABufSurfaceWrapper& operator=(DMABufSurfaceWrapper const&) = delete; -+ - private: - const RefPtr mSurface; - const FFmpegLibWrapper* mLib; - AVBufferRef* mAVHWFramesContext; - AVBufferRef* mHWAVBuffer; - }; - #endif - - diff --git a/mozilla-1663844.patch b/mozilla-1663844.patch deleted file mode 100644 index 3e55e80..0000000 --- a/mozilla-1663844.patch +++ /dev/null @@ -1,36 +0,0 @@ -diff --git a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp ---- a/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp -+++ b/dom/media/platforms/agnostic/gmp/GMPDecoderModule.cpp -@@ -86,7 +86,7 @@ bool GMPDecoderModule::SupportsMimeType( - - bool GMPDecoderModule::SupportsMimeType( - const nsACString& aMimeType, DecoderDoctorDiagnostics* aDiagnostics) const { -- return false; -+ return MP4Decoder::IsH264(aMimeType); - } - - } // namespace mozilla -diff --git a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp ---- a/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp -+++ b/dom/media/platforms/agnostic/gmp/GMPVideoDecoder.cpp -@@ -67,6 +67,8 @@ void GMPVideoDecoder::Decoded(GMPVideoi4 - RefPtr self = this; - if (v) { - mDecodedData.AppendElement(std::move(v)); -+ mDecodePromise.ResolveIfExists(std::move(mDecodedData), __func__); -+ mDecodedData = DecodedData(); - } else { - mDecodedData.Clear(); - mDecodePromise.RejectIfExists( -diff -up firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h.oldd firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h ---- firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h.oldd 2020-10-12 18:19:09.158070701 +0200 -+++ firefox-81.0.2/dom/media/gmp/GMPSharedMemManager.h 2020-10-12 18:19:18.398109540 +0200 -@@ -27,7 +27,7 @@ class GMPSharedMem { - // returned to the parent pool (which is not included). If more than - // this are needed, we presume the client has either crashed or hung - // (perhaps temporarily). -- static const uint32_t kGMPBufLimit = 20; -+ static const uint32_t kGMPBufLimit = 40; - - GMPSharedMem() { - for (size_t i = 0; i < sizeof(mGmpAllocated) / sizeof(mGmpAllocated[0]); diff --git a/mozilla-1667096.patch b/mozilla-1667096.patch index 5d98fe2..d26be4d 100644 --- a/mozilla-1667096.patch +++ b/mozilla-1667096.patch @@ -1,32 +1,20 @@ -changeset: 551978:40c95986d358 -tag: tip -parent: 551976:daadcfadb2f8 -user: stransky -date: Thu Sep 24 15:51:06 2020 +0200 -files: media/ffvpx/libavcodec/codec_list.c media/ffvpx/libavcodec/libfdk-aacdec.c media/ffvpx/libavcodec/moz.build toolkit/moz.configure -description: -Bug 1667096 Add libfdk-aacdec.c to bundled ffvpx and allow build Firefox with system fdk-aac-free library, r?jya - -Differential Revision: https://phabricator.services.mozilla.com/D91278 - - -diff --git a/media/ffvpx/libavcodec/codec_list.c b/media/ffvpx/libavcodec/codec_list.c ---- a/media/ffvpx/libavcodec/codec_list.c -+++ b/media/ffvpx/libavcodec/codec_list.c -@@ -11,4 +11,8 @@ static const AVCodec * const codec_list[ +diff -up firefox-127.0/media/ffvpx/libavcodec/codec_list.c.1667096 firefox-127.0/media/ffvpx/libavcodec/codec_list.c +--- firefox-127.0/media/ffvpx/libavcodec/codec_list.c.1667096 2024-06-06 23:33:57.000000000 +0200 ++++ firefox-127.0/media/ffvpx/libavcodec/codec_list.c 2024-06-10 12:42:39.353913204 +0200 +@@ -11,6 +11,9 @@ static const FFCodec * const codec_list[ #if CONFIG_MP3_DECODER &ff_mp3_decoder, #endif +#ifdef CONFIG_LIBFDK_AAC + &ff_libfdk_aac_decoder, +#endif -+ - NULL }; -diff --git a/media/ffvpx/libavcodec/libfdk-aacdec.c b/media/ffvpx/libavcodec/libfdk-aacdec.c -new file mode 100644 ---- /dev/null -+++ b/media/ffvpx/libavcodec/libfdk-aacdec.c -@@ -0,0 +1,409 @@ + #if CONFIG_LIBDAV1D + &ff_libdav1d_decoder, + #endif +diff -up firefox-127.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 firefox-127.0/media/ffvpx/libavcodec/libfdk-aacdec.c +--- firefox-127.0/media/ffvpx/libavcodec/libfdk-aacdec.c.1667096 2024-06-10 12:42:39.354913201 +0200 ++++ firefox-127.0/media/ffvpx/libavcodec/libfdk-aacdec.c 2024-06-10 16:28:30.332367814 +0200 +@@ -0,0 +1,498 @@ +/* + * AAC decoder wrapper + * Copyright (c) 2012 Martin Storsjo @@ -51,8 +39,10 @@ new file mode 100644 +#include "libavutil/channel_layout.h" +#include "libavutil/common.h" +#include "libavutil/opt.h" ++#include "libavutil/mem.h" +#include "avcodec.h" -+#include "internal.h" ++#include "codec_internal.h" ++#include "decode.h" + +#ifdef AACDECODER_LIB_VL0 +#define FDKDEC_VER_AT_LEAST(vl0, vl1) \ @@ -85,7 +75,14 @@ new file mode 100644 + int drc_heavy; + int drc_effect; + int drc_cut; ++ int album_mode; + int level_limit; ++#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ int output_delay_set; ++ int flush_samples; ++ int delay_samples; ++#endif ++ AVChannelLayout downmix_layout; +} FDKAACDecContext; + + @@ -104,17 +101,23 @@ new file mode 100644 + OFFSET(drc_boost), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, + { "drc_cut", "Dynamic Range Control: attenuation factor, where [0] is none and [127] is max compression", + OFFSET(drc_cut), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 127, AD, NULL }, -+ { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB", -+ OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 127, AD, NULL }, ++ { "drc_level", "Dynamic Range Control: reference level, quantized to 0.25dB steps where [0] is 0dB and [127] is -31.75dB, -1 for auto, and -2 for disabled", ++ OFFSET(drc_level), AV_OPT_TYPE_INT, { .i64 = -1}, -2, 127, AD, NULL }, + { "drc_heavy", "Dynamic Range Control: heavy compression, where [1] is on (RF mode) and [0] is off", + OFFSET(drc_heavy), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 -+ { "level_limit", "Signal level limiting", OFFSET(level_limit), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, 1, AD }, ++ { "level_limit", "Signal level limiting", ++ OFFSET(level_limit), AV_OPT_TYPE_BOOL, { .i64 = -1 }, -1, 1, AD }, +#endif +#if FDKDEC_VER_AT_LEAST(3, 0) // 3.0.0 + { "drc_effect","Dynamic Range Control: effect type, where e.g. [0] is none and [6] is general", + OFFSET(drc_effect), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 8, AD, NULL }, +#endif ++#if FDKDEC_VER_AT_LEAST(3, 1) // 3.1.0 ++ { "album_mode","Dynamic Range Control: album mode, where [0] is off and [1] is on", ++ OFFSET(album_mode), AV_OPT_TYPE_INT, { .i64 = -1}, -1, 1, AD, NULL }, ++#endif ++ { "downmix", "Request a specific channel layout from the decoder", OFFSET(downmix_layout), AV_OPT_TYPE_CHLAYOUT, {.str = NULL}, .flags = AD }, + { NULL } +}; + @@ -144,6 +147,14 @@ new file mode 100644 + } + avctx->sample_rate = info->sampleRate; + avctx->frame_size = info->frameSize; ++#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ if (!s->output_delay_set && info->outputDelay) { ++ // Set this only once. ++ s->flush_samples = info->outputDelay; ++ s->delay_samples = info->outputDelay; ++ s->output_delay_set = 1; ++ } ++#endif + + for (i = 0; i < info->numChannels; i++) { + AUDIO_CHANNEL_TYPE ctype = info->pChannelType[i]; @@ -221,17 +232,15 @@ new file mode 100644 + ch_error = 1; + } + } -+ if (!ch_error && -+ av_get_channel_layout_nb_channels(ch_layout) != info->numChannels) { ++ ++ av_channel_layout_uninit(&avctx->ch_layout); ++ av_channel_layout_from_mask(&avctx->ch_layout, ch_layout); ++ if (!ch_error && avctx->ch_layout.nb_channels != info->numChannels) { + av_log(avctx, AV_LOG_WARNING, "unsupported channel configuration\n"); + ch_error = 1; + } + if (ch_error) -+ avctx->channel_layout = 0; -+ else -+ avctx->channel_layout = ch_layout; -+ -+ avctx->channels = info->numChannels; ++ avctx->ch_layout.order = AV_CHANNEL_ORDER_UNSPEC; + + return 0; +} @@ -273,11 +282,19 @@ new file mode 100644 + return AVERROR_UNKNOWN; + } + -+ if (avctx->request_channel_layout > 0 && -+ avctx->request_channel_layout != AV_CH_LAYOUT_NATIVE) { ++#if FF_API_OLD_CHANNEL_LAYOUT ++FF_DISABLE_DEPRECATION_WARNINGS ++ if (avctx->request_channel_layout) { ++ av_channel_layout_uninit(&s->downmix_layout); ++ av_channel_layout_from_mask(&s->downmix_layout, avctx->request_channel_layout); ++ } ++FF_ENABLE_DEPRECATION_WARNINGS ++#endif ++ if (s->downmix_layout.nb_channels > 0 && ++ s->downmix_layout.order != AV_CHANNEL_ORDER_NATIVE) { + int downmix_channels = -1; + -+ switch (avctx->request_channel_layout) { ++ switch (s->downmix_layout.u.mask) { + case AV_CH_LAYOUT_STEREO: + case AV_CH_LAYOUT_STEREO_DOWNMIX: + downmix_channels = 2; @@ -286,7 +303,7 @@ new file mode 100644 + downmix_channels = 1; + break; + default: -+ av_log(avctx, AV_LOG_WARNING, "Invalid request_channel_layout\n"); ++ av_log(avctx, AV_LOG_WARNING, "Invalid downmix option\n"); + break; + } + @@ -323,6 +340,12 @@ new file mode 100644 + } + + if (s->drc_level != -1) { ++ // This option defaults to -1, i.e. not calling ++ // aacDecoder_SetParam(AAC_DRC_REFERENCE_LEVEL) at all, which defaults ++ // to the level from DRC metadata, if available. The user can set ++ // -drc_level -2, which calls aacDecoder_SetParam( ++ // AAC_DRC_REFERENCE_LEVEL) with a negative value, which then ++ // explicitly disables the feature. + if (aacDecoder_SetParam(s->handle, AAC_DRC_REFERENCE_LEVEL, s->drc_level) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set DRC reference level in the decoder\n"); + return AVERROR_UNKNOWN; @@ -337,6 +360,7 @@ new file mode 100644 + } + +#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ // Setting this parameter to -1 enables the auto behaviour in the library. + if (aacDecoder_SetParam(s->handle, AAC_PCM_LIMITER_ENABLE, s->level_limit) != AAC_DEC_OK) { + av_log(avctx, AV_LOG_ERROR, "Unable to set in signal level limiting in the decoder\n"); + return AVERROR_UNKNOWN; @@ -352,6 +376,15 @@ new file mode 100644 + } +#endif + ++#if FDKDEC_VER_AT_LEAST(3, 1) // 3.1.0 ++ if (s->album_mode != -1) { ++ if (aacDecoder_SetParam(s->handle, AAC_UNIDRC_ALBUM_MODE, s->album_mode) != AAC_DEC_OK) { ++ av_log(avctx, AV_LOG_ERROR, "Unable to set album mode in the decoder\n"); ++ return AVERROR_UNKNOWN; ++ } ++ } ++#endif ++ + avctx->sample_fmt = AV_SAMPLE_FMT_S16; + + s->decoder_buffer_size = DECODER_BUFFSIZE * DECODER_MAX_CHANNELS; @@ -362,22 +395,38 @@ new file mode 100644 + return 0; +} + -+static int fdk_aac_decode_frame(AVCodecContext *avctx, void *data, ++static int fdk_aac_decode_frame(AVCodecContext *avctx, AVFrame *frame, + int *got_frame_ptr, AVPacket *avpkt) +{ + FDKAACDecContext *s = avctx->priv_data; -+ AVFrame *frame = data; + int ret; + AAC_DECODER_ERROR err; + UINT valid = avpkt->size; ++ UINT flags = 0; ++ int input_offset = 0; + -+ err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); -+ if (err != AAC_DEC_OK) { -+ av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); -+ return AVERROR_INVALIDDATA; ++ if (avpkt->size) { ++ err = aacDecoder_Fill(s->handle, &avpkt->data, &avpkt->size, &valid); ++ if (err != AAC_DEC_OK) { ++ av_log(avctx, AV_LOG_ERROR, "aacDecoder_Fill() failed: %x\n", err); ++ return AVERROR_INVALIDDATA; ++ } ++ } else { ++#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ /* Handle decoder draining */ ++ if (s->flush_samples > 0) { ++ flags |= AACDEC_FLUSH; ++ } else { ++ return AVERROR_EOF; ++ } ++#else ++ return AVERROR_EOF; ++#endif + } + -+ err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, s->decoder_buffer_size / sizeof(INT_PCM), 0); ++ err = aacDecoder_DecodeFrame(s->handle, (INT_PCM *) s->decoder_buffer, ++ s->decoder_buffer_size / sizeof(INT_PCM), ++ flags); + if (err == AAC_DEC_NOT_ENOUGH_BITS) { + ret = avpkt->size - valid; + goto end; @@ -393,11 +442,36 @@ new file mode 100644 + goto end; + frame->nb_samples = avctx->frame_size; + ++#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ if (flags & AACDEC_FLUSH) { ++ // Only return the right amount of samples at the end; if calling the ++ // decoder with AACDEC_FLUSH, it will keep returning frames indefinitely. ++ frame->nb_samples = FFMIN(s->flush_samples, frame->nb_samples); ++ av_log(s, AV_LOG_DEBUG, "Returning %d/%d delayed samples.\n", ++ frame->nb_samples, s->flush_samples); ++ s->flush_samples -= frame->nb_samples; ++ } else { ++ // Trim off samples from the start to compensate for extra decoder ++ // delay. We could also just adjust the pts, but this avoids ++ // including the extra samples in the output altogether. ++ if (s->delay_samples) { ++ int drop_samples = FFMIN(s->delay_samples, frame->nb_samples); ++ av_log(s, AV_LOG_DEBUG, "Dropping %d/%d delayed samples.\n", ++ drop_samples, s->delay_samples); ++ s->delay_samples -= drop_samples; ++ frame->nb_samples -= drop_samples; ++ input_offset = drop_samples * avctx->ch_layout.nb_channels; ++ if (frame->nb_samples <= 0) ++ return 0; ++ } ++ } ++#endif ++ + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + goto end; + -+ memcpy(frame->extended_data[0], s->decoder_buffer, -+ avctx->channels * avctx->frame_size * ++ memcpy(frame->extended_data[0], s->decoder_buffer + input_offset, ++ avctx->ch_layout.nb_channels * frame->nb_samples * + av_get_bytes_per_sample(avctx->sample_fmt)); + + *got_frame_ptr = 1; @@ -420,28 +494,31 @@ new file mode 100644 + av_log(avctx, AV_LOG_WARNING, "failed to clear buffer when flushing\n"); +} + -+AVCodec ff_libfdk_aac_decoder = { -+ .name = "libfdk_aac", -+ .long_name = NULL_IF_CONFIG_SMALL("Fraunhofer FDK AAC"), -+ .type = AVMEDIA_TYPE_AUDIO, -+ .id = AV_CODEC_ID_AAC, ++const FFCodec ff_libfdk_aac_decoder = { ++ .p.name = "libfdk_aac", ++ CODEC_LONG_NAME("Fraunhofer FDK AAC"), ++ .p.type = AVMEDIA_TYPE_AUDIO, ++ .p.id = AV_CODEC_ID_AAC, + .priv_data_size = sizeof(FDKAACDecContext), + .init = fdk_aac_decode_init, -+ .decode = fdk_aac_decode_frame, ++ FF_CODEC_DECODE_CB(fdk_aac_decode_frame), + .close = fdk_aac_decode_close, + .flush = fdk_aac_decode_flush, -+ .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF, -+ .priv_class = &fdk_aac_dec_class, -+ .caps_internal = FF_CODEC_CAP_INIT_THREADSAFE | -+ FF_CODEC_CAP_INIT_CLEANUP, -+ .wrapper_name = "libfdk", ++ .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_CHANNEL_CONF ++#if FDKDEC_VER_AT_LEAST(2, 5) // 2.5.10 ++ | AV_CODEC_CAP_DELAY ++#endif ++ , ++ .p.priv_class = &fdk_aac_dec_class, ++ .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, ++ .p.wrapper_name = "libfdk", +}; -diff --git a/media/ffvpx/libavcodec/moz.build b/media/ffvpx/libavcodec/moz.build ---- a/media/ffvpx/libavcodec/moz.build -+++ b/media/ffvpx/libavcodec/moz.build -@@ -97,6 +97,12 @@ if not CONFIG['MOZ_FFVPX_AUDIOONLY']: - 'vp9recon.c' - ] +diff -up firefox-127.0/media/ffvpx/libavcodec/moz.build.1667096 firefox-127.0/media/ffvpx/libavcodec/moz.build +--- firefox-127.0/media/ffvpx/libavcodec/moz.build.1667096 2024-06-06 23:33:58.000000000 +0200 ++++ firefox-127.0/media/ffvpx/libavcodec/moz.build 2024-06-10 12:42:39.354913201 +0200 +@@ -151,6 +151,12 @@ else: + CXXFLAGS += CONFIG["MOZ_LIBVPX_CFLAGS"] + OS_LIBS += CONFIG["MOZ_LIBVPX_LIBS"] +if CONFIG['MOZ_FDK_AAC']: + SOURCES += [ @@ -449,17 +526,18 @@ diff --git a/media/ffvpx/libavcodec/moz.build b/media/ffvpx/libavcodec/moz.build + ] + OS_LIBS += CONFIG['MOZ_FDK_AAC_LIBS'] + - if CONFIG['MOZ_LIBAV_FFT']: - SOURCES += [ - 'avfft.c', -diff --git a/toolkit/moz.configure b/toolkit/moz.configure ---- a/toolkit/moz.configure -+++ b/toolkit/moz.configure -@@ -1592,6 +1592,14 @@ with only_when(compile_environment): - set_define('MOZ_LIBAV_FFT', depends(when=libav_fft)(lambda: True)) - set_config('LIBAV_FFT_ASFLAGS', libav_fft.flags) + SYMBOLS_FILE = 'avcodec.symbols' + NoVisibilityFlags() -+# fdk aac support +diff -up firefox-127.0/toolkit/moz.configure.1667096 firefox-127.0/toolkit/moz.configure +--- firefox-127.0/toolkit/moz.configure.1667096 2024-06-10 12:42:39.312913316 +0200 ++++ firefox-127.0/toolkit/moz.configure 2024-06-10 12:42:39.355913199 +0200 +@@ -2412,6 +2412,15 @@ with only_when(compile_environment): + + set_config("MOZ_SYSTEM_PNG", True, when="--with-system-png") + ++# FDK AAC support ++# ============================================================== +option('--with-system-fdk-aac', + help='Use system libfdk-aac (located with pkgconfig)') + @@ -470,4 +548,3 @@ diff --git a/toolkit/moz.configure b/toolkit/moz.configure # FFmpeg's ffvpx configuration # ============================================================== - diff --git a/mozilla-1669639.patch b/mozilla-1669639.patch deleted file mode 100644 index 2d79542..0000000 --- a/mozilla-1669639.patch +++ /dev/null @@ -1,15 +0,0 @@ -diff -up firefox-81.0.1/build/mach_bootstrap.py.old firefox-81.0.1/build/mach_bootstrap.py ---- firefox-81.0.1/build/mach_bootstrap.py.old 2020-10-06 14:16:06.212974910 +0200 -+++ firefox-81.0.1/build/mach_bootstrap.py 2020-10-06 14:19:03.313179557 +0200 -@@ -507,7 +507,10 @@ class ImportHook(object): - # doesn't happen or because it doesn't matter). - if not os.path.exists(module.__file__[:-1]): - if os.path.exists(module.__file__): -- os.remove(module.__file__) -+ try: -+ os.remove(module.__file__) -+ except: -+ pass - del sys.modules[module.__name__] - module = self(name, globals, locals, fromlist, level) - diff --git a/mozilla-1670333.patch b/mozilla-1670333.patch deleted file mode 100644 index a7c7f8a..0000000 --- a/mozilla-1670333.patch +++ /dev/null @@ -1,68 +0,0 @@ -diff -up firefox-82.0/dom/media/mp4/MP4Demuxer.cpp.1670333 firefox-82.0/dom/media/mp4/MP4Demuxer.cpp ---- firefox-82.0/dom/media/mp4/MP4Demuxer.cpp.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/mp4/MP4Demuxer.cpp 2020-10-19 20:56:38.362039524 +0200 -@@ -31,6 +31,8 @@ mozilla::LogModule* GetDemuxerLog() { re - DDMOZ_LOG(gMediaDemuxerLog, mozilla::LogLevel::Debug, "::%s: " arg, \ - __func__, ##__VA_ARGS__) - -+extern bool gUseKeyframeFromContainer; -+ - namespace mozilla { - - DDLoggedTypeDeclNameAndBase(MP4TrackDemuxer, MediaTrackDemuxer); -@@ -394,6 +396,12 @@ already_AddRefed MP4TrackD - [[fallthrough]]; - case H264::FrameType::OTHER: { - bool keyframe = type == H264::FrameType::I_FRAME; -+ if (gUseKeyframeFromContainer) { -+ if (sample->mKeyframe && sample->mKeyframe != keyframe) { -+ sample->mKeyframe = keyframe; -+ } -+ break; -+ } - if (sample->mKeyframe != keyframe) { - NS_WARNING(nsPrintfCString("Frame incorrectly marked as %skeyframe " - "@ pts:%" PRId64 " dur:%" PRId64 -diff -up firefox-82.0/dom/media/platforms/PDMFactory.cpp.1670333 firefox-82.0/dom/media/platforms/PDMFactory.cpp ---- firefox-82.0/dom/media/platforms/PDMFactory.cpp.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/platforms/PDMFactory.cpp 2020-10-19 20:53:14.631214334 +0200 -@@ -49,6 +49,8 @@ - - #include - -+bool gUseKeyframeFromContainer = false; -+ - namespace mozilla { - - extern already_AddRefed CreateBlankDecoderModule(); -@@ -380,7 +382,8 @@ void PDMFactory::CreatePDMs() { - #ifdef MOZ_FFMPEG - if (StaticPrefs::media_ffmpeg_enabled()) { - m = FFmpegRuntimeLinker::CreateDecoderModule(); -- mFFmpegFailedToLoad = !StartupPDM(m); -+ mFFmpegUsed = StartupPDM(m); -+ mFFmpegFailedToLoad = !mFFmpegUsed; - } else { - mFFmpegFailedToLoad = false; - } -@@ -395,7 +398,8 @@ void PDMFactory::CreatePDMs() { - m = new AgnosticDecoderModule(); - StartupPDM(m); - -- if (StaticPrefs::media_gmp_decoder_enabled()) { -+ if (StaticPrefs::media_gmp_decoder_enabled() && !mFFmpegUsed) { -+ gUseKeyframeFromContainer = true; - m = new GMPDecoderModule(); - mGMPPDMFailedToStartup = !StartupPDM(m); - } else { -diff -up firefox-82.0/dom/media/platforms/PDMFactory.h.1670333 firefox-82.0/dom/media/platforms/PDMFactory.h ---- firefox-82.0/dom/media/platforms/PDMFactory.h.1670333 2020-10-14 19:20:18.000000000 +0200 -+++ firefox-82.0/dom/media/platforms/PDMFactory.h 2020-10-19 20:53:14.631214334 +0200 -@@ -70,6 +70,7 @@ class PDMFactory final { - - bool mWMFFailedToLoad = false; - bool mFFmpegFailedToLoad = false; -+ bool mFFmpegUsed = false; - bool mGMPPDMFailedToStartup = false; - - friend class RemoteVideoDecoderParent; diff --git a/mozilla-1673202.patch b/mozilla-1673202.patch deleted file mode 100644 index b8695a1..0000000 --- a/mozilla-1673202.patch +++ /dev/null @@ -1,16 +0,0 @@ -diff -up firefox-82.0/security/sandbox/linux/SandboxFilter.cpp.1673202 firefox-82.0/security/sandbox/linux/SandboxFilter.cpp ---- firefox-82.0/security/sandbox/linux/SandboxFilter.cpp.1673202 2020-10-27 10:40:54.903158025 +0100 -+++ firefox-82.0/security/sandbox/linux/SandboxFilter.cpp 2020-10-27 10:43:19.024883597 +0100 -@@ -246,7 +246,11 @@ class SandboxPolicyCommon : public Sandb - - if (fd != AT_FDCWD && (flags & AT_EMPTY_PATH) != 0 && - strcmp(path, "") == 0) { -- return ConvertError(fstatsyscall(fd, buf)); -+#ifdef __NR_fstat64 -+ return DoSyscall(__NR_fstat64, fd, buf); -+#else -+ return DoSyscall(__NR_fstat, fd, buf); -+#endif - } - - if (fd != AT_FDCWD && path[0] != '/') { diff --git a/mozilla-1673313.patch b/mozilla-1673313.patch deleted file mode 100644 index 549243b..0000000 --- a/mozilla-1673313.patch +++ /dev/null @@ -1,351 +0,0 @@ -changeset: 556172:143b4ca96ec9 -tag: tip -parent: 556169:61c35792ca70 -user: stransky -date: Mon Oct 26 12:15:49 2020 +0100 -files: widget/gtk/WindowSurfaceWayland.cpp widget/gtk/WindowSurfaceWayland.h -description: -Bug 1673313 [Wayland] Don't fail when Shm allocation fails, r?jhorak - -- Make WaylandAllocateShmMemory() fallible. -- Implement WaylandReAllocateShmMemory() to re-allocate Shm pool. -- Remove WaylandShmPool::Resize() and use WaylandShmPool::Create() only. -- Implement and use WaylandShmPool::Release(). -- Make WindowSurfaceWayland::CreateWaylandBuffer() as fallible. - -Differential Revision: https://phabricator.services.mozilla.com/D94735 - - -diff --git a/widget/gtk/WindowSurfaceWayland.cpp b/widget/gtk/WindowSurfaceWayland.cpp ---- a/widget/gtk/WindowSurfaceWayland.cpp -+++ b/widget/gtk/WindowSurfaceWayland.cpp -@@ -209,14 +209,23 @@ RefPtr WindowBackBuffe - } - - static int WaylandAllocateShmMemory(int aSize) { -- static int counter = 0; -- nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++); -- int fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600); -- if (fd >= 0) { -- shm_unlink(shmName.get()); -- } else { -- printf_stderr("Unable to SHM memory segment\n"); -- MOZ_CRASH(); -+ int fd = -1; -+ do { -+ static int counter = 0; -+ nsPrintfCString shmName("/wayland.mozilla.ipc.%d", counter++); -+ fd = shm_open(shmName.get(), O_CREAT | O_RDWR | O_EXCL, 0600); -+ if (fd >= 0) { -+ // We don't want to use leaked file -+ if (shm_unlink(shmName.get()) != 0) { -+ NS_WARNING("shm_unlink failed"); -+ return -1; -+ } -+ } -+ } while (fd < 0 && errno == EEXIST); -+ -+ if (fd < 0) { -+ NS_WARNING(nsPrintfCString("shm_open failed: %s", strerror(errno)).get()); -+ return -1; - } - - int ret = 0; -@@ -225,59 +234,103 @@ static int WaylandAllocateShmMemory(int - ret = posix_fallocate(fd, 0, aSize); - } while (ret == EINTR); - if (ret != 0) { -+ NS_WARNING( -+ nsPrintfCString("posix_fallocate() fails to allocate shm memory: %s", -+ strerror(ret)) -+ .get()); - close(fd); -- MOZ_CRASH("posix_fallocate() fails to allocate shm memory"); -+ return -1; - } - #else - do { - ret = ftruncate(fd, aSize); - } while (ret < 0 && errno == EINTR); - if (ret < 0) { -+ NS_WARNING(nsPrintfCString("ftruncate() fails to allocate shm memory: %s", -+ strerror(ret)) -+ .get()); - close(fd); -- MOZ_CRASH("ftruncate() fails to allocate shm memory"); -+ fd = -1; - } - #endif - - return fd; - } - --WaylandShmPool::WaylandShmPool(RefPtr aWaylandDisplay, -- int aSize) -- : mAllocatedSize(aSize) { -- mShmPoolFd = WaylandAllocateShmMemory(mAllocatedSize); -- mImageData = mmap(nullptr, mAllocatedSize, PROT_READ | PROT_WRITE, MAP_SHARED, -- mShmPoolFd, 0); -- MOZ_RELEASE_ASSERT(mImageData != MAP_FAILED, -- "Unable to map drawing surface!"); -+static bool WaylandReAllocateShmMemory(int aFd, int aSize) { -+ if (ftruncate(aFd, aSize) < 0) { -+ return false; -+ } -+#ifdef HAVE_POSIX_FALLOCATE -+ do { -+ errno = posix_fallocate(aFd, 0, aSize); -+ } while (errno == EINTR); -+ if (errno != 0) { -+ return false; -+ } -+#endif -+ return true; -+} - -- mShmPool = -- wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, mAllocatedSize); -+WaylandShmPool::WaylandShmPool() -+ : mShmPool(nullptr), -+ mShmPoolFd(-1), -+ mAllocatedSize(0), -+ mImageData(MAP_FAILED){}; - -- // We set our queue to get mShmPool events at compositor thread. -- wl_proxy_set_queue((struct wl_proxy*)mShmPool, -- aWaylandDisplay->GetEventQueue()); -+void WaylandShmPool::Release() { -+ if (mImageData != MAP_FAILED) { -+ munmap(mImageData, mAllocatedSize); -+ mImageData = MAP_FAILED; -+ } -+ if (mShmPool) { -+ wl_shm_pool_destroy(mShmPool); -+ mShmPool = 0; -+ } -+ if (mShmPoolFd >= 0) { -+ close(mShmPoolFd); -+ mShmPoolFd = -1; -+ } - } - --bool WaylandShmPool::Resize(int aSize) { -+bool WaylandShmPool::Create(RefPtr aWaylandDisplay, -+ int aSize) { - // We do size increase only -- if (aSize <= mAllocatedSize) return true; -- -- if (ftruncate(mShmPoolFd, aSize) < 0) return false; -+ if (aSize <= mAllocatedSize) { -+ return true; -+ } - --#ifdef HAVE_POSIX_FALLOCATE -- do { -- errno = posix_fallocate(mShmPoolFd, 0, aSize); -- } while (errno == EINTR); -- if (errno != 0) return false; --#endif -+ if (mShmPoolFd < 0) { -+ mShmPoolFd = WaylandAllocateShmMemory(aSize); -+ if (mShmPoolFd < 0) { -+ return false; -+ } -+ } else { -+ if (!WaylandReAllocateShmMemory(mShmPoolFd, aSize)) { -+ Release(); -+ return false; -+ } -+ } - -- wl_shm_pool_resize(mShmPool, aSize); -- -- munmap(mImageData, mAllocatedSize); -- -+ if (mImageData != MAP_FAILED) { -+ munmap(mImageData, mAllocatedSize); -+ } - mImageData = - mmap(nullptr, aSize, PROT_READ | PROT_WRITE, MAP_SHARED, mShmPoolFd, 0); -- if (mImageData == MAP_FAILED) return false; -+ if (mImageData == MAP_FAILED) { -+ NS_WARNING("Unable to map drawing surface!"); -+ Release(); -+ return false; -+ } -+ -+ if (mShmPool) { -+ wl_shm_pool_resize(mShmPool, aSize); -+ } else { -+ mShmPool = wl_shm_create_pool(aWaylandDisplay->GetShm(), mShmPoolFd, aSize); -+ // We set our queue to get mShmPool events at compositor thread. -+ wl_proxy_set_queue((struct wl_proxy*)mShmPool, -+ aWaylandDisplay->GetEventQueue()); -+ } - - mAllocatedSize = aSize; - return true; -@@ -289,11 +342,7 @@ void WaylandShmPool::SetImageDataFromPoo - memcpy(mImageData, aSourcePool->GetImageData(), aImageDataSize); - } - --WaylandShmPool::~WaylandShmPool() { -- munmap(mImageData, mAllocatedSize); -- wl_shm_pool_destroy(mShmPool); -- close(mShmPoolFd); --} -+WaylandShmPool::~WaylandShmPool() { Release(); } - - static void buffer_release(void* data, wl_buffer* buffer) { - auto surface = reinterpret_cast(data); -@@ -302,14 +351,14 @@ static void buffer_release(void* data, w - - static const struct wl_buffer_listener buffer_listener = {buffer_release}; - --void WindowBackBufferShm::Create(int aWidth, int aHeight) { -+bool WindowBackBufferShm::Create(int aWidth, int aHeight) { - MOZ_ASSERT(!IsAttached(), "We can't create attached buffers."); -- MOZ_ASSERT(!mWLBuffer, "there is wl_buffer already!"); - -- int newBufferSize = aWidth * aHeight * BUFFER_BPP; -- if (!mShmPool.Resize(newBufferSize)) { -- mWLBuffer = nullptr; -- return; -+ ReleaseShmSurface(); -+ -+ int size = aWidth * aHeight * BUFFER_BPP; -+ if (!mShmPool.Create(GetWaylandDisplay(), size)) { -+ return false; - } - - mWLBuffer = -@@ -325,14 +374,16 @@ void WindowBackBufferShm::Create(int aWi - LOGWAYLAND(("WindowBackBufferShm::Create [%p] wl_buffer %p ID %d\n", - (void*)this, (void*)mWLBuffer, - mWLBuffer ? wl_proxy_get_id((struct wl_proxy*)mWLBuffer) : -1)); -+ return true; - } - - void WindowBackBufferShm::ReleaseShmSurface() { - LOGWAYLAND(("WindowBackBufferShm::Release [%p]\n", (void*)this)); -- -- wl_buffer_destroy(mWLBuffer); -+ if (mWLBuffer) { -+ wl_buffer_destroy(mWLBuffer); -+ mWLBuffer = nullptr; -+ } - mWidth = mHeight = 0; -- mWLBuffer = nullptr; - } - - void WindowBackBufferShm::Clear() { -@@ -340,16 +391,13 @@ void WindowBackBufferShm::Clear() { - } - - WindowBackBufferShm::WindowBackBufferShm( -- WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, int aHeight) -+ WindowSurfaceWayland* aWindowSurfaceWayland) - : WindowBackBuffer(aWindowSurfaceWayland), -- mShmPool(aWindowSurfaceWayland->GetWaylandDisplay(), -- aWidth * aHeight * BUFFER_BPP), -+ mShmPool(), - mWLBuffer(nullptr), -- mWidth(aWidth), -- mHeight(aHeight), -- mAttached(false) { -- Create(aWidth, aHeight); --} -+ mWidth(0), -+ mHeight(0), -+ mAttached(false) {} - - WindowBackBufferShm::~WindowBackBufferShm() { ReleaseShmSurface(); } - -@@ -357,13 +405,9 @@ bool WindowBackBufferShm::Resize(int aWi - if (aWidth == mWidth && aHeight == mHeight) { - return true; - } -- - LOGWAYLAND(("WindowBackBufferShm::Resize [%p] %d %d\n", (void*)this, aWidth, - aHeight)); -- -- ReleaseShmSurface(); - Create(aWidth, aHeight); -- - return (mWLBuffer != nullptr); - } - -@@ -488,11 +532,13 @@ WindowBackBuffer* WindowSurfaceWayland:: - return nullptr; - } - -- WindowBackBuffer* buffer = new WindowBackBufferShm(this, aWidth, aHeight); -- if (buffer) { -- mShmBackupBuffer[availableBuffer] = buffer; -+ WindowBackBuffer* buffer = new WindowBackBufferShm(this); -+ if (!buffer->Create(aWidth, aHeight)) { -+ delete buffer; -+ return nullptr; - } - -+ mShmBackupBuffer[availableBuffer] = buffer; - return buffer; - } - -diff --git a/widget/gtk/WindowSurfaceWayland.h b/widget/gtk/WindowSurfaceWayland.h ---- a/widget/gtk/WindowSurfaceWayland.h -+++ b/widget/gtk/WindowSurfaceWayland.h -@@ -25,14 +25,14 @@ class WindowSurfaceWayland; - // Allocates and owns shared memory for Wayland drawing surface - class WaylandShmPool { - public: -- WaylandShmPool(RefPtr aDisplay, int aSize); -- ~WaylandShmPool(); -- -- bool Resize(int aSize); -+ bool Create(RefPtr aWaylandDisplay, int aSize); -+ void Release(); - wl_shm_pool* GetShmPool() { return mShmPool; }; - void* GetImageData() { return mImageData; }; - void SetImageDataFromPool(class WaylandShmPool* aSourcePool, - int aImageDataSize); -+ WaylandShmPool(); -+ ~WaylandShmPool(); - - private: - wl_shm_pool* mShmPool; -@@ -53,6 +53,7 @@ class WindowBackBuffer { - virtual bool IsAttached() = 0; - - virtual void Clear() = 0; -+ virtual bool Create(int aWidth, int aHeight) = 0; - virtual bool Resize(int aWidth, int aHeight) = 0; - - virtual int GetWidth() = 0; -@@ -87,8 +88,7 @@ class WindowBackBuffer { - - class WindowBackBufferShm : public WindowBackBuffer { - public: -- WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland, int aWidth, -- int aHeight); -+ WindowBackBufferShm(WindowSurfaceWayland* aWindowSurfaceWayland); - ~WindowBackBufferShm(); - - already_AddRefed Lock(); -@@ -100,6 +100,7 @@ class WindowBackBufferShm : public Windo - void SetAttached() { mAttached = true; }; - - void Clear(); -+ bool Create(int aWidth, int aHeight); - bool Resize(int aWidth, int aHeight); - bool SetImageDataFromBuffer(class WindowBackBuffer* aSourceBuffer); - -@@ -109,7 +110,6 @@ class WindowBackBufferShm : public Windo - wl_buffer* GetWlBuffer() { return mWLBuffer; }; - - private: -- void Create(int aWidth, int aHeight); - void ReleaseShmSurface(); - - // WaylandShmPool provides actual shared memory we draw into - diff --git a/mozilla-1885133.patch b/mozilla-1885133.patch deleted file mode 100644 index a73503a..0000000 --- a/mozilla-1885133.patch +++ /dev/null @@ -1,21 +0,0 @@ -diff --git a/browser/components/shell/nsGNOMEShellDBusHelper.cpp b/browser/components/shell/nsGNOMEShellDBusHelper.cpp ---- a/browser/components/shell/nsGNOMEShellDBusHelper.cpp -+++ b/browser/components/shell/nsGNOMEShellDBusHelper.cpp -@@ -29,7 +29,7 @@ static bool GetGnomeSearchTitle(const ch - } - - AutoTArray formatStrings; -- CopyASCIItoUTF16(nsCString(aSearchedTerm), *formatStrings.AppendElement()); -+ CopyUTF8toUTF16(nsCString(aSearchedTerm), *formatStrings.AppendElement()); - - nsAutoString gnomeSearchTitle; - bundle->FormatStringFromName("gnomeSearchProviderSearch", formatStrings, -@@ -41,7 +41,7 @@ static bool GetGnomeSearchTitle(const ch - static const char* introspect_template = - "\n" -+ "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" - "\n" - " \n" - " \n" diff --git a/mozilla-440908.patch b/mozilla-440908.patch deleted file mode 100644 index cce5248..0000000 --- a/mozilla-440908.patch +++ /dev/null @@ -1,111 +0,0 @@ -diff -up firefox-56.0/modules/libpref/prefapi.cpp.440908 firefox-56.0/modules/libpref/prefapi.cpp ---- firefox-56.0/modules/libpref/prefapi.cpp.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefapi.cpp 2017-09-25 10:39:39.266572792 +0200 -@@ -1036,8 +1036,8 @@ void PREF_ReaderCallback(void *clo - PrefValue value, - PrefType type, - bool isDefault, -- bool isStickyDefault) -- -+ bool isStickyDefault, -+ bool isLocked) - { - uint32_t flags = 0; - if (isDefault) { -@@ -1049,4 +1049,6 @@ void PREF_ReaderCallback(void *clo - flags |= kPrefForceSet; - } - pref_HashPref(pref, value, type, flags); -+ if (isLocked) -+ PREF_LockPref(pref, true); - } -diff -up firefox-56.0/modules/libpref/prefapi.h.440908 firefox-56.0/modules/libpref/prefapi.h ---- firefox-56.0/modules/libpref/prefapi.h.440908 2017-07-31 18:20:51.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefapi.h 2017-09-25 10:39:39.267572789 +0200 -@@ -246,8 +246,8 @@ void PREF_ReaderCallback( void *closure, - PrefValue value, - PrefType type, - bool isDefault, -- bool isStickyDefault); -- -+ bool isStickyDefault, -+ bool isLocked); - - /* - * Callback whenever we change a preference -diff -up firefox-56.0/modules/libpref/prefread.cpp.440908 firefox-56.0/modules/libpref/prefread.cpp ---- firefox-56.0/modules/libpref/prefread.cpp.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefread.cpp 2017-09-25 10:39:39.267572789 +0200 -@@ -43,6 +43,7 @@ enum { - #define BITS_PER_HEX_DIGIT 4 - - static const char kUserPref[] = "user_pref"; -+static const char kLockPref[] = "lockPref"; - static const char kPref[] = "pref"; - static const char kPrefSticky[] = "sticky_pref"; - static const char kTrue[] = "true"; -@@ -146,7 +147,7 @@ pref_DoCallback(PrefParseState *ps) - break; - } - (*ps->reader)(ps->closure, ps->lb, value, ps->vtype, ps->fdefault, -- ps->fstickydefault); -+ ps->fstickydefault, ps->flock); - return true; - } - -@@ -215,6 +216,7 @@ PREF_ParseBuf(PrefParseState *ps, const - ps->vtype = PrefType::Invalid; - ps->fdefault = false; - ps->fstickydefault = false; -+ ps->flock = false; - } - switch (c) { - case '/': /* begin comment block or line? */ -@@ -225,11 +227,14 @@ PREF_ParseBuf(PrefParseState *ps, const - break; - case 'u': /* indicating user_pref */ - case 's': /* indicating sticky_pref */ -+ case 'l': /* indicating lockPref */ - case 'p': /* indicating pref */ - if (c == 'u') { - ps->smatch = kUserPref; - } else if (c == 's') { - ps->smatch = kPrefSticky; -+ } else if (c == 'l') { -+ ps->smatch = kLockPref; - } else { - ps->smatch = kPref; - } -@@ -277,8 +282,10 @@ PREF_ParseBuf(PrefParseState *ps, const - /* name parsing */ - case PREF_PARSE_UNTIL_NAME: - if (c == '\"' || c == '\'') { -- ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky); -+ ps->fdefault = (ps->smatch == kPref || ps->smatch == kPrefSticky -+ || ps->smatch == kLockPref); - ps->fstickydefault = (ps->smatch == kPrefSticky); -+ ps->flock = (ps->smatch == kLockPref); - ps->quotechar = c; - ps->nextstate = PREF_PARSE_UNTIL_COMMA; /* return here when done */ - state = PREF_PARSE_QUOTED_STRING; -diff -up firefox-56.0/modules/libpref/prefread.h.440908 firefox-56.0/modules/libpref/prefread.h ---- firefox-56.0/modules/libpref/prefread.h.440908 2017-09-14 22:15:52.000000000 +0200 -+++ firefox-56.0/modules/libpref/prefread.h 2017-09-25 10:39:39.267572789 +0200 -@@ -34,7 +34,8 @@ typedef void (*PrefReader)(void *c - PrefValue val, - PrefType type, - bool defPref, -- bool stickyPref); -+ bool stickyPref, -+ bool lockPref); - - /** - * Report any errors or warnings we encounter during parsing. -@@ -62,6 +63,7 @@ typedef struct PrefParseState { - PrefType vtype; /* PREF_STRING,INT,BOOL */ - bool fdefault; /* true if (default) pref */ - bool fstickydefault; /* true if (sticky) pref */ -+ bool flock; /* true if pref to be locked */ - } PrefParseState; - - /** diff --git a/mozilla-build-arm.patch b/mozilla-build-arm.patch deleted file mode 100644 index e390a28..0000000 --- a/mozilla-build-arm.patch +++ /dev/null @@ -1,14 +0,0 @@ -diff -up firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h.arm firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h ---- firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h.arm 2017-03-03 13:53:52.480754536 +0100 -+++ firefox-52.0/gfx/skia/skia/include/core/SkPreConfig.h 2017-03-03 13:56:01.476018102 +0100 -@@ -203,6 +203,10 @@ - #define SK_ARM_HAS_CRC32 - #endif - -+#if defined(__aarch64__) -+ #undef SK_ARM_HAS_NEON -+#endif -+ - ////////////////////////////////////////////////////////////////////// - - #if !defined(SKIA_IMPLEMENTATION) diff --git a/org.mozilla.firefox.SearchProvider.service b/org.mozilla.firefox.SearchProvider.service new file mode 100644 index 0000000..6b2bd1b --- /dev/null +++ b/org.mozilla.firefox.SearchProvider.service @@ -0,0 +1,3 @@ +[D-BUS Service] +Name=org.mozilla.firefox.SearchProvider +Exec=/usr/lib64/firefox/firefox --dbus-service /usr/bin/firefox diff --git a/org.mozilla.firefox.appdata.xml.in b/org.mozilla.firefox.appdata.xml.in new file mode 100644 index 0000000..3c086a1 --- /dev/null +++ b/org.mozilla.firefox.appdata.xml.in @@ -0,0 +1,61 @@ + + + + org.mozilla.firefox + CC0-1.0 + Firefox + Web Browser + Navegador web + Webový prohlížeč + Navegador web + مرورگر اینترنتی + WWW-selain + Navigateur Web + Webböngésző + Browser Web + ウェブ・ブラウザ + 웹 브라우저 + Nettleser + Webbrowser + Nettlesar + Nettleser + Przeglądarka WWW + Navegador Web + Navegador Web + Internetový prehliadač + Webbläsare + +

+ Bringing together all kinds of awesomeness to make browsing better for you. + Get to your favorite sites quickly – even if you don’t remember the URLs. + Type your term into the location bar (aka the Awesome Bar) and the autocomplete + function will include possible matches from your browsing history, bookmarked + sites and open tabs. +

+ + https://www.mozilla.org + stransky@redhat.com + + ModernToolkit + SearchProvider + + Mozilla + GPL-3.0+ + Mozilla Corporation + https://bugzilla.mozilla.org/ + https://support.mozilla.org/ + firefox + org.mozilla.firefox.desktop + + firefox.desktop + + + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/a.png + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/b.png + https://raw.githubusercontent.com/hughsie/fedora-appstream/master/screenshots-extra/firefox/c.png + + + + + + diff --git a/org.mozilla.firefox.desktop b/org.mozilla.firefox.desktop new file mode 100644 index 0000000..02e156d --- /dev/null +++ b/org.mozilla.firefox.desktop @@ -0,0 +1,276 @@ +[Desktop Entry] +Version=1.0 +Name=Firefox +GenericName=Web Browser +GenericName[ca]=Navegador web +GenericName[cs]=Webový prohlížeč +GenericName[es]=Navegador web +GenericName[fa]=مرورگر اینترنتی +GenericName[fi]=WWW-selain +GenericName[fr]=Navigateur Web +GenericName[hu]=Webböngésző +GenericName[it]=Browser Web +GenericName[ja]=ウェブ・ブラウザ +GenericName[ko]=웹 브라우저 +GenericName[nb]=Nettleser +GenericName[nl]=Webbrowser +GenericName[nn]=Nettlesar +GenericName[no]=Nettleser +GenericName[pl]=Przeglądarka WWW +GenericName[pt]=Navegador Web +GenericName[pt_BR]=Navegador Web +GenericName[sk]=Internetový prehliadač +GenericName[sv]=Webbläsare +Comment=Browse the Web +Comment[ca]=Navegueu per el web +Comment[cs]=Prohlížení stránek World Wide Webu +Comment[de]=Im Internet surfen +Comment[es]=Navegue por la web +Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید +Comment[fi]=Selaa Internetin WWW-sivuja +Comment[fr]=Navigue sur Internet +Comment[hu]=A világháló böngészése +Comment[it]=Esplora il web +Comment[ja]=ウェブを閲覧します +Comment[ko]=웹을 돌아 다닙니다 +Comment[nb]=Surf på nettet +Comment[nl]=Verken het internet +Comment[nn]=Surf på nettet +Comment[no]=Surf på nettet +Comment[pl]=Przeglądanie stron WWW +Comment[pt]=Navegue na Internet +Comment[pt_BR]=Navegue na Internet +Comment[sk]=Prehliadanie internetu +Comment[sv]=Surfa på webben +Exec=firefox %u +Icon=firefox +Terminal=false +Type=Application +MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;text/mml;x-scheme-handler/http;x-scheme-handler/https; +StartupNotify=true +Categories=Network;WebBrowser; +Keywords=web;browser;internet; +Actions=new-window;new-private-window;profile-manager-window; + +[Desktop Action new-window] +Name=Open a New Window +Name[ach]=Dirica manyen +Name[af]=Nuwe venster +Name[an]=Nueva finestra +Name[ar]=نافذة جديدة +Name[as]=নতুন উইন্ডো +Name[ast]=Ventana nueva +Name[az]=Yeni Pəncərə +Name[be]=Новае акно +Name[bg]=Нов прозорец +Name[bn_BD]=নতুন উইন্ডো (N) +Name[bn_IN]=নতুন উইন্ডো +Name[br]=Prenestr nevez +Name[brx]=गोदान उइन्ड'(N) +Name[bs]=Novi prozor +Name[ca]=Finestra nova +Name[cak]=K'ak'a' tzuwäch +Name[cs]=Nové okno +Name[cy]=Ffenestr Newydd +Name[da]=Nyt vindue +Name[de]=Neues Fenster +Name[dsb]=Nowe wokno +Name[el]=Νέο παράθυρο +Name[en_GB]=New Window +Name[en_US]=New Window +Name[en_ZA]=New Window +Name[eo]=Nova fenestro +Name[es_AR]=Nueva ventana +Name[es_CL]=Nueva ventana +Name[es_ES]=Nueva ventana +Name[es_MX]=Nueva ventana +Name[et]=Uus aken +Name[eu]=Leiho berria +Name[fa]=پنجره جدید‌ +Name[ff]=Henorde Hesere +Name[fi]=Uusi ikkuna +Name[fr]=Nouvelle fenêtre +Name[fy_NL]=Nij finster +Name[ga_IE]=Fuinneog Nua +Name[gd]=Uinneag ùr +Name[gl]=Nova xanela +Name[gn]=Ovetã pyahu +Name[gu_IN]=નવી વિન્ડો +Name[he]=חלון חדש +Name[hi_IN]=नया विंडो +Name[hr]=Novi prozor +Name[hsb]=Nowe wokno +Name[hu]=Új ablak +Name[hy_AM]=Նոր Պատուհան +Name[id]=Jendela Baru +Name[is]=Nýr gluggi +Name[it]=Nuova finestra +Name[ja]=新しいウィンドウ +Name[ja_JP-mac]=新規ウインドウ +Name[ka]=ახალი ფანჯარა +Name[kk]=Жаңа терезе +Name[km]=បង្អួច​​​ថ្មី +Name[kn]=ಹೊಸ ಕಿಟಕಿ +Name[ko]=새 창 +Name[kok]=नवें जनेल +Name[ks]=نئئ وِنڈو +Name[lij]=Neuvo barcon +Name[lo]=ຫນ້າຕ່າງໃຫມ່ +Name[lt]=Naujas langas +Name[ltg]=Jauns lūgs +Name[lv]=Jauns logs +Name[mai]=नव विंडो +Name[mk]=Нов прозорец +Name[ml]=പുതിയ ജാലകം +Name[mr]=नवीन पटल +Name[ms]=Tetingkap Baru +Name[my]=ဝင်းဒိုးအသစ် +Name[nb_NO]=Nytt vindu +Name[ne_NP]=नयाँ सञ्झ्याल +Name[nl]=Nieuw venster +Name[nn_NO]=Nytt vindauge +Name[or]=ନୂତନ ୱିଣ୍ଡୋ +Name[pa_IN]=ਨਵੀਂ ਵਿੰਡੋ +Name[pl]=Nowe okno +Name[pt_BR]=Nova janela +Name[pt_PT]=Nova janela +Name[rm]=Nova fanestra +Name[ro]=Fereastră nouă +Name[ru]=Новое окно +Name[sat]=नावा विंडो (N) +Name[si]=නව කවුළුවක් +Name[sk]=Nové okno +Name[sl]=Novo okno +Name[son]=Zanfun taaga +Name[sq]=Dritare e Re +Name[sr]=Нови прозор +Name[sv_SE]=Nytt fönster +Name[ta]=புதிய சாளரம் +Name[te]=కొత్త విండో +Name[th]=หน้าต่างใหม่ +Name[tr]=Yeni pencere +Name[tsz]=Eraatarakua jimpani +Name[uk]=Нове вікно +Name[ur]=نیا دریچہ +Name[uz]=Yangi oyna +Name[vi]=Cửa sổ mới +Name[wo]=Palanteer bu bees +Name[xh]=Ifestile entsha +Name[zh_CN]=新建窗口 +Name[zh_TW]=開新視窗 +Exec=firefox --new-window %u + +[Desktop Action new-private-window] +Name=Open a New Private Window +Name[ach]=Dirica manyen me mung +Name[af]=Nuwe privaatvenster +Name[an]=Nueva finestra privada +Name[ar]=نافذة خاصة جديدة +Name[as]=নতুন ব্যক্তিগত উইন্ডো +Name[ast]=Ventana privada nueva +Name[az]=Yeni Məxfi Pəncərə +Name[be]=Новае акно адасаблення +Name[bg]=Нов прозорец за поверително сърфиране +Name[bn_BD]=নতুন ব্যক্তিগত উইন্ডো +Name[bn_IN]=নতুন ব্যক্তিগত উইন্ডো +Name[br]=Prenestr merdeiñ prevez nevez +Name[brx]=गोदान प्राइभेट उइन्ड' +Name[bs]=Novi privatni prozor +Name[ca]=Finestra privada nova +Name[cak]=K'ak'a' ichinan tzuwäch +Name[cs]=Nové anonymní okno +Name[cy]=Ffenestr Breifat Newydd +Name[da]=Nyt privat vindue +Name[de]=Neues privates Fenster +Name[dsb]=Nowe priwatne wokno +Name[el]=Νέο παράθυρο ιδιωτικής περιήγησης +Name[en_GB]=New Private Window +Name[en_US]=New Private Window +Name[en_ZA]=New Private Window +Name[eo]=Nova privata fenestro +Name[es_AR]=Nueva ventana privada +Name[es_CL]=Nueva ventana privada +Name[es_ES]=Nueva ventana privada +Name[es_MX]=Nueva ventana privada +Name[et]=Uus privaatne aken +Name[eu]=Leiho pribatu berria +Name[fa]=پنجره ناشناس جدید +Name[ff]=Henorde Suturo Hesere +Name[fi]=Uusi yksityinen ikkuna +Name[fr]=Nouvelle fenêtre de navigation privée +Name[fy_NL]=Nij priveefinster +Name[ga_IE]=Fuinneog Nua Phríobháideach +Name[gd]=Uinneag phrìobhaideach ùr +Name[gl]=Nova xanela privada +Name[gn]=Ovetã ñemi pyahu +Name[gu_IN]=નવી ખાનગી વિન્ડો +Name[he]=חלון פרטי חדש +Name[hi_IN]=नयी निजी विंडो +Name[hr]=Novi privatni prozor +Name[hsb]=Nowe priwatne wokno +Name[hu]=Új privát ablak +Name[hy_AM]=Սկսել Գաղտնի դիտարկում +Name[id]=Jendela Mode Pribadi Baru +Name[is]=Nýr huliðsgluggi +Name[it]=Nuova finestra anonima +Name[ja]=新しいプライベートウィンドウ +Name[ja_JP-mac]=新規プライベートウインドウ +Name[ka]=ახალი პირადი ფანჯარა +Name[kk]=Жаңа жекелік терезе +Name[km]=បង្អួច​ឯកជន​ថ្មី +Name[kn]=ಹೊಸ ಖಾಸಗಿ ಕಿಟಕಿ +Name[ko]=새 사생활 보호 모드 +Name[kok]=नवो खाजगी विंडो +Name[ks]=نْو پرایوٹ وینڈو& +Name[lij]=Neuvo barcon privou +Name[lo]=ເປີດຫນ້າຕ່າງສວນຕົວຂື້ນມາໃຫມ່ +Name[lt]=Naujas privataus naršymo langas +Name[ltg]=Jauns privatais lūgs +Name[lv]=Jauns privātais logs +Name[mai]=नया निज विंडो (W) +Name[mk]=Нов приватен прозорец +Name[ml]=പുതിയ സ്വകാര്യ ജാലകം +Name[mr]=नवीन वैयक्तिक पटल +Name[ms]=Tetingkap Persendirian Baharu +Name[my]=New Private Window +Name[nb_NO]=Nytt privat vindu +Name[ne_NP]=नयाँ निजी सञ्झ्याल +Name[nl]=Nieuw privévenster +Name[nn_NO]=Nytt privat vindauge +Name[or]=ନୂତନ ବ୍ୟକ୍ତିଗତ ୱିଣ୍ଡୋ +Name[pa_IN]=ਨਵੀਂ ਪ੍ਰਾਈਵੇਟ ਵਿੰਡੋ +Name[pl]=Nowe okno prywatne +Name[pt_BR]=Nova janela privativa +Name[pt_PT]=Nova janela privada +Name[rm]=Nova fanestra privata +Name[ro]=Fereastră privată nouă +Name[ru]=Новое приватное окно +Name[sat]=नावा निजेराक् विंडो (W ) +Name[si]=නව පුද්ගලික කවුළුව (W) +Name[sk]=Nové okno v režime Súkromné prehliadanie +Name[sl]=Novo zasebno okno +Name[son]=Sutura zanfun taaga +Name[sq]=Dritare e Re Private +Name[sr]=Нови приватан прозор +Name[sv_SE]=Nytt privat fönster +Name[ta]=புதிய தனிப்பட்ட சாளரம் +Name[te]=కొత్త ఆంతరంగిక విండో +Name[th]=หน้าต่างส่วนตัวใหม่ +Name[tr]=Yeni gizli pencere +Name[tsz]=Juchiiti eraatarakua jimpani +Name[uk]=Приватне вікно +Name[ur]=نیا نجی دریچہ +Name[uz]=Yangi maxfiy oyna +Name[vi]=Cửa sổ riêng tư mới +Name[wo]=Panlanteeru biir bu bees +Name[xh]=Ifestile yangasese entsha +Name[zh_CN]=新建隐私浏览窗口 +Name[zh_TW]=新增隱私視窗 +Exec=firefox --private-window %u + +[Desktop Action profile-manager-window] +Name=Open the Profile Manager +Name[cs]=Správa profilů +Name[de]=Profilverwaltung öffnen +Name[fr]=Ouvrir le gestionnaire de profils +Exec=firefox --ProfileManager diff --git a/org.mozilla.firefox.search-provider.ini b/org.mozilla.firefox.search-provider.ini new file mode 100644 index 0000000..0211665 --- /dev/null +++ b/org.mozilla.firefox.search-provider.ini @@ -0,0 +1,5 @@ +[Shell Search Provider] +DesktopId=org.mozilla.firefox.desktop +BusName=org.mozilla.firefox.SearchProvider +ObjectPath=/org/mozilla/firefox/SearchProvider +Version=2 diff --git a/pgo.patch b/pgo.patch index c4a6bf4..c1ae97d 100644 --- a/pgo.patch +++ b/pgo.patch @@ -1,66 +1,50 @@ -diff -up firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo firefox-81.0.1/build/moz.configure/lto-pgo.configure ---- firefox-81.0.1/build/moz.configure/lto-pgo.configure.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/moz.configure/lto-pgo.configure 2020-10-07 09:16:44.071786956 +0200 -@@ -69,12 +69,14 @@ set_config('PGO_PROFILE_PATH', pgo_profi - @imports(_from='__builtin__', _import='min') - def pgo_flags(compiler, profdata, target_is_windows): - if compiler.type == 'gcc': -+ #profile_use = '-fprofile-use=$(topobjdir)' -+ profile_use = '-fprofile-use' +diff -up firefox-145.0/build/moz.configure/lto-pgo.configure.pgo firefox-145.0/build/moz.configure/lto-pgo.configure +--- firefox-145.0/build/moz.configure/lto-pgo.configure.pgo 2025-11-03 16:56:55.000000000 +0100 ++++ firefox-145.0/build/moz.configure/lto-pgo.configure 2025-11-05 13:59:53.477443914 +0100 +@@ -96,12 +96,16 @@ set_config("PGO_PROFILE_PATH", pgo_profi + + @depends( + "--enable-profile-use", ++ c_compiler, + pgo_profile_path, + llvm_profdata, + llvm_profdata_order, + build_environment, + ) +-def orderfile_path(profile_use, path, profdata, profdata_order, build_env): ++def orderfile_path(profile_use, compiler, path, profdata, profdata_order, build_env): ++ if compiler.type == "gcc": ++ return None ++ + if not profile_use: + return None + +@@ -145,7 +149,7 @@ def pgo_flags( return namespace( - gen_cflags=['-fprofile-generate'], - gen_ldflags=['-fprofile-generate'], -- use_cflags=['-fprofile-use', '-fprofile-correction', -+ use_cflags=[profile_use, '-fprofile-correction', - '-Wcoverage-mismatch'], -- use_ldflags=['-fprofile-use'], -+ use_ldflags=[profile_use], + gen_cflags=["-fprofile-generate"], + gen_ldflags=["-fprofile-generate"], +- use_cflags=["-fprofile-use", "-fprofile-correction", "-Wcoverage-mismatch"], ++ use_cflags=["-fprofile-use", "-fprofile-correction", "-Wno-coverage-mismatch"], + use_ldflags=["-fprofile-use"], ) - if compiler.type in ('clang-cl', 'clang'): -@@ -192,13 +194,13 @@ def lto(value, c_compiler, ld64_known_go - cflags.append("-flto") - ldflags.append("-flto") - else: -- cflags.append("-flto=thin") -- ldflags.append("-flto=thin") -+ cflags.append("-flto") -+ ldflags.append("-flto") - elif c_compiler.type == 'clang-cl': - if len(value) and value[0].lower() == 'full': - cflags.append("-flto") - else: -- cflags.append("-flto=thin") -+ cflags.append("-flto") - # With clang-cl, -flto can only be used with -c or -fuse-ld=lld. - # AC_TRY_LINKs during configure don't have -c, so pass -fuse-ld=lld. - cflags.append("-fuse-ld=lld"); -@@ -232,7 +234,7 @@ def lto(value, c_compiler, ld64_known_go - if len(value) and value[0].lower() == 'full': - cflags.append("-flto") - else: -- cflags.append("-flto=thin") -+ cflags.append("-flto") - cflags.append("-flifetime-dse=1") - - ldflags.append("-flto=%s" % num_cores) -diff -up firefox-81.0.1/build/pgo/profileserver.py.pgo firefox-81.0.1/build/pgo/profileserver.py ---- firefox-81.0.1/build/pgo/profileserver.py.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/pgo/profileserver.py 2020-10-07 09:16:44.071786956 +0200 -@@ -11,7 +11,7 @@ import glob - import subprocess +diff -up firefox-145.0/build/pgo/profileserver.py.pgo firefox-145.0/build/pgo/profileserver.py +--- firefox-145.0/build/pgo/profileserver.py.pgo 2025-11-03 16:56:55.000000000 +0100 ++++ firefox-145.0/build/pgo/profileserver.py 2025-11-05 13:59:53.477602066 +0100 +@@ -10,7 +10,7 @@ import subprocess + import sys import mozcrash --from mozbuild.base import MozbuildObject, BinaryNotFoundException -+from mozbuild.base import MozbuildObject, BinaryNotFoundException, BuildEnvironmentNotFoundException - from mozfile import TemporaryDirectory +-from mozbuild.base import BinaryNotFoundException, MozbuildObject ++from mozbuild.base import BinaryNotFoundException, MozbuildObject, BuildEnvironmentNotFoundException + from mozfile import TemporaryDirectory, json from mozhttpd import MozHttpd from mozprofile import FirefoxProfile, Preferences -@@ -84,9 +84,22 @@ if __name__ == '__main__': - port=PORT, - options='primary,privileged') +@@ -96,9 +96,22 @@ if __name__ == "__main__": + locations = ServerLocations() + locations.add_host(host="127.0.0.1", port=PORT, options="primary,privileged") -- old_profraw_files = glob.glob('*.profraw') +- old_profraw_files = glob.glob("*.profraw") - for f in old_profraw_files: - os.remove(f) + using_gcc = False @@ -82,64 +66,55 @@ diff -up firefox-81.0.1/build/pgo/profileserver.py.pgo firefox-81.0.1/build/pgo/ with TemporaryDirectory() as profilePath: # TODO: refactor this into mozprofile -@@ -191,6 +204,11 @@ if __name__ == '__main__': - print("Firefox exited successfully, but produced a crashreport") - sys.exit(1) +diff -up firefox-145.0/gfx/2d/moz.build.pgo firefox-145.0/gfx/2d/moz.build +--- firefox-145.0/gfx/2d/moz.build.pgo 2025-11-03 16:56:57.000000000 +0100 ++++ firefox-145.0/gfx/2d/moz.build 2025-11-05 14:21:20.485610837 +0100 +@@ -137,11 +137,11 @@ if CONFIG["INTEL_ARCHITECTURE"]: + DEFINES["USE_SSE2"] = True + # The file uses SSE2 intrinsics, so it needs special compile flags on some + # compilers. +- SOURCES["ConvolutionFilterAVX2.cpp"].flags += ["-mavx2"] ++ SOURCES["ConvolutionFilterAVX2.cpp"].flags += ["-mavx2", "-fno-lto"] + SOURCES["ConvolutionFilterSSE2.cpp"].flags += CONFIG["SSE2_FLAGS"] + SOURCES["FilterProcessingSSE2.cpp"].flags += CONFIG["SSE2_FLAGS"] + SOURCES["ImageScalingSSE2.cpp"].flags += CONFIG["SSE2_FLAGS"] +- SOURCES["SwizzleAVX2.cpp"].flags += ["-mavx2"] ++ SOURCES["SwizzleAVX2.cpp"].flags += ["-mavx2", "-fno-lto"] + SOURCES["SwizzleSSE2.cpp"].flags += CONFIG["SSE2_FLAGS"] + SOURCES["SwizzleSSSE3.cpp"].flags += CONFIG["SSSE3_FLAGS"] -+ -+ print('Copying profile data....') -+ os.system('pwd'); -+ os.system('tar cf profdata.tar.gz `find . -name "*.gcda"`; cd ..; tar xf instrumented/profdata.tar.gz;'); -+ - llvm_profdata = env.get('LLVM_PROFDATA') - if llvm_profdata: - profraw_files = glob.glob('*.profraw') -diff -up firefox-81.0.1/build/unix/mozconfig.unix.pgo firefox-81.0.1/build/unix/mozconfig.unix ---- firefox-81.0.1/build/unix/mozconfig.unix.pgo 2020-09-30 19:41:10.000000000 +0200 -+++ firefox-81.0.1/build/unix/mozconfig.unix 2020-10-07 09:16:44.071786956 +0200 -@@ -6,6 +6,15 @@ if [ -n "$FORCE_GCC" ]; then - CC="$MOZ_FETCHES_DIR/gcc/bin/gcc" - CXX="$MOZ_FETCHES_DIR/gcc/bin/g++" - -+ if [ -n "$MOZ_PGO" ]; then -+ if [ -z "$USE_ARTIFACT" ]; then -+ ac_add_options --enable-lto -+ fi -+ export AR="$topsrcdir/gcc/bin/gcc-ar" -+ export NM="$topsrcdir/gcc/bin/gcc-nm" -+ export RANLIB="$topsrcdir/gcc/bin/gcc-ranlib" -+ fi -+ - # We want to make sure we use binutils and other binaries in the tooltool - # package. - mk_add_options "export PATH=$MOZ_FETCHES_DIR/gcc/bin:$PATH" -diff -up firefox-81.0.1/extensions/spellcheck/src/moz.build.pgo firefox-81.0.1/extensions/spellcheck/src/moz.build ---- firefox-81.0.1/extensions/spellcheck/src/moz.build.pgo 2020-09-30 19:41:17.000000000 +0200 -+++ firefox-81.0.1/extensions/spellcheck/src/moz.build 2020-10-07 09:16:44.071786956 +0200 -@@ -31,3 +31,5 @@ EXPORTS.mozilla += [ - - if CONFIG['CC_TYPE'] in ('clang', 'gcc'): - CXXFLAGS += ['-Wno-error=shadow'] -+ -+CXXFLAGS += ['-fno-devirtualize'] -\ No newline at end of file -diff -up firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py.pgo firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py ---- firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py.pgo 2020-09-30 19:41:46.000000000 +0200 -+++ firefox-81.0.1/python/mozbuild/mozbuild/build_commands.py 2020-10-07 09:16:44.071786956 +0200 -@@ -108,7 +108,8 @@ class Build(MachCommandBase): - return status - - pgo_env = os.environ.copy() -- pgo_env['LLVM_PROFDATA'] = instr.config_environment.substs.get('LLVM_PROFDATA') -+ if instr.config_environment.substs.get('CC_TYPE') != 'gcc': -+ pgo_env['LLVM_PROFDATA'] = instr.config_environment.substs.get('LLVM_PROFDATA') - pgo_env['JARLOG_FILE'] = mozpath.join(orig_topobjdir, 'jarlog/en-US.log') - pgo_cmd = [ - instr.virtualenv_manager.python_path, -diff -up firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp.pgo firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp ---- firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp.pgo 2020-10-07 09:22:26.698243673 +0200 -+++ firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp 2020-10-07 09:22:43.026312999 +0200 -@@ -418,6 +418,11 @@ void nsTerminator::StartWatchdog() { +diff -up firefox-145.0/gfx/skia/generate_mozbuild.py.pgo firefox-145.0/gfx/skia/generate_mozbuild.py +--- firefox-145.0/gfx/skia/generate_mozbuild.py.pgo 2025-11-03 16:56:57.000000000 +0100 ++++ firefox-145.0/gfx/skia/generate_mozbuild.py 2025-11-05 13:59:53.477947055 +0100 +@@ -50,8 +50,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind + if CONFIG['INTEL_ARCHITECTURE']: + SOURCES['skia/modules/skcms/skcms.cc'].flags += ['-DSKCMS_DISABLE_SKX'] + skia_ssse3_flags = ['-Dskvx=skvx_ssse3', '-mssse3'] +- skia_avx_flags = ['-Dskvx=skvx_avx', '-mavx'] +- skia_hsw_flags = ['-Dskvx=skvx_hsw', '-mavx2', '-mf16c', '-mfma'] ++ skia_avx_flags = ['-Dskvx=skvx_avx', '-mavx', '-fno-lto'] ++ skia_hsw_flags = ['-Dskvx=skvx_hsw', '-mavx2', '-mf16c', '-mfma', '-fno-lto'] + SOURCES['skia/src/core/SkBitmapProcState_opts_ssse3.cpp'].flags += skia_ssse3_flags + SOURCES['skia/src/core/SkBlitMask_opts_ssse3.cpp'].flags += skia_ssse3_flags + SOURCES['skia/src/core/SkSwizzler_opts_ssse3.cpp'].flags += ['-Dskvx=skvx_ssse3'] +diff -up firefox-145.0/gfx/skia/moz.build.pgo firefox-145.0/gfx/skia/moz.build +--- firefox-145.0/gfx/skia/moz.build.pgo 2025-11-03 16:56:57.000000000 +0100 ++++ firefox-145.0/gfx/skia/moz.build 2025-11-05 13:59:53.478077484 +0100 +@@ -597,8 +597,8 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'wind + if CONFIG['INTEL_ARCHITECTURE']: + SOURCES['skia/modules/skcms/skcms.cc'].flags += ['-DSKCMS_DISABLE_SKX'] + skia_ssse3_flags = ['-Dskvx=skvx_ssse3', '-mssse3'] +- skia_avx_flags = ['-Dskvx=skvx_avx', '-mavx'] +- skia_hsw_flags = ['-Dskvx=skvx_hsw', '-mavx2', '-mf16c', '-mfma'] ++ skia_avx_flags = ['-Dskvx=skvx_avx', '-mavx', '-fno-lto'] ++ skia_hsw_flags = ['-Dskvx=skvx_hsw', '-mavx2', '-mf16c', '-mfma', '-fno-lto'] + SOURCES['skia/src/core/SkBitmapProcState_opts_ssse3.cpp'].flags += skia_ssse3_flags + SOURCES['skia/src/core/SkBlitMask_opts_ssse3.cpp'].flags += skia_ssse3_flags + SOURCES['skia/src/core/SkSwizzler_opts_ssse3.cpp'].flags += ['-Dskvx=skvx_ssse3'] +diff -up firefox-145.0/toolkit/components/terminator/nsTerminator.cpp.pgo firefox-145.0/toolkit/components/terminator/nsTerminator.cpp +--- firefox-145.0/toolkit/components/terminator/nsTerminator.cpp.pgo 2025-11-03 16:57:15.000000000 +0100 ++++ firefox-145.0/toolkit/components/terminator/nsTerminator.cpp 2025-11-05 13:59:53.478238011 +0100 +@@ -330,6 +330,11 @@ void nsTerminator::StartWatchdog() { } #endif @@ -149,5 +124,5 @@ diff -up firefox-81.0.1/toolkit/components/terminator/nsTerminator.cpp.pgo firef + crashAfterMS = INT32_MAX; + UniquePtr options(new Options()); - const PRIntervalTime ticksDuration = PR_MillisecondsToInterval(1000); - options->crashAfterTicks = crashAfterMS / ticksDuration; + // crashAfterTicks is guaranteed to be > 0 as + // crashAfterMS >= ADDITIONAL_WAIT_BEFORE_CRASH_MS >> HEARTBEAT_INTERVAL_MS diff --git a/print-error-reftest b/print-error-reftest new file mode 100755 index 0000000..7a58c1c --- /dev/null +++ b/print-error-reftest @@ -0,0 +1,13 @@ +#!/usr/bin/bash +# Print reftest failures and compose them to html + +TEST_DIR="$1" +TEST_FLAVOUR="$2" +OUTPUT_FILE="failures-reftest$TEST_FLAVOUR.html" + +grep --text -e "REFTEST TEST-UNEXPECTED-PASS" -e "REFTEST TEST-UNEXPECTED-FAIL" -e "IMAGE 1 (TEST):" -e "IMAGE 2 (REFERENCE):" $TEST_DIR/reftest$TEST_FLAVOUR 2>&1 > $OUTPUT_FILE +sed -i '/REFTEST IMAGE 1/a ">' $OUTPUT_FILE +sed -i '/REFTEST IMAGE 2/a ">

' $OUTPUT_FILE +sed -i '/REFTEST TEST/a
' $OUTPUT_FILE +sed -i -e 's/^REFTEST IMAGE 1 (TEST): /&1 > failures-mochitest$TEST_FLAVOUR.txt +grep --text -e " FAIL " -e " TIMEOUT " $TEST_DIR/xpcshell$TEST_FLAVOUR 2>&1 > failures-xpcshell$TEST_FLAVOUR.txt +grep --text -e "REFTEST TEST-UNEXPECTED-PASS" -e "REFTEST TEST-UNEXPECTED-FAIL" $TEST_DIR/reftest$TEST_FLAVOUR 2>&1 > failures-reftest$TEST_FLAVOUR.txt diff --git a/print_failures b/print_failures new file mode 100755 index 0000000..bc92b0c --- /dev/null +++ b/print_failures @@ -0,0 +1,9 @@ +#!/usr/bin/bash +# Analyze and print test failures + +export TEST_DIR="test_results" + +#./print-errors $TEST_DIR "" +./print-errors $TEST_DIR "-wr" +#./print-error-reftest $TEST_DIR "" +./print-error-reftest $TEST_DIR "-wr" diff --git a/print_results b/print_results new file mode 100755 index 0000000..d0b1307 --- /dev/null +++ b/print_results @@ -0,0 +1,10 @@ +#!/usr/bin/bash +# Analyze and print general test results + +export TEST_DIR="test_results" + +echo "Test results" +#echo "Basic compositor" +#./psummary $TEST_DIR "" +echo "WebRender" +./psummary $TEST_DIR "-wr" diff --git a/psummary b/psummary new file mode 100755 index 0000000..f64fc8f --- /dev/null +++ b/psummary @@ -0,0 +1,23 @@ +#!/usr/bin/bash +# Analyze and print specialized (basic/webrender) test results + +TEST_DIR=$1 +TEST_FLAVOUR=$2 + +MPASS=`grep "TEST_END: Test OK" $TEST_DIR/mochitest$TEST_FLAVOUR | wc -l` +MERR=`grep "TEST_END: Test ERROR" $TEST_DIR/mochitest$TEST_FLAVOUR | wc -l` +MUNEX=`grep "TEST-UNEXPECTED-FAIL" $TEST_DIR/mochitest$TEST_FLAVOUR | wc -l` +echo "Mochitest PASSED: $MPASS FAILED: $MERR UNEXPECTED-FAILURES: $MUNEX" + +XPCPASS=`grep --text "Expected results:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 3` +XPCFAIL=`grep --text "Unexpected results:" $TEST_DIR/xpcshell$TEST_FLAVOUR | cut -d ' ' -f 3` +echo "XPCShell: PASSED: $XPCPASS FAILED: $XPCFAIL" + +CRPASS=`grep "REFTEST INFO | Successful:" $TEST_DIR/crashtest$TEST_FLAVOUR | cut -d ' ' -f 5` +CRFAIL=`grep "^REFTEST INFO | Unexpected:" $TEST_DIR/crashtest$TEST_FLAVOUR | cut -d ' ' -f 5` +echo "Crashtest: PASSED: $CRPASS FAILED: $CRFAIL" + +RFPASS=`grep --text "REFTEST INFO | Successful:" $TEST_DIR/reftest$TEST_FLAVOUR | cut -d ' ' -f 5` +RFUN=`grep --text "^REFTEST INFO | Unexpected:" $TEST_DIR/reftest$TEST_FLAVOUR | cut -d ' ' -f 5` +RFKNOWN=`grep --text "REFTEST INFO | Known problems:" $TEST_DIR/reftest$TEST_FLAVOUR | cut -d ' ' -f 6` +echo "Reftest: PASSED: $RFPASS FAILED: $RFUN Known issues: $RFKNOWN" diff --git a/pw1.patch b/pw1.patch deleted file mode 100644 index 1f88545..0000000 --- a/pw1.patch +++ /dev/null @@ -1,78 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604562416 0 -# Node ID 1c126b520042591194e88618ae11a6adc1da9a08 -# Parent 6e2e4f0e4a95b0cae777dda9369a9e9bf49a51b1 -Bug 1672987 Use PipeWire when Wayland display is actually used, r=dminor - -Right now PipeWire is enabled when Wayland session is used regardless of an active Gtk backend (X11/Wayland). -Let's use PipeWire only when Wayland Gtk backend is used and disable it for X11 one to avoid possible regressions. - -Differential Revision: https://phabricator.services.mozilla.com/D94588 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -@@ -8,16 +8,21 @@ - * be found in the AUTHORS file in the root of the source tree. - */ - - #include "modules/desktop_capture/desktop_capturer.h" - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer_differ_wrapper.h" - -+#if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) -+#include -+#include -+#endif -+ - namespace webrtc { - - DesktopCapturer::~DesktopCapturer() = default; - - void DesktopCapturer::SetSharedMemoryFactory( - std::unique_ptr shared_memory_factory) {} - - void DesktopCapturer::SetExcludedWindow(WindowId window) {} -@@ -67,21 +72,37 @@ std::unique_ptr Desktop - if (capturer && options.detect_updated_region()) { - capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer))); - } - - return capturer; - } - - #if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) --bool DesktopCapturer::IsRunningUnderWayland() { -+// Return true if Firefox is actually running with Wayland backend. -+static bool IsWaylandDisplayUsed() { -+ const auto display = gdk_display_get_default(); -+ if (display == nullptr) { -+ // We're running in headless mode. -+ return false; -+ } -+ return !GDK_IS_X11_DISPLAY(display); -+} -+ -+// Return true if Firefox is actually running on Wayland enabled session. -+// It means some screensharing capabilities may be limited. -+static bool IsWaylandSessionUsed() { - const char* xdg_session_type = getenv("XDG_SESSION_TYPE"); - if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0) - return false; - - if (!(getenv("WAYLAND_DISPLAY"))) - return false; - - return true; - } -+ -+bool DesktopCapturer::IsRunningUnderWayland() { -+ return IsWaylandSessionUsed() ? IsWaylandDisplayUsed() : false; -+} - #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - - } // namespace webrtc - diff --git a/pw2.patch b/pw2.patch deleted file mode 100644 index 9390460..0000000 --- a/pw2.patch +++ /dev/null @@ -1,901 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604560111 0 -# Node ID 998e6d0b24e4a560e5664aaef87307e9c069ad87 -# Parent 1c126b520042591194e88618ae11a6adc1da9a08 -Bug 1672947 Update PipeWire WebRTC code to PipeWire 0.3, r=ng - -Differential Revision: https://phabricator.services.mozilla.com/D94589 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -@@ -10,18 +10,20 @@ - - #include "modules/desktop_capture/linux/base_capturer_pipewire.h" - - #include - #include - - #include - #include --#include --#include -+ -+#include -+#include -+#include - - #include - #include - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer.h" - #include "rtc_base/checks.h" - #include "rtc_base/logging.h" -@@ -32,180 +34,166 @@ const char kDesktopBusName[] = "org.free - const char kDesktopObjectPath[] = "/org/freedesktop/portal/desktop"; - const char kDesktopRequestObjectPath[] = - "/org/freedesktop/portal/desktop/request"; - const char kSessionInterfaceName[] = "org.freedesktop.portal.Session"; - const char kRequestInterfaceName[] = "org.freedesktop.portal.Request"; - const char kScreenCastInterfaceName[] = "org.freedesktop.portal.ScreenCast"; - - // static --void BaseCapturerPipeWire::OnStateChanged(void* data, -- pw_remote_state old_state, -- pw_remote_state state, -- const char* error_message) { -- BaseCapturerPipeWire* that = static_cast(data); -- RTC_DCHECK(that); -+struct dma_buf_sync { -+ uint64_t flags; -+}; -+#define DMA_BUF_SYNC_READ (1 << 0) -+#define DMA_BUF_SYNC_START (0 << 2) -+#define DMA_BUF_SYNC_END (1 << 2) -+#define DMA_BUF_BASE 'b' -+#define DMA_BUF_IOCTL_SYNC _IOW(DMA_BUF_BASE, 0, struct dma_buf_sync) - -- switch (state) { -- case PW_REMOTE_STATE_ERROR: -- RTC_LOG(LS_ERROR) << "PipeWire remote state error: " << error_message; -+static void SyncDmaBuf(int fd, uint64_t start_or_end) { -+ struct dma_buf_sync sync = { 0 }; -+ -+ sync.flags = start_or_end | DMA_BUF_SYNC_READ; -+ -+ while(true) { -+ int ret; -+ ret = ioctl (fd, DMA_BUF_IOCTL_SYNC, &sync); -+ if (ret == -1 && errno == EINTR) { -+ continue; -+ } else if (ret == -1) { -+ RTC_LOG(LS_ERROR) << "Failed to synchronize DMA buffer: " << g_strerror(errno); - break; -- case PW_REMOTE_STATE_CONNECTED: -- RTC_LOG(LS_INFO) << "PipeWire remote state: connected."; -- that->CreateReceivingStream(); -+ } else { - break; -- case PW_REMOTE_STATE_CONNECTING: -- RTC_LOG(LS_INFO) << "PipeWire remote state: connecting."; -- break; -- case PW_REMOTE_STATE_UNCONNECTED: -- RTC_LOG(LS_INFO) << "PipeWire remote state: unconnected."; -- break; -+ } - } - } - - // static -+void BaseCapturerPipeWire::OnCoreError(void *data, -+ uint32_t id, -+ int seq, -+ int res, -+ const char *message) { -+ RTC_LOG(LS_ERROR) << "core error: " << message; -+} -+ -+// static - void BaseCapturerPipeWire::OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - - switch (state) { - case PW_STREAM_STATE_ERROR: - RTC_LOG(LS_ERROR) << "PipeWire stream state error: " << error_message; - break; -- case PW_STREAM_STATE_CONFIGURE: -- pw_stream_set_active(that->pw_stream_, true); -- break; -+ case PW_STREAM_STATE_PAUSED: -+ case PW_STREAM_STATE_STREAMING: - case PW_STREAM_STATE_UNCONNECTED: - case PW_STREAM_STATE_CONNECTING: -- case PW_STREAM_STATE_READY: -- case PW_STREAM_STATE_PAUSED: -- case PW_STREAM_STATE_STREAMING: - break; - } - } - - // static --void BaseCapturerPipeWire::OnStreamFormatChanged(void* data, -- const struct spa_pod* format) { -+void BaseCapturerPipeWire::OnStreamParamChanged(void *data, uint32_t id, -+ const struct spa_pod *format) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - -- RTC_LOG(LS_INFO) << "PipeWire stream format changed."; -+ RTC_LOG(LS_INFO) << "PipeWire stream param changed."; - -- if (!format) { -- pw_stream_finish_format(that->pw_stream_, /*res=*/0, /*params=*/nullptr, -- /*n_params=*/0); -+ if (!format || id != SPA_PARAM_Format) { - return; - } - -- that->spa_video_format_ = new spa_video_info_raw(); -- spa_format_video_raw_parse(format, that->spa_video_format_, -- &that->pw_type_->format_video); -+ spa_format_video_raw_parse(format, &that->spa_video_format_); - -- auto width = that->spa_video_format_->size.width; -- auto height = that->spa_video_format_->size.height; -+ auto width = that->spa_video_format_.size.width; -+ auto height = that->spa_video_format_.size.height; - auto stride = SPA_ROUND_UP_N(width * kBytesPerPixel, 4); - auto size = height * stride; - -+ that->desktop_size_ = DesktopSize(width, height); -+ - uint8_t buffer[1024] = {}; - auto builder = spa_pod_builder{buffer, sizeof(buffer)}; - - // Setup buffers and meta header for new format. -- const struct spa_pod* params[2]; -- params[0] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate buffer requirements -- that->pw_core_type_->param.idBuffers, -- that->pw_core_type_->param_buffers.Buffers, -- // Size: specified as integer (i) and set to specified size -- ":", that->pw_core_type_->param_buffers.size, "i", size, -- // Stride: specified as integer (i) and set to specified stride -- ":", that->pw_core_type_->param_buffers.stride, "i", stride, -- // Buffers: specifies how many buffers we want to deal with, set as -- // integer (i) where preferred number is 8, then allowed number is defined -- // as range (r) from min and max values and it is undecided (u) to allow -- // negotiation -- ":", that->pw_core_type_->param_buffers.buffers, "iru", 8, -- SPA_POD_PROP_MIN_MAX(1, 32), -- // Align: memory alignment of the buffer, set as integer (i) to specified -- // value -- ":", that->pw_core_type_->param_buffers.align, "i", 16)); -- params[1] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate supported metadata -- that->pw_core_type_->param.idMeta, that->pw_core_type_->param_meta.Meta, -- // Type: specified as id or enum (I) -- ":", that->pw_core_type_->param_meta.type, "I", -- that->pw_core_type_->meta.Header, -- // Size: size of the metadata, specified as integer (i) -- ":", that->pw_core_type_->param_meta.size, "i", -- sizeof(struct spa_meta_header))); -- -- pw_stream_finish_format(that->pw_stream_, /*res=*/0, params, /*n_params=*/2); -+ const struct spa_pod* params[3]; -+ params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, -+ SPA_PARAM_BUFFERS_size, SPA_POD_Int(size), -+ SPA_PARAM_BUFFERS_stride, SPA_POD_Int(stride), -+ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(8, 1, 32))); -+ params[1] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, -+ SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), -+ SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header)))); -+ params[2] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, -+ SPA_PARAM_META_type, SPA_POD_Id (SPA_META_VideoCrop), -+ SPA_PARAM_META_size, SPA_POD_Int (sizeof(struct spa_meta_region)))); -+ pw_stream_update_params(that->pw_stream_, params, 3); - } - - // static - void BaseCapturerPipeWire::OnStreamProcess(void* data) { - BaseCapturerPipeWire* that = static_cast(data); - RTC_DCHECK(that); - -- pw_buffer* buf = nullptr; -+ struct pw_buffer *next_buffer; -+ struct pw_buffer *buffer = nullptr; - -- if (!(buf = pw_stream_dequeue_buffer(that->pw_stream_))) { -+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); -+ while (next_buffer) { -+ buffer = next_buffer; -+ next_buffer = pw_stream_dequeue_buffer(that->pw_stream_); -+ -+ if (next_buffer) { -+ pw_stream_queue_buffer (that->pw_stream_, buffer); -+ } -+ } -+ -+ if (!buffer) { - return; - } - -- that->HandleBuffer(buf); -+ that->HandleBuffer(buffer); - -- pw_stream_queue_buffer(that->pw_stream_, buf); -+ pw_stream_queue_buffer(that->pw_stream_, buffer); - } - - BaseCapturerPipeWire::BaseCapturerPipeWire(CaptureSourceType source_type) - : capture_source_type_(source_type) {} - - BaseCapturerPipeWire::~BaseCapturerPipeWire() { - if (pw_main_loop_) { - pw_thread_loop_stop(pw_main_loop_); - } - -- if (pw_type_) { -- delete pw_type_; -- } -- -- if (spa_video_format_) { -- delete spa_video_format_; -- } -- - if (pw_stream_) { - pw_stream_destroy(pw_stream_); - } - -- if (pw_remote_) { -- pw_remote_destroy(pw_remote_); -+ if (pw_core_) { -+ pw_core_disconnect(pw_core_); - } - -- if (pw_core_) { -- pw_core_destroy(pw_core_); -+ if (pw_context_) { -+ pw_context_destroy(pw_context_); - } - - if (pw_main_loop_) { - pw_thread_loop_destroy(pw_main_loop_); - } - -- if (pw_loop_) { -- pw_loop_destroy(pw_loop_); -- } -- -- if (current_frame_) { -- free(current_frame_); -- } -- - if (start_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, start_request_signal_id_); - } - if (sources_request_signal_id_) { - g_dbus_connection_signal_unsubscribe(connection_, - sources_request_signal_id_); - } - if (session_request_signal_id_) { -@@ -245,143 +233,210 @@ void BaseCapturerPipeWire::InitPortal() - kDesktopBusName, kDesktopObjectPath, kScreenCastInterfaceName, - /*cancellable=*/nullptr, - reinterpret_cast(OnProxyRequested), this); - } - - void BaseCapturerPipeWire::InitPipeWire() { - pw_init(/*argc=*/nullptr, /*argc=*/nullptr); - -- pw_loop_ = pw_loop_new(/*properties=*/nullptr); -- pw_main_loop_ = pw_thread_loop_new(pw_loop_, "pipewire-main-loop"); -+ pw_main_loop_ = pw_thread_loop_new("pipewire-main-loop", nullptr); -+ pw_context_ = pw_context_new(pw_thread_loop_get_loop(pw_main_loop_), nullptr, 0); -+ if (!pw_context_) { -+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire context"; -+ return; -+ } - -- pw_core_ = pw_core_new(pw_loop_, /*properties=*/nullptr); -- pw_core_type_ = pw_core_get_type(pw_core_); -- pw_remote_ = pw_remote_new(pw_core_, nullptr, /*user_data_size=*/0); -- -- InitPipeWireTypes(); -+ pw_core_ = pw_context_connect(pw_context_, nullptr, 0); -+ if (!pw_core_) { -+ RTC_LOG(LS_ERROR) << "Failed to connect PipeWire context"; -+ return; -+ } - - // Initialize event handlers, remote end and stream-related. -- pw_remote_events_.version = PW_VERSION_REMOTE_EVENTS; -- pw_remote_events_.state_changed = &OnStateChanged; -+ pw_core_events_.version = PW_VERSION_CORE_EVENTS; -+ pw_core_events_.error = &OnCoreError; - - pw_stream_events_.version = PW_VERSION_STREAM_EVENTS; - pw_stream_events_.state_changed = &OnStreamStateChanged; -- pw_stream_events_.format_changed = &OnStreamFormatChanged; -+ pw_stream_events_.param_changed = &OnStreamParamChanged; - pw_stream_events_.process = &OnStreamProcess; - -- pw_remote_add_listener(pw_remote_, &spa_remote_listener_, &pw_remote_events_, -- this); -- pw_remote_connect_fd(pw_remote_, pw_fd_); -+ pw_core_add_listener(pw_core_, &spa_core_listener_, &pw_core_events_, this); -+ -+ pw_stream_ = CreateReceivingStream(); -+ if (!pw_stream_) { -+ RTC_LOG(LS_ERROR) << "Failed to create PipeWire stream"; -+ return; -+ } - - if (pw_thread_loop_start(pw_main_loop_) < 0) { - RTC_LOG(LS_ERROR) << "Failed to start main PipeWire loop"; - portal_init_failed_ = true; - } - } - --void BaseCapturerPipeWire::InitPipeWireTypes() { -- spa_type_map* map = pw_core_type_->map; -- pw_type_ = new PipeWireType(); -- -- spa_type_media_type_map(map, &pw_type_->media_type); -- spa_type_media_subtype_map(map, &pw_type_->media_subtype); -- spa_type_format_video_map(map, &pw_type_->format_video); -- spa_type_video_format_map(map, &pw_type_->video_format); --} -+pw_stream* BaseCapturerPipeWire::CreateReceivingStream() { -+ spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; -+ spa_rectangle pwMaxScreenBounds = spa_rectangle{UINT32_MAX, UINT32_MAX}; - --void BaseCapturerPipeWire::CreateReceivingStream() { -- spa_rectangle pwMinScreenBounds = spa_rectangle{1, 1}; -- spa_rectangle pwScreenBounds = -- spa_rectangle{static_cast(desktop_size_.width()), -- static_cast(desktop_size_.height())}; -+ auto stream = pw_stream_new(pw_core_, "webrtc-pipewire-stream", nullptr); - -- spa_fraction pwFrameRateMin = spa_fraction{0, 1}; -- spa_fraction pwFrameRateMax = spa_fraction{60, 1}; -- -- pw_properties* reuseProps = pw_properties_new("pipewire.client.reuse", "1", -- /*end of varargs*/ nullptr); -- pw_stream_ = pw_stream_new(pw_remote_, "webrtc-consume-stream", reuseProps); -+ if (!stream) { -+ RTC_LOG(LS_ERROR) << "Could not create receiving stream."; -+ return nullptr; -+ } - - uint8_t buffer[1024] = {}; -- const spa_pod* params[1]; -- spa_pod_builder builder = spa_pod_builder{buffer, sizeof(buffer)}; -- params[0] = reinterpret_cast(spa_pod_builder_object( -- &builder, -- // id to enumerate formats -- pw_core_type_->param.idEnumFormat, pw_core_type_->spa_format, "I", -- pw_type_->media_type.video, "I", pw_type_->media_subtype.raw, -- // Video format: specified as id or enum (I), preferred format is BGRx, -- // then allowed formats are enumerated (e) and the format is undecided (u) -- // to allow negotiation -- ":", pw_type_->format_video.format, "Ieu", pw_type_->video_format.BGRx, -- SPA_POD_PROP_ENUM(2, pw_type_->video_format.RGBx, -- pw_type_->video_format.BGRx), -- // Video size: specified as rectangle (R), preferred size is specified as -- // first parameter, then allowed size is defined as range (r) from min and -- // max values and the format is undecided (u) to allow negotiation -- ":", pw_type_->format_video.size, "Rru", &pwScreenBounds, 2, -- &pwMinScreenBounds, &pwScreenBounds, -- // Frame rate: specified as fraction (F) and set to minimum frame rate -- // value -- ":", pw_type_->format_video.framerate, "F", &pwFrameRateMin, -- // Max frame rate: specified as fraction (F), preferred frame rate is set -- // to maximum value, then allowed frame rate is defined as range (r) from -- // min and max values and it is undecided (u) to allow negotiation -- ":", pw_type_->format_video.max_framerate, "Fru", &pwFrameRateMax, 2, -- &pwFrameRateMin, &pwFrameRateMax)); -+ const spa_pod* params[2]; -+ spa_pod_builder builder = SPA_POD_BUILDER_INIT(buffer, sizeof (buffer)); - -- pw_stream_add_listener(pw_stream_, &spa_stream_listener_, &pw_stream_events_, -- this); -- pw_stream_flags flags = static_cast( -- PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | -- PW_STREAM_FLAG_MAP_BUFFERS); -- if (pw_stream_connect(pw_stream_, PW_DIRECTION_INPUT, /*port_path=*/nullptr, -- flags, params, -- /*n_params=*/1) != 0) { -+ params[0] = reinterpret_cast(spa_pod_builder_add_object(&builder, -+ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_VIDEO_format, SPA_POD_CHOICE_ENUM_Id(5, SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_RGBx, SPA_VIDEO_FORMAT_RGBA, -+ SPA_VIDEO_FORMAT_BGRx, SPA_VIDEO_FORMAT_BGRA), -+ SPA_FORMAT_VIDEO_size, SPA_POD_CHOICE_RANGE_Rectangle(&pwMinScreenBounds, -+ &pwMinScreenBounds, -+ &pwMaxScreenBounds), -+ 0)); -+ pw_stream_add_listener(stream, &spa_stream_listener_, &pw_stream_events_, this); -+ -+ if (pw_stream_connect(stream, PW_DIRECTION_INPUT, pw_stream_node_id_, -+ PW_STREAM_FLAG_AUTOCONNECT, params, 1) != 0) { - RTC_LOG(LS_ERROR) << "Could not connect receiving stream."; - portal_init_failed_ = true; -- return; -+ } -+ -+ return stream; -+} -+ -+static void SpaBufferUnmap(unsigned char *map, int map_size, bool IsDMABuf, int fd) { -+ if (map) { -+ if (IsDMABuf) { -+ SyncDmaBuf(fd, DMA_BUF_SYNC_END); -+ } -+ munmap(map, map_size); - } - } - - void BaseCapturerPipeWire::HandleBuffer(pw_buffer* buffer) { - spa_buffer* spaBuffer = buffer->buffer; -- void* src = nullptr; -+ uint8_t *map = nullptr; -+ uint8_t* src = nullptr; - -- if (!(src = spaBuffer->datas[0].data)) { -+ if (spaBuffer->datas[0].chunk->size == 0) { -+ RTC_LOG(LS_ERROR) << "Failed to get video stream: Zero size."; - return; - } - -- uint32_t maxSize = spaBuffer->datas[0].maxsize; -- int32_t srcStride = spaBuffer->datas[0].chunk->stride; -- if (srcStride != (desktop_size_.width() * kBytesPerPixel)) { -- RTC_LOG(LS_ERROR) << "Got buffer with stride different from screen stride: " -- << srcStride -- << " != " << (desktop_size_.width() * kBytesPerPixel); -- portal_init_failed_ = true; -+ switch (spaBuffer->datas[0].type) { -+ case SPA_DATA_MemFd: -+ case SPA_DATA_DmaBuf: -+ map = static_cast(mmap( -+ nullptr, spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ PROT_READ, MAP_PRIVATE, spaBuffer->datas[0].fd, 0)); -+ if (map == MAP_FAILED) { -+ RTC_LOG(LS_ERROR) << "Failed to mmap memory: " << std::strerror(errno); -+ return; -+ } -+ if (spaBuffer->datas[0].type == SPA_DATA_DmaBuf) { -+ SyncDmaBuf(spaBuffer->datas[0].fd, DMA_BUF_SYNC_START); -+ } -+ src = SPA_MEMBER(map, spaBuffer->datas[0].mapoffset, uint8_t); -+ break; -+ case SPA_DATA_MemPtr: -+ map = nullptr; -+ src = static_cast(spaBuffer->datas[0].data); -+ break; -+ default: -+ return; -+ } -+ -+ if (!src) { -+ RTC_LOG(LS_ERROR) << "Failed to get video stream: Wrong data after mmap()"; -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); -+ return; -+ } -+ -+ struct spa_meta_region* video_metadata = -+ static_cast( -+ spa_buffer_find_meta_data(spaBuffer, SPA_META_VideoCrop, sizeof(*video_metadata))); -+ -+ // Video size from metada is bigger than an actual video stream size. -+ // The metadata are wrong or we should up-scale te video...in both cases -+ // just quit now. -+ if (video_metadata && -+ (video_metadata->region.size.width > (uint32_t)desktop_size_.width() || -+ video_metadata->region.size.height > (uint32_t)desktop_size_.height())) { -+ RTC_LOG(LS_ERROR) << "Stream metadata sizes are wrong!"; -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); - return; - } - -- if (!current_frame_) { -- current_frame_ = static_cast(malloc(maxSize)); -+ // Use video metada when video size from metadata is set and smaller than -+ // video stream size, so we need to adjust it. -+ video_metadata_use_ = (video_metadata && -+ video_metadata->region.size.width != 0 && -+ video_metadata->region.size.height != 0 && -+ (video_metadata->region.size.width < (uint32_t)desktop_size_.width() || -+ video_metadata->region.size.height < (uint32_t)desktop_size_.height())); -+ -+ DesktopSize video_size_prev = video_size_; -+ if (video_metadata_use_) { -+ video_size_ = DesktopSize(video_metadata->region.size.width, -+ video_metadata->region.size.height); -+ } else { -+ video_size_ = desktop_size_; - } -- RTC_DCHECK(current_frame_ != nullptr); -+ -+ if (!current_frame_ || -+ (video_metadata_use_ && !video_size_.equals(video_size_prev))) { -+ current_frame_ = -+ std::make_unique -+ (video_size_.width() * video_size_.height() * kBytesPerPixel); -+ } -+ -+ const int32_t dstStride = video_size_.width() * kBytesPerPixel; -+ const int32_t srcStride = spaBuffer->datas[0].chunk->stride; - -- // If both sides decided to go with the RGBx format we need to convert it to -- // BGRx to match color format expected by WebRTC. -- if (spa_video_format_->format == pw_type_->video_format.RGBx) { -- uint8_t* tempFrame = static_cast(malloc(maxSize)); -- std::memcpy(tempFrame, src, maxSize); -- ConvertRGBxToBGRx(tempFrame, maxSize); -- std::memcpy(current_frame_, tempFrame, maxSize); -- free(tempFrame); -- } else { -- std::memcpy(current_frame_, src, maxSize); -+ // Adjust source content based on metadata video position -+ if (video_metadata_use_ && -+ (video_metadata->region.position.y + video_size_.height() <= desktop_size_.height())) { -+ src += srcStride * video_metadata->region.position.y; - } -+ const int xOffset = -+ video_metadata_use_ && -+ (video_metadata->region.position.x + video_size_.width() <= desktop_size_.width()) -+ ? video_metadata->region.position.x * kBytesPerPixel -+ : 0; -+ -+ uint8_t* dst = current_frame_.get(); -+ for (int i = 0; i < video_size_.height(); ++i) { -+ // Adjust source content based on crop video position if needed -+ src += xOffset; -+ std::memcpy(dst, src, dstStride); -+ // If both sides decided to go with the RGBx format we need to convert it to -+ // BGRx to match color format expected by WebRTC. -+ if (spa_video_format_.format == SPA_VIDEO_FORMAT_RGBx || -+ spa_video_format_.format == SPA_VIDEO_FORMAT_RGBA) { -+ ConvertRGBxToBGRx(dst, dstStride); -+ } -+ src += srcStride - xOffset; -+ dst += dstStride; -+ } -+ -+ SpaBufferUnmap(map, -+ spaBuffer->datas[0].maxsize + spaBuffer->datas[0].mapoffset, -+ spaBuffer->datas[0].type == SPA_DATA_DmaBuf, spaBuffer->datas[0].fd); - } - - void BaseCapturerPipeWire::ConvertRGBxToBGRx(uint8_t* frame, uint32_t size) { - // Change color format for KDE KWin which uses RGBx and not BGRx - for (uint32_t i = 0; i < size; i += 4) { - uint8_t tempR = frame[i]; - uint8_t tempB = frame[i + 2]; - frame[i] = tempB; -@@ -713,27 +768,22 @@ void BaseCapturerPipeWire::OnStartReques - // Array of PipeWire streams. See - // https://github.com/flatpak/xdg-desktop-portal/blob/master/data/org.freedesktop.portal.ScreenCast.xml - // documentation for . - if (g_variant_lookup(response_data, "streams", "a(ua{sv})", &iter)) { - GVariant* variant; - - while (g_variant_iter_next(iter, "@(ua{sv})", &variant)) { - guint32 stream_id; -- gint32 width; -- gint32 height; - GVariant* options; - - g_variant_get(variant, "(u@a{sv})", &stream_id, &options); - RTC_DCHECK(options != nullptr); - -- g_variant_lookup(options, "size", "(ii)", &width, &height); -- -- that->desktop_size_.set(width, height); -- -+ that->pw_stream_node_id_ = stream_id; - g_variant_unref(options); - g_variant_unref(variant); - } - } - g_variant_iter_free(iter); - g_variant_unref(response_data); - - that->OpenPipeWireRemote(); -@@ -808,20 +858,25 @@ void BaseCapturerPipeWire::CaptureFrame( - return; - } - - if (!current_frame_) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - -- std::unique_ptr result(new BasicDesktopFrame(desktop_size_)); -+ DesktopSize frame_size = desktop_size_; -+ if (video_metadata_use_) { -+ frame_size = video_size_; -+ } -+ -+ std::unique_ptr result(new BasicDesktopFrame(frame_size)); - result->CopyPixelsFrom( -- current_frame_, (desktop_size_.width() * kBytesPerPixel), -- DesktopRect::MakeWH(desktop_size_.width(), desktop_size_.height())); -+ current_frame_.get(), (frame_size.width() * kBytesPerPixel), -+ DesktopRect::MakeWH(frame_size.width(), frame_size.height())); - if (!result) { - callback_->OnCaptureResult(Result::ERROR_TEMPORARY, nullptr); - return; - } - callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); - } - - bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { -@@ -832,9 +887,27 @@ bool BaseCapturerPipeWire::GetSourceList - return true; - } - - bool BaseCapturerPipeWire::SelectSource(SourceId id) { - // Screen selection is handled by the xdg-desktop-portal. - return true; - } - -+// static -+std::unique_ptr -+BaseCapturerPipeWire::CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options) { -+ std::unique_ptr capturer = -+ std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); -+ return std::move(capturer);} -+ -+// static -+std::unique_ptr -+BaseCapturerPipeWire::CreateRawWindowCapturer( -+ const DesktopCaptureOptions& options) { -+ -+ std::unique_ptr capturer = -+ std::make_unique(BaseCapturerPipeWire::CaptureSourceType::kAny); -+ return std::move(capturer); -+} -+ - } // namespace webrtc -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.h -@@ -17,99 +17,102 @@ - #include - - #include "modules/desktop_capture/desktop_capture_options.h" - #include "modules/desktop_capture/desktop_capturer.h" - #include "rtc_base/constructormagic.h" - - namespace webrtc { - --class PipeWireType { -- public: -- spa_type_media_type media_type; -- spa_type_media_subtype media_subtype; -- spa_type_format_video format_video; -- spa_type_video_format video_format; --}; -- - class BaseCapturerPipeWire : public DesktopCapturer { - public: -- enum CaptureSourceType { Screen = 1, Window }; -+ enum CaptureSourceType : uint32_t { -+ kScreen = 0b01, -+ kWindow = 0b10, -+ kAny = 0b11 -+ }; - - explicit BaseCapturerPipeWire(CaptureSourceType source_type); - ~BaseCapturerPipeWire() override; - - // DesktopCapturer interface. - void Start(Callback* delegate) override; - void CaptureFrame() override; - bool GetSourceList(SourceList* sources) override; - bool SelectSource(SourceId id) override; - -+ static std::unique_ptr CreateRawScreenCapturer( -+ const DesktopCaptureOptions& options); -+ -+ static std::unique_ptr CreateRawWindowCapturer( -+ const DesktopCaptureOptions& options); -+ - private: - // PipeWire types --> -+ pw_context* pw_context_ = nullptr; - pw_core* pw_core_ = nullptr; -- pw_type* pw_core_type_ = nullptr; - pw_stream* pw_stream_ = nullptr; -- pw_remote* pw_remote_ = nullptr; -- pw_loop* pw_loop_ = nullptr; - pw_thread_loop* pw_main_loop_ = nullptr; -- PipeWireType* pw_type_ = nullptr; - -+ spa_hook spa_core_listener_ = {}; - spa_hook spa_stream_listener_ = {}; -- spa_hook spa_remote_listener_ = {}; - -+ pw_core_events pw_core_events_ = {}; - pw_stream_events pw_stream_events_ = {}; -- pw_remote_events pw_remote_events_ = {}; - -- spa_video_info_raw* spa_video_format_ = nullptr; -+ struct spa_video_info_raw spa_video_format_; - -+ guint32 pw_stream_node_id_ = 0; - gint32 pw_fd_ = -1; - - CaptureSourceType capture_source_type_ = -- BaseCapturerPipeWire::CaptureSourceType::Screen; -+ BaseCapturerPipeWire::CaptureSourceType::kAny; - - // <-- end of PipeWire types - - GDBusConnection* connection_ = nullptr; - GDBusProxy* proxy_ = nullptr; - gchar* portal_handle_ = nullptr; - gchar* session_handle_ = nullptr; - gchar* sources_handle_ = nullptr; - gchar* start_handle_ = nullptr; - guint session_request_signal_id_ = 0; - guint sources_request_signal_id_ = 0; - guint start_request_signal_id_ = 0; - -+ bool video_metadata_use_ = false; -+ DesktopSize video_size_; - DesktopSize desktop_size_ = {}; - DesktopCaptureOptions options_ = {}; - -- uint8_t* current_frame_ = nullptr; -+ std::unique_ptr current_frame_; - Callback* callback_ = nullptr; - - bool portal_init_failed_ = false; - - void InitPortal(); - void InitPipeWire(); -- void InitPipeWireTypes(); - -- void CreateReceivingStream(); -+ pw_stream* CreateReceivingStream(); - void HandleBuffer(pw_buffer* buffer); - - void ConvertRGBxToBGRx(uint8_t* frame, uint32_t size); - -- static void OnStateChanged(void* data, -- pw_remote_state old_state, -- pw_remote_state state, -- const char* error); -+ static void OnCoreError(void *data, -+ uint32_t id, -+ int seq, -+ int res, -+ const char *message); -+ static void OnStreamParamChanged(void *data, -+ uint32_t id, -+ const struct spa_pod *format); - static void OnStreamStateChanged(void* data, - pw_stream_state old_state, - pw_stream_state state, - const char* error_message); -- -- static void OnStreamFormatChanged(void* data, const struct spa_pod* format); - static void OnStreamProcess(void* data); - static void OnNewBuffer(void* data, uint32_t id); - - guint SetupRequestResponseSignal(const gchar* object_path, - GDBusSignalCallback callback); - - static void OnProxyRequested(GObject* object, - GAsyncResult* result, -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc -@@ -10,17 +10,17 @@ - - #include "modules/desktop_capture/linux/screen_capturer_pipewire.h" - - #include - - namespace webrtc { - - ScreenCapturerPipeWire::ScreenCapturerPipeWire() -- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Screen) {} -+ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kScreen) {} - ScreenCapturerPipeWire::~ScreenCapturerPipeWire() {} - - // static - std::unique_ptr - ScreenCapturerPipeWire::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - return std::make_unique(); - } -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc -@@ -10,17 +10,17 @@ - - #include "modules/desktop_capture/linux/window_capturer_pipewire.h" - - #include - - namespace webrtc { - - WindowCapturerPipeWire::WindowCapturerPipeWire() -- : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::Window) {} -+ : BaseCapturerPipeWire(BaseCapturerPipeWire::CaptureSourceType::kWindow) {} - WindowCapturerPipeWire::~WindowCapturerPipeWire() {} - - // static - std::unique_ptr - WindowCapturerPipeWire::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { - return std::make_unique(); - } -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc -@@ -21,17 +21,17 @@ - - namespace webrtc { - - // static - std::unique_ptr DesktopCapturer::CreateRawScreenCapturer( - const DesktopCaptureOptions& options) { - #if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { -- return ScreenCapturerPipeWire::CreateRawScreenCapturer(options); -+ return BaseCapturerPipeWire::CreateRawScreenCapturer(options); - } - #endif // defined(WEBRTC_USE_PIPEWIRE) - - #if defined(USE_X11) - return ScreenCapturerX11::CreateRawScreenCapturer(options); - #endif // defined(USE_X11) - - return nullptr; -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc -@@ -21,17 +21,17 @@ - - namespace webrtc { - - // static - std::unique_ptr DesktopCapturer::CreateRawWindowCapturer( - const DesktopCaptureOptions& options) { - #if defined(WEBRTC_USE_PIPEWIRE) - if (options.allow_pipewire() && DesktopCapturer::IsRunningUnderWayland()) { -- return WindowCapturerPipeWire::CreateRawWindowCapturer(options); -+ return BaseCapturerPipeWire::CreateRawWindowCapturer(options); - } - #endif // defined(WEBRTC_USE_PIPEWIRE) - - #if defined(USE_X11) - return WindowCapturerX11::CreateRawWindowCapturer(options); - #endif // defined(USE_X11) - - return nullptr; - diff --git a/pw3.patch b/pw3.patch deleted file mode 100644 index 82d451e..0000000 --- a/pw3.patch +++ /dev/null @@ -1,183 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604562423 0 -# Node ID d1a244822d7811575f5bb3cd024f8f324275aec2 -# Parent 998e6d0b24e4a560e5664aaef87307e9c069ad87 -Bug 1672989 Build PipeWire as a part of default builds, r=dminor - -Differential Revision: https://phabricator.services.mozilla.com/D94590 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn b/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/BUILD.gn -@@ -152,22 +152,17 @@ if (rtc_include_tests) { - "../../rtc_base:rtc_base_approved", - "../../test:test_support", - ] - } - } - - if (is_linux) { - if (rtc_use_pipewire) { -- pkg_config("pipewire") { -- packages = [ "libpipewire-0.2" ] -- -- defines = [ "WEBRTC_USE_PIPEWIRE" ] -- } -- -+ defines = [ "WEBRTC_USE_PIPEWIRE" ] - pkg_config("gio") { - packages = [ - "gio-2.0", - "gio-unix-2.0", - ] - } - } - } -@@ -326,16 +321,17 @@ rtc_static_library("desktop_capture_gene - } else { - sources += [ - "fake_desktop_capturer.cc", - "fake_desktop_capturer.h", - ] - } - - if (use_x11 || rtc_use_pipewire) { -+ include_dirs = [ "/third_party/libwebrtc/third_party/pipewire" ] - sources += [ - "mouse_cursor_monitor_linux.cc", - "screen_capturer_linux.cc", - "window_capturer_linux.cc", - ] - } - - if (use_x11) { -@@ -367,16 +363,17 @@ rtc_static_library("desktop_capture_gene - "linux/desktop_device_info_x11.h", - "linux/shared_x_util.cc", - "linux/shared_x_util.h", - ] - } - } - - if (rtc_use_pipewire) { -+ include_dirs = [ "/third_party/libwebrtc/third_party/pipewire" ] - sources += [ - "linux/base_capturer_pipewire.cc", - "linux/base_capturer_pipewire.h", - "linux/screen_capturer_pipewire.cc", - "linux/screen_capturer_pipewire.h", - "linux/window_capturer_pipewire.cc", - "linux/window_capturer_pipewire.h", - ] -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn/moz.build -@@ -20,17 +20,18 @@ DEFINES["WEBRTC_RESTRICT_LOGGING"] = Tru - FINAL_LIBRARY = "webrtc" - - - LOCAL_INCLUDES += [ - "!/ipc/ipdl/_ipdlheaders", - "/ipc/chromium/src", - "/ipc/glue", - "/media/libyuv/libyuv/include/", -- "/third_party/libwebrtc/webrtc/" -+ "/third_party/libwebrtc/webrtc/", -+ "/third_party/pipewire" - ] - - UNIFIED_SOURCES += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/blank_detector_desktop_capturer_wrapper.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/capture_result_desktop_capturer_wrapper.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/cropped_desktop_frame.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/cropping_window_capturer.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_and_cursor_composer.cc", -@@ -156,16 +157,17 @@ if CONFIG["OS_TARGET"] == "FreeBSD": - - if CONFIG["OS_TARGET"] == "Linux": - - DEFINES["USE_NSS_CERTS"] = "1" - DEFINES["USE_X11"] = "1" - DEFINES["WEBRTC_LINUX"] = True - DEFINES["WEBRTC_POSIX"] = True - DEFINES["_FILE_OFFSET_BITS"] = "64" -+ DEFINES["WEBRTC_USE_PIPEWIRE"] = "1" - - OS_LIBS += [ - "rt", - "X11", - "X11-xcb", - "xcb", - "Xcomposite", - "Xcursor", -@@ -188,16 +190,24 @@ if CONFIG["OS_TARGET"] == "Linux": - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_atom_cache.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_error_trap.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/x_server_pixel_buffer.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/mouse_cursor_monitor_linux.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/screen_capturer_linux.cc", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/window_capturer_linux.cc" - ] - -+ CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -+ UNIFIED_SOURCES += [ -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc", -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/screen_capturer_pipewire.cc", -+ "/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/window_capturer_pipewire.cc" -+ ] -+ - if CONFIG["OS_TARGET"] == "NetBSD": - - DEFINES["USE_X11"] = "1" - DEFINES["WEBRTC_BSD"] = True - DEFINES["WEBRTC_POSIX"] = True - DEFINES["_FILE_OFFSET_BITS"] = "64" - - OS_LIBS += [ -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_options.h -@@ -136,15 +136,15 @@ class DesktopCaptureOptions { - #if defined(USE_X11) - bool use_update_notifications_ = false; - #else - bool use_update_notifications_ = true; - #endif - bool disable_effects_ = true; - bool detect_updated_region_ = false; - #if defined(WEBRTC_USE_PIPEWIRE) -- bool allow_pipewire_ = false; -+ bool allow_pipewire_ = true; - #endif - }; - - } // namespace webrtc - - #endif // MODULES_DESKTOP_CAPTURE_DESKTOP_CAPTURE_OPTIONS_H_ -diff --git a/third_party/libwebrtc/webrtc/moz.build b/third_party/libwebrtc/webrtc/moz.build ---- a/third_party/libwebrtc/webrtc/moz.build -+++ b/third_party/libwebrtc/webrtc/moz.build -@@ -181,16 +181,19 @@ if CONFIG["OS_TARGET"] == "Linux": - - DIRS += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/primitives_gn", - "/third_party/libwebrtc/webrtc/modules/video_capture/video_capture_internal_impl_gn", - "/third_party/libwebrtc/webrtc/system_wrappers/cpu_features_linux_gn" - ] -+ DIRS += [ -+ "/third_party/pipewire/libpipewire" -+ ] - - if CONFIG["OS_TARGET"] == "NetBSD": - - DIRS += [ - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_generic_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capture_gn", - "/third_party/libwebrtc/webrtc/modules/desktop_capture/primitives_gn", - "/third_party/libwebrtc/webrtc/modules/video_capture/video_capture_internal_impl_gn" - diff --git a/pw4.patch b/pw4.patch deleted file mode 100644 index 03bda37..0000000 --- a/pw4.patch +++ /dev/null @@ -1,18928 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1604009732 0 -# Node ID e5e706b532041baa3ef46420c9bf10629b0cb3ba -# Parent 7dad14e6de1a80a5c6a194df8a7b16504fb3d617 -Bug 1672945 Ship PipeWire 0.3 headers and library wrapper to build PW support out of the box, r=dminor - -- Ship PipeWire 0.3 headers at third_party/pipewire/pipewire -- Ship SPA 0.2 headers at third_party/pipewire/spa -- Ship PipeWire library wrapper at third_party/pipewire/libpipewire - -Differential Revision: https://phabricator.services.mozilla.com/D94580 - -diff --git a/third_party/pipewire/README b/third_party/pipewire/README -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/README -@@ -0,0 +1,4 @@ -+Libpipewire is a pipewire library wrapper needed to build and run Firefox with -+Pipewire support on Linux (https://pipewire.org/). -+ -+Pipewire directory stores headers of pipewire-0.2 and spa-0.2 needed for build only. -diff --git a/third_party/pipewire/libpipewire/moz.build b/third_party/pipewire/libpipewire/moz.build -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/libpipewire/moz.build -@@ -0,0 +1,15 @@ -+# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- -+# vim: set filetype=python: -+# This Source Code Form is subject to the terms of the Mozilla Public -+# License, v. 2.0. If a copy of the MPL was not distributed with this -+# file, You can obtain one at http://mozilla.org/MPL/2.0/. -+ -+SOURCES += [ -+ 'mozpipewire.cpp', -+] -+ -+CXXFLAGS += CONFIG['TK_CFLAGS'] -+ -+LOCAL_INCLUDES += ['/third_party/pipewire'] -+ -+FINAL_LIBRARY = 'xul' -diff --git a/third_party/pipewire/libpipewire/mozpipewire.cpp b/third_party/pipewire/libpipewire/mozpipewire.cpp -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/libpipewire/mozpipewire.cpp -@@ -0,0 +1,312 @@ -+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -+/* vim:expandtab:shiftwidth=4:tabstop=4: -+ */ -+/* This Source Code Form is subject to the terms of the Mozilla Public -+ * License, v. 2.0. If a copy of the MPL was not distributed with this -+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -+ -+#include -+#include "mozilla/Types.h" -+#include "prlink.h" -+ -+#include -+ -+#define GET_FUNC(func, lib) \ -+ func##_fn = \ -+ (decltype(func##_fn))PR_FindFunctionSymbol(lib, #func) \ -+ -+#define IS_FUNC_LOADED(func) \ -+ (func != nullptr) \ -+ -+struct GUnixFDList; -+ -+extern "C" gint -+g_unix_fd_list_get(struct GUnixFDList *list, -+ gint index_, -+ GError **error) -+{ -+ static PRLibrary* gioLib = nullptr; -+ static bool gioInitialized = false; -+ static gint (*g_unix_fd_list_get_fn)(struct GUnixFDList *list, -+ gint index_, GError **error) = nullptr; -+ -+ if (!gioInitialized) { -+ gioInitialized = true; -+ gioLib = PR_LoadLibrary("libgio-2.0.so.0"); -+ if (!gioLib) { -+ return -1; -+ } -+ GET_FUNC(g_unix_fd_list_get, gioLib); -+ } -+ -+ if (!g_unix_fd_list_get_fn) { -+ return -1; -+ } -+ -+ return g_unix_fd_list_get_fn(list, index_, error); -+} -+ -+static struct pw_core * (*pw_context_connect_fn)(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+static void (*pw_context_destroy_fn)(struct pw_context *context); -+struct pw_context * (*pw_context_new_fn)(struct pw_loop *main_loop, -+ struct pw_properties *props, -+ size_t user_data_size); -+static int (*pw_core_disconnect_fn)(struct pw_core *core); -+static void (*pw_init_fn)(int *argc, char **argv[]); -+static void (*pw_stream_add_listener_fn)(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data); -+static int (*pw_stream_connect_fn)(struct pw_stream *stream, -+ enum pw_direction direction, -+ uint32_t target_id, -+ enum pw_stream_flags flags, -+ const struct spa_pod **params, -+ uint32_t n_params); -+static struct pw_buffer* (*pw_stream_dequeue_buffer_fn)(struct pw_stream *stream); -+static void (*pw_stream_destroy_fn)(struct pw_stream *stream); -+static struct pw_stream* (*pw_stream_new_fn)(struct pw_core *core, -+ const char *name, -+ struct pw_properties *props); -+static int (*pw_stream_queue_buffer_fn)(struct pw_stream *stream, -+ struct pw_buffer *buffer); -+static int (*pw_stream_update_params_fn)(struct pw_stream *stream, -+ const struct spa_pod **params, -+ uint32_t n_params); -+static void (*pw_thread_loop_destroy_fn)(struct pw_thread_loop *loop); -+static struct pw_loop* (*pw_thread_loop_get_loop_fn)(struct pw_thread_loop *loop); -+static struct pw_thread_loop* (*pw_thread_loop_new_fn)(const char *name, -+ const struct spa_dict *props); -+static int (*pw_thread_loop_start_fn)(struct pw_thread_loop *loop); -+static void (*pw_thread_loop_stop_fn)(struct pw_thread_loop *loop); -+ -+bool IsPwLibraryLoaded() { -+ static bool isLoaded = -+ (IS_FUNC_LOADED(pw_context_connect_fn) && -+ IS_FUNC_LOADED(pw_context_destroy_fn) && -+ IS_FUNC_LOADED(pw_context_new_fn) && -+ IS_FUNC_LOADED(pw_core_disconnect_fn) && -+ IS_FUNC_LOADED(pw_init_fn) && -+ IS_FUNC_LOADED(pw_stream_add_listener_fn) && -+ IS_FUNC_LOADED(pw_stream_connect_fn) && -+ IS_FUNC_LOADED(pw_stream_dequeue_buffer_fn) && -+ IS_FUNC_LOADED(pw_stream_destroy_fn) && -+ IS_FUNC_LOADED(pw_stream_new_fn) && -+ IS_FUNC_LOADED(pw_stream_queue_buffer_fn) && -+ IS_FUNC_LOADED(pw_stream_update_params_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_destroy_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_get_loop_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_new_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_start_fn) && -+ IS_FUNC_LOADED(pw_thread_loop_stop_fn)); -+ -+ return isLoaded; -+} -+ -+bool LoadPWLibrary() { -+ static PRLibrary* pwLib = nullptr; -+ static bool pwInitialized = false; -+ -+ //TODO Thread safe -+ if (!pwInitialized) { -+ pwInitialized = true; -+ pwLib = PR_LoadLibrary("libpipewire-0.3.so.0"); -+ if (!pwLib) { -+ return false; -+ } -+ -+ GET_FUNC(pw_context_connect, pwLib); -+ GET_FUNC(pw_context_destroy, pwLib); -+ GET_FUNC(pw_context_new, pwLib); -+ GET_FUNC(pw_core_disconnect, pwLib); -+ GET_FUNC(pw_init, pwLib); -+ GET_FUNC(pw_stream_add_listener, pwLib); -+ GET_FUNC(pw_stream_connect, pwLib); -+ GET_FUNC(pw_stream_dequeue_buffer, pwLib); -+ GET_FUNC(pw_stream_destroy, pwLib); -+ GET_FUNC(pw_stream_new, pwLib); -+ GET_FUNC(pw_stream_queue_buffer, pwLib); -+ GET_FUNC(pw_stream_update_params, pwLib); -+ GET_FUNC(pw_thread_loop_destroy, pwLib); -+ GET_FUNC(pw_thread_loop_get_loop, pwLib); -+ GET_FUNC(pw_thread_loop_new, pwLib); -+ GET_FUNC(pw_thread_loop_start, pwLib); -+ GET_FUNC(pw_thread_loop_stop, pwLib); -+ } -+ -+ return IsPwLibraryLoaded(); -+} -+ -+struct pw_core * -+pw_context_connect(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_context_connect_fn(context, properties, user_data_size); -+} -+ -+void -+pw_context_destroy(struct pw_context *context) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ pw_context_destroy_fn(context); -+} -+ -+struct pw_context * -+pw_context_new(struct pw_loop *main_loop, -+ struct pw_properties *props, -+ size_t user_data_size) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_context_new_fn(main_loop, props, user_data_size); -+} -+ -+int -+pw_core_disconnect(struct pw_core *core) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_core_disconnect_fn(core); -+} -+ -+void -+pw_init(int *argc, char **argv[]) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_init_fn(argc, argv); -+} -+ -+void -+pw_stream_add_listener(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_stream_add_listener_fn(stream, listener, events, data); -+} -+ -+int -+pw_stream_connect(struct pw_stream *stream, -+ enum pw_direction direction, -+ uint32_t target_id, -+ enum pw_stream_flags flags, -+ const struct spa_pod **params, -+ uint32_t n_params) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_connect_fn(stream, direction, target_id, flags, -+ params, n_params); -+} -+ -+struct pw_buffer * -+pw_stream_dequeue_buffer(struct pw_stream *stream) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_stream_dequeue_buffer_fn(stream); -+} -+ -+void -+pw_stream_destroy(struct pw_stream *stream) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_stream_destroy_fn(stream); -+} -+ -+struct pw_stream * -+pw_stream_new(struct pw_core *core, -+ const char *name, -+ struct pw_properties *props) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_stream_new_fn(core, name, props); -+} -+ -+int -+pw_stream_queue_buffer(struct pw_stream *stream, -+ struct pw_buffer *buffer) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_queue_buffer_fn(stream, buffer); -+} -+ -+int -+pw_stream_update_params(struct pw_stream *stream, -+ const struct spa_pod **params, -+ uint32_t n_params) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_stream_update_params_fn(stream, params, n_params); -+} -+ -+void -+pw_thread_loop_destroy(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_thread_loop_destroy_fn(loop); -+} -+ -+struct pw_loop * -+pw_thread_loop_get_loop(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_thread_loop_get_loop_fn(loop); -+} -+ -+struct pw_thread_loop * -+pw_thread_loop_new(const char *name, -+ const struct spa_dict *props) -+{ -+ if (!LoadPWLibrary()) { -+ return nullptr; -+ } -+ return pw_thread_loop_new_fn(name, props); -+} -+ -+int -+pw_thread_loop_start(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return 0; -+ } -+ return pw_thread_loop_start_fn(loop); -+} -+ -+void -+pw_thread_loop_stop(struct pw_thread_loop *loop) -+{ -+ if (!LoadPWLibrary()) { -+ return; -+ } -+ return pw_thread_loop_stop_fn(loop); -+} -diff --git a/third_party/pipewire/pipewire/array.h b/third_party/pipewire/pipewire/array.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/array.h -@@ -0,0 +1,165 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_ARRAY_H -+#define PIPEWIRE_ARRAY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+/** \class pw_array -+ * -+ * \brief An array object -+ * -+ * The array is a dynamically resizable data structure that can -+ * hold items of the same size. -+ */ -+struct pw_array { -+ void *data; /**< pointer to array data */ -+ size_t size; /**< length of array in bytes */ -+ size_t alloc; /**< number of allocated memory in \a data */ -+ size_t extend; /**< number of bytes to extend with */ -+}; -+ -+#define PW_ARRAY_INIT(extend) (struct pw_array) { NULL, 0, 0, extend } -+ -+#define pw_array_get_len_s(a,s) ((a)->size / (s)) -+#define pw_array_get_unchecked_s(a,idx,s,t) SPA_MEMBER((a)->data,(idx)*(s),t) -+#define pw_array_check_index_s(a,idx,s) ((idx) < pw_array_get_len_s(a,s)) -+ -+/** Get the number of items of type \a t in array \memberof pw_array */ -+#define pw_array_get_len(a,t) pw_array_get_len_s(a,sizeof(t)) -+/** Get the item with index \a idx and type \a t from array \memberof pw_array */ -+#define pw_array_get_unchecked(a,idx,t) pw_array_get_unchecked_s(a,idx,sizeof(t),t) -+/** Check if an item with index \a idx and type \a t exist in array \memberof pw_array */ -+#define pw_array_check_index(a,idx,t) pw_array_check_index_s(a,idx,sizeof(t)) -+ -+#define pw_array_first(a) ((a)->data) -+#define pw_array_end(a) SPA_MEMBER((a)->data, (a)->size, void) -+#define pw_array_check(a,p) (SPA_MEMBER(p,sizeof(*p),void) <= pw_array_end(a)) -+ -+#define pw_array_for_each(pos, array) \ -+ for (pos = (__typeof__(pos)) pw_array_first(array); \ -+ pw_array_check(array, pos); \ -+ (pos)++) -+ -+#define pw_array_consume(pos, array) \ -+ for (pos = (__typeof__(pos)) pw_array_first(array); \ -+ pw_array_check(array, pos); \ -+ pos = (__typeof__(pos)) pw_array_first(array)) -+ -+#define pw_array_remove(a,p) \ -+({ \ -+ (a)->size -= sizeof(*(p)); \ -+ memmove(p, SPA_MEMBER((p), sizeof(*(p)), void), \ -+ SPA_PTRDIFF(pw_array_end(a),(p))); \ -+}) -+ -+/** Initialize the array with given extend \memberof pw_array */ -+static inline void pw_array_init(struct pw_array *arr, size_t extend) -+{ -+ arr->data = NULL; -+ arr->size = arr->alloc = 0; -+ arr->extend = extend; -+} -+ -+/** Clear the array */ -+static inline void pw_array_clear(struct pw_array *arr) -+{ -+ free(arr->data); -+} -+ -+/** Reset the array */ -+static inline void pw_array_reset(struct pw_array *arr) -+{ -+ arr->size = 0; -+} -+ -+/** Make sure \a size bytes can be added to the array \memberof pw_array */ -+static inline int pw_array_ensure_size(struct pw_array *arr, size_t size) -+{ -+ size_t alloc, need; -+ -+ alloc = arr->alloc; -+ need = arr->size + size; -+ -+ if (SPA_UNLIKELY(alloc < need)) { -+ void *data; -+ alloc = SPA_MAX(alloc, arr->extend); -+ while (alloc < need) -+ alloc *= 2; -+ if (SPA_UNLIKELY((data = realloc(arr->data, alloc)) == NULL)) -+ return -errno; -+ arr->data = data; -+ arr->alloc = alloc; -+ } -+ return 0; -+} -+ -+/** Add \a ref size bytes to \a arr. A pointer to memory that can -+ * hold at least \a size bytes is returned \memberof pw_array */ -+static inline void *pw_array_add(struct pw_array *arr, size_t size) -+{ -+ void *p; -+ -+ if (pw_array_ensure_size(arr, size) < 0) -+ return NULL; -+ -+ p = SPA_MEMBER(arr->data, arr->size, void); -+ arr->size += size; -+ -+ return p; -+} -+ -+/** Add \a ref size bytes to \a arr. When there is not enough memory to -+ * hold \a size bytes, NULL is returned \memberof pw_array */ -+static inline void *pw_array_add_fixed(struct pw_array *arr, size_t size) -+{ -+ void *p; -+ -+ if (SPA_UNLIKELY(arr->alloc < arr->size + size)) { -+ errno = ENOSPC; -+ return NULL; -+ } -+ -+ p = SPA_MEMBER(arr->data, arr->size, void); -+ arr->size += size; -+ -+ return p; -+} -+ -+/** Add a pointer to array \memberof pw_array */ -+#define pw_array_add_ptr(a,p) \ -+ *((void**) pw_array_add(a, sizeof(void*))) = (p) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_ARRAY_H */ -diff --git a/third_party/pipewire/pipewire/buffers.h b/third_party/pipewire/pipewire/buffers.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/buffers.h -@@ -0,0 +1,60 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_BUFFERS_H -+#define PIPEWIRE_BUFFERS_H -+ -+#include -+ -+#include -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#define PW_BUFFERS_FLAG_NONE 0 -+#define PW_BUFFERS_FLAG_NO_MEM (1<<0) /**< don't allocate buffer memory */ -+#define PW_BUFFERS_FLAG_SHARED (1<<1) /**< buffers can be shared */ -+#define PW_BUFFERS_FLAG_DYNAMIC (1<<2) /**< buffers have dynamic data */ -+ -+struct pw_buffers { -+ struct pw_memblock *mem; /**< allocated buffer memory */ -+ struct spa_buffer **buffers; /**< port buffers */ -+ uint32_t n_buffers; /**< number of port buffers */ -+ uint32_t flags; /**< flags */ -+}; -+ -+int pw_buffers_negotiate(struct pw_context *context, uint32_t flags, -+ struct spa_node *outnode, uint32_t out_port_id, -+ struct spa_node *innode, uint32_t in_port_id, -+ struct pw_buffers *result); -+ -+void pw_buffers_clear(struct pw_buffers *buffers); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_BUFFERS_H */ -diff --git a/third_party/pipewire/pipewire/client.h b/third_party/pipewire/pipewire/client.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/client.h -@@ -0,0 +1,171 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CLIENT_H -+#define PIPEWIRE_CLIENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#define PW_TYPE_INTERFACE_Client PW_TYPE_INFO_INTERFACE_BASE "Client" -+ -+#define PW_VERSION_CLIENT 3 -+struct pw_client; -+ -+/* default ID of the current client after connect */ -+#define PW_ID_CLIENT 1 -+ -+/** The client information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_client_info { -+ uint32_t id; /**< id of the global */ -+#define PW_CLIENT_CHANGE_MASK_PROPS (1 << 0) -+#define PW_CLIENT_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+/** Update and existing \ref pw_client_info with \a update \memberof pw_introspect */ -+struct pw_client_info * -+pw_client_info_update(struct pw_client_info *info, -+ const struct pw_client_info *update); -+ -+/** Free a \ref pw_client_info \memberof pw_introspect */ -+void pw_client_info_free(struct pw_client_info *info); -+ -+ -+#define PW_CLIENT_EVENT_INFO 0 -+#define PW_CLIENT_EVENT_PERMISSIONS 1 -+#define PW_CLIENT_EVENT_NUM 2 -+ -+/** Client events */ -+struct pw_client_events { -+#define PW_VERSION_CLIENT_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify client info -+ * -+ * \param info info about the client -+ */ -+ void (*info) (void *object, const struct pw_client_info *info); -+ /** -+ * Notify a client permission -+ * -+ * Event emitted as a result of the get_permissions method. -+ * -+ * \param default_permissions the default permissions -+ * \param index the index of the first permission entry -+ * \param n_permissions the number of permissions -+ * \param permissions the permissions -+ */ -+ void (*permissions) (void *object, -+ uint32_t index, -+ uint32_t n_permissions, -+ const struct pw_permission *permissions); -+}; -+ -+ -+#define PW_CLIENT_METHOD_ADD_LISTENER 0 -+#define PW_CLIENT_METHOD_ERROR 1 -+#define PW_CLIENT_METHOD_UPDATE_PROPERTIES 2 -+#define PW_CLIENT_METHOD_GET_PERMISSIONS 3 -+#define PW_CLIENT_METHOD_UPDATE_PERMISSIONS 4 -+#define PW_CLIENT_METHOD_NUM 5 -+ -+/** Client methods */ -+struct pw_client_methods { -+#define PW_VERSION_CLIENT_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_client_events *events, -+ void *data); -+ /** -+ * Send an error to a client -+ * -+ * \param id the global id to report the error on -+ * \param res an errno style error code -+ * \param message an error string -+ */ -+ int (*error) (void *object, uint32_t id, int res, const char *message); -+ /** -+ * Update client properties -+ * -+ * \param props new properties -+ */ -+ int (*update_properties) (void *object, const struct spa_dict *props); -+ -+ /** -+ * Get client permissions -+ * -+ * A permissions event will be emitted with the permissions. -+ * -+ * \param index the first index to query, 0 for first -+ * \param num the maximum number of items to get -+ */ -+ int (*get_permissions) (void *object, uint32_t index, uint32_t num); -+ /** -+ * Manage the permissions of the global objects for this -+ * client -+ * -+ * Update the permissions of the global objects using the -+ * provided array with permissions -+ * -+ * Globals can use the default permissions or can have specific -+ * permissions assigned to them. -+ * -+ * \param n_permissions number of permissions -+ * \param permissions array of permissions -+ */ -+ int (*update_permissions) (void *object, uint32_t n_permissions, -+ const struct pw_permission *permissions); -+}; -+ -+#define pw_client_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_client_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_client_add_listener(c,...) pw_client_method(c,add_listener,0,__VA_ARGS__) -+#define pw_client_error(c,...) pw_client_method(c,error,0,__VA_ARGS__) -+#define pw_client_update_properties(c,...) pw_client_method(c,update_properties,0,__VA_ARGS__) -+#define pw_client_get_permissions(c,...) pw_client_method(c,get_permissions,0,__VA_ARGS__) -+#define pw_client_update_permissions(c,...) pw_client_method(c,update_permissions,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_CLIENT_H */ -diff --git a/third_party/pipewire/pipewire/context.h b/third_party/pipewire/pipewire/context.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/context.h -@@ -0,0 +1,188 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CONTEXT_H -+#define PIPEWIRE_CONTEXT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_context -+ * -+ * \brief the PipeWire context -+ * -+ * The context object manages all locally available resources. It -+ * is used by both clients and servers. -+ * -+ * The context is used to: -+ * -+ * - Load modules and extend the functionality. This includes -+ * extending the protocol with new object types or creating -+ * any of the available objects. -+ * -+ * - Create implementations of various objects like nodes, -+ * devices, factories, modules, etc.. This will usually also -+ * create pw_global objects that can then be shared with -+ * clients. -+ * -+ * - Connect to another PipeWire instance (the main daemon, for -+ * example) and interact with it (See \subpage page_core_api). -+ * -+ * - Export a local implementation of an object to another -+ * instance. -+ */ -+struct pw_context; -+ -+struct pw_global; -+struct pw_impl_client; -+ -+#include -+#include -+#include -+ -+/** \page page_context_api Core API -+ * -+ * \section page_context_overview Overview -+ * -+ * \subpage page_context -+ * -+ * \subpage page_global -+ * -+ * \subpage page_client -+ * -+ * \subpage page_resource -+ * -+ * \subpage page_node -+ * -+ * \subpage page_port -+ * -+ * \subpage page_link -+ */ -+ -+/** \page page_context Context -+ * -+ * \section page_context_overview Overview -+ * -+ * The context object is an object that manages the state and -+ * resources of a PipeWire instance. -+ */ -+ -+/** context events emitted by the context object added with \ref pw_context_add_listener */ -+struct pw_context_events { -+#define PW_VERSION_CONTEXT_EVENTS 0 -+ uint32_t version; -+ -+ /** The context is being destroyed */ -+ void (*destroy) (void *data); -+ /** The context is being freed */ -+ void (*free) (void *data); -+ /** a new client object is added */ -+ void (*check_access) (void *data, struct pw_impl_client *client); -+ /** a new global object was added */ -+ void (*global_added) (void *data, struct pw_global *global); -+ /** a global object was removed */ -+ void (*global_removed) (void *data, struct pw_global *global); -+}; -+ -+/** Make a new context object for a given main_loop. Ownership of the properties is taken */ -+struct pw_context * pw_context_new(struct pw_loop *main_loop, /**< a main loop to run in */ -+ struct pw_properties *props, /**< extra properties */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** destroy a context object, all resources except the main_loop will be destroyed */ -+void pw_context_destroy(struct pw_context *context); -+ -+/** Get the context user data */ -+void *pw_context_get_user_data(struct pw_context *context); -+ -+/** Add a new event listener to a context */ -+void pw_context_add_listener(struct pw_context *context, -+ struct spa_hook *listener, -+ const struct pw_context_events *events, -+ void *data); -+ -+/** Get the context properties */ -+const struct pw_properties *pw_context_get_properties(struct pw_context *context); -+ -+/** Update the context properties */ -+int pw_context_update_properties(struct pw_context *context, const struct spa_dict *dict); -+ -+/** Get the context support objects */ -+const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support); -+ -+/** get the context main loop */ -+struct pw_loop *pw_context_get_main_loop(struct pw_context *context); -+ -+/** Iterate the globals of the context. The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * globals are iterated. */ -+int pw_context_for_each_global(struct pw_context *context, /**< the context */ -+ int (*callback) (void *data, struct pw_global *global), -+ void *data); -+ -+/** Find a context global by id */ -+struct pw_global *pw_context_find_global(struct pw_context *context, /**< the context */ -+ uint32_t id /**< the global id */); -+ -+/** add a spa library for the given factory_name regex */ -+int pw_context_add_spa_lib(struct pw_context *context, const char *factory_regex, const char *lib); -+ -+/** find the library name for a spa factory */ -+const char * pw_context_find_spa_lib(struct pw_context *context, const char *factory_name); -+ -+struct spa_handle *pw_context_load_spa_handle(struct pw_context *context, -+ const char *factory_name, -+ const struct spa_dict *info); -+ -+ -+/** data for registering export functions */ -+struct pw_export_type { -+ struct spa_list link; -+ const char *type; -+ struct pw_proxy * (*func) (struct pw_core *core, -+ const char *type, const struct spa_dict *props, void *object, -+ size_t user_data_size); -+}; -+ -+/** register a type that can be exported on a context_proxy. This is usually used by -+ * extension modules */ -+int pw_context_register_export_type(struct pw_context *context, struct pw_export_type *type); -+/** find information about registered export type */ -+const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type); -+ -+/** add an object to the context */ -+int pw_context_set_object(struct pw_context *context, const char *type, void *value); -+/** get an object from the context */ -+void *pw_context_get_object(struct pw_context *context, const char *type); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CONTEXT_H */ -diff --git a/third_party/pipewire/pipewire/control.h b/third_party/pipewire/pipewire/control.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/control.h -@@ -0,0 +1,79 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CONTROL_H -+#define PIPEWIRE_CONTROL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_control Control -+ * -+ * \section page_control_overview Overview -+ * -+ * A control can be used to control a port property. -+ */ -+/** \class pw_control -+ * -+ * The control object -+ */ -+struct pw_control; -+ -+#include -+ -+/** Port events, use \ref pw_control_add_listener */ -+struct pw_control_events { -+#define PW_VERSION_CONTROL_EVENTS 0 -+ uint32_t version; -+ -+ /** The control is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** The control is freed */ -+ void (*free) (void *data); -+ -+ /** control is linked to another control */ -+ void (*linked) (void *data, struct pw_control *other); -+ /** control is unlinked from another control */ -+ void (*unlinked) (void *data, struct pw_control *other); -+ -+}; -+ -+/** Get the control parent port or NULL when not set */ -+struct pw_impl_port *pw_control_get_port(struct pw_control *control); -+ -+/** Add an event listener on the control */ -+void pw_control_add_listener(struct pw_control *control, -+ struct spa_hook *listener, -+ const struct pw_control_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CONTROL_H */ -diff --git a/third_party/pipewire/pipewire/core.h b/third_party/pipewire/pipewire/core.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/core.h -@@ -0,0 +1,584 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_CORE_H -+#define PIPEWIRE_CORE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Core PW_TYPE_INFO_INTERFACE_BASE "Core" -+#define PW_TYPE_INTERFACE_Registry PW_TYPE_INFO_INTERFACE_BASE "Registry" -+ -+#define PW_VERSION_CORE 3 -+struct pw_core; -+#define PW_VERSION_REGISTRY 3 -+struct pw_registry; -+ -+/* the default remote name to connect to */ -+#define PW_DEFAULT_REMOTE "pipewire-0" -+ -+/* default ID for the core object after connect */ -+#define PW_ID_CORE 0 -+ -+/* invalid ID that matches any object when used for permissions */ -+#define PW_ID_ANY (uint32_t)(0xffffffff) -+ -+/** The core information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_core_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t cookie; /**< a random cookie for identifying this instance of PipeWire */ -+ const char *user_name; /**< name of the user that started the core */ -+ const char *host_name; /**< name of the machine the core is running on */ -+ const char *version; /**< version of the core */ -+ const char *name; /**< name of the core */ -+#define PW_CORE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_CORE_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+#include -+#include -+#include -+ -+/** Update and existing \ref pw_core_info with \a update \memberof pw_introspect */ -+struct pw_core_info * -+pw_core_info_update(struct pw_core_info *info, -+ const struct pw_core_info *update); -+ -+/** Free a \ref pw_core_info \memberof pw_introspect */ -+void pw_core_info_free(struct pw_core_info *info); -+ -+/** -+ * \page page_iface_pw_core pw_core -+ * \section page_iface_pw_core_desc Description -+ * -+ * The core global object. This is a special singleton object. It -+ * is used for internal PipeWire protocol features. -+ * \section page_iface_pw_core API -+ */ -+ -+/** Core */ -+ -+#define PW_CORE_EVENT_INFO 0 -+#define PW_CORE_EVENT_DONE 1 -+#define PW_CORE_EVENT_PING 2 -+#define PW_CORE_EVENT_ERROR 3 -+#define PW_CORE_EVENT_REMOVE_ID 4 -+#define PW_CORE_EVENT_BOUND_ID 5 -+#define PW_CORE_EVENT_ADD_MEM 6 -+#define PW_CORE_EVENT_REMOVE_MEM 7 -+#define PW_CORE_EVENT_NUM 8 -+ -+/** \struct pw_core_events -+ * \brief Core events -+ * \ingroup pw_core_interface The pw_core interface -+ */ -+struct pw_core_events { -+#define PW_VERSION_CORE_EVENTS 0 -+ uint32_t version; -+ -+ /** -+ * Notify new core info -+ * -+ * This event is emitted when first bound to the core or when the -+ * hello method is called. -+ * -+ * \param info new core info -+ */ -+ void (*info) (void *object, const struct pw_core_info *info); -+ /** -+ * Emit a done event -+ * -+ * The done event is emitted as a result of a sync method with the -+ * same seq number. -+ * -+ * \param seq the seq number passed to the sync method call -+ */ -+ void (*done) (void *object, uint32_t id, int seq); -+ -+ /** Emit a ping event -+ * -+ * The client should reply with a pong reply with the same seq -+ * number. -+ */ -+ void (*ping) (void *object, uint32_t id, int seq); -+ -+ /** -+ * Fatal error event -+ * -+ * The error event is sent out when a fatal (non-recoverable) -+ * error has occurred. The id argument is the proxy object where -+ * the error occurred, most often in response to a request to that -+ * object. The message is a brief description of the error, -+ * for (debugging) convenience. -+ * -+ * This event is usually also emitted on the proxy object with -+ * \a id. -+ * -+ * \param id object where the error occurred -+ * \param seq the sequence number that generated the error -+ * \param res error code -+ * \param message error description -+ */ -+ void (*error) (void *object, uint32_t id, int seq, int res, const char *message); -+ /** -+ * Remove an object ID -+ * -+ * This event is used internally by the object ID management -+ * logic. When a client deletes an object, the server will send -+ * this event to acknowledge that it has seen the delete request. -+ * When the client receives this event, it will know that it can -+ * safely reuse the object ID. -+ * -+ * \param id deleted object ID -+ */ -+ void (*remove_id) (void *object, uint32_t id); -+ -+ /** -+ * Notify an object binding -+ * -+ * This event is emitted when a local object ID is bound to a -+ * global ID. It is emitted before the global becomes visible in the -+ * registry. -+ * -+ * \param id bound object ID -+ * \param global_id the global id bound to -+ */ -+ void (*bound_id) (void *object, uint32_t id, uint32_t global_id); -+ -+ /** -+ * Add memory for a client -+ * -+ * Memory is given to a client as \a fd of a certain -+ * memory \a type. -+ * -+ * Further references to this fd will be made with the per memory -+ * unique identifier \a id. -+ * -+ * \param id the unique id of the memory -+ * \param type the memory type, one of enum spa_data_type -+ * \param fd the file descriptor -+ * \param flags extra flags -+ */ -+ void (*add_mem) (void *object, uint32_t id, uint32_t type, int fd, uint32_t flags); -+ -+ /** -+ * Remove memory for a client -+ * -+ * \param id the memory id to remove -+ */ -+ void (*remove_mem) (void *object, uint32_t id); -+}; -+ -+#define PW_CORE_METHOD_ADD_LISTENER 0 -+#define PW_CORE_METHOD_HELLO 1 -+#define PW_CORE_METHOD_SYNC 2 -+#define PW_CORE_METHOD_PONG 3 -+#define PW_CORE_METHOD_ERROR 4 -+#define PW_CORE_METHOD_GET_REGISTRY 5 -+#define PW_CORE_METHOD_CREATE_OBJECT 6 -+#define PW_CORE_METHOD_DESTROY 7 -+#define PW_CORE_METHOD_NUM 8 -+ -+/** -+ * \struct pw_core_methods -+ * \brief Core methods -+ * -+ * The core global object. This is a singleton object used for -+ * creating new objects in the remote PipeWire instance. It is -+ * also used for internal features. -+ */ -+struct pw_core_methods { -+#define PW_VERSION_CORE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_core_events *events, -+ void *data); -+ /** -+ * Start a conversation with the server. This will send -+ * the core info and will destroy all resources for the client -+ * (except the core and client resource). -+ */ -+ int (*hello) (void *object, uint32_t version); -+ /** -+ * Do server roundtrip -+ * -+ * Ask the server to emit the 'done' event with \a seq. -+ * -+ * Since methods are handled in-order and events are delivered -+ * in-order, this can be used as a barrier to ensure all previous -+ * methods and the resulting events have been handled. -+ * -+ * \param seq the seq number passed to the done event -+ */ -+ int (*sync) (void *object, uint32_t id, int seq); -+ /** -+ * Reply to a server ping event. -+ * -+ * Reply to the server ping event with the same seq. -+ * -+ * \param seq the seq number received in the ping event -+ */ -+ int (*pong) (void *object, uint32_t id, int seq); -+ /** -+ * Fatal error event -+ * -+ * The error method is sent out when a fatal (non-recoverable) -+ * error has occurred. The id argument is the proxy object where -+ * the error occurred, most often in response to an event on that -+ * object. The message is a brief description of the error, -+ * for (debugging) convenience. -+ * -+ * This method is usually also emitted on the resource object with -+ * \a id. -+ * -+ * \param id object where the error occurred -+ * \param res error code -+ * \param message error description -+ */ -+ int (*error) (void *object, uint32_t id, int seq, int res, const char *message); -+ /** -+ * Get the registry object -+ * -+ * Create a registry object that allows the client to list and bind -+ * the global objects available from the PipeWire server -+ * \param version the client version -+ * \param user_data_size extra size -+ */ -+ struct pw_registry * (*get_registry) (void *object, uint32_t version, -+ size_t user_data_size); -+ -+ /** -+ * Create a new object on the PipeWire server from a factory. -+ * -+ * \param factory_name the factory name to use -+ * \param type the interface to bind to -+ * \param version the version of the interface -+ * \param props extra properties -+ * \param user_data_size extra size -+ */ -+ void * (*create_object) (void *object, -+ const char *factory_name, -+ const char *type, -+ uint32_t version, -+ const struct spa_dict *props, -+ size_t user_data_size); -+ /** -+ * Destroy an resource -+ * -+ * Destroy the server resource for the given proxy. -+ * -+ * \param obj the proxy to destroy -+ */ -+ int (*destroy) (void *object, void *proxy); -+}; -+ -+#define pw_core_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_core_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_core_add_listener(c,...) pw_core_method(c,add_listener,0,__VA_ARGS__) -+#define pw_core_hello(c,...) pw_core_method(c,hello,0,__VA_ARGS__) -+#define pw_core_sync(c,...) pw_core_method(c,sync,0,__VA_ARGS__) -+#define pw_core_pong(c,...) pw_core_method(c,pong,0,__VA_ARGS__) -+#define pw_core_error(c,...) pw_core_method(c,error,0,__VA_ARGS__) -+ -+ -+static inline -+SPA_PRINTF_FUNC(5, 0) int -+pw_core_errorv(struct pw_core *core, uint32_t id, int seq, -+ int res, const char *message, va_list args) -+{ -+ char buffer[1024]; -+ vsnprintf(buffer, sizeof(buffer), message, args); -+ buffer[1023] = '\0'; -+ return pw_core_error(core, id, seq, res, buffer); -+} -+ -+static inline -+SPA_PRINTF_FUNC(5, 6) int -+pw_core_errorf(struct pw_core *core, uint32_t id, int seq, -+ int res, const char *message, ...) -+{ -+ va_list args; -+ int r; -+ va_start(args, message); -+ r = pw_core_errorv(core, id, seq, res, message, args); -+ va_end(args); -+ return r; -+} -+ -+static inline struct pw_registry * -+pw_core_get_registry(struct pw_core *core, uint32_t version, size_t user_data_size) -+{ -+ struct pw_registry *res = NULL; -+ spa_interface_call_res((struct spa_interface*)core, -+ struct pw_core_methods, res, -+ get_registry, 0, version, user_data_size); -+ return res; -+} -+ -+static inline void * -+pw_core_create_object(struct pw_core *core, -+ const char *factory_name, -+ const char *type, -+ uint32_t version, -+ const struct spa_dict *props, -+ size_t user_data_size) -+{ -+ void *res = NULL; -+ spa_interface_call_res((struct spa_interface*)core, -+ struct pw_core_methods, res, -+ create_object, 0, factory_name, -+ type, version, props, user_data_size); -+ return res; -+} -+ -+#define pw_core_destroy(c,...) pw_core_method(c,destroy,0,__VA_ARGS__) -+ -+/** \page page_registry Registry -+ * -+ * \section page_registry_overview Overview -+ * -+ * The registry object is a singleton object that keeps track of -+ * global objects on the PipeWire instance. See also \ref page_global. -+ * -+ * Global objects typically represent an actual object in PipeWire -+ * (for example, a module or node) or they are singleton -+ * objects such as the core. -+ * -+ * When a client creates a registry object, the registry object -+ * will emit a global event for each global currently in the -+ * registry. Globals come and go as a result of device hotplugs or -+ * reconfiguration or other events, and the registry will send out -+ * global and global_remove events to keep the client up to date -+ * with the changes. To mark the end of the initial burst of -+ * events, the client can use the pw_core.sync methosd immediately -+ * after calling pw_core.get_registry. -+ * -+ * A client can bind to a global object by using the bind -+ * request. This creates a client-side proxy that lets the object -+ * emit events to the client and lets the client invoke methods on -+ * the object. See \ref page_proxy -+ * -+ * Clients can also change the permissions of the global objects that -+ * it can see. This is interesting when you want to configure a -+ * pipewire session before handing it to another application. You -+ * can, for example, hide certain existing or new objects or limit -+ * the access permissions on an object. -+ */ -+ -+#define PW_REGISTRY_EVENT_GLOBAL 0 -+#define PW_REGISTRY_EVENT_GLOBAL_REMOVE 1 -+#define PW_REGISTRY_EVENT_NUM 2 -+ -+/** Registry events */ -+struct pw_registry_events { -+#define PW_VERSION_REGISTRY_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify of a new global object -+ * -+ * The registry emits this event when a new global object is -+ * available. -+ * -+ * \param id the global object id -+ * \param permissions the permissions of the object -+ * \param type the type of the interface -+ * \param version the version of the interface -+ * \param props extra properties of the global -+ */ -+ void (*global) (void *object, uint32_t id, -+ uint32_t permissions, const char *type, uint32_t version, -+ const struct spa_dict *props); -+ /** -+ * Notify of a global object removal -+ * -+ * Emitted when a global object was removed from the registry. -+ * If the client has any bindings to the global, it should destroy -+ * those. -+ * -+ * \param id the id of the global that was removed -+ */ -+ void (*global_remove) (void *object, uint32_t id); -+}; -+ -+#define PW_REGISTRY_METHOD_ADD_LISTENER 0 -+#define PW_REGISTRY_METHOD_BIND 1 -+#define PW_REGISTRY_METHOD_DESTROY 2 -+#define PW_REGISTRY_METHOD_NUM 3 -+ -+/** Registry methods */ -+struct pw_registry_methods { -+#define PW_VERSION_REGISTRY_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_registry_events *events, -+ void *data); -+ /** -+ * Bind to a global object -+ * -+ * Bind to the global object with \a id and use the client proxy -+ * with new_id as the proxy. After this call, methods can be -+ * send to the remote global object and events can be received -+ * -+ * \param id the global id to bind to -+ * \param type the interface type to bind to -+ * \param version the interface version to use -+ * \returns the new object -+ */ -+ void * (*bind) (void *object, uint32_t id, const char *type, uint32_t version, -+ size_t use_data_size); -+ -+ /** -+ * Attempt to destroy a global object -+ * -+ * Try to destroy the global object. -+ * -+ * \param id the global id to destroy -+ */ -+ int (*destroy) (void *object, uint32_t id); -+}; -+ -+#define pw_registry_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_registry_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+/** Registry */ -+#define pw_registry_add_listener(p,...) pw_registry_method(p,add_listener,0,__VA_ARGS__) -+ -+static inline void * -+pw_registry_bind(struct pw_registry *registry, -+ uint32_t id, const char *type, uint32_t version, -+ size_t user_data_size) -+{ -+ void *res = NULL; -+ spa_interface_call_res((struct spa_interface*)registry, -+ struct pw_registry_methods, res, -+ bind, 0, id, type, version, user_data_size); -+ return res; -+} -+ -+#define pw_registry_destroy(p,...) pw_registry_method(p,destroy,0,__VA_ARGS__) -+ -+ -+/** Connect to a PipeWire instance \memberof pw_core -+ * \return a pw_core on success or NULL with errno set on error. The core -+ * will have an id of PW_ID_CORE (0) */ -+struct pw_core * -+pw_context_connect(struct pw_context *context, /**< a \ref pw_context */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Connect to a PipeWire instance on the given socket \memberof pw_core -+ * \param fd the connected socket to use, the socket will be closed -+ * automatically on disconnect or error. -+ * \return a pw_core on success or NULL with errno set on error */ -+struct pw_core * -+pw_context_connect_fd(struct pw_context *context, /**< a \ref pw_context */ -+ int fd, /**< an fd */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Connect to a given PipeWire instance \memberof pw_core -+ * \return a pw_core on success or NULL with errno set on error */ -+struct pw_core * -+pw_context_connect_self(struct pw_context *context, /**< a \ref pw_context to connect to */ -+ struct pw_properties *properties, /**< optional properties, ownership of -+ * the properties is taken.*/ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Steal the fd of the core connection or < 0 on error. The core -+ * will be disconnected after this call. */ -+int pw_core_steal_fd(struct pw_core *core); -+ -+/** Pause or resume the core. When the core is paused, no new events -+ * will be dispatched until the core is resumed again. */ -+int pw_core_set_paused(struct pw_core *core, bool paused); -+ -+/** disconnect and destroy a core */ -+int pw_core_disconnect(struct pw_core *core); -+ -+/** Get the user_data. It is of the size specified when this object was -+ * constructed */ -+void *pw_core_get_user_data(struct pw_core *core); -+ -+/** Get the client proxy of the connected core. This will have the id -+ * of PW_ID_CLIENT (1) */ -+struct pw_client * pw_core_get_client(struct pw_core *core); -+ -+/** Get the context object used to created this core */ -+struct pw_context * pw_core_get_context(struct pw_core *core); -+ -+/** Get properties from the core */ -+const struct pw_properties *pw_core_get_properties(struct pw_core *core); -+ -+/** Update the core properties. This updates the properties -+ * of the associated client. -+ * \return the number of properties that were updated */ -+int pw_core_update_properties(struct pw_core *core, const struct spa_dict *dict); -+ -+/** Get the core mempool object */ -+struct pw_mempool * pw_core_get_mempool(struct pw_core *core); -+ -+/** Get the proxy with the given id */ -+struct pw_proxy *pw_core_find_proxy(struct pw_core *core, uint32_t id); -+ -+/** Export an object into the PipeWire instance associated with core */ -+struct pw_proxy *pw_core_export(struct pw_core *core, /**< the core */ -+ const char *type, /**< the type of object */ -+ const struct spa_dict *props, /**< extra properties */ -+ void *object, /**< object to export */ -+ size_t user_data_size /**< extra user data */); -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_CORE_H */ -diff --git a/third_party/pipewire/pipewire/data-loop.h b/third_party/pipewire/pipewire/data-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/data-loop.h -@@ -0,0 +1,95 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_DATA_LOOP_H -+#define PIPEWIRE_DATA_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_data_loop -+ * -+ * PipeWire rt-loop object. This loop starts a new real-time thread that -+ * is designed to run the processing graph. -+ */ -+struct pw_data_loop; -+ -+#include -+#include -+ -+/** Loop events, use \ref pw_data_loop_add_listener to add a listener */ -+struct pw_data_loop_events { -+#define PW_VERSION_DATA_LOOP_EVENTS 0 -+ uint32_t version; -+ /** The loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Make a new loop. */ -+struct pw_data_loop * -+pw_data_loop_new(const struct spa_dict *props); -+ -+/** Add an event listener to loop */ -+void pw_data_loop_add_listener(struct pw_data_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_data_loop_events *events, -+ void *data); -+ -+/** wait for activity on the loop up to \a timeout milliseconds. -+ * Should be called from the loop function */ -+int pw_data_loop_wait(struct pw_data_loop *loop, int timeout); -+ -+/** make sure the thread will exit. Can be called from a loop callback */ -+void pw_data_loop_exit(struct pw_data_loop *loop); -+ -+/** Get the loop implementation of this data loop */ -+struct pw_loop * -+pw_data_loop_get_loop(struct pw_data_loop *loop); -+ -+/** Destroy the loop */ -+void pw_data_loop_destroy(struct pw_data_loop *loop); -+ -+/** Start the processing thread */ -+int pw_data_loop_start(struct pw_data_loop *loop); -+ -+/** Stop the processing thread */ -+int pw_data_loop_stop(struct pw_data_loop *loop); -+ -+/** Check if the current thread is the processing thread */ -+bool pw_data_loop_in_thread(struct pw_data_loop *loop); -+ -+/** invoke func in the context of the thread or in the caller thread when -+ * the loop is not running. Since 0.3.3 */ -+int pw_data_loop_invoke(struct pw_data_loop *loop, -+ spa_invoke_func_t func, uint32_t seq, const void *data, size_t size, -+ bool block, void *user_data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_DATA_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/device.h b/third_party/pipewire/pipewire/device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/device.h -@@ -0,0 +1,162 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_DEVICE_H -+#define PIPEWIRE_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Device PW_TYPE_INFO_INTERFACE_BASE "Device" -+ -+#define PW_VERSION_DEVICE 3 -+struct pw_device; -+ -+/** The device information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_device_info { -+ uint32_t id; /**< id of the global */ -+#define PW_DEVICE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_DEVICE_CHANGE_MASK_PARAMS (1 << 1) -+#define PW_DEVICE_CHANGE_MASK_ALL ((1 << 2)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+/** Update and existing \ref pw_device_info with \a update \memberof pw_introspect */ -+struct pw_device_info * -+pw_device_info_update(struct pw_device_info *info, -+ const struct pw_device_info *update); -+ -+/** Free a \ref pw_device_info \memberof pw_introspect */ -+void pw_device_info_free(struct pw_device_info *info); -+ -+#define PW_DEVICE_EVENT_INFO 0 -+#define PW_DEVICE_EVENT_PARAM 1 -+#define PW_DEVICE_EVENT_NUM 2 -+ -+/** Device events */ -+struct pw_device_events { -+#define PW_VERSION_DEVICE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify device info -+ * -+ * \param info info about the device -+ */ -+ void (*info) (void *object, const struct pw_device_info *info); -+ /** -+ * Notify a device param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+ -+#define PW_DEVICE_METHOD_ADD_LISTENER 0 -+#define PW_DEVICE_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_DEVICE_METHOD_ENUM_PARAMS 2 -+#define PW_DEVICE_METHOD_SET_PARAM 3 -+#define PW_DEVICE_METHOD_NUM 4 -+ -+/** Device methods */ -+struct pw_device_methods { -+#define PW_VERSION_DEVICE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_device_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate device parameters -+ * -+ * Start enumeration of device parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number to place in the reply -+ * \param id the parameter id to enum or PW_ID_ANY for all -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, uint32_t id, uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+ /** -+ * Set a parameter on the device -+ * -+ * \param id the parameter id to set -+ * \param flags extra parameter flags -+ * \param param the parameter to set -+ */ -+ int (*set_param) (void *object, uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+}; -+ -+#define pw_device_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_device_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_device_add_listener(c,...) pw_device_method(c,add_listener,0,__VA_ARGS__) -+#define pw_device_subscribe_params(c,...) pw_device_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_device_enum_params(c,...) pw_device_method(c,enum_params,0,__VA_ARGS__) -+#define pw_device_set_param(c,...) pw_device_method(c,set_param,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_DEVICE_H */ -diff --git a/third_party/pipewire/pipewire/factory.h b/third_party/pipewire/pipewire/factory.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/factory.h -@@ -0,0 +1,109 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_FACTORY_H -+#define PIPEWIRE_FACTORY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Factory PW_TYPE_INFO_INTERFACE_BASE "Factory" -+ -+#define PW_VERSION_FACTORY 3 -+struct pw_factory; -+ -+/** The factory information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_factory_info { -+ uint32_t id; /**< id of the global */ -+ const char *name; /**< name the factory */ -+ const char *type; /**< type of the objects created by this factory */ -+ uint32_t version; /**< version of the objects */ -+#define PW_FACTORY_CHANGE_MASK_PROPS (1 << 0) -+#define PW_FACTORY_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< the properties of the factory */ -+}; -+ -+struct pw_factory_info * -+pw_factory_info_update(struct pw_factory_info *info, -+ const struct pw_factory_info *update); -+ -+void -+pw_factory_info_free(struct pw_factory_info *info); -+ -+ -+#define PW_FACTORY_EVENT_INFO 0 -+#define PW_FACTORY_EVENT_NUM 1 -+ -+/** Factory events */ -+struct pw_factory_events { -+#define PW_VERSION_FACTORY_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify factory info -+ * -+ * \param info info about the factory -+ */ -+ void (*info) (void *object, const struct pw_factory_info *info); -+}; -+ -+#define PW_FACTORY_METHOD_ADD_LISTENER 0 -+#define PW_FACTORY_METHOD_NUM 1 -+ -+/** Factory methods */ -+struct pw_factory_methods { -+#define PW_VERSION_FACTORY_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_factory_events *events, -+ void *data); -+}; -+ -+#define pw_factory_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_factory_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_factory_add_listener(c,...) pw_factory_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_FACTORY_H */ -diff --git a/third_party/pipewire/pipewire/filter.h b/third_party/pipewire/pipewire/filter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/filter.h -@@ -0,0 +1,240 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_FILTER_H -+#define PIPEWIRE_FILTER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_filter -+ * -+ * \brief PipeWire filter object class -+ * -+ * The filter object provides a convenient way to implement -+ * processing filters. -+ * -+ * See also \ref page_filters and \ref page_core_api -+ */ -+struct pw_filter; -+ -+#include -+#include -+#include -+ -+#include -+#include -+ -+/** \enum pw_filter_state The state of a filter \memberof pw_filter */ -+enum pw_filter_state { -+ PW_FILTER_STATE_ERROR = -1, /**< the strean is in error */ -+ PW_FILTER_STATE_UNCONNECTED = 0, /**< unconnected */ -+ PW_FILTER_STATE_CONNECTING = 1, /**< connection is in progress */ -+ PW_FILTER_STATE_PAUSED = 2, /**< filter is connected and paused */ -+ PW_FILTER_STATE_STREAMING = 3 /**< filter is streaming */ -+}; -+ -+#if 0 -+struct pw_buffer { -+ struct spa_buffer *buffer; /**< the spa buffer */ -+ void *user_data; /**< user data attached to the buffer */ -+ uint64_t size; /**< For input ports, this field is set by pw_filter -+ * with the duration of the buffer in ticks. -+ * For output ports, this field is set by the user. -+ * This field is added for all queued buffers and -+ * returned in the time info. */ -+}; -+#endif -+ -+/** Events for a filter. These events are always called from the mainloop -+ * unless explicitly documented otherwise. */ -+struct pw_filter_events { -+#define PW_VERSION_FILTER_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+ /** when the filter state changes */ -+ void (*state_changed) (void *data, enum pw_filter_state old, -+ enum pw_filter_state state, const char *error); -+ -+ /** when io changed on a port of the filter (when port_data is NULL). */ -+ void (*io_changed) (void *data, void *port_data, -+ uint32_t id, void *area, uint32_t size); -+ /** when a parameter changed on a port of the filter (when port_data is NULL). */ -+ void (*param_changed) (void *data, void *port_data, -+ uint32_t id, const struct spa_pod *param); -+ -+ /** when a new buffer was created for a port */ -+ void (*add_buffer) (void *data, void *port_data, struct pw_buffer *buffer); -+ /** when a buffer was destroyed for a port */ -+ void (*remove_buffer) (void *data, void *port_data, struct pw_buffer *buffer); -+ -+ /** do processing. This is normally called from the -+ * mainloop but can also be called directly from the realtime data -+ * thread if the user is prepared to deal with this. */ -+ void (*process) (void *data, struct spa_io_position *position); -+ -+ /** The filter is drained */ -+ void (*drained) (void *data); -+}; -+ -+/** Convert a filter state to a readable string \memberof pw_filter */ -+const char * pw_filter_state_as_string(enum pw_filter_state state); -+ -+/** \enum pw_filter_flags Extra flags that can be used in \ref pw_filter_connect() \memberof pw_filter */ -+enum pw_filter_flags { -+ PW_FILTER_FLAG_NONE = 0, /**< no flags */ -+ PW_FILTER_FLAG_INACTIVE = (1 << 0), /**< start the filter inactive, -+ * pw_filter_set_active() needs to be -+ * called explicitly */ -+ PW_FILTER_FLAG_DRIVER = (1 << 1), /**< be a driver */ -+ PW_FILTER_FLAG_RT_PROCESS = (1 << 2), /**< call process from the realtime -+ * thread */ -+}; -+ -+enum pw_filter_port_flags { -+ PW_FILTER_PORT_FLAG_NONE = 0, /**< no flags */ -+ PW_FILTER_PORT_FLAG_MAP_BUFFERS = (1 << 0), /**< mmap the buffers */ -+ PW_FILTER_PORT_FLAG_ALLOC_BUFFERS = (1 << 1), /**< the application will allocate buffer -+ * memory. In the add_buffer event, the -+ * data of the buffer should be set */ -+}; -+ -+/** Create a new unconneced \ref pw_filter \memberof pw_filter -+ * \return a newly allocated \ref pw_filter */ -+struct pw_filter * -+pw_filter_new(struct pw_core *core, /**< a \ref pw_core */ -+ const char *name, /**< a filter media name */ -+ struct pw_properties *props /**< filter properties, ownership is taken */); -+ -+struct pw_filter * -+pw_filter_new_simple(struct pw_loop *loop, /**< a \ref pw_loop to use */ -+ const char *name, /**< a filter media name */ -+ struct pw_properties *props, /**< filter properties, ownership is taken */ -+ const struct pw_filter_events *events, /**< filter events */ -+ void *data /**< data passed to events */); -+ -+/** Destroy a filter \memberof pw_filter */ -+void pw_filter_destroy(struct pw_filter *filter); -+ -+void pw_filter_add_listener(struct pw_filter *filter, -+ struct spa_hook *listener, -+ const struct pw_filter_events *events, -+ void *data); -+ -+enum pw_filter_state pw_filter_get_state(struct pw_filter *filter, const char **error); -+ -+const char *pw_filter_get_name(struct pw_filter *filter); -+ -+struct pw_core *pw_filter_get_core(struct pw_filter *filter); -+ -+/** Connect a filter for processing. \memberof pw_filter -+ * \return 0 on success < 0 on error. -+ * -+ * You should connect to the process event and use pw_filter_dequeue_buffer() -+ * to get the latest metadata and data. */ -+int -+pw_filter_connect(struct pw_filter *filter, /**< a \ref pw_filter */ -+ enum pw_filter_flags flags, /**< filter flags */ -+ const struct spa_pod **params, /**< an array with params. */ -+ uint32_t n_params /**< number of items in \a params */); -+ -+/** Get the node ID of the filter. \memberof pw_filter -+ * \return node ID. */ -+uint32_t -+pw_filter_get_node_id(struct pw_filter *filter); -+ -+/** Disconnect \a filter \memberof pw_filter */ -+int pw_filter_disconnect(struct pw_filter *filter); -+ -+/** add a port to the filter, returns user data of port_data_size. */ -+void *pw_filter_add_port(struct pw_filter *filter, -+ enum pw_direction direction, /**< port direction */ -+ enum pw_filter_port_flags flags, /**< port flags */ -+ size_t port_data_size, /**< allocated and given to the user as port_data */ -+ struct pw_properties *props, /**< port properties, ownership is taken */ -+ const struct spa_pod **params, /**< an array of params. The params should -+ * ideally contain the supported formats */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+/** remove a port from the filter */ -+int pw_filter_remove_port(void *port_data /**< data associated with port */); -+ -+/** get properties, port_data of NULL will give global properties */ -+const struct pw_properties *pw_filter_get_properties(struct pw_filter *filter, -+ void *port_data); -+ -+/** Update properties, use NULL port_data for global filter properties */ -+int pw_filter_update_properties(struct pw_filter *filter, -+ void *port_data, const struct spa_dict *dict); -+ -+/** Set the filter in error state */ -+int pw_filter_set_error(struct pw_filter *filter, /**< a \ref pw_filter */ -+ int res, /**< a result code */ -+ const char *error, ... /**< an error message */) SPA_PRINTF_FUNC(3, 4); -+ -+/** Update params, use NULL port_data for global filter params */ -+int -+pw_filter_update_params(struct pw_filter *filter, /**< a \ref pw_filter */ -+ void *port_data, /**< data associated with port */ -+ const struct spa_pod **params, /**< an array of params. */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+ -+#if 0 -+/** A time structure \memberof pw_filter */ -+struct pw_time { -+ int64_t now; /**< the monotonic time */ -+ struct spa_fraction rate; /**< the rate of \a ticks and delay */ -+ uint64_t ticks; /**< the ticks at \a now. This is the current time that -+ * the remote end is reading/writing. */ -+}; -+#endif -+ -+/** Query the time on the filter \memberof pw_filter */ -+int pw_filter_get_time(struct pw_filter *filter, struct pw_time *time); -+ -+/** Get a buffer that can be filled for output ports or consumed -+ * for input ports. */ -+struct pw_buffer *pw_filter_dequeue_buffer(void *port_data); -+ -+/** Submit a buffer for playback or recycle a buffer for capture. */ -+int pw_filter_queue_buffer(void *port_data, struct pw_buffer *buffer); -+ -+/** Get a data pointer to the buffer data */ -+void *pw_filter_get_dsp_buffer(void *port_data, uint32_t n_samples); -+ -+/** Activate or deactivate the filter \memberof pw_filter */ -+int pw_filter_set_active(struct pw_filter *filter, bool active); -+ -+/** Flush a filter. When \a drain is true, the drained callback will -+ * be called when all data is played or recorded */ -+int pw_filter_flush(struct pw_filter *filter, bool drain); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_FILTER_H */ -diff --git a/third_party/pipewire/pipewire/global.h b/third_party/pipewire/pipewire/global.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/global.h -@@ -0,0 +1,155 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_GLOBAL_H -+#define PIPEWIRE_GLOBAL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_global Global -+ * -+ * Global objects represent resources that are available on the PipeWire -+ * context and are accessible to remote clients. -+ * Globals come and go when devices or other resources become available for -+ * clients. -+ * -+ * Remote clients receives a list of globals when it binds to the registry -+ * object. See \ref page_registry. -+ * -+ * A client can bind to a global to send methods or receive events from -+ * the global. -+ */ -+/** \class pw_global -+ * -+ * \brief A global object visible to remote clients -+ * -+ * A global object is visible to remote clients and represents a resource -+ * that can be used or inspected. -+ * -+ * See \ref page_remote_api -+ */ -+struct pw_global; -+ -+#include -+ -+typedef int (*pw_global_bind_func_t) (void *object, -+ struct pw_impl_client *client, /**< client that binds */ -+ uint32_t permissions, /**< permissions for the bind */ -+ uint32_t version, /**< client interface version */ -+ uint32_t id /**< client proxy id */); -+ -+/** Global events, use \ref pw_global_add_listener */ -+struct pw_global_events { -+#define PW_VERSION_GLOBAL_EVENTS 0 -+ uint32_t version; -+ -+ /** The global is destroyed */ -+ void (*destroy) (void *data); -+ /** The global is freed */ -+ void (*free) (void *data); -+ /** The permissions changed for a client */ -+ void (*permissions_changed) (void *data, -+ struct pw_impl_client *client, -+ uint32_t old_permissions, -+ uint32_t new_permissions); -+}; -+ -+/** Create a new global object */ -+struct pw_global * -+pw_global_new(struct pw_context *context, /**< the context */ -+ const char *type, /**< the interface type of the global */ -+ uint32_t version, /**< the interface version of the global */ -+ struct pw_properties *properties, /**< extra properties */ -+ pw_global_bind_func_t func, /**< function to bind */ -+ void *object /**< global object */); -+ -+/** Register a global object to the context registry */ -+int pw_global_register(struct pw_global *global); -+ -+/** Add an event listener on the global */ -+void pw_global_add_listener(struct pw_global *global, -+ struct spa_hook *listener, -+ const struct pw_global_events *events, -+ void *data); -+ -+/** Get the permissions of the global for a given client */ -+uint32_t pw_global_get_permissions(struct pw_global *global, struct pw_impl_client *client); -+ -+/** Get the context object of this global */ -+struct pw_context *pw_global_get_context(struct pw_global *global); -+ -+/** Get the global type */ -+const char *pw_global_get_type(struct pw_global *global); -+ -+/** Check a global type */ -+bool pw_global_is_type(struct pw_global *global, const char *type); -+ -+/** Get the global version */ -+uint32_t pw_global_get_version(struct pw_global *global); -+ -+/** Get the global properties */ -+const struct pw_properties *pw_global_get_properties(struct pw_global *global); -+ -+/** Update the global properties, must be done when unregistered */ -+int pw_global_update_keys(struct pw_global *global, -+ const struct spa_dict *dict, const char *keys[]); -+ -+/** Get the object associated with the global. This depends on the type of the -+ * global */ -+void *pw_global_get_object(struct pw_global *global); -+ -+/** Get the unique id of the global */ -+uint32_t pw_global_get_id(struct pw_global *global); -+ -+/** Add a resource to a global */ -+int pw_global_add_resource(struct pw_global *global, struct pw_resource *resource); -+ -+/** Iterate all resources added to the global The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * items are iterated. */ -+int pw_global_for_each_resource(struct pw_global *global, -+ int (*callback) (void *data, struct pw_resource *resource), -+ void *data); -+ -+/** Let a client bind to a global */ -+int pw_global_bind(struct pw_global *global, -+ struct pw_impl_client *client, -+ uint32_t permissions, -+ uint32_t version, -+ uint32_t id); -+ -+int pw_global_update_permissions(struct pw_global *global, struct pw_impl_client *client, -+ uint32_t old_permissions, uint32_t new_permissions); -+ -+/** Destroy a global */ -+void pw_global_destroy(struct pw_global *global); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_GLOBAL_H */ -diff --git a/third_party/pipewire/pipewire/impl-client.h b/third_party/pipewire/pipewire/impl-client.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-client.h -@@ -0,0 +1,174 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_CLIENT_H -+#define PIPEWIRE_IMPL_CLIENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_impl_client -+ * -+ * \brief PipeWire client object class. -+ * -+ * The client object represents a client connection with the PipeWire -+ * server. -+ * -+ * Each client has its own list of resources it is bound to along with -+ * a mapping between the client types and server types. -+ */ -+struct pw_impl_client; -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** \page page_client Client -+ * -+ * \section sec_page_client_overview Overview -+ * -+ * The \ref pw_impl_client object is created by a protocol implementation when -+ * a new client connects. -+ * -+ * The client is used to keep track of all resources belonging to one -+ * connection with the PipeWire server. -+ * -+ * \section sec_page_client_credentials Credentials -+ * -+ * The client object will have its credentials filled in by the protocol. -+ * This information is used to check if a resource or action is available -+ * for this client. See also \ref page_access -+ * -+ * \section sec_page_client_types Types -+ * -+ * The client and server maintain a mapping between the client and server -+ * types. All type ids that are in messages exchanged between the client -+ * and server will automatically be remapped. See also \ref page_types. -+ * -+ * \section sec_page_client_resources Resources -+ * -+ * When a client binds to context global object, a resource is made for this -+ * binding and a unique id is assigned to the resources. The client and -+ * server will use this id as the destination when exchanging messages. -+ * See also \ref page_resource -+ */ -+ -+/** The events that a client can emit */ -+struct pw_impl_client_events { -+#define PW_VERSION_IMPL_CLIENT_EVENTS 0 -+ uint32_t version; -+ -+ /** emitted when the client is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** emitted right before the client is freed */ -+ void (*free) (void *data); -+ -+ /** the client is initialized */ -+ void (*initialized) (void *data); -+ -+ /** emitted when the client info changed */ -+ void (*info_changed) (void *data, const struct pw_client_info *info); -+ -+ /** emitted when a new resource is added for client */ -+ void (*resource_added) (void *data, struct pw_resource *resource); -+ -+ /** emitted when a resource is removed */ -+ void (*resource_removed) (void *data, struct pw_resource *resource); -+ -+ /** emitted when the client becomes busy processing an asynchronous -+ * message. In the busy state no messages should be processed. -+ * Processing should resume when the client becomes not busy */ -+ void (*busy_changed) (void *data, bool busy); -+}; -+ -+/** Create a new client. This is mainly used by protocols. */ -+struct pw_impl_client * -+pw_context_create_client(struct pw_impl_core *core, /**< the core object */ -+ struct pw_protocol *prototol, /**< the client protocol */ -+ struct pw_properties *properties, /**< client properties */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a previously created client */ -+void pw_impl_client_destroy(struct pw_impl_client *client); -+ -+/** Finish configuration and register a client */ -+int pw_impl_client_register(struct pw_impl_client *client, /**< the client to register */ -+ struct pw_properties *properties/**< extra properties */); -+ -+/** Get the client user data */ -+void *pw_impl_client_get_user_data(struct pw_impl_client *client); -+ -+/** Get the client information */ -+const struct pw_client_info *pw_impl_client_get_info(struct pw_impl_client *client); -+ -+/** Update the client properties */ -+int pw_impl_client_update_properties(struct pw_impl_client *client, const struct spa_dict *dict); -+ -+/** Update the client permissions */ -+int pw_impl_client_update_permissions(struct pw_impl_client *client, uint32_t n_permissions, -+ const struct pw_permission *permissions); -+ -+/** check if a client has permissions for global_id, Since 0.3.9 */ -+int pw_impl_client_check_permissions(struct pw_impl_client *client, -+ uint32_t global_id, uint32_t permissions); -+ -+/** Get the client properties */ -+const struct pw_properties *pw_impl_client_get_properties(struct pw_impl_client *client); -+ -+/** Get the context used to create this client */ -+struct pw_context *pw_impl_client_get_context(struct pw_impl_client *client); -+/** Get the protocol used to create this client */ -+struct pw_protocol *pw_impl_client_get_protocol(struct pw_impl_client *client); -+ -+/** Get the client core resource */ -+struct pw_resource *pw_impl_client_get_core_resource(struct pw_impl_client *client); -+ -+/** Get a resource with the given id */ -+struct pw_resource *pw_impl_client_find_resource(struct pw_impl_client *client, uint32_t id); -+ -+/** Get the global associated with this client */ -+struct pw_global *pw_impl_client_get_global(struct pw_impl_client *client); -+ -+/** listen to events from this client */ -+void pw_impl_client_add_listener(struct pw_impl_client *client, -+ struct spa_hook *listener, -+ const struct pw_impl_client_events *events, -+ void *data); -+ -+ -+/** Mark the client busy. This can be used when an asynchronous operation is -+ * started and no further processing is allowed to happen for the client */ -+void pw_impl_client_set_busy(struct pw_impl_client *client, bool busy); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_CLIENT_H */ -diff --git a/third_party/pipewire/pipewire/impl-core.h b/third_party/pipewire/pipewire/impl-core.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-core.h -@@ -0,0 +1,94 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_CORE_H -+#define PIPEWIRE_IMPL_CORE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_core -+ * -+ * \brief PipeWire core interface. -+ * -+ * The core is used to make objects on demand. -+ */ -+struct pw_impl_core; -+ -+#include -+#include -+#include -+#include -+ -+/** Factory events, listen to them with \ref pw_impl_core_add_listener */ -+struct pw_impl_core_events { -+#define PW_VERSION_IMPL_CORE_EVENTS 0 -+ uint32_t version; -+ -+ /** the core is destroyed */ -+ void (*destroy) (void *data); -+ /** the core is freed */ -+ void (*free) (void *data); -+ /** the core is initialized */ -+ void (*initialized) (void *data); -+}; -+ -+struct pw_impl_core *pw_context_create_core(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+/* get the default core in a context */ -+struct pw_impl_core *pw_context_get_default_core(struct pw_context *context); -+ -+/** Get the core properties */ -+const struct pw_properties *pw_impl_core_get_properties(struct pw_impl_core *core); -+ -+/** Get the core information */ -+const struct pw_core_info *pw_impl_core_get_info(struct pw_impl_core *core); -+ -+/** Update the core properties */ -+int pw_impl_core_update_properties(struct pw_impl_core *core, const struct spa_dict *dict); -+ -+int pw_impl_core_register(struct pw_impl_core *core, -+ struct pw_properties *properties); -+ -+void pw_impl_core_destroy(struct pw_impl_core *core); -+ -+void *pw_impl_core_get_user_data(struct pw_impl_core *core); -+ -+/** Get the global of this core */ -+struct pw_global *pw_impl_core_get_global(struct pw_impl_core *core); -+ -+/** Add an event listener */ -+void pw_impl_core_add_listener(struct pw_impl_core *core, -+ struct spa_hook *listener, -+ const struct pw_impl_core_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_CORE_H */ -diff --git a/third_party/pipewire/pipewire/impl-device.h b/third_party/pipewire/pipewire/impl-device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-device.h -@@ -0,0 +1,109 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_DEVICE_H -+#define PIPEWIRE_IMPL_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_device -+ * -+ * \brief PipeWire device interface. -+ * -+ * The device is an object that manages nodes. It typically -+ * corresponds to a physical hardware device but it does not -+ * have to be. -+ * -+ * The purpose of the device is to provide an interface to -+ * dynamically create/remove/configure the nodes it manages. -+ */ -+struct pw_impl_device; -+ -+#include -+ -+#include -+#include -+#include -+#include -+ -+/** Device events, listen to them with \ref pw_impl_device_add_listener */ -+struct pw_impl_device_events { -+#define PW_VERSION_IMPL_DEVICE_EVENTS 0 -+ uint32_t version; -+ -+ /** the device is destroyed */ -+ void (*destroy) (void *data); -+ /** the device is freed */ -+ void (*free) (void *data); -+ /** the device is initialized */ -+ void (*initialized) (void *data); -+ -+ /** the device info changed */ -+ void (*info_changed) (void *data, const struct pw_device_info *info); -+}; -+ -+struct pw_impl_device *pw_context_create_device(struct pw_context *context, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+int pw_impl_device_register(struct pw_impl_device *device, -+ struct pw_properties *properties); -+ -+void pw_impl_device_destroy(struct pw_impl_device *device); -+ -+void *pw_impl_device_get_user_data(struct pw_impl_device *device); -+ -+/** Set the device implementation */ -+int pw_impl_device_set_implementation(struct pw_impl_device *device, struct spa_device *spa_device); -+/** Get the device implementation */ -+struct spa_device *pw_impl_device_get_implementation(struct pw_impl_device *device); -+ -+/** Get the global of this device */ -+struct pw_global *pw_impl_device_get_global(struct pw_impl_device *device); -+ -+/** Add an event listener */ -+void pw_impl_device_add_listener(struct pw_impl_device *device, -+ struct spa_hook *listener, -+ const struct pw_impl_device_events *events, -+ void *data); -+ -+int pw_impl_device_update_properties(struct pw_impl_device *device, const struct spa_dict *dict); -+ -+const struct pw_properties *pw_impl_device_get_properties(struct pw_impl_device *device); -+ -+int pw_impl_device_for_each_param(struct pw_impl_device *device, -+ int seq, uint32_t param_id, -+ uint32_t index, uint32_t max, -+ const struct spa_pod *filter, -+ int (*callback) (void *data, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ struct spa_pod *param), -+ void *data); -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_DEVICE_H */ -diff --git a/third_party/pipewire/pipewire/impl-factory.h b/third_party/pipewire/pipewire/impl-factory.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-factory.h -@@ -0,0 +1,124 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_FACTORY_H -+#define PIPEWIRE_IMPL_FACTORY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_factory -+ * -+ * \brief PipeWire factory interface. -+ * -+ * The factory is used to make objects on demand. -+ */ -+struct pw_impl_factory; -+ -+#include -+#include -+#include -+#include -+#include -+ -+/** Factory events, listen to them with \ref pw_impl_factory_add_listener */ -+struct pw_impl_factory_events { -+#define PW_VERSION_IMPL_FACTORY_EVENTS 0 -+ uint32_t version; -+ -+ /** the factory is destroyed */ -+ void (*destroy) (void *data); -+ /** the factory is freed */ -+ void (*free) (void *data); -+ /** the factory is initialized */ -+ void (*initialized) (void *data); -+}; -+ -+struct pw_impl_factory_implementation { -+#define PW_VERSION_IMPL_FACTORY_IMPLEMENTATION 0 -+ uint32_t version; -+ -+ /** The function to create an object from this factory */ -+ void *(*create_object) (void *data, -+ struct pw_resource *resource, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ uint32_t new_id); -+}; -+ -+struct pw_impl_factory *pw_context_create_factory(struct pw_context *context, -+ const char *name, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ size_t user_data_size); -+ -+/** Get the factory properties */ -+const struct pw_properties *pw_impl_factory_get_properties(struct pw_impl_factory *factory); -+ -+/** Get the factory info */ -+const struct pw_factory_info *pw_impl_factory_get_info(struct pw_impl_factory *factory); -+ -+/** Update the factory properties */ -+int pw_impl_factory_update_properties(struct pw_impl_factory *factory, const struct spa_dict *dict); -+ -+int pw_impl_factory_register(struct pw_impl_factory *factory, -+ struct pw_properties *properties); -+ -+void pw_impl_factory_destroy(struct pw_impl_factory *factory); -+ -+void *pw_impl_factory_get_user_data(struct pw_impl_factory *factory); -+ -+/** Get the global of this factory */ -+struct pw_global *pw_impl_factory_get_global(struct pw_impl_factory *factory); -+ -+/** Add an event listener */ -+void pw_impl_factory_add_listener(struct pw_impl_factory *factory, -+ struct spa_hook *listener, -+ const struct pw_impl_factory_events *events, -+ void *data); -+ -+void pw_impl_factory_set_implementation(struct pw_impl_factory *factory, -+ const struct pw_impl_factory_implementation *implementation, -+ void *data); -+ -+void *pw_impl_factory_create_object(struct pw_impl_factory *factory, -+ struct pw_resource *resource, -+ const char *type, -+ uint32_t version, -+ struct pw_properties *properties, -+ uint32_t new_id); -+ -+/** Find a factory by name */ -+struct pw_impl_factory * -+pw_context_find_factory(struct pw_context *context /**< the context */, -+ const char *name /**< the factory name */); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_FACTORY_H */ -diff --git a/third_party/pipewire/pipewire/impl-link.h b/third_party/pipewire/pipewire/impl-link.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-link.h -@@ -0,0 +1,128 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_LINK_H -+#define PIPEWIRE_IMPL_LINK_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_impl_link -+ * -+ * PipeWire link object. -+ */ -+struct pw_impl_link; -+struct pw_impl_port; -+ -+#include -+ -+/** \page page_link Link -+ * -+ * \section page_link_overview Overview -+ * -+ * A link is the connection between 2 nodes (\ref page_node). Nodes are -+ * linked together on ports. -+ * -+ * The link is responsible for negotiating the format and buffers for -+ * the nodes. -+ */ -+ -+/** link events added with \ref pw_impl_link_add_listener */ -+struct pw_impl_link_events { -+#define PW_VERSION_IMPL_LINK_EVENTS 0 -+ uint32_t version; -+ -+ /** A link is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** A link is freed */ -+ void (*free) (void *data); -+ -+ /** a Link is initialized */ -+ void (*initialized) (void *data); -+ -+ /** The info changed on a link */ -+ void (*info_changed) (void *data, const struct pw_link_info *info); -+ -+ /** The link state changed, \a error is only valid when the state is -+ * in error. */ -+ void (*state_changed) (void *data, enum pw_link_state old, -+ enum pw_link_state state, const char *error); -+ -+ /** A port is unlinked */ -+ void (*port_unlinked) (void *data, struct pw_impl_port *port); -+}; -+ -+ -+/** Make a new link between two ports \memberof pw_impl_link -+ * \return a newly allocated link */ -+struct pw_impl_link * -+pw_context_create_link(struct pw_context *context, /**< the context object */ -+ struct pw_impl_port *output, /**< an output port */ -+ struct pw_impl_port *input, /**< an input port */ -+ struct spa_pod *format_filter, /**< an optional format filter */ -+ struct pw_properties *properties /**< extra properties */, -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a link \memberof pw_impl_link */ -+void pw_impl_link_destroy(struct pw_impl_link *link); -+ -+/** Add an event listener to \a link */ -+void pw_impl_link_add_listener(struct pw_impl_link *link, -+ struct spa_hook *listener, -+ const struct pw_impl_link_events *events, -+ void *data); -+ -+/** Finish link configuration and register */ -+int pw_impl_link_register(struct pw_impl_link *link, /**< the link to register */ -+ struct pw_properties *properties /**< extra properties */); -+ -+/** Get the context of a link */ -+struct pw_context *pw_impl_link_get_context(struct pw_impl_link *link); -+ -+/** Get the user_data of a link, the size of the memory is given when -+ * constructing the link */ -+void *pw_impl_link_get_user_data(struct pw_impl_link *link); -+ -+/** Get the link info */ -+const struct pw_link_info *pw_impl_link_get_info(struct pw_impl_link *link); -+ -+/** Get the global of the link */ -+struct pw_global *pw_impl_link_get_global(struct pw_impl_link *link); -+ -+/** Get the output port of the link */ -+struct pw_impl_port *pw_impl_link_get_output(struct pw_impl_link *link); -+ -+/** Get the input port of the link */ -+struct pw_impl_port *pw_impl_link_get_input(struct pw_impl_link *link); -+ -+/** Find the link between 2 ports \memberof pw_impl_link */ -+struct pw_impl_link *pw_impl_link_find(struct pw_impl_port *output, struct pw_impl_port *input); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_LINK_H */ -diff --git a/third_party/pipewire/pipewire/impl-module.h b/third_party/pipewire/pipewire/impl-module.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-module.h -@@ -0,0 +1,110 @@ -+/* PipeWire -+ * Copyright © 2016 Axis Communications -+ * @author Linus Svensson -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_MODULE_H -+#define PIPEWIRE_IMPL_MODULE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+#define PIPEWIRE_SYMBOL_MODULE_INIT "pipewire__module_init" -+#define PIPEWIRE_MODULE_PREFIX "libpipewire-" -+ -+/** \class pw_impl_module -+ * -+ * A dynamically loadable module -+ */ -+struct pw_impl_module; -+ -+/** Module init function signature -+ * -+ * \param module A \ref pw_impl_module -+ * \param args Arguments to the module -+ * \return 0 on success, < 0 otherwise with an errno style error -+ * -+ * A module should provide an init function with this signature. This function -+ * will be called when a module is loaded. -+ * -+ * \memberof pw_impl_module -+ */ -+typedef int (*pw_impl_module_init_func_t) (struct pw_impl_module *module, const char *args); -+ -+/** Module events added with \ref pw_impl_module_add_listener */ -+struct pw_impl_module_events { -+#define PW_VERSION_IMPL_MODULE_EVENTS 0 -+ uint32_t version; -+ -+ /** The module is destroyed */ -+ void (*destroy) (void *data); -+ /** The module is freed */ -+ void (*free) (void *data); -+ /** The module is initialized */ -+ void (*initialized) (void *data); -+ -+ /** The module is registered. This is a good time to register -+ * objectes created from the module. */ -+ void (*registered) (void *data); -+}; -+ -+struct pw_impl_module * -+pw_context_load_module(struct pw_context *context, -+ const char *name, /**< name of the module */ -+ const char *args /**< arguments of the module */, -+ struct pw_properties *properties /**< extra global properties */); -+ -+/** Get the context of a module */ -+struct pw_context * pw_impl_module_get_context(struct pw_impl_module *module); -+ -+/** Get the global of a module */ -+struct pw_global * pw_impl_module_get_global(struct pw_impl_module *module); -+ -+/** Get the node properties */ -+const struct pw_properties *pw_impl_module_get_properties(struct pw_impl_module *module); -+ -+/** Update the module properties */ -+int pw_impl_module_update_properties(struct pw_impl_module *module, const struct spa_dict *dict); -+ -+/** Get the module info */ -+const struct pw_module_info *pw_impl_module_get_info(struct pw_impl_module *module); -+ -+/** Add an event listener to a module */ -+void pw_impl_module_add_listener(struct pw_impl_module *module, -+ struct spa_hook *listener, -+ const struct pw_impl_module_events *events, -+ void *data); -+ -+/** Destroy a module */ -+void pw_impl_module_destroy(struct pw_impl_module *module); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_MODULE_H */ -diff --git a/third_party/pipewire/pipewire/impl-node.h b/third_party/pipewire/pipewire/impl-node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-node.h -@@ -0,0 +1,182 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_NODE_H -+#define PIPEWIRE_IMPL_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_node Node -+ * -+ * \section page_node_overview Overview -+ * -+ * The node object processes data. The node has a list of -+ * input and output ports (\ref page_port) on which it -+ * will receive and send out buffers respectively. -+ */ -+/** \class pw_impl_node -+ * -+ * PipeWire node class. -+ */ -+struct pw_impl_node; -+struct pw_impl_port; -+ -+#include -+#include -+ -+#include -+ -+/** Node events, listen to them with \ref pw_impl_node_add_listener */ -+struct pw_impl_node_events { -+#define PW_VERSION_IMPL_NODE_EVENTS 0 -+ uint32_t version; -+ -+ /** the node is destroyed */ -+ void (*destroy) (void *data); -+ /** the node is about to be freed */ -+ void (*free) (void *data); -+ /** the node is initialized */ -+ void (*initialized) (void *data); -+ -+ /** a port is being initialized on the node */ -+ void (*port_init) (void *data, struct pw_impl_port *port); -+ /** a port was added */ -+ void (*port_added) (void *data, struct pw_impl_port *port); -+ /** a port was removed */ -+ void (*port_removed) (void *data, struct pw_impl_port *port); -+ -+ /** the node info changed */ -+ void (*info_changed) (void *data, const struct pw_node_info *info); -+ /** a port on the node changed info */ -+ void (*port_info_changed) (void *data, struct pw_impl_port *port, -+ const struct pw_port_info *info); -+ /** the node active state changed */ -+ void (*active_changed) (void *data, bool active); -+ -+ /** a new state is requested on the node */ -+ void (*state_request) (void *data, enum pw_node_state state); -+ /** the state of the node changed */ -+ void (*state_changed) (void *data, enum pw_node_state old, -+ enum pw_node_state state, const char *error); -+ -+ /** a result was received */ -+ void (*result) (void *data, int seq, int res, uint32_t type, const void *result); -+ -+ /** an event is emitted */ -+ void (*event) (void *data, const struct spa_event *event); -+ -+ /** the driver of the node changed */ -+ void (*driver_changed) (void *data, struct pw_impl_node *old, struct pw_impl_node *driver); -+ -+ /** a peer was added */ -+ void (*peer_added) (void *data, struct pw_impl_node *peer); -+ /** a peer was removed */ -+ void (*peer_removed) (void *data, struct pw_impl_node *peer); -+}; -+ -+/** Create a new node \memberof pw_impl_node */ -+struct pw_impl_node * -+pw_context_create_node(struct pw_context *context, /**< the context */ -+ struct pw_properties *properties, /**< extra properties */ -+ size_t user_data_size /**< user data size */); -+ -+/** Complete initialization of the node and register */ -+int pw_impl_node_register(struct pw_impl_node *node, /**< node to register */ -+ struct pw_properties *properties /**< extra properties */); -+ -+/** Destroy a node */ -+void pw_impl_node_destroy(struct pw_impl_node *node); -+ -+/** Get the node info */ -+const struct pw_node_info *pw_impl_node_get_info(struct pw_impl_node *node); -+ -+/** Get node user_data. The size of the memory was given in \ref pw_context_create_node */ -+void * pw_impl_node_get_user_data(struct pw_impl_node *node); -+ -+/** Get the context of this node */ -+struct pw_context *pw_impl_node_get_context(struct pw_impl_node *node); -+ -+/** Get the global of this node */ -+struct pw_global *pw_impl_node_get_global(struct pw_impl_node *node); -+ -+/** Get the node properties */ -+const struct pw_properties *pw_impl_node_get_properties(struct pw_impl_node *node); -+ -+/** Update the node properties */ -+int pw_impl_node_update_properties(struct pw_impl_node *node, const struct spa_dict *dict); -+ -+/** Set the node implementation */ -+int pw_impl_node_set_implementation(struct pw_impl_node *node, struct spa_node *spa_node); -+ -+/** Get the node implementation */ -+struct spa_node *pw_impl_node_get_implementation(struct pw_impl_node *node); -+ -+/** Add an event listener */ -+void pw_impl_node_add_listener(struct pw_impl_node *node, -+ struct spa_hook *listener, -+ const struct pw_impl_node_events *events, -+ void *data); -+ -+/** Iterate the ports in the given direction. The callback should return -+ * 0 to fetch the next item, any other value stops the iteration and returns -+ * the value. When all callbacks return 0, this function returns 0 when all -+ * items are iterated. */ -+int pw_impl_node_for_each_port(struct pw_impl_node *node, -+ enum pw_direction direction, -+ int (*callback) (void *data, struct pw_impl_port *port), -+ void *data); -+ -+int pw_impl_node_for_each_param(struct pw_impl_node *node, -+ int seq, uint32_t param_id, -+ uint32_t index, uint32_t max, -+ const struct spa_pod *filter, -+ int (*callback) (void *data, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ struct spa_pod *param), -+ void *data); -+ -+/** Find the port with direction and port_id or NULL when not found. Passing -+ * PW_ID_ANY for port_id will return any port, preferably an unlinked one. */ -+struct pw_impl_port * -+pw_impl_node_find_port(struct pw_impl_node *node, enum pw_direction direction, uint32_t port_id); -+ -+/** Get a free unused port_id from the node */ -+uint32_t pw_impl_node_get_free_port_id(struct pw_impl_node *node, enum pw_direction direction); -+ -+int pw_impl_node_initialized(struct pw_impl_node *node); -+ -+/** Set a node active. This will start negotiation with all linked active -+ * nodes and start data transport */ -+int pw_impl_node_set_active(struct pw_impl_node *node, bool active); -+ -+/** Check if a node is active */ -+bool pw_impl_node_is_active(struct pw_impl_node *node); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_NODE_H */ -diff --git a/third_party/pipewire/pipewire/impl-port.h b/third_party/pipewire/pipewire/impl-port.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl-port.h -@@ -0,0 +1,138 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_PORT_H -+#define PIPEWIRE_IMPL_PORT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_port Port -+ * -+ * \section page_node_overview Overview -+ * -+ * A port can be used to link two nodes. -+ */ -+/** \class pw_impl_port -+ * -+ * The port object -+ */ -+struct pw_impl_port; -+struct pw_impl_link; -+struct pw_control; -+ -+#include -+ -+enum pw_impl_port_state { -+ PW_IMPL_PORT_STATE_ERROR = -1, /**< the port is in error */ -+ PW_IMPL_PORT_STATE_INIT = 0, /**< the port is being created */ -+ PW_IMPL_PORT_STATE_CONFIGURE = 1, /**< the port is ready for format negotiation */ -+ PW_IMPL_PORT_STATE_READY = 2, /**< the port is ready for buffer allocation */ -+ PW_IMPL_PORT_STATE_PAUSED = 3, /**< the port is paused */ -+}; -+ -+/** Port events, use \ref pw_impl_port_add_listener */ -+struct pw_impl_port_events { -+#define PW_VERSION_IMPL_PORT_EVENTS 1 -+ uint32_t version; -+ -+ /** The port is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** The port is freed */ -+ void (*free) (void *data); -+ -+ /** The port is initialized */ -+ void (*initialized) (void *data); -+ -+ /** the port info changed */ -+ void (*info_changed) (void *data, const struct pw_port_info *info); -+ -+ /** a new link is added on this port */ -+ void (*link_added) (void *data, struct pw_impl_link *link); -+ -+ /** a link is removed from this port */ -+ void (*link_removed) (void *data, struct pw_impl_link *link); -+ -+ /** the state of the port changed */ -+ void (*state_changed) (void *data, enum pw_impl_port_state old, -+ enum pw_impl_port_state state, const char *error); -+ -+ /** a control was added to the port */ -+ void (*control_added) (void *data, struct pw_control *control); -+ -+ /** a control was removed from the port */ -+ void (*control_removed) (void *data, struct pw_control *control); -+ -+ /** a parameter changed, since version 1 */ -+ void (*param_changed) (void *data, uint32_t id); -+}; -+ -+/** Create a new port \memberof pw_impl_port -+ * \return a newly allocated port */ -+struct pw_impl_port * -+pw_context_create_port(struct pw_context *context, -+ enum pw_direction direction, -+ uint32_t port_id, -+ const struct spa_port_info *info, -+ size_t user_data_size); -+ -+/** Get the port direction */ -+enum pw_direction pw_impl_port_get_direction(struct pw_impl_port *port); -+ -+/** Get the port properties */ -+const struct pw_properties *pw_impl_port_get_properties(struct pw_impl_port *port); -+ -+/** Update the port properties */ -+int pw_impl_port_update_properties(struct pw_impl_port *port, const struct spa_dict *dict); -+ -+/** Get the port info */ -+const struct pw_port_info *pw_impl_port_get_info(struct pw_impl_port *port); -+ -+/** Get the port id */ -+uint32_t pw_impl_port_get_id(struct pw_impl_port *port); -+ -+/** Get the port parent node or NULL when not yet set */ -+struct pw_impl_node *pw_impl_port_get_node(struct pw_impl_port *port); -+ -+/** check is a port has links, return 0 if not, 1 if it is linked */ -+int pw_impl_port_is_linked(struct pw_impl_port *port); -+ -+/** Add a port to a node \memberof pw_impl_port */ -+int pw_impl_port_add(struct pw_impl_port *port, struct pw_impl_node *node); -+ -+/** Add an event listener on the port */ -+void pw_impl_port_add_listener(struct pw_impl_port *port, -+ struct spa_hook *listener, -+ const struct pw_impl_port_events *events, -+ void *data); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_PORT_H */ -diff --git a/third_party/pipewire/pipewire/impl.h b/third_party/pipewire/pipewire/impl.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/impl.h -@@ -0,0 +1,57 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_IMPL_H -+#define PIPEWIRE_IMPL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct pw_impl_client; -+struct pw_impl_module; -+struct pw_global; -+struct pw_node; -+struct pw_impl_port; -+struct pw_resource; -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_IMPL_H */ -diff --git a/third_party/pipewire/pipewire/keys.h b/third_party/pipewire/pipewire/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/keys.h -@@ -0,0 +1,278 @@ -+/* PipeWire -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_KEYS_H -+#define PIPEWIRE_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * A collection of keys that are used to add extra information on objects. -+ * -+ * Keys that start with "pipewire." are in general set-once and then -+ * read-only. They are usually used for security sensitive information that -+ * needs to be fixed. -+ * -+ * Properties from other objects can also appear. This usually suggests some -+ * sort of parent/child or owner/owned relationship. -+ */ -+#define PW_KEY_PROTOCOL "pipewire.protocol" /**< protocol used for connection */ -+#define PW_KEY_ACCESS "pipewire.access" /**< how the client access is controlled */ -+ -+/** Various keys related to the identity of a client process and its security. -+ * Must be obtained from trusted sources by the protocol and placed as -+ * read-only properties. */ -+#define PW_KEY_SEC_PID "pipewire.sec.pid" /**< Client pid, set by protocol */ -+#define PW_KEY_SEC_UID "pipewire.sec.uid" /**< Client uid, set by protocol*/ -+#define PW_KEY_SEC_GID "pipewire.sec.gid" /**< client gid, set by protocol*/ -+#define PW_KEY_SEC_LABEL "pipewire.sec.label" /**< client security label, set by protocol*/ -+ -+#define PW_KEY_LIBRARY_NAME_SYSTEM "library.name.system" /**< name of the system library to use */ -+#define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */ -+#define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */ -+ -+#define PW_KEY_OBJECT_PATH "object.path" /**< unique path to construct the object */ -+#define PW_KEY_OBJECT_ID "object.id" /**< a global object id */ -+ -+/* context */ -+#define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules" /**< a context profile for modules */ -+#define PW_KEY_USER_NAME "context.user-name" /**< The user name that runs pipewire */ -+#define PW_KEY_HOST_NAME "context.host-name" /**< The host name of the machine */ -+ -+/* core */ -+#define PW_KEY_CORE_NAME "core.name" /**< The name of the core. Default is -+ * pipewire--, overwritten -+ * by env(PIPEWIRE_CORE) */ -+#define PW_KEY_CORE_VERSION "core.version" /**< The version of the core. */ -+#define PW_KEY_CORE_DAEMON "core.daemon" /**< If the core is listening for connections. */ -+ -+#define PW_KEY_CORE_ID "core.id" /**< the core id */ -+#define PW_KEY_CORE_MONITORS "core.monitors" /**< the apis monitored by core. */ -+ -+/* cpu */ -+#define PW_KEY_CPU_MAX_ALIGN "cpu.max-align" /**< maximum alignment needed to support -+ * all CPU optimizations */ -+#define PW_KEY_CPU_CORES "cpu.cores" /**< number of cores */ -+ -+/* priorities */ -+#define PW_KEY_PRIORITY_SESSION "priority.session" /**< priority in session manager */ -+#define PW_KEY_PRIORITY_DRIVER "priority.driver" /**< priority to be a driver */ -+ -+/* remote keys */ -+#define PW_KEY_REMOTE_NAME "remote.name" /**< The name of the remote to connect to, -+ * default pipewire-0, overwritten by -+ * env(PIPEWIRE_REMOTE) */ -+#define PW_KEY_REMOTE_INTENTION "remote.intention" /**< The intention of the remote connection, -+ * "generic", "screencast" */ -+ -+/** application keys */ -+#define PW_KEY_APP_NAME "application.name" /**< application name. Ex: "Totem Music Player" */ -+#define PW_KEY_APP_ID "application.id" /**< a textual id for identifying an -+ * application logically. Ex: "org.gnome.Totem" */ -+#define PW_KEY_APP_VERSION "application.version" -+#define PW_KEY_APP_ICON "application.icon" /**< aa base64 blob with PNG image data */ -+#define PW_KEY_APP_ICON_NAME "application.icon-name" /**< an XDG icon name for the application. -+ * Ex: "totem" */ -+#define PW_KEY_APP_LANGUAGE "application.language" /**< application language if applicable, in -+ * standard POSIX format. Ex: "en_GB" */ -+ -+#define PW_KEY_APP_PROCESS_ID "application.process.id" /**< process id (pid)*/ -+#define PW_KEY_APP_PROCESS_BINARY "application.process.binary" /**< binary name */ -+#define PW_KEY_APP_PROCESS_USER "application.process.user" /**< user name */ -+#define PW_KEY_APP_PROCESS_HOST "application.process.host" /**< host name */ -+#define PW_KEY_APP_PROCESS_MACHINE_ID "application.process.machine-id" /**< the D-Bus host id the -+ * application runs on */ -+#define PW_KEY_APP_PROCESS_SESSION_ID "application.process.session-id" /**< login session of the -+ * application, on Unix the -+ * value of $XDG_SESSION_ID. */ -+/** window system */ -+#define PW_KEY_WINDOW_X11_DISPLAY "window.x11.display" /**< the X11 display string. Ex. ":0.0" */ -+ -+/** Client properties */ -+#define PW_KEY_CLIENT_ID "client.id" /**< a client id */ -+#define PW_KEY_CLIENT_NAME "client.name" /**< the client name */ -+#define PW_KEY_CLIENT_API "client.api" /**< the client api used to access -+ * PipeWire */ -+ -+/** Node keys */ -+#define PW_KEY_NODE_ID "node.id" /**< node id */ -+#define PW_KEY_NODE_NAME "node.name" /**< node name */ -+#define PW_KEY_NODE_NICK "node.nick" /**< short node name */ -+#define PW_KEY_NODE_DESCRIPTION "node.description" /**< localized human readable node one-line -+ * description. Ex. "Foobar USB Headset" */ -+#define PW_KEY_NODE_PLUGGED "node.plugged" /**< when the node was created. As a uint64 in -+ * nanoseconds. */ -+ -+#define PW_KEY_NODE_SESSION "node.session" /**< the session id this node is part of */ -+#define PW_KEY_NODE_GROUP "node.group" /**< the group id this node is part of. Nodes -+ * in the same group are always scheduled -+ * with the same driver. */ -+#define PW_KEY_NODE_EXCLUSIVE "node.exclusive" /**< node wants exclusive access to resources */ -+#define PW_KEY_NODE_AUTOCONNECT "node.autoconnect" /**< node wants to be automatically connected -+ * to a compatible node */ -+#define PW_KEY_NODE_TARGET "node.target" /**< node wants to be connected to the target -+ * node/session */ -+#define PW_KEY_NODE_LATENCY "node.latency" /**< the requested latency of the node as -+ * a fraction. Ex: 128/48000 */ -+#define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect" /**< don't reconnect this node */ -+#define PW_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< process even when unlinked */ -+#define PW_KEY_NODE_PAUSE_ON_IDLE "node.pause-on-idle" /**< pause the node when idle */ -+#define PW_KEY_NODE_DRIVER "node.driver" /**< node can drive the graph */ -+#define PW_KEY_NODE_STREAM "node.stream" /**< node is a stream, the server side should -+ * add a converter */ -+/** Port keys */ -+#define PW_KEY_PORT_ID "port.id" /**< port id */ -+#define PW_KEY_PORT_NAME "port.name" /**< port name */ -+#define PW_KEY_PORT_DIRECTION "port.direction" /**< the port direction, one of "in" or "out" -+ * or "control" and "notify" for control ports */ -+#define PW_KEY_PORT_ALIAS "port.alias" /**< port alias */ -+#define PW_KEY_PORT_PHYSICAL "port.physical" /**< if this is a physical port */ -+#define PW_KEY_PORT_TERMINAL "port.terminal" /**< if this port consumes the data */ -+#define PW_KEY_PORT_CONTROL "port.control" /**< if this port is a control port */ -+#define PW_KEY_PORT_MONITOR "port.monitor" /**< if this port is a monitor port */ -+ -+/** link properties */ -+#define PW_KEY_LINK_ID "link.id" /**< a link id */ -+#define PW_KEY_LINK_INPUT_NODE "link.input.node" /**< input node id of a link */ -+#define PW_KEY_LINK_INPUT_PORT "link.input.port" /**< input port id of a link */ -+#define PW_KEY_LINK_OUTPUT_NODE "link.output.node" /**< output node id of a link */ -+#define PW_KEY_LINK_OUTPUT_PORT "link.output.port" /**< output port id of a link */ -+#define PW_KEY_LINK_PASSIVE "link.passive" /**< indicate that a link is passive and -+ * does not cause the graph to be -+ * runnable. */ -+/** device properties */ -+#define PW_KEY_DEVICE_ID "device.id" /**< device id */ -+#define PW_KEY_DEVICE_NAME "device.name" /**< device name */ -+#define PW_KEY_DEVICE_PLUGGED "device.plugged" /**< when the device was created. As a uint64 in -+ * nanoseconds. */ -+#define PW_KEY_DEVICE_NICK "device.nick" /**< a short device nickname */ -+#define PW_KEY_DEVICE_STRING "device.string" /**< device string in the underlying layer's -+ * format. Ex. "surround51:0" */ -+#define PW_KEY_DEVICE_API "device.api" /**< API this device is accessed with. -+ * Ex. "alsa", "v4l2" */ -+#define PW_KEY_DEVICE_DESCRIPTION "device.description" /**< localized human readable device one-line -+ * description. Ex. "Foobar USB Headset" */ -+#define PW_KEY_DEVICE_BUS_PATH "device.bus-path" /**< bus path to the device in the OS' -+ * format. Ex. "pci-0000:00:14.0-usb-0:3.2:1.0" */ -+#define PW_KEY_DEVICE_SERIAL "device.serial" /**< Serial number if applicable */ -+#define PW_KEY_DEVICE_VENDOR_ID "device.vendor.id" /**< vendor ID if applicable */ -+#define PW_KEY_DEVICE_VENDOR_NAME "device.vendor.name" /**< vendor name if applicable */ -+#define PW_KEY_DEVICE_PRODUCT_ID "device.product.id" /**< product ID if applicable */ -+#define PW_KEY_DEVICE_PRODUCT_NAME "device.product.name" /**< product name if applicable */ -+#define PW_KEY_DEVICE_CLASS "device.class" /**< device class */ -+#define PW_KEY_DEVICE_FORM_FACTOR "device.form-factor" /**< form factor if applicable. One of -+ * "internal", "speaker", "handset", "tv", -+ * "webcam", "microphone", "headset", -+ * "headphone", "hands-free", "car", "hifi", -+ * "computer", "portable" */ -+#define PW_KEY_DEVICE_BUS "device.bus" /**< bus of the device if applicable. One of -+ * "isa", "pci", "usb", "firewire", -+ * "bluetooth" */ -+#define PW_KEY_DEVICE_SUBSYSTEM "device.subsystem" /**< device subsystem */ -+#define PW_KEY_DEVICE_ICON "device.icon" /**< icon for the device. A base64 blob -+ * containing PNG image data */ -+#define PW_KEY_DEVICE_ICON_NAME "device.icon-name" /**< an XDG icon name for the device. -+ * Ex. "sound-card-speakers-usb" */ -+#define PW_KEY_DEVICE_INTENDED_ROLES "device.intended-roles" /**< intended use. A space separated list of -+ * roles (see PW_KEY_MEDIA_ROLE) this device -+ * is particularly well suited for, due to -+ * latency, quality or form factor. */ -+ -+/** module properties */ -+#define PW_KEY_MODULE_ID "module.id" /**< the module id */ -+#define PW_KEY_MODULE_NAME "module.name" /**< the name of the module */ -+#define PW_KEY_MODULE_AUTHOR "module.author" /**< the author's name */ -+#define PW_KEY_MODULE_DESCRIPTION "module.description" /**< a human readable one-line description -+ * of the module's purpose.*/ -+#define PW_KEY_MODULE_USAGE "module.usage" /**< a human readable usage description of -+ * the module's arguments. */ -+#define PW_KEY_MODULE_VERSION "module.version" /**< a version string for the module. */ -+ -+/** Factory properties */ -+#define PW_KEY_FACTORY_ID "factory.id" /**< the factory id */ -+#define PW_KEY_FACTORY_NAME "factory.name" /**< the name of the factory */ -+#define PW_KEY_FACTORY_USAGE "factory.usage" /**< the usage of the factory */ -+#define PW_KEY_FACTORY_TYPE_NAME "factory.type.name" /**< the name of the type created by a factory */ -+#define PW_KEY_FACTORY_TYPE_VERSION "factory.type.version" /**< the version of the type created by a factory */ -+ -+/** Stream properties */ -+#define PW_KEY_STREAM_IS_LIVE "stream.is-live" /**< Indicates that the stream is live. */ -+#define PW_KEY_STREAM_LATENCY_MIN "stream.latency.min" /**< The minimum latency of the stream. */ -+#define PW_KEY_STREAM_LATENCY_MAX "stream.latency.max" /**< The maximum latency of the stream */ -+#define PW_KEY_STREAM_MONITOR "stream.monitor" /**< Indicates that the stream is monitoring -+ * and might select a less accurate but faster -+ * conversion algorithm. */ -+#define PW_KEY_STREAM_DONT_REMIX "stream.dont-remix" /**< don't remix channels */ -+ -+/** object properties */ -+#define PW_KEY_OBJECT_LINGER "object.linger" /**< the object lives on even after the client -+ * that created it has been destroyed */ -+ -+/** Media */ -+#define PW_KEY_MEDIA_TYPE "media.type" /**< Media type, one of -+ * Audio, Video, Midi */ -+#define PW_KEY_MEDIA_CATEGORY "media.category" /**< Media Category: -+ * Playback, Capture, Duplex, Monitor */ -+#define PW_KEY_MEDIA_ROLE "media.role" /**< Role: Movie, Music, Camera, -+ * Screen, Communication, Game, -+ * Notification, DSP, Production, -+ * Accessibility, Test */ -+#define PW_KEY_MEDIA_CLASS "media.class" /**< class Ex: "Video/Source" */ -+#define PW_KEY_MEDIA_NAME "media.name" /**< media name. Ex: "Pink Floyd: Time" */ -+#define PW_KEY_MEDIA_TITLE "media.title" /**< title. Ex: "Time" */ -+#define PW_KEY_MEDIA_ARTIST "media.artist" /**< artist. Ex: "Pink Floyd" */ -+#define PW_KEY_MEDIA_COPYRIGHT "media.copyright" /**< copyright string */ -+#define PW_KEY_MEDIA_SOFTWARE "media.software" /**< generator software */ -+#define PW_KEY_MEDIA_LANGUAGE "media.language" /**< language in POSIX format. Ex: en_GB */ -+#define PW_KEY_MEDIA_FILENAME "media.filename" /**< filename */ -+#define PW_KEY_MEDIA_ICON "media.icon" /**< icon for the media, a base64 blob with -+ * PNG image data */ -+#define PW_KEY_MEDIA_ICON_NAME "media.icon-name" /**< an XDG icon name for the media. -+ * Ex: "audio-x-mp3" */ -+ -+/** format related properties */ -+#define PW_KEY_FORMAT_DSP "format.dsp" /**< a dsp format. -+ * Ex: "32 bit float mono audio" */ -+/** audio related properties */ -+#define PW_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel. Ex: "FL" */ -+#define PW_KEY_AUDIO_RATE "audio.samplerate" /**< an audio samplerate */ -+#define PW_KEY_AUDIO_CHANNELS "audio.channels" /**< number of audio channels */ -+#define PW_KEY_AUDIO_FORMAT "audio.format" /**< an audio format. Ex: "S16LE" */ -+ -+/** video related properties */ -+#define PW_KEY_VIDEO_RATE "video.framerate" /**< a video framerate */ -+#define PW_KEY_VIDEO_FORMAT "video.format" /**< a video format */ -+#define PW_KEY_VIDEO_SIZE "video.size" /**< a video size as "x -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Link PW_TYPE_INFO_INTERFACE_BASE "Link" -+ -+#define PW_VERSION_LINK 3 -+struct pw_link; -+ -+/** \enum pw_link_state The different link states \memberof pw_link */ -+enum pw_link_state { -+ PW_LINK_STATE_ERROR = -2, /**< the link is in error */ -+ PW_LINK_STATE_UNLINKED = -1, /**< the link is unlinked */ -+ PW_LINK_STATE_INIT = 0, /**< the link is initialized */ -+ PW_LINK_STATE_NEGOTIATING = 1, /**< the link is negotiating formats */ -+ PW_LINK_STATE_ALLOCATING = 2, /**< the link is allocating buffers */ -+ PW_LINK_STATE_PAUSED = 3, /**< the link is paused */ -+}; -+ -+/** Convert a \ref pw_link_state to a readable string \memberof pw_link */ -+const char * pw_link_state_as_string(enum pw_link_state state); -+/** The link information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_link_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t output_node_id; /**< server side output node id */ -+ uint32_t output_port_id; /**< output port id */ -+ uint32_t input_node_id; /**< server side input node id */ -+ uint32_t input_port_id; /**< input port id */ -+#define PW_LINK_CHANGE_MASK_STATE (1 << 0) -+#define PW_LINK_CHANGE_MASK_FORMAT (1 << 1) -+#define PW_LINK_CHANGE_MASK_PROPS (1 << 2) -+#define PW_LINK_CHANGE_MASK_ALL ((1 << 3)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ enum pw_link_state state; /**< the current state of the link */ -+ const char *error; /**< an error reason if \a state is error */ -+ struct spa_pod *format; /**< format over link */ -+ struct spa_dict *props; /**< the properties of the link */ -+}; -+ -+struct pw_link_info * -+pw_link_info_update(struct pw_link_info *info, -+ const struct pw_link_info *update); -+ -+void -+pw_link_info_free(struct pw_link_info *info); -+ -+ -+#define PW_LINK_EVENT_INFO 0 -+#define PW_LINK_EVENT_NUM 1 -+ -+/** Link events */ -+struct pw_link_events { -+#define PW_VERSION_LINK_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify link info -+ * -+ * \param info info about the link -+ */ -+ void (*info) (void *object, const struct pw_link_info *info); -+}; -+ -+#define PW_LINK_METHOD_ADD_LISTENER 0 -+#define PW_LINK_METHOD_NUM 1 -+ -+/** Link methods */ -+struct pw_link_methods { -+#define PW_VERSION_LINK_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_link_events *events, -+ void *data); -+}; -+ -+#define pw_link_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_link_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_link_add_listener(c,...) pw_link_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_LINK_H */ -diff --git a/third_party/pipewire/pipewire/log.h b/third_party/pipewire/pipewire/log.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/log.h -@@ -0,0 +1,97 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_LOG_H -+#define PIPEWIRE_LOG_H -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_log -+ * -+ * Logging functions of PipeWire -+ * -+ * Logging is performed to stdout and stderr. Trace logging is performed -+ * in a lockfree ringbuffer and written out from the main thread as to not -+ * block the realtime threads. -+ */ -+ -+/** The global log level */ -+extern enum spa_log_level pw_log_level; -+ -+/** Configure a logging module. This is usually done automatically -+ * in pw_init() but you can install a custom logger before calling -+ * pw_init(). */ -+void pw_log_set(struct spa_log *log); -+ -+/** Get the log interface */ -+struct spa_log *pw_log_get(void); -+ -+/** Configure the logging level */ -+void pw_log_set_level(enum spa_log_level level); -+ -+ -+/** Log a message */ -+void -+pw_log_log(enum spa_log_level level, -+ const char *file, -+ int line, const char *func, -+ const char *fmt, ...) SPA_PRINTF_FUNC(5, 6); -+ -+/** Log a message */ -+void -+pw_log_logv(enum spa_log_level level, -+ const char *file, -+ int line, const char *func, -+ const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0); -+ -+ -+/** Check if a loglevel is enabled \memberof pw_log */ -+#define pw_log_level_enabled(lev) (pw_log_level >= (lev)) -+ -+#define pw_log(lev,...) \ -+({ \ -+ if (SPA_UNLIKELY(pw_log_level_enabled (lev))) \ -+ pw_log_log(lev,__FILE__,__LINE__,__func__,__VA_ARGS__); \ -+}) -+ -+#define pw_log_error(...) pw_log(SPA_LOG_LEVEL_ERROR,__VA_ARGS__) -+#define pw_log_warn(...) pw_log(SPA_LOG_LEVEL_WARN,__VA_ARGS__) -+#define pw_log_info(...) pw_log(SPA_LOG_LEVEL_INFO,__VA_ARGS__) -+#define pw_log_debug(...) pw_log(SPA_LOG_LEVEL_DEBUG,__VA_ARGS__) -+#define pw_log_trace(...) pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__) -+ -+#ifndef FASTPATH -+#define pw_log_trace_fp(...) pw_log(SPA_LOG_LEVEL_TRACE,__VA_ARGS__) -+#else -+#define pw_log_trace_fp(...) -+#endif -+ -+#ifdef __cplusplus -+} -+#endif -+#endif /* PIPEWIRE_LOG_H */ -diff --git a/third_party/pipewire/pipewire/loop.h b/third_party/pipewire/pipewire/loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/loop.h -@@ -0,0 +1,80 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_LOOP_H -+#define PIPEWIRE_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_loop -+ * -+ * PipeWire loop object provides an implementation of -+ * the spa loop interfaces. It can be used to implement various -+ * event loops. -+ */ -+struct pw_loop { -+ struct spa_system *system; /**< system utils */ -+ struct spa_loop *loop; /**< wrapped loop */ -+ struct spa_loop_control *control; /**< loop control */ -+ struct spa_loop_utils *utils; /**< loop utils */ -+}; -+ -+struct pw_loop * -+pw_loop_new(const struct spa_dict *props); -+ -+void -+pw_loop_destroy(struct pw_loop *loop); -+ -+#define pw_loop_add_source(l,...) spa_loop_add_source((l)->loop,__VA_ARGS__) -+#define pw_loop_update_source(l,...) spa_loop_update_source(__VA_ARGS__) -+#define pw_loop_remove_source(l,...) spa_loop_remove_source(__VA_ARGS__) -+#define pw_loop_invoke(l,...) spa_loop_invoke((l)->loop,__VA_ARGS__) -+ -+#define pw_loop_get_fd(l) spa_loop_control_get_fd((l)->control) -+#define pw_loop_add_hook(l,...) spa_loop_control_add_hook((l)->control,__VA_ARGS__) -+#define pw_loop_enter(l) spa_loop_control_enter((l)->control) -+#define pw_loop_iterate(l,...) spa_loop_control_iterate((l)->control,__VA_ARGS__) -+#define pw_loop_leave(l) spa_loop_control_leave((l)->control) -+ -+#define pw_loop_add_io(l,...) spa_loop_utils_add_io((l)->utils,__VA_ARGS__) -+#define pw_loop_update_io(l,...) spa_loop_utils_update_io((l)->utils,__VA_ARGS__) -+#define pw_loop_add_idle(l,...) spa_loop_utils_add_idle((l)->utils,__VA_ARGS__) -+#define pw_loop_enable_idle(l,...) spa_loop_utils_enable_idle((l)->utils,__VA_ARGS__) -+#define pw_loop_add_event(l,...) spa_loop_utils_add_event((l)->utils,__VA_ARGS__) -+#define pw_loop_signal_event(l,...) spa_loop_utils_signal_event((l)->utils,__VA_ARGS__) -+#define pw_loop_add_timer(l,...) spa_loop_utils_add_timer((l)->utils,__VA_ARGS__) -+#define pw_loop_update_timer(l,...) spa_loop_utils_update_timer((l)->utils,__VA_ARGS__) -+#define pw_loop_add_signal(l,...) spa_loop_utils_add_signal((l)->utils,__VA_ARGS__) -+#define pw_loop_destroy_source(l,...) spa_loop_utils_destroy_source((l)->utils,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/main-loop.h b/third_party/pipewire/pipewire/main-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/main-loop.h -@@ -0,0 +1,78 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MAIN_LOOP_H -+#define PIPEWIRE_MAIN_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_main_loop -+ * -+ * \brief PipeWire main-loop interface. -+ * -+ * A main loop object -+ */ -+/** A main loop object \memberof pw_main_loop */ -+struct pw_main_loop; -+ -+#include -+ -+/** Events of the main loop */ -+struct pw_main_loop_events { -+#define PW_VERSION_MAIN_LOOP_EVENTS 0 -+ uint32_t version; -+ -+ /** Emitted when the main loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Create a new main loop. */ -+struct pw_main_loop * -+pw_main_loop_new(const struct spa_dict *props); -+ -+/** Add an event listener */ -+void pw_main_loop_add_listener(struct pw_main_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_main_loop_events *events, -+ void *data); -+ -+/** Get the loop implementation */ -+struct pw_loop * pw_main_loop_get_loop(struct pw_main_loop *loop); -+ -+/** Destroy a loop */ -+void pw_main_loop_destroy(struct pw_main_loop *loop); -+ -+/** Run a main loop. This blocks until \ref pw_main_loop_quit is called */ -+int pw_main_loop_run(struct pw_main_loop *loop); -+ -+/** Quit a main loop */ -+int pw_main_loop_quit(struct pw_main_loop *loop); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_MAIN_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/map.h b/third_party/pipewire/pipewire/map.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/map.h -@@ -0,0 +1,206 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MAP_H -+#define PIPEWIRE_MAP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+/** \class pw_map -+ * -+ * A map that holds objects indexed by id -+ */ -+ -+/** An entry in the map \memberof pw_map */ -+union pw_map_item { -+ uint32_t next; /**< next free index */ -+ void *data; /**< data of this item, must be an even address */ -+}; -+ -+/** A map \memberof pw_map */ -+struct pw_map { -+ struct pw_array items; /**< an array with the map items */ -+ uint32_t free_list; /**< the free items */ -+}; -+ -+#define PW_MAP_INIT(extend) (struct pw_map) { PW_ARRAY_INIT(extend), 0 } -+ -+#define pw_map_get_size(m) pw_array_get_len(&(m)->items, union pw_map_item) -+#define pw_map_get_item(m,id) pw_array_get_unchecked(&(m)->items,id,union pw_map_item) -+#define pw_map_item_is_free(item) ((item)->next & 0x1) -+#define pw_map_id_is_free(m,id) (pw_map_item_is_free(pw_map_get_item(m,id))) -+#define pw_map_check_id(m,id) ((id) < pw_map_get_size(m)) -+#define pw_map_has_item(m,id) (pw_map_check_id(m,id) && !pw_map_id_is_free(m, id)) -+#define pw_map_lookup_unchecked(m,id) pw_map_get_item(m,id)->data -+ -+/** Convert an id to a pointer that can be inserted into the map \memberof pw_map */ -+#define PW_MAP_ID_TO_PTR(id) (SPA_UINT32_TO_PTR((id)<<1)) -+/** Convert a pointer to an id that can be retrieved from the map \memberof pw_map */ -+#define PW_MAP_PTR_TO_ID(p) (SPA_PTR_TO_UINT32(p)>>1) -+ -+/** Initialize a map -+ * \param map the map to initialize -+ * \param size the initial size of the map -+ * \param extend the amount to bytes to grow the map with when needed -+ * \memberof pw_map -+ */ -+static inline void pw_map_init(struct pw_map *map, size_t size, size_t extend) -+{ -+ pw_array_init(&map->items, extend); -+ pw_array_ensure_size(&map->items, size * sizeof(union pw_map_item)); -+ map->free_list = SPA_ID_INVALID; -+} -+ -+/** Clear a map -+ * \param map the map to clear -+ * \memberof pw_map -+ */ -+static inline void pw_map_clear(struct pw_map *map) -+{ -+ pw_array_clear(&map->items); -+} -+ -+static inline void pw_map_reset(struct pw_map *map) -+{ -+ pw_array_reset(&map->items); -+ map->free_list = SPA_ID_INVALID; -+} -+ -+/** Insert data in the map -+ * \param map the map to insert into -+ * \param data the item to add -+ * \return the id where the item was inserted or SPA_ID_INVALID when the -+ * item can not be inserted. -+ * \memberof pw_map -+ */ -+static inline uint32_t pw_map_insert_new(struct pw_map *map, void *data) -+{ -+ union pw_map_item *start, *item; -+ uint32_t id; -+ -+ if (map->free_list != SPA_ID_INVALID) { -+ start = (union pw_map_item *) map->items.data; -+ item = &start[map->free_list >> 1]; -+ map->free_list = item->next; -+ } else { -+ item = (union pw_map_item *) pw_array_add(&map->items, sizeof(union pw_map_item)); -+ if (item == NULL) -+ return SPA_ID_INVALID; -+ start = (union pw_map_item *) map->items.data; -+ } -+ item->data = data; -+ id = (item - start); -+ return id; -+} -+ -+/** Insert data in the map at an index -+ * \param map the map to inser into -+ * \param id the index to insert at -+ * \param data the data to insert -+ * \return 0 on success, -ENOSPC value when the index is invalid or a < 0 -+ * errno value. -+ * \memberof pw_map -+ */ -+static inline int pw_map_insert_at(struct pw_map *map, uint32_t id, void *data) -+{ -+ size_t size = pw_map_get_size(map); -+ union pw_map_item *item; -+ -+ if (id > size) -+ return -ENOSPC; -+ else if (id == size) { -+ item = (union pw_map_item *) pw_array_add(&map->items, sizeof(union pw_map_item)); -+ if (item == NULL) -+ return -errno; -+ } -+ else { -+ item = pw_map_get_item(map, id); -+ } -+ item->data = data; -+ return 0; -+} -+ -+/** Remove an item at index -+ * \param map the map to remove from -+ * \param id the index to remove -+ * \memberof pw_map -+ */ -+static inline void pw_map_remove(struct pw_map *map, uint32_t id) -+{ -+ pw_map_get_item(map, id)->next = map->free_list; -+ map->free_list = (id << 1) | 1; -+} -+ -+/** Find an item in the map -+ * \param map the map to use -+ * \param id the index to look at -+ * \return the item at \a id or NULL when no such item exists -+ * \memberof pw_map -+ */ -+static inline void *pw_map_lookup(struct pw_map *map, uint32_t id) -+{ -+ if (SPA_LIKELY(pw_map_check_id(map, id))) { -+ union pw_map_item *item = pw_map_get_item(map, id); -+ if (!pw_map_item_is_free(item)) -+ return item->data; -+ } -+ return NULL; -+} -+ -+/** Iterate all map items -+ * \param map the map to iterate -+ * \param func the function to call for each item, the item data and \a data is -+ * passed to the function. When \a func returns a non-zero result, -+ * iteration ends and the result is returned. -+ * \param data data to pass to \a func -+ * \return the result of the last call to \a func or 0 when all callbacks returned 0. -+ * \memberof pw_map -+ */ -+static inline int pw_map_for_each(struct pw_map *map, -+ int (*func) (void *item_data, void *data), void *data) -+{ -+ union pw_map_item *item; -+ int res = 0; -+ -+ pw_array_for_each(item, &map->items) { -+ if (!pw_map_item_is_free(item)) -+ if ((res = func(item->data, data)) != 0) -+ break; -+ } -+ return res; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_MAP_H */ -diff --git a/third_party/pipewire/pipewire/mem.h b/third_party/pipewire/pipewire/mem.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/mem.h -@@ -0,0 +1,199 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MEM_H -+#define PIPEWIRE_MEM_H -+ -+#include -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Flags passed to \ref pw_mempool_alloc() \memberof pw_memblock */ -+enum pw_memblock_flags { -+ PW_MEMBLOCK_FLAG_NONE = 0, -+ PW_MEMBLOCK_FLAG_READABLE = (1 << 0), /**< memory is readable */ -+ PW_MEMBLOCK_FLAG_WRITABLE = (1 << 1), /**< memory is writable */ -+ PW_MEMBLOCK_FLAG_SEAL = (1 << 2), /**< seal the fd */ -+ PW_MEMBLOCK_FLAG_MAP = (1 << 3), /**< mmap the fd */ -+ PW_MEMBLOCK_FLAG_DONT_CLOSE = (1 << 4), /**< don't close fd */ -+ PW_MEMBLOCK_FLAG_DONT_NOTIFY = (1 << 5), /**< don't notify events */ -+ -+ PW_MEMBLOCK_FLAG_READWRITE = PW_MEMBLOCK_FLAG_READABLE | PW_MEMBLOCK_FLAG_WRITABLE, -+}; -+ -+enum pw_memmap_flags { -+ PW_MEMMAP_FLAG_NONE = 0, -+ PW_MEMMAP_FLAG_READ = (1 << 0), /**< map in read mode */ -+ PW_MEMMAP_FLAG_WRITE = (1 << 1), /**< map in write mode */ -+ PW_MEMMAP_FLAG_TWICE = (1 << 2), /**< map the same area twice after each other, -+ * creating a circular ringbuffer */ -+ PW_MEMMAP_FLAG_PRIVATE = (1 << 3), /**< writes will be private */ -+ PW_MEMMAP_FLAG_READWRITE = PW_MEMMAP_FLAG_READ | PW_MEMMAP_FLAG_WRITE, -+}; -+ -+struct pw_memchunk; -+ -+/** \class pw_memblock -+ * -+ * A memory pool is a collection of pw_memblocks */ -+struct pw_mempool { -+ struct pw_properties *props; -+}; -+ -+/** \class pw_memblock -+ * Memory block structure */ -+struct pw_memblock { -+ struct pw_mempool *pool; /**< owner pool */ -+ uint32_t id; /**< unique id */ -+ int ref; /**< refcount */ -+ uint32_t flags; /**< flags for the memory block on of enum pw_memblock_flags */ -+ uint32_t type; /**< type of the fd, one of enum spa_data_type */ -+ int fd; /**< fd */ -+ uint32_t size; /**< size of memory */ -+ struct pw_memmap *map; /**< optional map when PW_MEMBLOCK_FLAG_MAP was given */ -+}; -+ -+/** a mapped region of a pw_memblock */ -+struct pw_memmap { -+ struct pw_memblock *block; /**< owner memblock */ -+ void *ptr; /**< mapped pointer */ -+ uint32_t flags; /**< flags for the mapping on of enum pw_memmap_flags */ -+ uint32_t offset; /**< offset in memblock */ -+ uint32_t size; /**< size in memblock */ -+ uint32_t tag[5]; /**< user tag */ -+}; -+ -+struct pw_mempool_events { -+#define PW_VERSION_MEMPOOL_EVENTS 0 -+ uint32_t version; -+ -+ /** the pool is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a new memory block is added to the pool */ -+ void (*added) (void *data, struct pw_memblock *block); -+ -+ /** a memory block is removed from the pool */ -+ void (*removed) (void *data, struct pw_memblock *block); -+}; -+ -+/** Create a new memory pool */ -+struct pw_mempool *pw_mempool_new(struct pw_properties *props); -+ -+/** Listen for events */ -+void pw_mempool_add_listener(struct pw_mempool *pool, -+ struct spa_hook *listener, -+ const struct pw_mempool_events *events, -+ void *data); -+ -+/** Clear a pool */ -+void pw_mempool_clear(struct pw_mempool *pool); -+ -+/** Clear and destroy a pool */ -+void pw_mempool_destroy(struct pw_mempool *pool); -+ -+ -+/** Allocate a memory block from the pool */ -+struct pw_memblock * pw_mempool_alloc(struct pw_mempool *pool, -+ enum pw_memblock_flags flags, uint32_t type, size_t size); -+ -+/** Import a block from another pool */ -+struct pw_memblock * pw_mempool_import_block(struct pw_mempool *pool, -+ struct pw_memblock *mem); -+ -+/** Import an fd into the pool */ -+struct pw_memblock * pw_mempool_import(struct pw_mempool *pool, -+ enum pw_memblock_flags flags, uint32_t type, int fd); -+ -+/** Free a memblock regardless of the refcount and destroy all mappings */ -+void pw_memblock_free(struct pw_memblock *mem); -+ -+/** Unref a memblock */ -+static inline void pw_memblock_unref(struct pw_memblock *mem) -+{ -+ if (--mem->ref == 0) -+ pw_memblock_free(mem); -+} -+ -+/** Remove a memblock for given \a id */ -+int pw_mempool_remove_id(struct pw_mempool *pool, uint32_t id); -+ -+/** Find memblock for given \a ptr */ -+struct pw_memblock * pw_mempool_find_ptr(struct pw_mempool *pool, const void *ptr); -+ -+/** Find memblock for given \a id */ -+struct pw_memblock * pw_mempool_find_id(struct pw_mempool *pool, uint32_t id); -+ -+/** Find memblock for given \a fd */ -+struct pw_memblock * pw_mempool_find_fd(struct pw_mempool *pool, int fd); -+ -+ -+/** Map a region of a memory block */ -+struct pw_memmap * pw_memblock_map(struct pw_memblock *block, -+ enum pw_memmap_flags flags, uint32_t offset, uint32_t size, -+ uint32_t tag[5]); -+ -+/** Map a region of a memory block with \a id */ -+struct pw_memmap * pw_mempool_map_id(struct pw_mempool *pool, uint32_t id, -+ enum pw_memmap_flags flags, uint32_t offset, uint32_t size, -+ uint32_t tag[5]); -+ -+struct pw_memmap * pw_mempool_import_map(struct pw_mempool *pool, -+ struct pw_mempool *other, void *data, uint32_t size, uint32_t tag[5]); -+ -+/** find a map with the given tag */ -+struct pw_memmap * pw_mempool_find_tag(struct pw_mempool *pool, uint32_t tag[5], size_t size); -+ -+/** Unmap a region */ -+int pw_memmap_free(struct pw_memmap *map); -+ -+ -+/** parameters to map a memory range */ -+struct pw_map_range { -+ uint32_t start; /** offset in first page with start of data */ -+ uint32_t offset; /** page aligned offset to map */ -+ uint32_t size; /** size to map */ -+}; -+ -+#define PW_MAP_RANGE_INIT (struct pw_map_range){ 0, } -+ -+/** Calculate parameters to mmap() memory into \a range so that -+ * \a size bytes at \a offset can be mapped with mmap(). */ -+static inline void pw_map_range_init(struct pw_map_range *range, -+ uint32_t offset, uint32_t size, -+ uint32_t page_size) -+{ -+ range->offset = SPA_ROUND_DOWN_N(offset, page_size); -+ range->start = offset - range->offset; -+ range->size = SPA_ROUND_UP_N(range->start + size, page_size); -+} -+ -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_MEM_H */ -diff --git a/third_party/pipewire/pipewire/module.h b/third_party/pipewire/pipewire/module.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/module.h -@@ -0,0 +1,106 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_MODULE_H -+#define PIPEWIRE_MODULE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Module PW_TYPE_INFO_INTERFACE_BASE "Module" -+ -+#define PW_VERSION_MODULE 3 -+struct pw_module; -+ -+/** The module information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_module_info { -+ uint32_t id; /**< id of the global */ -+ const char *name; /**< name of the module */ -+ const char *filename; /**< filename of the module */ -+ const char *args; /**< arguments passed to the module */ -+#define PW_MODULE_CHANGE_MASK_PROPS (1 << 0) -+#define PW_MODULE_CHANGE_MASK_ALL ((1 << 1)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< extra properties */ -+}; -+ -+/** Update and existing \ref pw_module_info with \a update \memberof pw_introspect */ -+struct pw_module_info * -+pw_module_info_update(struct pw_module_info *info, -+ const struct pw_module_info *update); -+ -+/** Free a \ref pw_module_info \memberof pw_introspect */ -+void pw_module_info_free(struct pw_module_info *info); -+ -+#define PW_MODULE_EVENT_INFO 0 -+#define PW_MODULE_EVENT_NUM 1 -+ -+/** Module events */ -+struct pw_module_events { -+#define PW_VERSION_MODULE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify module info -+ * -+ * \param info info about the module -+ */ -+ void (*info) (void *object, const struct pw_module_info *info); -+}; -+ -+#define PW_MODULE_METHOD_ADD_LISTENER 0 -+#define PW_MODULE_METHOD_NUM 1 -+ -+/** Module methods */ -+struct pw_module_methods { -+#define PW_VERSION_MODULE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_module_events *events, -+ void *data); -+}; -+ -+#define pw_module_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_module_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_module_add_listener(c,...) pw_module_method(c,add_listener,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_MODULE_H */ -diff --git a/third_party/pipewire/pipewire/node.h b/third_party/pipewire/pipewire/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/node.h -@@ -0,0 +1,200 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_NODE_H -+#define PIPEWIRE_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Node PW_TYPE_INFO_INTERFACE_BASE "Node" -+ -+#define PW_VERSION_NODE 3 -+struct pw_node; -+ -+/** \enum pw_node_state The different node states \memberof pw_node */ -+enum pw_node_state { -+ PW_NODE_STATE_ERROR = -1, /**< error state */ -+ PW_NODE_STATE_CREATING = 0, /**< the node is being created */ -+ PW_NODE_STATE_SUSPENDED = 1, /**< the node is suspended, the device might -+ * be closed */ -+ PW_NODE_STATE_IDLE = 2, /**< the node is running but there is no active -+ * port */ -+ PW_NODE_STATE_RUNNING = 3, /**< the node is running */ -+}; -+ -+/** Convert a \ref pw_node_state to a readable string \memberof pw_node */ -+const char * pw_node_state_as_string(enum pw_node_state state); -+ -+/** The node information. Extra information can be added in later versions \memberof pw_introspect */ -+struct pw_node_info { -+ uint32_t id; /**< id of the global */ -+ uint32_t max_input_ports; /**< maximum number of inputs */ -+ uint32_t max_output_ports; /**< maximum number of outputs */ -+#define PW_NODE_CHANGE_MASK_INPUT_PORTS (1 << 0) -+#define PW_NODE_CHANGE_MASK_OUTPUT_PORTS (1 << 1) -+#define PW_NODE_CHANGE_MASK_STATE (1 << 2) -+#define PW_NODE_CHANGE_MASK_PROPS (1 << 3) -+#define PW_NODE_CHANGE_MASK_PARAMS (1 << 4) -+#define PW_NODE_CHANGE_MASK_ALL ((1 << 5)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ uint32_t n_input_ports; /**< number of inputs */ -+ uint32_t n_output_ports; /**< number of outputs */ -+ enum pw_node_state state; /**< the current state of the node */ -+ const char *error; /**< an error reason if \a state is error */ -+ struct spa_dict *props; /**< the properties of the node */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+struct pw_node_info * -+pw_node_info_update(struct pw_node_info *info, -+ const struct pw_node_info *update); -+ -+void -+pw_node_info_free(struct pw_node_info *info); -+ -+#define PW_NODE_EVENT_INFO 0 -+#define PW_NODE_EVENT_PARAM 1 -+#define PW_NODE_EVENT_NUM 2 -+ -+/** Node events */ -+struct pw_node_events { -+#define PW_VERSION_NODE_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify node info -+ * -+ * \param info info about the node -+ */ -+ void (*info) (void *object, const struct pw_node_info *info); -+ /** -+ * Notify a node param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+#define PW_NODE_METHOD_ADD_LISTENER 0 -+#define PW_NODE_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_NODE_METHOD_ENUM_PARAMS 2 -+#define PW_NODE_METHOD_SET_PARAM 3 -+#define PW_NODE_METHOD_SEND_COMMAND 4 -+#define PW_NODE_METHOD_NUM 5 -+ -+/** Node methods */ -+struct pw_node_methods { -+#define PW_VERSION_NODE_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_node_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate node parameters -+ * -+ * Start enumeration of node parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number to place in the reply -+ * \param id the parameter id to enum or PW_ID_ANY for all -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, uint32_t id, -+ uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set a parameter on the node -+ * -+ * \param id the parameter id to set -+ * \param flags extra parameter flags -+ * \param param the parameter to set -+ */ -+ int (*set_param) (void *object, uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Send a command to the node -+ * -+ * \param command the command to send -+ */ -+ int (*send_command) (void *object, const struct spa_command *command); -+}; -+ -+#define pw_node_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_node_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+/** Node */ -+#define pw_node_add_listener(c,...) pw_node_method(c,add_listener,0,__VA_ARGS__) -+#define pw_node_subscribe_params(c,...) pw_node_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_node_enum_params(c,...) pw_node_method(c,enum_params,0,__VA_ARGS__) -+#define pw_node_set_param(c,...) pw_node_method(c,set_param,0,__VA_ARGS__) -+#define pw_node_send_command(c,...) pw_node_method(c,send_command,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_NODE_H */ -diff --git a/third_party/pipewire/pipewire/permission.h b/third_party/pipewire/pipewire/permission.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/permission.h -@@ -0,0 +1,79 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PERMISSION_H -+#define PIPEWIRE_PERMISSION_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \class pw_permission -+ * -+ * \brief a PipeWire permission -+ * -+ * Permissions are kept for a client and describe what the client is -+ * allowed to do with an object. -+ * -+ * See \ref page_core_api -+ */ -+ -+#define PW_PERM_R 0400 /**< object can be seen and events can be received */ -+#define PW_PERM_W 0200 /**< methods can be called that modify the object */ -+#define PW_PERM_X 0100 /**< methods can be called on the object. The W flag must be -+ * present in order to call methods that modify the object. */ -+#define PW_PERM_M 0010 /**< metadata can be set on object, Since 0.3.9 */ -+ -+#define PW_PERM_RWX (PW_PERM_R|PW_PERM_W|PW_PERM_X) -+#define PW_PERM_RWXM (PW_PERM_RWX|PW_PERM_M) -+ -+#define PW_PERM_IS_R(p) (((p)&PW_PERM_R) == PW_PERM_R) -+#define PW_PERM_IS_W(p) (((p)&PW_PERM_W) == PW_PERM_W) -+#define PW_PERM_IS_X(p) (((p)&PW_PERM_X) == PW_PERM_X) -+#define PW_PERM_IS_M(p) (((p)&PW_PERM_M) == PW_PERM_M) -+ -+#define PW_PERM_ALL PW_PERM_RWXM -+#define PW_PERM_INVALID (uint32_t)(0xffffffff) -+ -+struct pw_permission { -+ uint32_t id; /**< id of object, PW_ID_ANY for default permission */ -+ uint32_t permissions; /**< bitmask of above permissions */ -+}; -+ -+#define PW_PERMISSION_INIT(id,p) (struct pw_permission){ (id), (p) } -+ -+#define PW_PERMISSION_FORMAT "%c%c%c%c" -+#define PW_PERMISSION_ARGS(permission) \ -+ (permission) & PW_PERM_R ? 'r' : '-', \ -+ (permission) & PW_PERM_W ? 'w' : '-', \ -+ (permission) & PW_PERM_X ? 'x' : '-', \ -+ (permission) & PW_PERM_M ? 'm' : '-' -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PERMISSION_H */ -diff --git a/third_party/pipewire/pipewire/pipewire.h b/third_party/pipewire/pipewire/pipewire.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/pipewire.h -@@ -0,0 +1,158 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_H -+#define PIPEWIRE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+#include -+ -+/** \mainpage -+ * -+ * \section sec_intro Introduction -+ * -+ * This document describes the API for the PipeWire multimedia framework. -+ * The API consists of two parts: -+ * -+ * \li The core API to access a PipeWire instance. -+ * (See \subpage page_core_api) -+ * \li The implementation API and tools to build new objects and -+ * modules (See \subpage page_implementation_api) -+ * -+ * \section sec_errors Error reporting -+ * -+ * Functions return either NULL with errno set or a negative int error -+ * code when an error occurs. Error codes are used from the SPA plugin -+ * library on which PipeWire is built. -+ * -+ * Some functions might return asynchronously. The error code for such -+ * functions is positive and SPA_RESULT_IS_ASYNC() will return true. -+ * SPA_RESULT_ASYNC_SEQ() can be used to get the unique sequence number -+ * associated with the async operation. -+ * -+ * The object returning the async result code will have some way to -+ * signal the completion of the async operation (with, for example, a -+ * callback). The sequence number can be used to see which operation -+ * completed. -+ * -+ * \section sec_logging Logging -+ * -+ * The 'PIPEWIRE_DEBUG' environment variable can be used to enable -+ * more debugging. The format is: -+ * -+ * <level>[:<category>,...] -+ * -+ * - <level>: specifies the log level: -+ * + `0`: no logging is enabled -+ * + `1`: Error logging is enabled -+ * + `2`: Warnings are enabled -+ * + `3`: Informational messages are enabled -+ * + `4`: Debug messages are enabled -+ * + `5`: Trace messages are enabled. These messages can be logged -+ * from the realtime threads. -+ * -+ * - <category>: Specifies a string category to enable. Many categories -+ * can be separated by commas. Current categories are: -+ * + `connection`: to log connection messages -+ */ -+ -+/** \class pw_pipewire -+ * -+ * \brief PipeWire initialization and infrastructure functions -+ */ -+void -+pw_init(int *argc, char **argv[]); -+ -+void pw_deinit(void); -+ -+bool -+pw_debug_is_category_enabled(const char *name); -+ -+const char * -+pw_get_application_name(void); -+ -+const char * -+pw_get_prgname(void); -+ -+const char * -+pw_get_user_name(void); -+ -+const char * -+pw_get_host_name(void); -+ -+const char * -+pw_get_client_name(void); -+ -+bool pw_in_valgrind(void); -+ -+enum pw_direction -+pw_direction_reverse(enum pw_direction direction); -+ -+uint32_t pw_get_support(struct spa_support *support, uint32_t max_support); -+ -+struct spa_handle *pw_load_spa_handle(const char *lib, -+ const char *factory_name, -+ const struct spa_dict *info, -+ uint32_t n_support, -+ const struct spa_support support[]); -+ -+int pw_unload_spa_handle(struct spa_handle *handle); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_H */ -diff --git a/third_party/pipewire/pipewire/port.h b/third_party/pipewire/pipewire/port.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/port.h -@@ -0,0 +1,169 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PORT_H -+#define PIPEWIRE_PORT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+#include -+ -+#include -+ -+#define PW_TYPE_INTERFACE_Port PW_TYPE_INFO_INTERFACE_BASE "Port" -+ -+#define PW_VERSION_PORT 3 -+struct pw_port; -+ -+/** \enum pw_direction The direction of a port \memberof pw_introspect */ -+#define pw_direction spa_direction -+#define PW_DIRECTION_INPUT SPA_DIRECTION_INPUT -+#define PW_DIRECTION_OUTPUT SPA_DIRECTION_OUTPUT -+ -+/** Convert a \ref pw_direction to a readable string \memberof pw_introspect */ -+const char * pw_direction_as_string(enum pw_direction direction); -+ -+ -+/** \class pw_introspect -+ * -+ * The introspection methods and structures are used to get information -+ * about the object in the PipeWire server -+ */ -+ -+struct pw_port_info { -+ uint32_t id; /**< id of the global */ -+ enum pw_direction direction; /**< port direction */ -+#define PW_PORT_CHANGE_MASK_PROPS (1 << 0) -+#define PW_PORT_CHANGE_MASK_PARAMS (1 << 1) -+#define PW_PORT_CHANGE_MASK_ALL ((1 << 2)-1) -+ uint64_t change_mask; /**< bitfield of changed fields since last call */ -+ struct spa_dict *props; /**< the properties of the port */ -+ struct spa_param_info *params; /**< parameters */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+struct pw_port_info * -+pw_port_info_update(struct pw_port_info *info, -+ const struct pw_port_info *update); -+ -+void -+pw_port_info_free(struct pw_port_info *info); -+ -+#define PW_PORT_EVENT_INFO 0 -+#define PW_PORT_EVENT_PARAM 1 -+#define PW_PORT_EVENT_NUM 2 -+ -+/** Port events */ -+struct pw_port_events { -+#define PW_VERSION_PORT_EVENTS 0 -+ uint32_t version; -+ /** -+ * Notify port info -+ * -+ * \param info info about the port -+ */ -+ void (*info) (void *object, const struct pw_port_info *info); -+ /** -+ * Notify a port param -+ * -+ * Event emitted as a result of the enum_params method. -+ * -+ * \param seq the sequence number of the request -+ * \param id the param id -+ * \param index the param index -+ * \param next the param index of the next param -+ * \param param the parameter -+ */ -+ void (*param) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t next, -+ const struct spa_pod *param); -+}; -+ -+#define PW_PORT_METHOD_ADD_LISTENER 0 -+#define PW_PORT_METHOD_SUBSCRIBE_PARAMS 1 -+#define PW_PORT_METHOD_ENUM_PARAMS 2 -+#define PW_PORT_METHOD_NUM 3 -+ -+/** Port methods */ -+struct pw_port_methods { -+#define PW_VERSION_PORT_METHODS 0 -+ uint32_t version; -+ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct pw_port_events *events, -+ void *data); -+ /** -+ * Subscribe to parameter changes -+ * -+ * Automatically emit param events for the given ids when -+ * they are changed. -+ * -+ * \param ids an array of param ids -+ * \param n_ids the number of ids in \a ids -+ */ -+ int (*subscribe_params) (void *object, uint32_t *ids, uint32_t n_ids); -+ -+ /** -+ * Enumerate port parameters -+ * -+ * Start enumeration of port parameters. For each param, a -+ * param event will be emitted. -+ * -+ * \param seq a sequence number returned in the reply -+ * \param id the parameter id to enumerate -+ * \param start the start index or 0 for the first param -+ * \param num the maximum number of params to retrieve -+ * \param filter a param filter or NULL -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t start, uint32_t num, -+ const struct spa_pod *filter); -+}; -+ -+#define pw_port_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)o, \ -+ struct pw_port_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define pw_port_add_listener(c,...) pw_port_method(c,add_listener,0,__VA_ARGS__) -+#define pw_port_subscribe_params(c,...) pw_port_method(c,subscribe_params,0,__VA_ARGS__) -+#define pw_port_enum_params(c,...) pw_port_method(c,enum_params,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_PORT_H */ -diff --git a/third_party/pipewire/pipewire/properties.h b/third_party/pipewire/pipewire/properties.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/properties.h -@@ -0,0 +1,121 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROPERTIES_H -+#define PIPEWIRE_PROPERTIES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+/** \class pw_properties -+ * -+ * \brief A collection of key/value pairs -+ * -+ * Properties are used to pass around arbitrary key/value pairs. -+ * Both keys and values are strings which keeps things simple. -+ * Encoding of arbitrary values should be done by using a string -+ * serialization such as base64 for binary blobs. -+ */ -+struct pw_properties { -+ struct spa_dict dict; /**< dictionary of key/values */ -+ uint32_t flags; /**< extra flags */ -+}; -+ -+struct pw_properties * -+pw_properties_new(const char *key, ...) SPA_SENTINEL; -+ -+struct pw_properties * -+pw_properties_new_dict(const struct spa_dict *dict); -+ -+struct pw_properties * -+pw_properties_new_string(const char *args); -+ -+struct pw_properties * -+pw_properties_copy(const struct pw_properties *properties); -+ -+int pw_properties_update_keys(struct pw_properties *props, -+ const struct spa_dict *dict, const char *keys[]); -+ -+int pw_properties_update(struct pw_properties *oldprops, -+ const struct spa_dict *dict); -+ -+int pw_properties_add(struct pw_properties *oldprops, -+ const struct spa_dict *dict); -+int pw_properties_add_keys(struct pw_properties *oldprops, -+ const struct spa_dict *dict, const char *keys[]); -+ -+void pw_properties_clear(struct pw_properties *properties); -+ -+void -+pw_properties_free(struct pw_properties *properties); -+ -+int -+pw_properties_set(struct pw_properties *properties, const char *key, const char *value); -+ -+int -+pw_properties_setf(struct pw_properties *properties, -+ const char *key, const char *format, ...) SPA_PRINTF_FUNC(3, 4); -+int -+pw_properties_setva(struct pw_properties *properties, -+ const char *key, const char *format, va_list args) SPA_PRINTF_FUNC(3,0); -+const char * -+pw_properties_get(const struct pw_properties *properties, const char *key); -+ -+const char * -+pw_properties_iterate(const struct pw_properties *properties, void **state); -+ -+static inline bool pw_properties_parse_bool(const char *value) { -+ return (strcmp(value, "true") == 0 || atoi(value) == 1); -+} -+ -+static inline int pw_properties_parse_int(const char *value) { -+ return strtol(value, NULL, 0); -+} -+ -+static inline int64_t pw_properties_parse_int64(const char *value) { -+ return strtoll(value, NULL, 0); -+} -+ -+static inline uint64_t pw_properties_parse_uint64(const char *value) { -+ return strtoull(value, NULL, 0); -+} -+ -+static inline float pw_properties_parse_float(const char *value) { -+ return strtof(value, NULL); -+} -+ -+static inline double pw_properties_parse_double(const char *value) { -+ return strtod(value, NULL); -+} -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PROPERTIES_H */ -diff --git a/third_party/pipewire/pipewire/protocol.h b/third_party/pipewire/pipewire/protocol.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/protocol.h -@@ -0,0 +1,152 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROTOCOL_H -+#define PIPEWIRE_PROTOCOL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+struct pw_protocol; -+ -+#include -+#include -+#include -+ -+#define PW_TYPE_INFO_Protocol "PipeWire:Protocol" -+#define PW_TYPE_INFO_PROTOCOL_BASE PW_TYPE_INFO_Protocol ":" -+ -+struct pw_protocol_client { -+ struct spa_list link; /**< link in protocol client_list */ -+ struct pw_protocol *protocol; /**< the owner protocol */ -+ -+ struct pw_core *core; -+ -+ int (*connect) (struct pw_protocol_client *client, -+ const struct spa_dict *props, -+ void (*done_callback) (void *data, int result), -+ void *data); -+ int (*connect_fd) (struct pw_protocol_client *client, int fd, bool close); -+ int (*steal_fd) (struct pw_protocol_client *client); -+ void (*disconnect) (struct pw_protocol_client *client); -+ void (*destroy) (struct pw_protocol_client *client); -+ int (*set_paused) (struct pw_protocol_client *client, bool paused); -+}; -+ -+#define pw_protocol_client_connect(c,p,cb,d) ((c)->connect(c,p,cb,d)) -+#define pw_protocol_client_connect_fd(c,fd,cl) ((c)->connect_fd(c,fd,cl)) -+#define pw_protocol_client_steal_fd(c) ((c)->steal_fd(c)) -+#define pw_protocol_client_disconnect(c) ((c)->disconnect(c)) -+#define pw_protocol_client_destroy(c) ((c)->destroy(c)) -+#define pw_protocol_client_set_paused(c,p) ((c)->set_paused(c,p)) -+ -+struct pw_protocol_server { -+ struct spa_list link; /**< link in protocol server_list */ -+ struct pw_protocol *protocol; /**< the owner protocol */ -+ -+ struct pw_impl_core *core; -+ -+ struct spa_list client_list; /**< list of clients of this protocol */ -+ -+ void (*destroy) (struct pw_protocol_server *listen); -+}; -+ -+#define pw_protocol_server_destroy(l) ((l)->destroy(l)) -+ -+struct pw_protocol_marshal { -+ const char *type; /**< interface type */ -+ uint32_t version; /**< version */ -+#define PW_PROTOCOL_MARSHAL_FLAG_IMPL (1 << 0) /**< marshal for implementations */ -+ uint32_t flags; /**< version */ -+ uint32_t n_client_methods; /**< number of client methods */ -+ uint32_t n_server_methods; /**< number of server methods */ -+ const void *client_marshal; -+ const void *server_demarshal; -+ const void *server_marshal; -+ const void *client_demarshal; -+}; -+ -+struct pw_protocol_implementaton { -+#define PW_VERSION_PROTOCOL_IMPLEMENTATION 0 -+ uint32_t version; -+ -+ struct pw_protocol_client * (*new_client) (struct pw_protocol *protocol, -+ struct pw_core *core, -+ const struct spa_dict *props); -+ struct pw_protocol_server * (*add_server) (struct pw_protocol *protocol, -+ struct pw_impl_core *core, -+ const struct spa_dict *props); -+}; -+ -+struct pw_protocol_events { -+#define PW_VERSION_PROTOCOL_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+}; -+ -+#define pw_protocol_new_client(p,...) (pw_protocol_get_implementation(p)->new_client(p,__VA_ARGS__)) -+#define pw_protocol_add_server(p,...) (pw_protocol_get_implementation(p)->add_server(p,__VA_ARGS__)) -+#define pw_protocol_ext(p,type,method,...) (((type*)pw_protocol_get_extension(p))->method( __VA_ARGS__)) -+ -+struct pw_protocol *pw_protocol_new(struct pw_context *context, const char *name, size_t user_data_size); -+ -+void pw_protocol_destroy(struct pw_protocol *protocol); -+ -+struct pw_context *pw_protocol_get_context(struct pw_protocol *protocol); -+ -+void *pw_protocol_get_user_data(struct pw_protocol *protocol); -+ -+const struct pw_protocol_implementaton * -+pw_protocol_get_implementation(struct pw_protocol *protocol); -+ -+const void * -+pw_protocol_get_extension(struct pw_protocol *protocol); -+ -+ -+void pw_protocol_add_listener(struct pw_protocol *protocol, -+ struct spa_hook *listener, -+ const struct pw_protocol_events *events, -+ void *data); -+ -+/** \class pw_protocol -+ * -+ * \brief Manages protocols and their implementation -+ */ -+int pw_protocol_add_marshal(struct pw_protocol *protocol, -+ const struct pw_protocol_marshal *marshal); -+ -+const struct pw_protocol_marshal * -+pw_protocol_get_marshal(struct pw_protocol *protocol, const char *type, uint32_t version, uint32_t flags); -+ -+struct pw_protocol * pw_context_find_protocol(struct pw_context *context, const char *name); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_PROTOCOL_H */ -diff --git a/third_party/pipewire/pipewire/proxy.h b/third_party/pipewire/pipewire/proxy.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/proxy.h -@@ -0,0 +1,207 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_PROXY_H -+#define PIPEWIRE_PROXY_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_proxy Proxy -+ * -+ * \section sec_page_proxy_overview Overview -+ * -+ * The proxy object is a client side representation of a resource -+ * that lives on a remote PipeWire instance. -+ * -+ * It is used to communicate with the remote object. -+ * -+ * \section sec_page_proxy_core Core proxy -+ * -+ * A proxy for a remote core object can be obtained by making -+ * a remote connection with \ref pw_core_connect. -+ * See \ref pw_page_remote_api -+ * -+ * Some methods on proxy object allow creation of more proxy objects or -+ * create a binding between a local proxy and global resource. -+ * -+ * \section sec_page_proxy_create Create -+ * -+ * A client first creates a new proxy object with pw_proxy_new(). A -+ * type must be provided for this object. -+ * -+ * The protocol of the context will usually install an interface to -+ * translate method calls and events to the wire format. -+ * -+ * The creator of the proxy will usually also install an event -+ * implementation of the particular object type. -+ * -+ * \section sec_page_proxy_bind Bind -+ * -+ * To actually use the proxy object, one needs to create a server -+ * side resource for it. This can be done by, for example, binding -+ * to a global object or by calling a method that creates and binds -+ * to a new remote object. In all cases, the local id is passed to -+ * the server and is used to create a resource with the same id. -+ * -+ * \section sec_page_proxy_methods Methods -+ * -+ * To call a method on the proxy use the interface methods. Calling -+ * any interface method will result in a request to the server to -+ * perform the requested action on the corresponding resource. -+ * -+ * \section sec_page_proxy_events Events -+ * -+ * Events send from the server to the proxy will be demarshalled by -+ * the protocol and will then result in a call to the installed -+ * implementation of the proxy. -+ * -+ * \section sec_page_proxy_destroy Destroy -+ * -+ * Use pw_proxy_destroy() to destroy the client side object. This -+ * is usually done automatically when the server removes the resource -+ * associated to the proxy. -+ */ -+ -+/** \class pw_proxy -+ * -+ * \brief Represents an object on the client side. -+ * -+ * A pw_proxy acts as a client side proxy to an object existing in a remote -+ * pipewire instance. The proxy is responsible for converting interface functions -+ * invoked by the client to PipeWire messages. Events will call the handlers -+ * set in listener. -+ * -+ * See \ref page_proxy -+ */ -+struct pw_proxy; -+ -+#include -+ -+/** Proxy events, use \ref pw_proxy_add_listener */ -+struct pw_proxy_events { -+#define PW_VERSION_PROXY_EVENTS 0 -+ uint32_t version; -+ -+ /** The proxy is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a proxy is bound to a global id */ -+ void (*bound) (void *data, uint32_t global_id); -+ -+ /** a proxy is removed from the server. Use pw_proxy_destroy to -+ * free the proxy. */ -+ void (*removed) (void *data); -+ -+ /** a reply to a sync method completed */ -+ void (*done) (void *data, int seq); -+ -+ /** an error occurred on the proxy */ -+ void (*error) (void *data, int seq, int res, const char *message); -+}; -+ -+/** Make a new proxy object. The id can be used to bind to a remote object and -+ * can be retrieved with \ref pw_proxy_get_id . */ -+struct pw_proxy * -+pw_proxy_new(struct pw_proxy *factory, /**< factory */ -+ const char *type, /**< interface type */ -+ uint32_t version, /**< interface version */ -+ size_t user_data_size /**< size of user data */); -+ -+/** Add an event listener to proxy */ -+void pw_proxy_add_listener(struct pw_proxy *proxy, -+ struct spa_hook *listener, -+ const struct pw_proxy_events *events, -+ void *data); -+ -+/** Add a listener for the events received from the remote object. The -+ * events depend on the type of the remote object type. */ -+void pw_proxy_add_object_listener(struct pw_proxy *proxy, /**< the proxy */ -+ struct spa_hook *listener, /**< listener */ -+ const void *funcs, /**< proxied functions */ -+ void *data /**< data passed to events */); -+ -+/** destroy a proxy */ -+void pw_proxy_destroy(struct pw_proxy *proxy); -+ -+/** Get the user_data. The size was given in \ref pw_proxy_new */ -+void *pw_proxy_get_user_data(struct pw_proxy *proxy); -+ -+/** Get the local id of the proxy */ -+uint32_t pw_proxy_get_id(struct pw_proxy *proxy); -+ -+/** Get the type and version of the proxy */ -+const char *pw_proxy_get_type(struct pw_proxy *proxy, uint32_t *version); -+ -+/** Get the protocol used for the proxy */ -+struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy); -+ -+/** Generate an sync method for a proxy. This will generate a done event -+ * with the same seq number of the reply. */ -+int pw_proxy_sync(struct pw_proxy *proxy, int seq); -+ -+/** Set the global id this proxy is bound to. This is usually used internally -+ * and will also emit the bound event */ -+int pw_proxy_set_bound_id(struct pw_proxy *proxy, uint32_t global_id); -+/** Get the global id bound to this proxy of SPA_ID_INVALID when not bound -+ * to a global */ -+uint32_t pw_proxy_get_bound_id(struct pw_proxy *proxy); -+ -+/** Generate an error for a proxy */ -+int pw_proxy_error(struct pw_proxy *proxy, int res, const char *error); -+int pw_proxy_errorf(struct pw_proxy *proxy, int res, const char *error, ...) SPA_PRINTF_FUNC(3, 4); -+ -+/** Get the listener of proxy */ -+struct spa_hook_list *pw_proxy_get_object_listeners(struct pw_proxy *proxy); -+ -+/** Get the marshal functions for the proxy */ -+const struct pw_protocol_marshal *pw_proxy_get_marshal(struct pw_proxy *proxy); -+ -+/** Install a marshal function on a proxy */ -+int pw_proxy_install_marshal(struct pw_proxy *proxy, bool implementor); -+ -+#define pw_proxy_notify(p,type,event,version,...) \ -+ spa_hook_list_call(pw_proxy_get_object_listeners(p), \ -+ type, event, version, ## __VA_ARGS__) -+ -+#define pw_proxy_call(p,type,method,version,...) \ -+ spa_interface_call((struct spa_interface*)p, \ -+ type, method, version, ##__VA_ARGS__) -+ -+#define pw_proxy_call_res(p,type,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)p, \ -+ type, _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_PROXY_H */ -diff --git a/third_party/pipewire/pipewire/resource.h b/third_party/pipewire/pipewire/resource.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/resource.h -@@ -0,0 +1,168 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_RESOURCE_H -+#define PIPEWIRE_RESOURCE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_resource Resource -+ * -+ * \section sec_page_resource Overview -+ * -+ * Resources represent objects owned by a \ref pw_impl_client. They are -+ * the result of binding to a global resource or by calling API that -+ * creates client owned objects. -+ * -+ * The client usually has a proxy object associated with the resource -+ * that it can use to communicate with the resource. See \ref page_proxy. -+ * -+ * Resources are destroyed when the client or the bound object is -+ * destroyed. -+ * -+ */ -+ -+/** \class pw_resource -+ * -+ * \brief Client owned objects -+ * -+ * Resources are objects owned by a client and are destroyed when the -+ * client disappears. -+ * -+ * See also \ref page_resource -+ */ -+struct pw_resource; -+ -+#include -+ -+/** Resource events */ -+struct pw_resource_events { -+#define PW_VERSION_RESOURCE_EVENTS 0 -+ uint32_t version; -+ -+ /** The resource is destroyed */ -+ void (*destroy) (void *data); -+ -+ /** a reply to a ping event completed */ -+ void (*pong) (void *data, int seq); -+ -+ /** an error occurred on the resource */ -+ void (*error) (void *data, int seq, int res, const char *message); -+}; -+ -+/** Make a new resource for client */ -+struct pw_resource * -+pw_resource_new(struct pw_impl_client *client, /**< the client owning the resource */ -+ uint32_t id, /**< the remote per client id */ -+ uint32_t permissions, /**< permissions on this resource */ -+ const char *type, /**< interface of the resource */ -+ uint32_t version, /**< requested interface version */ -+ size_t user_data_size /**< extra user data size */); -+ -+/** Destroy a resource */ -+void pw_resource_destroy(struct pw_resource *resource); -+ -+/** Remove a resource, like pw_resource_destroy but without sending a -+ * remove_id message to the client */ -+void pw_resource_remove(struct pw_resource *resource); -+ -+/** Get the client owning this resource */ -+struct pw_impl_client *pw_resource_get_client(struct pw_resource *resource); -+ -+/** Get the unique id of this resource */ -+uint32_t pw_resource_get_id(struct pw_resource *resource); -+ -+/** Get the permissions of this resource */ -+uint32_t pw_resource_get_permissions(struct pw_resource *resource); -+ -+/** Get the type and optionally the version of this resource */ -+const char *pw_resource_get_type(struct pw_resource *resource, uint32_t *version); -+ -+/** Get the protocol used for this resource */ -+struct pw_protocol *pw_resource_get_protocol(struct pw_resource *resource); -+ -+/** Get the user data for the resource, the size was given in \ref pw_resource_new */ -+void *pw_resource_get_user_data(struct pw_resource *resource); -+ -+/** Add an event listener */ -+void pw_resource_add_listener(struct pw_resource *resource, -+ struct spa_hook *listener, -+ const struct pw_resource_events *events, -+ void *data); -+ -+/** Set the resource implementation. */ -+void pw_resource_add_object_listener(struct pw_resource *resource, -+ struct spa_hook *listener, -+ const void *funcs, -+ void *data); -+ -+/** Generate an ping event for a resource. This will generate a pong event -+ * with the same \a sequence number in the return value. */ -+int pw_resource_ping(struct pw_resource *resource, int seq); -+ -+/** Notify global id this resource is bound to */ -+int pw_resource_set_bound_id(struct pw_resource *resource, uint32_t global_id); -+ -+/** Get the global id this resource is bound to or SPA_ID_INVALID when not bound */ -+uint32_t pw_resource_get_bound_id(struct pw_resource *resource); -+ -+/** Generate an error for a resource */ -+void pw_resource_error(struct pw_resource *resource, int res, const char *error); -+void pw_resource_errorf(struct pw_resource *resource, int res, const char *error, ...) SPA_PRINTF_FUNC(3, 4); -+void pw_resource_errorf_id(struct pw_resource *resource, uint32_t id, int res, const char *error, ...) SPA_PRINTF_FUNC(4, 5); -+ -+/** Get the list of object listeners from a resource */ -+struct spa_hook_list *pw_resource_get_object_listeners(struct pw_resource *resource); -+ -+/** Get the marshal functions for the resource */ -+const struct pw_protocol_marshal *pw_resource_get_marshal(struct pw_resource *resource); -+ -+/** install a marshal function on a resource */ -+int pw_resource_install_marshal(struct pw_resource *resource, bool implementor); -+ -+#define pw_resource_notify(r,type,event,version,...) \ -+ spa_hook_list_call(pw_resource_get_object_listeners(r), \ -+ type, event, version, ## __VA_ARGS__) -+ -+#define pw_resource_call(r,type,method,version,...) \ -+ spa_interface_call((struct spa_interface*)r, \ -+ type, method, version, ##__VA_ARGS__) -+ -+#define pw_resource_call_res(r,type,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_interface_call_res((struct spa_interface*)r, \ -+ type, _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_RESOURCE_H */ -diff --git a/third_party/pipewire/pipewire/stream.h b/third_party/pipewire/pipewire/stream.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/stream.h -@@ -0,0 +1,358 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_STREAM_H -+#define PIPEWIRE_STREAM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \page page_streams Media Streams -+ * -+ * \section sec_overview Overview -+ * -+ * Media streams are used to exchange data with the PipeWire server. A -+ * stream is a wrapper around a proxy for a \ref pw_client_node with -+ * an adapter. This means the stream will automatically do conversion -+ * to the type required by the server. -+ * -+ * Streams can be used to: -+ * -+ * \li Consume a stream from PipeWire. This is a PW_DIRECTION_INPUT stream. -+ * \li Produce a stream to PipeWire. This is a PW_DIRECTION_OUTPUT stream -+ * -+ * You can connect the stream port to a specific server port or let PipeWire -+ * choose a port for you. -+ * -+ * For more complicated nodes such as filters or ports with multiple -+ * inputs and/or outputs you will need to use the pw_filter or make -+ * a pw_node yourself and export it with \ref pw_core_export. -+ * -+ * \section sec_create Create -+ * -+ * Make a new stream with \ref pw_stream_new(). You will need to specify -+ * a name for the stream and extra properties. You can use \ref -+ * pw_fill_stream_properties() to get a basic set of properties for the -+ * stream. -+ * -+ * Once the stream is created, the state_changed event should be used to -+ * track the state of the stream. -+ * -+ * \section sec_connect Connect -+ * -+ * The stream is initially unconnected. To connect the stream, use -+ * \ref pw_stream_connect(). Pass the desired direction as an argument. -+ * -+ * \subsection ssec_stream_target Stream target -+ * -+ * To make the newly connected stream automatically connect to an existing -+ * PipeWire node, use the \ref PW_STREAM_FLAG_AUTOCONNECT and the port_path -+ * argument while connecting. -+ * -+ * \subsection ssec_stream_formats Stream formats -+ * -+ * An array of possible formats that this stream can consume or provide -+ * must be specified. -+ * -+ * \section sec_format Format negotiation -+ * -+ * After connecting the stream, the server will want to configure some -+ * parameters on the stream. You will be notified of these changes -+ * with the param_changed event. -+ * -+ * When a format param change is emitted, the client should now prepare -+ * itself to deal with the format and complete the negotiation procedure -+ * with a call to \ref pw_stream_update_params(). -+ * -+ * As arguments to \ref pw_stream_update_params() an array of spa_param -+ * structures must be given. They contain parameters such as buffer size, -+ * number of buffers, required metadata and other parameters for the -+ * media buffers. -+ * -+ * \section sec_buffers Buffer negotiation -+ * -+ * After completing the format negotiation, PipeWire will allocate and -+ * notify the stream of the buffers that will be used to exchange data -+ * between client and server. -+ * -+ * With the add_buffer event, a stream will be notified of a new buffer -+ * that can be used for data transport. You can attach user_data to these -+ * buffers. -+ * -+ * After the buffers are negotiated, the stream will transition to the -+ * \ref PW_STREAM_STATE_PAUSED state. -+ * -+ * \section sec_streaming Streaming -+ * -+ * From the \ref PW_STREAM_STATE_PAUSED state, the stream can be set to -+ * the \ref PW_STREAM_STATE_STREAMING state by the PipeWire server when -+ * data transport is started. -+ * -+ * Depending on how the stream was connected it will need to Produce or -+ * Consume data for/from PipeWire as explained in the following -+ * subsections. -+ * -+ * \subsection ssec_consume Consume data -+ * -+ * The process event is emitted for each new buffer that can can be -+ * consumed. -+ * -+ * \ref pw_stream_dequeue_buffer() should be used to get the data and -+ * metadata of the buffer. -+ * -+ * When the buffer is no longer in use, call \ref pw_stream_queue_buffer() -+ * to let PipeWire reuse the buffer. -+ * -+ * \subsection ssec_produce Produce data -+ * -+ * \ref pw_stream_dequeue_buffer() gives an empty buffer that can be filled. -+ * -+ * Filled buffers should be queued with \ref pw_stream_queue_buffer(). -+ * -+ * The process event is emitted when PipeWire has emptied a buffer that -+ * can now be refilled. -+ * -+ * \section sec_stream_disconnect Disconnect -+ * -+ * Use \ref pw_stream_disconnect() to disconnect a stream after use. -+ */ -+/** \class pw_stream -+ * -+ * \brief PipeWire stream object class -+ * -+ * The stream object provides a convenient way to send and -+ * receive data streams from/to PipeWire. -+ * -+ * See also \ref page_streams and \ref page_context_api -+ */ -+struct pw_stream; -+ -+#include -+#include -+ -+/** \enum pw_stream_state The state of a stream \memberof pw_stream */ -+enum pw_stream_state { -+ PW_STREAM_STATE_ERROR = -1, /**< the stream is in error */ -+ PW_STREAM_STATE_UNCONNECTED = 0, /**< unconnected */ -+ PW_STREAM_STATE_CONNECTING = 1, /**< connection is in progress */ -+ PW_STREAM_STATE_PAUSED = 2, /**< paused */ -+ PW_STREAM_STATE_STREAMING = 3 /**< streaming */ -+}; -+ -+struct pw_buffer { -+ struct spa_buffer *buffer; /**< the spa buffer */ -+ void *user_data; /**< user data attached to the buffer */ -+ uint64_t size; /**< This field is set by the user and the sum of -+ * all queued buffer is returned in the time info */ -+}; -+ -+struct pw_stream_control { -+ const char *name; /**< name of the control */ -+ uint32_t flags; /**< extra flags (unused) */ -+ float def; /**< default value */ -+ float min; /**< min value */ -+ float max; /**< max value */ -+ float *values; /**< array of values */ -+ uint32_t n_values; /**< number of values in array */ -+ uint32_t max_values; /**< max values that can be set on this control */ -+}; -+ -+/** A time structure \memberof pw_stream */ -+struct pw_time { -+ int64_t now; /**< the monotonic time */ -+ struct spa_fraction rate; /**< the rate of \a ticks and delay */ -+ uint64_t ticks; /**< the ticks at \a now. This is the current time that -+ * the remote end is reading/writing. */ -+ int64_t delay; /**< delay to device, add to ticks to get the time of the -+ * device. Positive for INPUT streams and -+ * negative for OUTPUT streams. */ -+ uint64_t queued; /**< data queued in the stream, this is the sum -+ * of the size fields in the pw_buffer that are -+ * currently queued */ -+}; -+ -+#include -+ -+/** Events for a stream. These events are always called from the mainloop -+ * unless explicitly documented otherwise. */ -+struct pw_stream_events { -+#define PW_VERSION_STREAM_EVENTS 0 -+ uint32_t version; -+ -+ void (*destroy) (void *data); -+ /** when the stream state changes */ -+ void (*state_changed) (void *data, enum pw_stream_state old, -+ enum pw_stream_state state, const char *error); -+ -+ /** Notify information about a control. */ -+ void (*control_info) (void *data, uint32_t id, const struct pw_stream_control *control); -+ -+ /** when io changed on the stream. */ -+ void (*io_changed) (void *data, uint32_t id, void *area, uint32_t size); -+ /** when a parameter changed */ -+ void (*param_changed) (void *data, uint32_t id, const struct spa_pod *param); -+ -+ /** when a new buffer was created for this stream */ -+ void (*add_buffer) (void *data, struct pw_buffer *buffer); -+ /** when a buffer was destroyed for this stream */ -+ void (*remove_buffer) (void *data, struct pw_buffer *buffer); -+ -+ /** when a buffer can be queued (for playback streams) or -+ * dequeued (for capture streams). This is normally called from the -+ * mainloop but can also be called directly from the realtime data -+ * thread if the user is prepared to deal with this. */ -+ void (*process) (void *data); -+ -+ /** The stream is drained */ -+ void (*drained) (void *data); -+ -+}; -+ -+/** Convert a stream state to a readable string \memberof pw_stream */ -+const char * pw_stream_state_as_string(enum pw_stream_state state); -+ -+/** \enum pw_stream_flags Extra flags that can be used in \ref pw_stream_connect() \memberof pw_stream */ -+enum pw_stream_flags { -+ PW_STREAM_FLAG_NONE = 0, /**< no flags */ -+ PW_STREAM_FLAG_AUTOCONNECT = (1 << 0), /**< try to automatically connect -+ * this stream */ -+ PW_STREAM_FLAG_INACTIVE = (1 << 1), /**< start the stream inactive, -+ * pw_stream_set_active() needs to be -+ * called explicitly */ -+ PW_STREAM_FLAG_MAP_BUFFERS = (1 << 2), /**< mmap the buffers */ -+ PW_STREAM_FLAG_DRIVER = (1 << 3), /**< be a driver */ -+ PW_STREAM_FLAG_RT_PROCESS = (1 << 4), /**< call process from the realtime -+ * thread. You MUST use RT safe functions -+ * in the process callback. */ -+ PW_STREAM_FLAG_NO_CONVERT = (1 << 5), /**< don't convert format */ -+ PW_STREAM_FLAG_EXCLUSIVE = (1 << 6), /**< require exclusive access to the -+ * device */ -+ PW_STREAM_FLAG_DONT_RECONNECT = (1 << 7), /**< don't try to reconnect this stream -+ * when the sink/source is removed */ -+ PW_STREAM_FLAG_ALLOC_BUFFERS = (1 << 8), /**< the application will allocate buffer -+ * memory. In the add_buffer event, the -+ * data of the buffer should be set */ -+}; -+ -+/** Create a new unconneced \ref pw_stream \memberof pw_stream -+ * \return a newly allocated \ref pw_stream */ -+struct pw_stream * -+pw_stream_new(struct pw_core *core, /**< a \ref pw_core */ -+ const char *name, /**< a stream media name */ -+ struct pw_properties *props /**< stream properties, ownership is taken */); -+ -+struct pw_stream * -+pw_stream_new_simple(struct pw_loop *loop, /**< a \ref pw_loop to use */ -+ const char *name, /**< a stream media name */ -+ struct pw_properties *props,/**< stream properties, ownership is taken */ -+ const struct pw_stream_events *events, /**< stream events */ -+ void *data /**< data passed to events */); -+ -+/** Destroy a stream \memberof pw_stream */ -+void pw_stream_destroy(struct pw_stream *stream); -+ -+void pw_stream_add_listener(struct pw_stream *stream, -+ struct spa_hook *listener, -+ const struct pw_stream_events *events, -+ void *data); -+ -+enum pw_stream_state pw_stream_get_state(struct pw_stream *stream, const char **error); -+ -+const char *pw_stream_get_name(struct pw_stream *stream); -+ -+struct pw_core *pw_stream_get_core(struct pw_stream *stream); -+ -+const struct pw_properties *pw_stream_get_properties(struct pw_stream *stream); -+ -+int pw_stream_update_properties(struct pw_stream *stream, const struct spa_dict *dict); -+ -+/** Connect a stream for input or output on \a port_path. \memberof pw_stream -+ * \return 0 on success < 0 on error. -+ * -+ * You should connect to the process event and use pw_stream_dequeue_buffer() -+ * to get the latest metadata and data. */ -+int -+pw_stream_connect(struct pw_stream *stream, /**< a \ref pw_stream */ -+ enum pw_direction direction, /**< the stream direction */ -+ uint32_t target_id, /**< the target object id to connect to or -+ * PW_ID_ANY to let the manager -+ * select a target. */ -+ enum pw_stream_flags flags, /**< stream flags */ -+ const struct spa_pod **params, /**< an array with params. The params -+ * should ideally contain supported -+ * formats. */ -+ uint32_t n_params /**< number of items in \a params */); -+ -+/** Get the node ID of the stream. \memberof pw_stream -+ * \return node ID. */ -+uint32_t -+pw_stream_get_node_id(struct pw_stream *stream); -+ -+/** Disconnect \a stream \memberof pw_stream */ -+int pw_stream_disconnect(struct pw_stream *stream); -+ -+/** Set the stream in error state */ -+int pw_stream_set_error(struct pw_stream *stream, /**< a \ref pw_stream */ -+ int res, /**< a result code */ -+ const char *error, ... /**< an error message */) SPA_PRINTF_FUNC(3, 4); -+ -+/** Complete the negotiation process with result code \a res \memberof pw_stream -+ * -+ * This function should be called after notification of the format. -+ -+ * When \a res indicates success, \a params contain the parameters for the -+ * allocation state. */ -+int -+pw_stream_update_params(struct pw_stream *stream, /**< a \ref pw_stream */ -+ const struct spa_pod **params, /**< an array of params. The params should -+ * ideally contain parameters for doing -+ * buffer allocation. */ -+ uint32_t n_params /**< number of elements in \a params */); -+ -+/** Set control values */ -+int pw_stream_set_control(struct pw_stream *stream, uint32_t id, uint32_t n_values, float *values, ...); -+ -+/** Query the time on the stream \memberof pw_stream */ -+int pw_stream_get_time(struct pw_stream *stream, struct pw_time *time); -+ -+/** Get a buffer that can be filled for playback streams or consumed -+ * for capture streams. */ -+struct pw_buffer *pw_stream_dequeue_buffer(struct pw_stream *stream); -+ -+/** Submit a buffer for playback or recycle a buffer for capture. */ -+int pw_stream_queue_buffer(struct pw_stream *stream, struct pw_buffer *buffer); -+ -+/** Activate or deactivate the stream \memberof pw_stream */ -+int pw_stream_set_active(struct pw_stream *stream, bool active); -+ -+/** Flush a stream. When \a drain is true, the drained callback will -+ * be called when all data is played or recorded */ -+int pw_stream_flush(struct pw_stream *stream, bool drain); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_STREAM_H */ -diff --git a/third_party/pipewire/pipewire/thread-loop.h b/third_party/pipewire/pipewire/thread-loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/thread-loop.h -@@ -0,0 +1,168 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_THREAD_LOOP_H -+#define PIPEWIRE_THREAD_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** \page page_thread_loop Threaded Loop -+ * -+ * \section sec_thread_loop_overview Overview -+ * -+ * The threaded loop implementation is a special wrapper around the -+ * regular \ref pw_loop implementation. -+ * -+ * The added feature in the threaded loop is that it spawns a new thread -+ * that runs the wrapped loop. This allows a synchronous application to use -+ * the asynchronous API without risking to stall the PipeWire library. -+ * -+ * \section sec_thread_loop_create Creation -+ * -+ * A \ref pw_thread_loop object is created using pw_thread_loop_new(). -+ * The \ref pw_loop to wrap must be given as an argument along with the name -+ * for the thread that will be spawned. -+ * -+ * After allocating the object, the thread must be started with -+ * pw_thread_loop_start() -+ * -+ * \section sec_thread_loop_destruction Destruction -+ * -+ * When the PipeWire connection has been terminated, the thread must be -+ * stopped and the resources freed. Stopping the thread is done using -+ * pw_thread_loop_stop(), which must be called without the lock (see -+ * below) held. When that function returns, the thread is stopped and the -+ * \ref pw_thread_loop object can be freed using pw_thread_loop_destroy(). -+ * -+ * \section sec_thread_loop_locking Locking -+ * -+ * Since the PipeWire API doesn't allow concurrent accesses to objects, -+ * a locking scheme must be used to guarantee safe usage. The threaded -+ * loop API provides such a scheme through the functions -+ * pw_thread_loop_lock() and pw_thread_loop_unlock(). -+ * -+ * The lock is recursive, so it's safe to use it multiple times from the same -+ * thread. Just make sure you call pw_thread_loop_unlock() the same -+ * number of times you called pw_thread_loop_lock(). -+ * -+ * The lock needs to be held whenever you call any PipeWire function that -+ * uses an object associated with this loop. Make sure you do not hold -+ * on to the lock more than necessary though, as the threaded loop stops -+ * while the lock is held. -+ * -+ * \section sec_thread_loop_events Events and Callbacks -+ * -+ * All events and callbacks are called with the thread lock held. -+ * -+ */ -+/** \class pw_thread_loop -+ * -+ * \brief PipeWire threaded loop object -+ * -+ * The threaded loop object runs a \ref pw_loop in a separate thread -+ * and ensures proper locking is done. -+ * -+ * All of the loop callbacks will be executed with the loop -+ * lock held. -+ * -+ * See also \ref page_thread_loop -+ */ -+struct pw_thread_loop; -+ -+/** Thread loop events */ -+struct pw_thread_loop_events { -+#define PW_VERSION_THREAD_LOOP_EVENTS 0 -+ uint32_t version; -+ -+ /** the loop is destroyed */ -+ void (*destroy) (void *data); -+}; -+ -+/** Make a new thread loop with the given name and optional properties. */ -+struct pw_thread_loop * -+pw_thread_loop_new(const char *name, const struct spa_dict *props); -+ -+/** Make a new thread loop with the given loop, name and optional properties. -+ * When \a loop is NULL, a new loop will be created. */ -+struct pw_thread_loop * -+pw_thread_loop_new_full(struct pw_loop *loop, const char *name, const struct spa_dict *props); -+ -+/** Destroy a thread loop */ -+void pw_thread_loop_destroy(struct pw_thread_loop *loop); -+ -+/** Add an event listener */ -+void pw_thread_loop_add_listener(struct pw_thread_loop *loop, -+ struct spa_hook *listener, -+ const struct pw_thread_loop_events *events, -+ void *data); -+ -+/** Get the loop implementation of the thread loop */ -+struct pw_loop * pw_thread_loop_get_loop(struct pw_thread_loop *loop); -+ -+/** Start the thread loop */ -+int pw_thread_loop_start(struct pw_thread_loop *loop); -+ -+/** Stop the thread loop */ -+void pw_thread_loop_stop(struct pw_thread_loop *loop); -+ -+/** Lock the loop. This ensures exclusive ownership of the loop */ -+void pw_thread_loop_lock(struct pw_thread_loop *loop); -+ -+/** Unlock the loop */ -+void pw_thread_loop_unlock(struct pw_thread_loop *loop); -+ -+/** Release the lock and wait until some thread calls \ref pw_thread_loop_signal */ -+void pw_thread_loop_wait(struct pw_thread_loop *loop); -+ -+/** Release the lock and wait a maximum of 'wait_max_sec' seconds -+ * until some thread calls \ref pw_thread_loop_signal or time out */ -+int pw_thread_loop_timed_wait(struct pw_thread_loop *loop, int wait_max_sec); -+ -+/** Get a struct timespec suitable for \ref pw_thread_loop_timed_wait_full. -+ * Since: 0.3.7 */ -+int pw_thread_loop_get_time(struct pw_thread_loop *loop, struct timespec *abstime, int64_t timeout); -+ -+/** Release the lock and wait up to \a abstime until some thread calls -+ * \ref pw_thread_loop_signal. Use \ref pw_thread_loop_get_time to make a timeout. -+ * Since: 0.3.7 */ -+int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime); -+ -+/** Signal all threads waiting with \ref pw_thread_loop_wait */ -+void pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept); -+ -+/** Signal all threads executing \ref pw_thread_loop_signal with wait_for_accept */ -+void pw_thread_loop_accept(struct pw_thread_loop *loop); -+ -+/** Check if inside the thread */ -+bool pw_thread_loop_in_thread(struct pw_thread_loop *loop); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_THREAD_LOOP_H */ -diff --git a/third_party/pipewire/pipewire/type.h b/third_party/pipewire/pipewire/type.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/type.h -@@ -0,0 +1,52 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_TYPE_H -+#define PIPEWIRE_TYPE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum { -+ PW_TYPE_FIRST = SPA_TYPE_VENDOR_PipeWire, -+}; -+ -+#define PW_TYPE_INFO_BASE "PipeWire:" -+ -+#define PW_TYPE_INFO_Object PW_TYPE_INFO_BASE "Object" -+#define PW_TYPE_INFO_OBJECT_BASE PW_TYPE_INFO_Object ":" -+ -+#define PW_TYPE_INFO_Interface PW_TYPE_INFO_BASE "Interface" -+#define PW_TYPE_INFO_INTERFACE_BASE PW_TYPE_INFO_Interface ":" -+ -+const struct spa_type_info * pw_type_info(void); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_TYPE_H */ -diff --git a/third_party/pipewire/pipewire/utils.h b/third_party/pipewire/pipewire/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/utils.h -@@ -0,0 +1,59 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_UTILS_H -+#define PIPEWIRE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class pw_utils -+ * -+ * Various utility functions -+ */ -+ -+/** a function to destroy an item \memberof pw_utils */ -+typedef void (*pw_destroy_t) (void *object); -+ -+const char * -+pw_split_walk(const char *str, const char *delimiter, size_t *len, const char **state); -+ -+char ** -+pw_split_strv(const char *str, const char *delimiter, int max_tokens, int *n_tokens); -+ -+void -+pw_free_strv(char **str); -+ -+char * -+pw_strip(char *str, const char *whitespace); -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* PIPEWIRE_UTILS_H */ -diff --git a/third_party/pipewire/pipewire/version.h b/third_party/pipewire/pipewire/version.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/version.h -@@ -0,0 +1,68 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_VERSION_H -+#define PIPEWIRE_VERSION_H -+ -+/* WARNING: Make sure to edit the real source file version.h.in! */ -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Return the version of the header files. Keep in mind that this is -+a macro and not a function, so it is impossible to get the pointer of -+it. */ -+#define pw_get_headers_version() ("0.3.13") -+ -+/** Return the version of the library the current application is -+ * linked to. */ -+const char* pw_get_library_version(void); -+ -+/** The current API version. Versions prior to 0.2.0 have -+ * PW_API_VERSION undefined. Please note that this is only ever -+ * increased on incompatible API changes! */ -+#define PW_API_VERSION "0.3" -+ -+/** The major version of PipeWire. \since 0.2.0 */ -+#define PW_MAJOR 0 -+ -+/** The minor version of PipeWire. \since 0.2.0 */ -+#define PW_MINOR 3 -+ -+/** The micro version of PipeWire. \since 0.2.0 */ -+#define PW_MICRO 13 -+ -+/** Evaluates to TRUE if the PipeWire library version is equal or -+ * newer than the specified. \since 0.2.0 */ -+#define PW_CHECK_VERSION(major,minor,micro) \ -+ ((PW_MAJOR > (major)) || \ -+ (PW_MAJOR == (major) && PW_MINOR > (minor)) || \ -+ (PW_MAJOR == (major) && PW_MINOR == (minor) && PW_MICRO >= (micro))) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_VERION_H */ -diff --git a/third_party/pipewire/pipewire/work-queue.h b/third_party/pipewire/pipewire/work-queue.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/pipewire/work-queue.h -@@ -0,0 +1,63 @@ -+/* PipeWire -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef PIPEWIRE_WORK_QUEUE_H -+#define PIPEWIRE_WORK_QUEUE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** \class pw_work_queue -+ * -+ * PipeWire work queue object -+ */ -+struct pw_work_queue; -+ -+#include -+ -+typedef void (*pw_work_func_t) (void *obj, void *data, int res, uint32_t id); -+ -+struct pw_work_queue * -+pw_work_queue_new(struct pw_loop *loop); -+ -+void -+pw_work_queue_destroy(struct pw_work_queue *queue); -+ -+uint32_t -+pw_work_queue_add(struct pw_work_queue *queue, -+ void *obj, int res, -+ pw_work_func_t func, void *data); -+ -+int -+pw_work_queue_cancel(struct pw_work_queue *queue, void *obj, uint32_t id); -+ -+int -+pw_work_queue_complete(struct pw_work_queue *queue, void *obj, uint32_t seq, int res); -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* PIPEWIRE_WORK_QUEUE_H */ -diff --git a/third_party/pipewire/spa/buffer/alloc.h b/third_party/pipewire/spa/buffer/alloc.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/alloc.h -@@ -0,0 +1,338 @@ -+/* Simple Plugin API -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+#ifndef SPA_BUFFER_ALLOC_H -+#define SPA_BUFFER_ALLOC_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** information about the buffer layout */ -+struct spa_buffer_alloc_info { -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_META (1<<0) /**< add metadata data in the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK (1<<1) /**< add chunk data in the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_DATA (1<<2) /**< add buffer data to the skeleton */ -+#define SPA_BUFFER_ALLOC_FLAG_INLINE_ALL 0b111 -+#define SPA_BUFFER_ALLOC_FLAG_NO_DATA (1<<3) /**< don't set data pointers */ -+ uint32_t flags; -+ uint32_t max_align; /**< max of all alignments */ -+ uint32_t n_metas; -+ uint32_t n_datas; -+ struct spa_meta *metas; -+ struct spa_data *datas; -+ uint32_t *data_aligns; -+ size_t skel_size; /**< size of the struct spa_buffer and inlined meta/chunk/data */ -+ size_t meta_size; /**< size of the meta if not inlined */ -+ size_t chunk_size; /**< size of the chunk if not inlined */ -+ size_t data_size; /**< size of the data if not inlined */ -+ size_t mem_size; /**< size of the total memory if not inlined */ -+}; -+ -+/** -+ * Fill buffer allocation information -+ * -+ * Fill \a info with allocation information needed to allocate buffers -+ * with the given number of metadata and data members. -+ * -+ * The required size of the skeleton (the struct spa_buffer) information -+ * and the memory (for the metadata, chunk and buffer memory) will be -+ * calculated. -+ * -+ * The flags member in \a info should be configured before calling this -+ * functions. -+ * -+ * \param info the information to fill -+ * \param n_metas the number of metadatas for the buffer -+ * \param metas an array of metadata items -+ * \param n_datas the number of datas for the buffer -+ * \param datas an array of \a n_datas items -+ * \param data_aligns \a n_datas alignments -+ * \return 0 on success. -+ * */ -+static inline int spa_buffer_alloc_fill_info(struct spa_buffer_alloc_info *info, -+ uint32_t n_metas, struct spa_meta metas[], -+ uint32_t n_datas, struct spa_data datas[], -+ uint32_t data_aligns[]) -+{ -+ size_t size, *target; -+ uint32_t i; -+ -+ info->n_metas = n_metas; -+ info->metas = metas; -+ info->n_datas = n_datas; -+ info->datas = datas; -+ info->data_aligns = data_aligns; -+ info->max_align = 16; -+ info->mem_size = 0; -+ /* -+ * The buffer skeleton is placed in memory like below and can -+ * be accessed as a regular structure. -+ * -+ * +==============================+ -+ * | struct spa_buffer | -+ * | uint32_t n_metas | number of metas -+ * | uint32_t n_datas | number of datas -+ * +-| struct spa_meta *metas | pointer to array of metas -+ * +|-| struct spa_data *datas | pointer to array of datas -+ * || +------------------------------+ -+ * |+>| struct spa_meta | -+ * | | uint32_t type | metadata -+ * | | uint32_t size | size of metadata -+ * +|--| void *data | pointer to metadata -+ * || | ... | more spa_meta follow -+ * || +------------------------------+ -+ * |+->| struct spa_data | -+ * | | uint32_t type | memory type -+ * | | uint32_t flags | -+ * | | int fd | fd of shared memory block -+ * | | uint32_t mapoffset | offset in shared memory of data -+ * | | uint32_t maxsize | size of data block -+ * | +-| void *data | pointer to data -+ * |+|-| struct spa_chunk *chunk | pointer to chunk -+ * ||| | ... | more spa_data follow -+ * ||| +==============================+ -+ * VVV -+ * -+ * metadata, chunk and memory can either be placed right -+ * after the skeleton (inlined) or in a separate piece of memory. -+ * -+ * vvv -+ * ||| +==============================+ -+ * +-->| meta data memory | metadata memory, 8 byte aligned -+ * || | ... | -+ * || +------------------------------+ -+ * +->| struct spa_chunk | memory for n_datas chunks -+ * | | uint32_t offset | -+ * | | uint32_t size | -+ * | | int32_t stride | -+ * | | int32_t dummy | -+ * | | ... chunks | -+ * | +------------------------------+ -+ * +>| data | memory for n_datas data, aligned -+ * | ... blocks | according to alignments -+ * +==============================+ -+ */ -+ info->skel_size = sizeof(struct spa_buffer); -+ info->skel_size += n_metas * sizeof(struct spa_meta); -+ info->skel_size += n_datas * sizeof(struct spa_data); -+ -+ for (i = 0, size = 0; i < n_metas; i++) -+ size += SPA_ROUND_UP_N(metas[i].size, 8); -+ info->meta_size = size; -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ *target += info->meta_size; -+ -+ info->chunk_size = n_datas * sizeof(struct spa_chunk); -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ *target += info->chunk_size; -+ -+ for (i = 0, size = 0; i < n_datas; i++) { -+ info->max_align = SPA_MAX(info->max_align, data_aligns[i]); -+ size = SPA_ROUND_UP_N(size, data_aligns[i]); -+ size += datas[i].maxsize; -+ } -+ info->data_size = size; -+ -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA) && -+ SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) -+ target = &info->skel_size; -+ else -+ target = &info->mem_size; -+ -+ *target = SPA_ROUND_UP_N(*target, n_datas ? data_aligns[0] : 1); -+ *target += info->data_size; -+ *target = SPA_ROUND_UP_N(*target, info->max_align); -+ -+ return 0; -+} -+ -+/** -+ * Fill skeleton and data according to the allocation info -+ * -+ * Use the allocation info to create a \ref struct spa_buffer into -+ * \a skel_mem and \a data_mem. -+ * -+ * Depending on the flags given when calling \ref -+ * spa_buffer_alloc_fill_info(), the buffer meta, chunk and memory -+ * will be referenced in either skel_mem or data_mem. -+ * -+ * \param info an allocation info -+ * \param skel_mem memory to hold the \ref struct spa_buffer and the -+ * pointers to meta, chunk and memory. -+ * \param data_mem memory to hold the meta, chunk and memory -+ * \return a \ref struct spa_buffer in \a skel_mem -+ */ -+static inline struct spa_buffer * -+spa_buffer_alloc_layout(struct spa_buffer_alloc_info *info, -+ void *skel_mem, void *data_mem) -+{ -+ struct spa_buffer *b = (struct spa_buffer*)skel_mem; -+ size_t size; -+ uint32_t i; -+ void **dp, *skel, *data; -+ struct spa_chunk *cp; -+ -+ b->n_metas = info->n_metas; -+ b->metas = SPA_MEMBER(b, sizeof(struct spa_buffer), struct spa_meta); -+ b->n_datas = info->n_datas; -+ b->datas = SPA_MEMBER(b->metas, info->n_metas * sizeof(struct spa_meta), struct spa_data); -+ -+ skel = SPA_MEMBER(b->datas, info->n_datas * sizeof(struct spa_data), void); -+ data = data_mem; -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_META)) -+ dp = &skel; -+ else -+ dp = &data; -+ -+ for (i = 0; i < info->n_metas; i++) { -+ struct spa_meta *m = &b->metas[i]; -+ *m = info->metas[i]; -+ m->data = *dp; -+ *dp = SPA_MEMBER(*dp, SPA_ROUND_UP_N(m->size, 8), void); -+ } -+ -+ size = info->n_datas * sizeof(struct spa_chunk); -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_CHUNK)) { -+ cp = (struct spa_chunk*)skel; -+ skel = SPA_MEMBER(skel, size, void); -+ } -+ else { -+ cp = (struct spa_chunk*)data; -+ data = SPA_MEMBER(data, size, void); -+ } -+ -+ if (SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_INLINE_DATA)) -+ dp = &skel; -+ else -+ dp = &data; -+ -+ for (i = 0; i < info->n_datas; i++) { -+ struct spa_data *d = &b->datas[i]; -+ -+ *d = info->datas[i]; -+ d->chunk = &cp[i]; -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_BUFFER_ALLOC_FLAG_NO_DATA)) { -+ *dp = SPA_PTR_ALIGN(*dp, info->data_aligns[i], void); -+ d->data = *dp; -+ *dp = SPA_MEMBER(*dp, d->maxsize, void); -+ } -+ } -+ return b; -+} -+ -+/** -+ * Layout an array of buffers -+ * -+ * Use the allocation info to layout the memory of an array of buffers. -+ * -+ * \a skel_mem should point to at least info->skel_size * \a n_buffers bytes -+ * of memory. -+ * \a data_mem should point to at least info->mem_size * \a n_buffers bytes -+ * of memory. -+ * -+ * \param info the allocation info for one buffer -+ * \param n_buffers the number of buffers to create -+ * \param buffer a array with space to hold \a n_buffers pointers to buffers -+ * \param skel_mem memory for the \ref struct spa_buffer -+ * \param data_mem memory for the meta, chunk, memory of the buffer if not -+ * inlined in the skeleton. -+ * \return 0 on success. -+ * -+ */ -+static inline int -+spa_buffer_alloc_layout_array(struct spa_buffer_alloc_info *info, -+ uint32_t n_buffers, struct spa_buffer *buffers[], -+ void *skel_mem, void *data_mem) -+{ -+ uint32_t i; -+ for (i = 0; i < n_buffers; i++) { -+ buffers[i] = spa_buffer_alloc_layout(info, skel_mem, data_mem); -+ skel_mem = SPA_MEMBER(skel_mem, info->skel_size, void); -+ data_mem = SPA_MEMBER(data_mem, info->mem_size, void); -+ } -+ return 0; -+} -+ -+/** -+ * Allocate an array of buffers -+ * -+ * Allocate \a n_buffers with the given metadata, memory and alignment -+ * information. -+ * -+ * The buffer array, structures, data and metadata will all be allocated -+ * in one block of memory with the proper requested alignment. -+ * -+ * \param n_buffers the number of buffers to create -+ * \param flags extra flags -+ * \param n_metas number of metadatas -+ * \param metas \a n_metas metadata specification -+ * \param n_datas number of datas -+ * \param datas \a n_datas memory specification -+ * \param data_aligns \a n_datas alignment specifications -+ * \returns an array of \a n_buffers pointers to \ref struct spa_buffer -+ * with the given metadata, data and alignment or NULL when -+ * allocation failed. -+ * -+ */ -+static inline struct spa_buffer ** -+spa_buffer_alloc_array(uint32_t n_buffers, uint32_t flags, -+ uint32_t n_metas, struct spa_meta metas[], -+ uint32_t n_datas, struct spa_data datas[], -+ uint32_t data_aligns[]) -+{ -+ -+ struct spa_buffer **buffers; -+ struct spa_buffer_alloc_info info = { flags | SPA_BUFFER_ALLOC_FLAG_INLINE_ALL, }; -+ void *skel; -+ -+ spa_buffer_alloc_fill_info(&info, n_metas, metas, n_datas, datas, data_aligns); -+ -+ buffers = (struct spa_buffer **)calloc(1, info.max_align + -+ n_buffers * (sizeof(struct spa_buffer *) + info.skel_size)); -+ if (buffers == NULL) -+ return NULL; -+ -+ skel = SPA_MEMBER(buffers, sizeof(struct spa_buffer *) * n_buffers, void); -+ skel = SPA_PTR_ALIGN(skel, info.max_align, void); -+ -+ spa_buffer_alloc_layout_array(&info, n_buffers, buffers, skel, NULL); -+ -+ return buffers; -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_ALLOC_H */ -diff --git a/third_party/pipewire/spa/buffer/buffer.h b/third_party/pipewire/spa/buffer/buffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/buffer.h -@@ -0,0 +1,114 @@ -+/* Simple Plugin API -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_BUFFER_H -+#define SPA_BUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \page page_buffer Buffers -+ * -+ * Buffers describe the data and metadata that is exchanged between -+ * ports of a node. -+ */ -+ -+enum spa_data_type { -+ SPA_DATA_Invalid, -+ SPA_DATA_MemPtr, /**< pointer to memory, the data field in -+ * struct spa_data is set. */ -+ SPA_DATA_MemFd, /**< generic fd, mmap to get to memory */ -+ SPA_DATA_DmaBuf, /**< fd to dmabuf memory */ -+ SPA_DATA_MemId, /**< memory is identified with an id */ -+ -+ SPA_DATA_LAST, /**< not part of ABI */ -+}; -+ -+/** Chunk of memory, can change for each buffer */ -+struct spa_chunk { -+ uint32_t offset; /**< offset of valid data. Should be taken -+ * modulo the data maxsize to get the offset -+ * in the data memory. */ -+ uint32_t size; /**< size of valid data. Should be clamped to -+ * maxsize. */ -+ int32_t stride; /**< stride of valid data */ -+#define SPA_CHUNK_FLAG_NONE 0 -+#define SPA_CHUNK_FLAG_CORRUPTED (1u<<0) /**< chunk data is corrupted in some way */ -+ int32_t flags; /**< chunk flags */ -+}; -+ -+/** Data for a buffer this stays constant for a buffer */ -+struct spa_data { -+ uint32_t type; /**< memory type, one of enum spa_data_type, when -+ * allocating memory, the type contains a bitmask -+ * of allowed types */ -+#define SPA_DATA_FLAG_NONE 0 -+#define SPA_DATA_FLAG_READABLE (1u<<0) /**< data is readable */ -+#define SPA_DATA_FLAG_WRITABLE (1u<<1) /**< data is writable */ -+#define SPA_DATA_FLAG_DYNAMIC (1u<<2) /**< data pointer can be changed */ -+#define SPA_DATA_FLAG_READWRITE (SPA_DATA_FLAG_READABLE|SPA_DATA_FLAG_WRITABLE) -+ uint32_t flags; /**< data flags */ -+ int64_t fd; /**< optional fd for data */ -+ uint32_t mapoffset; /**< offset to map fd at */ -+ uint32_t maxsize; /**< max size of data */ -+ void *data; /**< optional data pointer */ -+ struct spa_chunk *chunk; /**< valid chunk of memory */ -+}; -+ -+/** A Buffer */ -+struct spa_buffer { -+ uint32_t n_metas; /**< number of metadata */ -+ uint32_t n_datas; /**< number of data members */ -+ struct spa_meta *metas; /**< array of metadata */ -+ struct spa_data *datas; /**< array of data members */ -+}; -+ -+/** Find metadata in a buffer */ -+static inline struct spa_meta *spa_buffer_find_meta(const struct spa_buffer *b, uint32_t type) -+{ -+ uint32_t i; -+ -+ for (i = 0; i < b->n_metas; i++) -+ if (b->metas[i].type == type) -+ return &b->metas[i]; -+ -+ return NULL; -+} -+ -+static inline void *spa_buffer_find_meta_data(const struct spa_buffer *b, uint32_t type, size_t size) -+{ -+ struct spa_meta *m; -+ if ((m = spa_buffer_find_meta(b, type)) && m->size >= size) -+ return m->data; -+ return NULL; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_H */ -diff --git a/third_party/pipewire/spa/buffer/meta.h b/third_party/pipewire/spa/buffer/meta.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/meta.h -@@ -0,0 +1,151 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_META_H -+#define SPA_META_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \page page_meta Metadata -+ * -+ * Metadata contains extra information on a buffer. -+ */ -+enum spa_meta_type { -+ SPA_META_Invalid, -+ SPA_META_Header, /**< struct spa_meta_header */ -+ SPA_META_VideoCrop, /**< struct spa_meta_region with cropping data */ -+ SPA_META_VideoDamage, /**< array of struct spa_meta_region with damage */ -+ SPA_META_Bitmap, /**< struct spa_meta_bitmap */ -+ SPA_META_Cursor, /**< struct spa_meta_cursor */ -+ SPA_META_Control, /**< metadata contains a spa_meta_control -+ * associated with the data */ -+ -+ SPA_META_LAST, /**< not part of ABI/API */ -+}; -+ -+/** -+ * A metadata element. -+ * -+ * This structure is available on the buffer structure and contains -+ * the type of the metadata and a pointer/size to the actual metadata -+ * itself. -+ */ -+struct spa_meta { -+ uint32_t type; /**< metadata type, one of enum spa_meta_type */ -+ uint32_t size; /**< size of metadata */ -+ void *data; /**< pointer to metadata */ -+}; -+ -+#define spa_meta_first(m) ((m)->data) -+#define spa_meta_end(m) SPA_MEMBER((m)->data,(m)->size,void) -+#define spa_meta_check(p,m) (SPA_MEMBER(p,sizeof(*p),void) <= spa_meta_end(m)) -+ -+/** -+ * Describes essential buffer header metadata such as flags and -+ * timestamps. -+ */ -+struct spa_meta_header { -+#define SPA_META_HEADER_FLAG_DISCONT (1 << 0) /**< data is not continuous with previous buffer */ -+#define SPA_META_HEADER_FLAG_CORRUPTED (1 << 1) /**< data might be corrupted */ -+#define SPA_META_HEADER_FLAG_MARKER (1 << 2) /**< media specific marker */ -+#define SPA_META_HEADER_FLAG_HEADER (1 << 3) /**< data contains a codec specific header */ -+#define SPA_META_HEADER_FLAG_GAP (1 << 4) /**< data contains media neutral data */ -+#define SPA_META_HEADER_FLAG_DELTA_UNIT (1 << 5) /**< cannot be decoded independently */ -+ uint32_t flags; /**< flags */ -+ uint32_t offset; /**< offset in current cycle */ -+ int64_t pts; /**< presentation timestamp */ -+ int64_t dts_offset; /**< decoding timestamp as a difference with pts */ -+ uint64_t seq; /**< sequence number, increments with a -+ * media specific frequency */ -+}; -+ -+/** metadata structure for Region or an array of these for RegionArray */ -+struct spa_meta_region { -+ struct spa_region region; -+}; -+ -+#define spa_meta_region_is_valid(m) ((m)->region.size.width != 0 && (m)->region.size.height != 0) -+ -+/** iterate all the items in a metadata */ -+#define spa_meta_for_each(pos,meta) \ -+ for (pos = (__typeof(pos))spa_meta_first(meta); \ -+ spa_meta_check(pos, meta); \ -+ (pos)++) -+ -+#define spa_meta_bitmap_is_valid(m) ((m)->format != 0) -+ -+/** -+ * Bitmap information -+ * -+ * This metadata contains a bitmap image in the given format and size. -+ * It is typically used for cursor images or other small images that are -+ * better transferred inline. -+ */ -+struct spa_meta_bitmap { -+ uint32_t format; /**< bitmap video format, one of enum spa_video_format. 0 is -+ * and invalid format and should be handled as if there is -+ * no new bitmap information. */ -+ struct spa_rectangle size; /**< width and height of bitmap */ -+ int32_t stride; /**< stride of bitmap data */ -+ uint32_t offset; /**< offset of bitmap data in this structure. An offset of -+ * 0 means no image data (invisible), an offset >= -+ * sizeof(struct spa_meta_bitmap) contains valid bitmap -+ * info. */ -+}; -+ -+#define spa_meta_cursor_is_valid(m) ((m)->id != 0) -+ -+/** -+ * Cursor information -+ * -+ * Metadata to describe the position and appearance of a pointing device. -+ */ -+struct spa_meta_cursor { -+ uint32_t id; /**< cursor id. an id of 0 is an invalid id and means that -+ * there is no new cursor data */ -+ uint32_t flags; /**< extra flags */ -+ struct spa_point position; /**< position on screen */ -+ struct spa_point hotspot; /**< offsets for hotspot in bitmap, this field has no meaning -+ * when there is no valid bitmap (see below) */ -+ uint32_t bitmap_offset; /**< offset of bitmap meta in this structure. When the offset -+ * is 0, there is no new bitmap information. When the offset is -+ * >= sizeof(struct spa_meta_cursor) there is a -+ * struct spa_meta_bitmap at the offset. */ -+}; -+ -+/** a timed set of events associated with the buffer */ -+struct spa_meta_control { -+ struct spa_pod_sequence sequence; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_META_H */ -diff --git a/third_party/pipewire/spa/buffer/type-info.h b/third_party/pipewire/spa/buffer/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/buffer/type-info.h -@@ -0,0 +1,83 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_BUFFER_TYPES_H -+#define SPA_BUFFER_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INFO_Buffer SPA_TYPE_INFO_POINTER_BASE "Buffer" -+#define SPA_TYPE_INFO_BUFFER_BASE SPA_TYPE_INFO_Buffer ":" -+ -+/** Buffers contain data of a certain type */ -+#define SPA_TYPE_INFO_Data SPA_TYPE_INFO_ENUM_BASE "Data" -+#define SPA_TYPE_INFO_DATA_BASE SPA_TYPE_INFO_Data ":" -+ -+/** base type for fd based memory */ -+#define SPA_TYPE_INFO_DATA_Fd SPA_TYPE_INFO_DATA_BASE "Fd" -+#define SPA_TYPE_INFO_DATA_FD_BASE SPA_TYPE_INFO_DATA_Fd ":" -+ -+static const struct spa_type_info spa_type_data_type[] = { -+ { SPA_DATA_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "Invalid", NULL }, -+ { SPA_DATA_MemPtr, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "MemPtr", NULL }, -+ { SPA_DATA_MemFd, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "MemFd", NULL }, -+ { SPA_DATA_DmaBuf, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_FD_BASE "DmaBuf", NULL }, -+ { SPA_DATA_MemId, SPA_TYPE_Int, SPA_TYPE_INFO_DATA_BASE "MemId", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_Meta SPA_TYPE_INFO_POINTER_BASE "Meta" -+#define SPA_TYPE_INFO_META_BASE SPA_TYPE_INFO_Meta ":" -+ -+#define SPA_TYPE_INFO_META_Array SPA_TYPE_INFO_META_BASE "Array" -+#define SPA_TYPE_INFO_META_ARRAY_BASE SPA_TYPE_INFO_META_Array ":" -+ -+#define SPA_TYPE_INFO_META_Region SPA_TYPE_INFO_META_BASE "Region" -+#define SPA_TYPE_INFO_META_REGION_BASE SPA_TYPE_INFO_META_Region ":" -+ -+#define SPA_TYPE_INFO_META_ARRAY_Region SPA_TYPE_INFO_META_ARRAY_BASE "Region" -+#define SPA_TYPE_INFO_META_ARRAY_REGION_BASE SPA_TYPE_INFO_META_ARRAY_Region ":" -+ -+static const struct spa_type_info spa_type_meta_type[] = { -+ { SPA_META_Invalid, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Invalid", NULL }, -+ { SPA_META_Header, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Header", NULL }, -+ { SPA_META_VideoCrop, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_REGION_BASE "VideoCrop", NULL }, -+ { SPA_META_VideoDamage, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_ARRAY_REGION_BASE "VideoDamage", NULL }, -+ { SPA_META_Bitmap, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Bitmap", NULL }, -+ { SPA_META_Cursor, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Cursor", NULL }, -+ { SPA_META_Control, SPA_TYPE_Pointer, SPA_TYPE_INFO_META_BASE "Control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_BUFFER_TYPES_H */ -diff --git a/third_party/pipewire/spa/control/control.h b/third_party/pipewire/spa/control/control.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/control/control.h -@@ -0,0 +1,53 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CONTROL_H -+#define SPA_CONTROL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** Controls -+ * -+ */ -+ -+/** Different Control types */ -+enum spa_control_type { -+ SPA_CONTROL_Invalid, -+ SPA_CONTROL_Properties, /**< data contains a SPA_TYPE_OBJECT_Props */ -+ SPA_CONTROL_Midi, /**< data contains a spa_pod_bytes with raw midi data */ -+ SPA_CONTROL_OSC, /**< data contains a spa_pod_bytes with an OSC packet */ -+ -+ SPA_CONTROL_LAST, /**< not part of ABI */ -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CONTROL_H */ -diff --git a/third_party/pipewire/spa/control/type-info.h b/third_party/pipewire/spa/control/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/control/type-info.h -@@ -0,0 +1,52 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CONTROL_TYPES_H -+#define SPA_CONTROL_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Control SPA_TYPE_INFO_ENUM_BASE "Control" -+#define SPA_TYPE_INFO_CONTROL_BASE SPA_TYPE_INFO_Control ":" -+ -+static const struct spa_type_info spa_type_control[] = { -+ { SPA_CONTROL_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Invalid", NULL }, -+ { SPA_CONTROL_Properties, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Properties", NULL }, -+ { SPA_CONTROL_Midi, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "Midi", NULL }, -+ { SPA_CONTROL_OSC, SPA_TYPE_Int, SPA_TYPE_INFO_CONTROL_BASE "OSC", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CONTROL_TYPES_H */ -diff --git a/third_party/pipewire/spa/debug/buffer.h b/third_party/pipewire/spa/debug/buffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/buffer.h -@@ -0,0 +1,119 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_BUFFER_H -+#define SPA_DEBUG_BUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_buffer(int indent, const struct spa_buffer *buffer) -+{ -+ uint32_t i; -+ -+ spa_debug("%*s" "struct spa_buffer %p:", indent, "", buffer); -+ spa_debug("%*s" " n_metas: %u (at %p)", indent, "", buffer->n_metas, buffer->metas); -+ for (i = 0; i < buffer->n_metas; i++) { -+ struct spa_meta *m = &buffer->metas[i]; -+ const char *type_name; -+ -+ type_name = spa_debug_type_find_name(spa_type_meta_type, m->type); -+ spa_debug("%*s" " meta %d: type %d (%s), data %p, size %d:", indent, "", i, m->type, -+ type_name, m->data, m->size); -+ -+ switch (m->type) { -+ case SPA_META_Header: -+ { -+ struct spa_meta_header *h = (struct spa_meta_header*)m->data; -+ spa_debug("%*s" " struct spa_meta_header:", indent, ""); -+ spa_debug("%*s" " flags: %08x", indent, "", h->flags); -+ spa_debug("%*s" " offset: %u", indent, "", h->offset); -+ spa_debug("%*s" " seq: %" PRIu64, indent, "", h->seq); -+ spa_debug("%*s" " pts: %" PRIi64, indent, "", h->pts); -+ spa_debug("%*s" " dts_offset: %" PRIi64, indent, "", h->dts_offset); -+ break; -+ } -+ case SPA_META_VideoCrop: -+ { -+ struct spa_meta_region *h = (struct spa_meta_region*)m->data; -+ spa_debug("%*s" " struct spa_meta_region:", indent, ""); -+ spa_debug("%*s" " x: %d", indent, "", h->region.position.x); -+ spa_debug("%*s" " y: %d", indent, "", h->region.position.y); -+ spa_debug("%*s" " width: %d", indent, "", h->region.size.width); -+ spa_debug("%*s" " height: %d", indent, "", h->region.size.height); -+ break; -+ } -+ case SPA_META_VideoDamage: -+ { -+ struct spa_meta_region *h; -+ spa_meta_for_each(h, m) { -+ spa_debug("%*s" " struct spa_meta_region:", indent, ""); -+ spa_debug("%*s" " x: %d", indent, "", h->region.position.x); -+ spa_debug("%*s" " y: %d", indent, "", h->region.position.y); -+ spa_debug("%*s" " width: %d", indent, "", h->region.size.width); -+ spa_debug("%*s" " height: %d", indent, "", h->region.size.height); -+ } -+ break; -+ } -+ case SPA_META_Bitmap: -+ break; -+ case SPA_META_Cursor: -+ break; -+ default: -+ spa_debug("%*s" " Unknown:", indent, ""); -+ spa_debug_mem(5, m->data, m->size); -+ } -+ } -+ spa_debug("%*s" " n_datas: \t%u (at %p)", indent, "", buffer->n_datas, buffer->datas); -+ for (i = 0; i < buffer->n_datas; i++) { -+ struct spa_data *d = &buffer->datas[i]; -+ spa_debug("%*s" " type: %d (%s)", indent, "", d->type, -+ spa_debug_type_find_name(spa_type_data_type, d->type)); -+ spa_debug("%*s" " flags: %d", indent, "", d->flags); -+ spa_debug("%*s" " data: %p", indent, "", d->data); -+ spa_debug("%*s" " fd: %" PRIi64, indent, "", d->fd); -+ spa_debug("%*s" " offset: %d", indent, "", d->mapoffset); -+ spa_debug("%*s" " maxsize: %u", indent, "", d->maxsize); -+ spa_debug("%*s" " chunk: %p", indent, "", d->chunk); -+ spa_debug("%*s" " offset: %d", indent, "", d->chunk->offset); -+ spa_debug("%*s" " size: %u", indent, "", d->chunk->size); -+ spa_debug("%*s" " stride: %d", indent, "", d->chunk->stride); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_BUFFER_H */ -diff --git a/third_party/pipewire/spa/debug/dict.h b/third_party/pipewire/spa/debug/dict.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/dict.h -@@ -0,0 +1,52 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_DICT_H -+#define SPA_DEBUG_DICT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_dict(int indent, const struct spa_dict *dict) -+{ -+ const struct spa_dict_item *item; -+ spa_debug("%*sflags:%08x n_items:%d", indent, "", dict->flags, dict->n_items); -+ spa_dict_for_each(item, dict) { -+ spa_debug("%*s %s = \"%s\"", indent, "", item->key, item->value); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_DICT_H */ -diff --git a/third_party/pipewire/spa/debug/format.h b/third_party/pipewire/spa/debug/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/format.h -@@ -0,0 +1,201 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_FORMAT_H -+#define SPA_DEBUG_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_debug_format_value(const struct spa_type_info *info, -+ uint32_t type, void *body, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Bool: -+ fprintf(stderr, "%s", *(int32_t *) body ? "true" : "false"); -+ break; -+ case SPA_TYPE_Id: -+ { -+ const char *str = spa_debug_type_find_short_name(info, *(int32_t *) body); -+ char tmp[64]; -+ if (str == NULL) { -+ snprintf(tmp, sizeof(tmp), "%d", *(int32_t*)body); -+ str = tmp; -+ } -+ fprintf(stderr, "%s", str); -+ break; -+ } -+ case SPA_TYPE_Int: -+ fprintf(stderr, "%d", *(int32_t *) body); -+ break; -+ case SPA_TYPE_Long: -+ fprintf(stderr, "%" PRIi64, *(int64_t *) body); -+ break; -+ case SPA_TYPE_Float: -+ fprintf(stderr, "%f", *(float *) body); -+ break; -+ case SPA_TYPE_Double: -+ fprintf(stderr, "%g", *(double *) body); -+ break; -+ case SPA_TYPE_String: -+ fprintf(stderr, "%s", (char *) body); -+ break; -+ case SPA_TYPE_Rectangle: -+ { -+ struct spa_rectangle *r = (struct spa_rectangle *)body; -+ fprintf(stderr, "%" PRIu32 "x%" PRIu32, r->width, r->height); -+ break; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ struct spa_fraction *f = (struct spa_fraction *)body; -+ fprintf(stderr, "%" PRIu32 "/%" PRIu32, f->num, f->denom); -+ break; -+ } -+ case SPA_TYPE_Bitmap: -+ fprintf(stderr, "Bitmap"); -+ break; -+ case SPA_TYPE_Bytes: -+ fprintf(stderr, "Bytes"); -+ break; -+ case SPA_TYPE_Array: -+ { -+ void *p; -+ struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; -+ int i = 0; -+ fprintf(stderr, "< "); -+ SPA_POD_ARRAY_BODY_FOREACH(b, size, p) { -+ if (i++ > 0) -+ fprintf(stderr, ", "); -+ spa_debug_format_value(info, b->child.type, p, b->child.size); -+ } -+ fprintf(stderr, " >"); -+ break; -+ } -+ default: -+ fprintf(stderr, "INVALID type %d", type); -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_debug_format(int indent, -+ const struct spa_type_info *info, const struct spa_pod *format) -+{ -+ const char *media_type; -+ const char *media_subtype; -+ struct spa_pod_prop *prop; -+ uint32_t mtype, mstype; -+ -+ if (info == NULL) -+ info = spa_type_format; -+ -+ if (format == NULL || SPA_POD_TYPE(format) != SPA_TYPE_Object) -+ return -EINVAL; -+ -+ if (spa_format_parse(format, &mtype, &mstype) < 0) -+ return -EINVAL; -+ -+ media_type = spa_debug_type_find_name(spa_type_media_type, mtype); -+ media_subtype = spa_debug_type_find_name(spa_type_media_subtype, mstype); -+ -+ fprintf(stderr, "%*s %s/%s\n", indent, "", -+ media_type ? spa_debug_type_short_name(media_type) : "unknown", -+ media_subtype ? spa_debug_type_short_name(media_subtype) : "unknown"); -+ -+ SPA_POD_OBJECT_FOREACH((struct spa_pod_object*)format, prop) { -+ const char *key; -+ const struct spa_type_info *ti; -+ uint32_t i, type, size, n_vals, choice; -+ const struct spa_pod *val; -+ void *vals; -+ -+ if (prop->key == SPA_FORMAT_mediaType || -+ prop->key == SPA_FORMAT_mediaSubtype) -+ continue; -+ -+ val = spa_pod_get_values(&prop->value, &n_vals, &choice); -+ -+ type = val->type; -+ size = val->size; -+ vals = SPA_POD_BODY(val); -+ -+ if (type < SPA_TYPE_None || type >= SPA_TYPE_LAST) -+ continue; -+ -+ ti = spa_debug_type_find(info, prop->key); -+ key = ti ? ti->name : NULL; -+ -+ fprintf(stderr, "%*s %16s : (%s) ", indent, "", -+ key ? spa_debug_type_short_name(key) : "unknown", -+ spa_debug_type_short_name(spa_types[type].name)); -+ -+ if (choice == SPA_CHOICE_None) { -+ spa_debug_format_value(ti ? ti->values : NULL, type, vals, size); -+ } else { -+ const char *ssep, *esep, *sep; -+ -+ switch (choice) { -+ case SPA_CHOICE_Range: -+ case SPA_CHOICE_Step: -+ ssep = "[ "; -+ sep = ", "; -+ esep = " ]"; -+ break; -+ default: -+ case SPA_CHOICE_Enum: -+ case SPA_CHOICE_Flags: -+ ssep = "{ "; -+ sep = ", "; -+ esep = " }"; -+ break; -+ } -+ -+ fprintf(stderr, "%s", ssep); -+ -+ for (i = 1; i < n_vals; i++) { -+ vals = SPA_MEMBER(vals, size, void); -+ if (i > 1) -+ fprintf(stderr, "%s", sep); -+ spa_debug_format_value(ti ? ti->values : NULL, type, vals, size); -+ } -+ fprintf(stderr, "%s", esep); -+ } -+ fprintf(stderr, "\n"); -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_FORMAT_H */ -diff --git a/third_party/pipewire/spa/debug/mem.h b/third_party/pipewire/spa/debug/mem.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/mem.h -@@ -0,0 +1,60 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_MEM_H -+#define SPA_DEBUG_MEM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_mem(int indent, const void *data, size_t size) -+{ -+ const uint8_t *t = (const uint8_t*)data; -+ char buffer[512]; -+ size_t i; -+ int pos = 0; -+ -+ for (i = 0; i < size; i++) { -+ if (i % 16 == 0) -+ pos = sprintf(buffer, "%p: ", &t[i]); -+ pos += sprintf(buffer + pos, "%02x ", t[i]); -+ if (i % 16 == 15 || i == size - 1) { -+ spa_debug("%*s" "%s", indent, "", buffer); -+ } -+ } -+ return 0; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_MEM_H */ -diff --git a/third_party/pipewire/spa/debug/node.h b/third_party/pipewire/spa/debug/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/node.h -@@ -0,0 +1,57 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_NODE_H -+#define SPA_DEBUG_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int spa_debug_port_info(int indent, const struct spa_port_info *info) -+{ -+ spa_debug("%*s" "struct spa_port_info %p:", indent, "", info); -+ spa_debug("%*s" " flags: \t%08" PRIx64, indent, "", info->flags); -+ spa_debug("%*s" " rate: \t%d/%d", indent, "", info->rate.num, info->rate.denom); -+ spa_debug("%*s" " props:", indent, ""); -+ if (info->props) -+ spa_debug_dict(indent + 2, info->props); -+ else -+ spa_debug("%*s" " none", indent, ""); -+ return 0; -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_NODE_H */ -diff --git a/third_party/pipewire/spa/debug/pod.h b/third_party/pipewire/spa/debug/pod.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/pod.h -@@ -0,0 +1,207 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_POD_H -+#define SPA_DEBUG_POD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -+#endif -+ -+static inline int -+spa_debug_pod_value(int indent, const struct spa_type_info *info, -+ uint32_t type, void *body, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Bool: -+ spa_debug("%*s" "Bool %s", indent, "", (*(int32_t *) body) ? "true" : "false"); -+ break; -+ case SPA_TYPE_Id: -+ spa_debug("%*s" "Id %-8d (%s)", indent, "", *(int32_t *) body, -+ spa_debug_type_find_name(info, *(int32_t *) body)); -+ break; -+ case SPA_TYPE_Int: -+ spa_debug("%*s" "Int %d", indent, "", *(int32_t *) body); -+ break; -+ case SPA_TYPE_Long: -+ spa_debug("%*s" "Long %" PRIi64 "", indent, "", *(int64_t *) body); -+ break; -+ case SPA_TYPE_Float: -+ spa_debug("%*s" "Float %f", indent, "", *(float *) body); -+ break; -+ case SPA_TYPE_Double: -+ spa_debug("%*s" "Double %f", indent, "", *(double *) body); -+ break; -+ case SPA_TYPE_String: -+ spa_debug("%*s" "String \"%s\"", indent, "", (char *) body); -+ break; -+ case SPA_TYPE_Fd: -+ spa_debug("%*s" "Fd %d", indent, "", *(int *) body); -+ break; -+ case SPA_TYPE_Pointer: -+ { -+ struct spa_pod_pointer_body *b = (struct spa_pod_pointer_body *)body; -+ spa_debug("%*s" "Pointer %s %p", indent, "", -+ spa_debug_type_find_name(SPA_TYPE_ROOT, b->type), b->value); -+ break; -+ } -+ case SPA_TYPE_Rectangle: -+ { -+ struct spa_rectangle *r = (struct spa_rectangle *)body; -+ spa_debug("%*s" "Rectangle %dx%d", indent, "", r->width, r->height); -+ break; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ struct spa_fraction *f = (struct spa_fraction *)body; -+ spa_debug("%*s" "Fraction %d/%d", indent, "", f->num, f->denom); -+ break; -+ } -+ case SPA_TYPE_Bitmap: -+ spa_debug("%*s" "Bitmap", indent, ""); -+ break; -+ case SPA_TYPE_Array: -+ { -+ struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; -+ void *p; -+ const struct spa_type_info *ti = spa_debug_type_find(SPA_TYPE_ROOT, b->child.type); -+ -+ spa_debug("%*s" "Array: child.size %d, child.type %s", indent, "", -+ b->child.size, ti ? ti->name : "unknown"); -+ -+ SPA_POD_ARRAY_BODY_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, b->child.type, p, b->child.size); -+ break; -+ } -+ case SPA_TYPE_Choice: -+ { -+ struct spa_pod_choice_body *b = (struct spa_pod_choice_body *)body; -+ void *p; -+ const struct spa_type_info *ti = spa_debug_type_find(spa_type_choice, b->type); -+ -+ spa_debug("%*s" "Choice: type %s, flags %08x %d %d", indent, "", -+ ti ? ti->name : "unknown", b->flags, size, b->child.size); -+ -+ SPA_POD_CHOICE_BODY_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, b->child.type, p, b->child.size); -+ break; -+ } -+ case SPA_TYPE_Struct: -+ { -+ struct spa_pod *b = (struct spa_pod *)body, *p; -+ spa_debug("%*s" "Struct: size %d", indent, "", size); -+ SPA_POD_FOREACH(b, size, p) -+ spa_debug_pod_value(indent + 2, info, p->type, SPA_POD_BODY(p), p->size); -+ break; -+ } -+ case SPA_TYPE_Object: -+ { -+ struct spa_pod_object_body *b = (struct spa_pod_object_body *)body; -+ struct spa_pod_prop *p; -+ const struct spa_type_info *ti, *ii; -+ -+ ti = spa_debug_type_find(info, b->type); -+ ii = ti ? spa_debug_type_find(ti->values, 0) : NULL; -+ ii = ii ? spa_debug_type_find(ii->values, b->id) : NULL; -+ -+ spa_debug("%*s" "Object: size %d, type %s (%d), id %s (%d)", indent, "", size, -+ ti ? ti->name : "unknown", b->type, ii ? ii->name : "unknown", b->id); -+ -+ info = ti ? ti->values : info; -+ -+ SPA_POD_OBJECT_BODY_FOREACH(b, size, p) { -+ ii = spa_debug_type_find(info, p->key); -+ -+ spa_debug("%*s" "Prop: key %s (%d), flags %08x", indent+2, "", -+ ii ? ii->name : "unknown", p->key, p->flags); -+ -+ spa_debug_pod_value(indent + 4, ii ? ii->values : NULL, -+ p->value.type, -+ SPA_POD_CONTENTS(struct spa_pod_prop, p), -+ p->value.size); -+ } -+ break; -+ } -+ case SPA_TYPE_Sequence: -+ { -+ struct spa_pod_sequence_body *b = (struct spa_pod_sequence_body *)body; -+ const struct spa_type_info *ti, *ii; -+ struct spa_pod_control *c; -+ -+ ti = spa_debug_type_find(info, b->unit); -+ -+ spa_debug("%*s" "Sequence: size %d, unit %s", indent, "", size, -+ ti ? ti->name : "unknown"); -+ -+ SPA_POD_SEQUENCE_BODY_FOREACH(b, size, c) { -+ ii = spa_debug_type_find(spa_type_control, c->type); -+ -+ spa_debug("%*s" "Control: offset %d, type %s", indent+2, "", -+ c->offset, ii ? ii->name : "unknown"); -+ -+ spa_debug_pod_value(indent + 4, ii ? ii->values : NULL, -+ c->value.type, -+ SPA_POD_CONTENTS(struct spa_pod_control, c), -+ c->value.size); -+ } -+ break; -+ } -+ case SPA_TYPE_Bytes: -+ spa_debug("%*s" "Bytes", indent, ""); -+ spa_debug_mem(indent + 2, body, size); -+ break; -+ case SPA_TYPE_None: -+ spa_debug("%*s" "None", indent, ""); -+ spa_debug_mem(indent + 2, body, size); -+ break; -+ default: -+ spa_debug("%*s" "unhandled POD type %d", indent, "", type); -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_debug_pod(int indent, -+ const struct spa_type_info *info, const struct spa_pod *pod) -+{ -+ return spa_debug_pod_value(indent, info ? info : SPA_TYPE_ROOT, -+ SPA_POD_TYPE(pod), -+ SPA_POD_BODY(pod), -+ SPA_POD_BODY_SIZE(pod)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_POD_H */ -diff --git a/third_party/pipewire/spa/debug/types.h b/third_party/pipewire/spa/debug/types.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/debug/types.h -@@ -0,0 +1,98 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEBUG_TYPES_H -+#define SPA_DEBUG_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+static inline const struct spa_type_info *spa_debug_type_find(const struct spa_type_info *info, uint32_t type) -+{ -+ const struct spa_type_info *res; -+ -+ if (info == NULL) -+ info = SPA_TYPE_ROOT; -+ -+ while (info && info->name) { -+ if (info->type == SPA_ID_INVALID) { -+ if (info->values && (res = spa_debug_type_find(info->values, type))) -+ return res; -+ } -+ else if (info->type == type) -+ return info; -+ info++; -+ } -+ return NULL; -+} -+ -+static inline const char *spa_debug_type_short_name(const char *name) -+{ -+ const char *h; -+ if ((h = strrchr(name, ':')) != NULL) -+ name = h + 1; -+ return name; -+} -+ -+static inline const char *spa_debug_type_find_name(const struct spa_type_info *info, uint32_t type) -+{ -+ if ((info = spa_debug_type_find(info, type)) == NULL) -+ return NULL; -+ return info->name; -+} -+ -+static inline const char *spa_debug_type_find_short_name(const struct spa_type_info *info, uint32_t type) -+{ -+ const char *str; -+ if ((str = spa_debug_type_find_name(info, type)) == NULL) -+ return NULL; -+ return spa_debug_type_short_name(str); -+} -+ -+static inline uint32_t spa_debug_type_find_type(const struct spa_type_info *info, const char *name) -+{ -+ if (info == NULL) -+ info = SPA_TYPE_ROOT; -+ -+ while (info && info->name) { -+ uint32_t res; -+ if (strcmp(info->name, name) == 0) -+ return info->type; -+ if (info->values && (res = spa_debug_type_find_type(info->values, name)) != SPA_ID_INVALID) -+ return res; -+ info++; -+ } -+ return SPA_ID_INVALID; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEBUG_NODE_H */ -diff --git a/third_party/pipewire/spa/graph/graph.h b/third_party/pipewire/spa/graph/graph.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/graph/graph.h -@@ -0,0 +1,352 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_GRAPH_H -+#define SPA_GRAPH_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+ -+#ifndef spa_debug -+#define spa_debug(...) -+#endif -+ -+struct spa_graph; -+struct spa_graph_node; -+struct spa_graph_link; -+struct spa_graph_port; -+ -+struct spa_graph_state { -+ int status; /**< current status */ -+ int32_t required; /**< required number of signals */ -+ int32_t pending; /**< number of pending signals */ -+}; -+ -+static inline void spa_graph_state_reset(struct spa_graph_state *state) -+{ -+ state->pending = state->required; -+} -+ -+struct spa_graph_link { -+ struct spa_list link; -+ struct spa_graph_state *state; -+ int (*signal) (void *data); -+ void *signal_data; -+}; -+ -+#define spa_graph_link_signal(l) ((l)->signal((l)->signal_data)) -+ -+#define spa_graph_state_dec(s,c) (__atomic_sub_fetch(&(s)->pending, c, __ATOMIC_SEQ_CST) == 0) -+ -+static inline int spa_graph_link_trigger(struct spa_graph_link *link) -+{ -+ struct spa_graph_state *state = link->state; -+ -+ spa_debug("link %p: state %p: pending %d/%d", link, state, -+ state->pending, state->required); -+ -+ if (spa_graph_state_dec(state, 1)) -+ spa_graph_link_signal(link); -+ -+ return state->status; -+} -+struct spa_graph { -+ uint32_t flags; /* flags */ -+ struct spa_graph_node *parent; /* parent node or NULL when driver */ -+ struct spa_graph_state *state; /* state of graph */ -+ struct spa_list nodes; /* list of nodes of this graph */ -+}; -+ -+struct spa_graph_node_callbacks { -+#define SPA_VERSION_GRAPH_NODE_CALLBACKS 0 -+ uint32_t version; -+ -+ int (*process) (void *data, struct spa_graph_node *node); -+ int (*reuse_buffer) (void *data, struct spa_graph_node *node, -+ uint32_t port_id, uint32_t buffer_id); -+}; -+ -+struct spa_graph_node { -+ struct spa_list link; /**< link in graph nodes list */ -+ struct spa_graph *graph; /**< owner graph */ -+ struct spa_list ports[2]; /**< list of input and output ports */ -+ struct spa_list links; /**< list of links to next nodes */ -+ uint32_t flags; /**< node flags */ -+ struct spa_graph_state *state; /**< state of the node */ -+ struct spa_graph_link graph_link; /**< link in graph */ -+ struct spa_graph *subgraph; /**< subgraph or NULL */ -+ struct spa_callbacks callbacks; -+ struct spa_list sched_link; /**< link for scheduler */ -+}; -+ -+#define spa_graph_node_call(n,method,version,...) \ -+({ \ -+ int __res = 0; \ -+ spa_callbacks_call_res(&(n)->callbacks, \ -+ struct spa_graph_node_callbacks, __res, \ -+ method, version, ##__VA_ARGS__); \ -+ __res; \ -+}) -+ -+#define spa_graph_node_process(n) spa_graph_node_call(n, process, 0, n) -+#define spa_graph_node_reuse_buffer(n,p,i) spa_graph_node_call(n, reuse_buffer, 0, n, p, i) -+ -+struct spa_graph_port { -+ struct spa_list link; /**< link in node port list */ -+ struct spa_graph_node *node; /**< owner node */ -+ enum spa_direction direction; /**< port direction */ -+ uint32_t port_id; /**< port id */ -+ uint32_t flags; /**< port flags */ -+ struct spa_graph_port *peer; /**< peer */ -+}; -+ -+static inline int spa_graph_node_trigger(struct spa_graph_node *node) -+{ -+ struct spa_graph_link *l; -+ spa_debug("node %p trigger", node); -+ spa_list_for_each(l, &node->links, link) -+ spa_graph_link_trigger(l); -+ return 0; -+} -+ -+static inline int spa_graph_run(struct spa_graph *graph) -+{ -+ struct spa_graph_node *n, *t; -+ struct spa_list pending; -+ -+ spa_graph_state_reset(graph->state); -+ spa_debug("graph %p run with state %p pending %d/%d", graph, graph->state, -+ graph->state->pending, graph->state->required); -+ -+ spa_list_init(&pending); -+ -+ spa_list_for_each(n, &graph->nodes, link) { -+ struct spa_graph_state *s = n->state; -+ spa_graph_state_reset(s); -+ spa_debug("graph %p node %p: state %p pending %d/%d status %d", graph, n, -+ s, s->pending, s->required, s->status); -+ if (--s->pending == 0) -+ spa_list_append(&pending, &n->sched_link); -+ } -+ spa_list_for_each_safe(n, t, &pending, sched_link) -+ spa_graph_node_process(n); -+ -+ return 0; -+} -+ -+static inline int spa_graph_finish(struct spa_graph *graph) -+{ -+ spa_debug("graph %p finish", graph); -+ if (graph->parent) -+ return spa_graph_node_trigger(graph->parent); -+ return 0; -+} -+static inline int spa_graph_link_signal_node(void *data) -+{ -+ struct spa_graph_node *node = (struct spa_graph_node *)data; -+ spa_debug("node %p call process", node); -+ return spa_graph_node_process(node); -+} -+ -+static inline int spa_graph_link_signal_graph(void *data) -+{ -+ struct spa_graph_node *node = (struct spa_graph_node *)data; -+ return spa_graph_finish(node->graph); -+} -+ -+static inline void spa_graph_init(struct spa_graph *graph, struct spa_graph_state *state) -+{ -+ spa_list_init(&graph->nodes); -+ graph->flags = 0; -+ graph->state = state; -+ spa_debug("graph %p init state %p", graph, state); -+} -+ -+static inline void -+spa_graph_link_add(struct spa_graph_node *out, -+ struct spa_graph_state *state, -+ struct spa_graph_link *link) -+{ -+ link->state = state; -+ state->required++; -+ spa_debug("node %p add link %p to state %p %d", out, link, state, state->required); -+ spa_list_append(&out->links, &link->link); -+} -+ -+static inline void spa_graph_link_remove(struct spa_graph_link *link) -+{ -+ link->state->required--; -+ spa_debug("link %p state %p remove %d", link, link->state, link->state->required); -+ spa_list_remove(&link->link); -+} -+ -+static inline void -+spa_graph_node_init(struct spa_graph_node *node, struct spa_graph_state *state) -+{ -+ spa_list_init(&node->ports[SPA_DIRECTION_INPUT]); -+ spa_list_init(&node->ports[SPA_DIRECTION_OUTPUT]); -+ spa_list_init(&node->links); -+ node->flags = 0; -+ node->subgraph = NULL; -+ node->state = state; -+ node->state->required = node->state->pending = 0; -+ node->state->status = SPA_STATUS_OK; -+ node->graph_link.signal = spa_graph_link_signal_graph; -+ node->graph_link.signal_data = node; -+ spa_debug("node %p init state %p", node, state); -+} -+ -+ -+static inline int spa_graph_node_impl_sub_process(void *data, struct spa_graph_node *node) -+{ -+ struct spa_graph *graph = node->subgraph; -+ spa_debug("node %p: sub process %p", node, graph); -+ return spa_graph_run(graph); -+} -+ -+static const struct spa_graph_node_callbacks spa_graph_node_sub_impl_default = { -+ SPA_VERSION_GRAPH_NODE_CALLBACKS, -+ .process = spa_graph_node_impl_sub_process, -+}; -+ -+static inline void spa_graph_node_set_subgraph(struct spa_graph_node *node, -+ struct spa_graph *subgraph) -+{ -+ node->subgraph = subgraph; -+ subgraph->parent = node; -+ spa_debug("node %p set subgraph %p", node, subgraph); -+} -+ -+static inline void -+spa_graph_node_set_callbacks(struct spa_graph_node *node, -+ const struct spa_graph_node_callbacks *callbacks, -+ void *data) -+{ -+ node->callbacks = SPA_CALLBACKS_INIT(callbacks, data); -+} -+ -+static inline void -+spa_graph_node_add(struct spa_graph *graph, -+ struct spa_graph_node *node) -+{ -+ node->graph = graph; -+ spa_list_append(&graph->nodes, &node->link); -+ node->state->required++; -+ spa_debug("node %p add to graph %p, state %p required %d", -+ node, graph, node->state, node->state->required); -+ spa_graph_link_add(node, graph->state, &node->graph_link); -+} -+ -+static inline void spa_graph_node_remove(struct spa_graph_node *node) -+{ -+ spa_debug("node %p remove from graph %p, state %p required %d", -+ node, node->graph, node->state, node->state->required); -+ spa_graph_link_remove(&node->graph_link); -+ node->state->required--; -+ spa_list_remove(&node->link); -+} -+ -+ -+static inline void -+spa_graph_port_init(struct spa_graph_port *port, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t flags) -+{ -+ spa_debug("port %p init type %d id %d", port, direction, port_id); -+ port->direction = direction; -+ port->port_id = port_id; -+ port->flags = flags; -+} -+ -+static inline void -+spa_graph_port_add(struct spa_graph_node *node, -+ struct spa_graph_port *port) -+{ -+ spa_debug("port %p add to node %p", port, node); -+ port->node = node; -+ spa_list_append(&node->ports[port->direction], &port->link); -+} -+ -+static inline void spa_graph_port_remove(struct spa_graph_port *port) -+{ -+ spa_debug("port %p remove", port); -+ spa_list_remove(&port->link); -+} -+ -+static inline void -+spa_graph_port_link(struct spa_graph_port *out, struct spa_graph_port *in) -+{ -+ spa_debug("port %p link to %p %p %p", out, in, in->node, in->node->state); -+ out->peer = in; -+ in->peer = out; -+} -+ -+static inline void -+spa_graph_port_unlink(struct spa_graph_port *port) -+{ -+ spa_debug("port %p unlink from %p", port, port->peer); -+ if (port->peer) { -+ port->peer->peer = NULL; -+ port->peer = NULL; -+ } -+} -+ -+static inline int spa_graph_node_impl_process(void *data, struct spa_graph_node *node) -+{ -+ struct spa_node *n = (struct spa_node *)data; -+ struct spa_graph_state *state = node->state; -+ -+ spa_debug("node %p: process state %p: %d, node %p", node, state, state->status, n); -+ if ((state->status = spa_node_process(n)) != SPA_STATUS_OK) -+ spa_graph_node_trigger(node); -+ -+ return state->status; -+} -+ -+static inline int spa_graph_node_impl_reuse_buffer(void *data, struct spa_graph_node *node, -+ uint32_t port_id, uint32_t buffer_id) -+{ -+ struct spa_node *n = (struct spa_node *)data; -+ return spa_node_port_reuse_buffer(n, port_id, buffer_id); -+} -+ -+static const struct spa_graph_node_callbacks spa_graph_node_impl_default = { -+ SPA_VERSION_GRAPH_NODE_CALLBACKS, -+ .process = spa_graph_node_impl_process, -+ .reuse_buffer = spa_graph_node_impl_reuse_buffer, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_GRAPH_H */ -diff --git a/third_party/pipewire/spa/monitor/device.h b/third_party/pipewire/spa/monitor/device.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/device.h -@@ -0,0 +1,297 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEVICE_H -+#define SPA_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+/** -+ * spa_device: -+ * -+ * The device interface can be used to monitor all kinds of devices -+ * and create objects as a result. Objects a typically other -+ * Devices or Nodes. -+ * -+ */ -+#define SPA_TYPE_INTERFACE_Device SPA_TYPE_INFO_INTERFACE_BASE "Device" -+ -+#define SPA_VERSION_DEVICE 0 -+struct spa_device { struct spa_interface iface; }; -+ -+/** -+ * Information about the device and parameters it supports -+ * -+ * This information is part of the info event on a device. -+ */ -+struct spa_device_info { -+#define SPA_VERSION_DEVICE_INFO 0 -+ uint32_t version; -+ -+#define SPA_DEVICE_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_DEVICE_CHANGE_MASK_PROPS (1u<<1) -+#define SPA_DEVICE_CHANGE_MASK_PARAMS (1u<<2) -+ uint64_t change_mask; -+ uint64_t flags; -+ const struct spa_dict *props; /**< device properties */ -+ struct spa_param_info *params; /**< supported parameters */ -+ uint32_t n_params; /**< number of elements in params */ -+}; -+ -+#define SPA_DEVICE_INFO_INIT() (struct spa_device_info){ SPA_VERSION_DEVICE_INFO, } -+ -+/** -+ * Information about a device object -+ * -+ * This information is part of the object_info event on the device. -+ */ -+struct spa_device_object_info { -+#define SPA_VERSION_DEVICE_OBJECT_INFO 0 -+ uint32_t version; -+ -+ const char *type; /**< the object type managed by this device */ -+ const char *factory_name; /**< a factory name that implements the object */ -+ -+#define SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS (1u<<1) -+ uint64_t change_mask; -+ uint64_t flags; -+ const struct spa_dict *props; /**< extra object properties */ -+}; -+ -+#define SPA_DEVICE_OBJECT_INFO_INIT() (struct spa_device_object_info){ SPA_VERSION_DEVICE_OBJECT_INFO, } -+ -+/** the result of spa_device_enum_params() */ -+#define SPA_RESULT_TYPE_DEVICE_PARAMS 1 -+struct spa_result_device_params { -+ uint32_t id; -+ uint32_t index; -+ uint32_t next; -+ struct spa_pod *param; -+}; -+ -+#define SPA_DEVICE_EVENT_INFO 0 -+#define SPA_DEVICE_EVENT_RESULT 1 -+#define SPA_DEVICE_EVENT_EVENT 2 -+#define SPA_DEVICE_EVENT_OBJECT_INFO 3 -+#define SPA_DEVICE_EVENT_NUM 4 -+ -+/** -+ * spa_device_events: -+ * -+ * Events are always emitted from the main thread -+ */ -+struct spa_device_events { -+ /** version of the structure */ -+#define SPA_VERSION_DEVICE_EVENTS 0 -+ uint32_t version; -+ -+ /** notify extra information about the device */ -+ void (*info) (void *data, const struct spa_device_info *info); -+ -+ /** notify a result */ -+ void (*result) (void *data, int seq, int res, uint32_t type, const void *result); -+ -+ /** a device event */ -+ void (*event) (void *data, const struct spa_event *event); -+ -+ /** info changed for an object managed by the device, info is NULL when -+ * the object is removed */ -+ void (*object_info) (void *data, uint32_t id, -+ const struct spa_device_object_info *info); -+}; -+ -+#define SPA_DEVICE_METHOD_ADD_LISTENER 0 -+#define SPA_DEVICE_METHOD_SYNC 1 -+#define SPA_DEVICE_METHOD_ENUM_PARAMS 2 -+#define SPA_DEVICE_METHOD_SET_PARAM 3 -+#define SPA_DEVICE_METHOD_NUM 4 -+ -+/** -+ * spa_device_methods: -+ */ -+struct spa_device_methods { -+ /* the version of the methods. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_DEVICE_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Set events to receive asynchronous notifications from -+ * the device. -+ * -+ * Setting the events will trigger the info event and an -+ * object_info event for each managed object on the new -+ * listener. -+ * -+ * \param device a #spa_device -+ * \param listener a listener -+ * \param events a #struct spa_device_events -+ * \param data data passed as first argument in functions of \a events -+ * \return 0 on success -+ * < 0 errno on error -+ */ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct spa_device_events *events, -+ void *data); -+ /** -+ * Perform a sync operation. -+ * -+ * This method will emit the result event with the given sequence -+ * number synchronously or with the returned async return value -+ * asynchronously. -+ * -+ * Because all methods are serialized in the device, this can be used -+ * to wait for completion of all previous method calls. -+ * -+ * \param seq a sequence number -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * an async result -+ */ -+ int (*sync) (void *object, int seq); -+ -+ /** -+ * Enumerate the parameters of a device. -+ * -+ * Parameters are identified with an \a id. Some parameters can have -+ * multiple values, see the documentation of the parameter id. -+ * -+ * Parameters can be filtered by passing a non-NULL \a filter. -+ * -+ * The result callback will be called at most \max times with a -+ * struct spa_result_device_params as the result. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param device a \ref spa_device -+ * \param seq a sequence number to pass to the result function -+ * \param id the param id to enumerate -+ * \param index the index of enumeration, pass 0 for the first item. -+ * \param max the maximum number of items to iterate -+ * \param filter and optional filter to use -+ * \return 0 when there are no more parameters to enumerate -+ * -EINVAL when invalid arguments are given -+ * -ENOENT the parameter \a id is unknown -+ * -ENOTSUP when there are no parameters -+ * implemented on \a device -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t index, uint32_t max, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set the configurable parameter in \a device. -+ * -+ * Usually, \a param will be obtained from enum_params and then -+ * modified but it is also possible to set another spa_pod -+ * as long as its keys and types match a supported object. -+ * -+ * Objects with property keys that are not known are ignored. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param device a \ref spa_device -+ * \param id the parameter id to configure -+ * \param flags additional flags -+ * \param param the parameter to configure -+ * -+ * \return 0 on success -+ * -EINVAL when invalid arguments are given -+ * -ENOTSUP when there are no parameters implemented on \a device -+ * -ENOENT the parameter is unknown -+ */ -+ int (*set_param) (void *object, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+}; -+ -+#define spa_device_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_device *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_device_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_device_add_listener(d,...) spa_device_method(d, add_listener, 0, __VA_ARGS__) -+#define spa_device_sync(d,...) spa_device_method(d, sync, 0, __VA_ARGS__) -+#define spa_device_enum_params(d,...) spa_device_method(d, enum_params, 0, __VA_ARGS__) -+#define spa_device_set_param(d,...) spa_device_method(d, set_param, 0, __VA_ARGS__) -+ -+#define SPA_KEY_DEVICE_ENUM_API "device.enum.api" /**< the api used to discover this -+ * device */ -+#define SPA_KEY_DEVICE_API "device.api" /**< the api used by the device -+ * Ex. "udev", "alsa", "v4l2". */ -+#define SPA_KEY_DEVICE_NAME "device.name" /**< the name of the device */ -+#define SPA_KEY_DEVICE_ALIAS "device.alias" /**< alternative name of the device */ -+#define SPA_KEY_DEVICE_NICK "device.nick" /**< the device short name */ -+#define SPA_KEY_DEVICE_DESCRIPTION "device.description" /**< a device description */ -+#define SPA_KEY_DEVICE_ICON "device.icon" /**< icon for the device. A base64 blob -+ * containing PNG image data */ -+#define SPA_KEY_DEVICE_ICON_NAME "device.icon-name" /**< an XDG icon name for the device. -+ * Ex. "sound-card-speakers-usb" */ -+#define SPA_KEY_DEVICE_PLUGGED_USEC "device.plugged.usec" /**< when the device was plugged */ -+ -+#define SPA_KEY_DEVICE_BUS_ID "device.bus-id" /**< the device bus-id */ -+#define SPA_KEY_DEVICE_BUS_PATH "device.bus-path" /**< bus path to the device in the OS' -+ * format. -+ * Ex. "pci-0000:00:14.0-usb-0:3.2:1.0" */ -+#define SPA_KEY_DEVICE_BUS "device.bus" /**< bus of the device if applicable. One of -+ * "isa", "pci", "usb", "firewire", -+ * "bluetooth" */ -+#define SPA_KEY_DEVICE_SUBSYSTEM "device.subsystem" /**< device subsystem */ -+#define SPA_KEY_DEVICE_SYSFS_PATH "device.sysfs.path" /**< device sysfs path */ -+ -+#define SPA_KEY_DEVICE_VENDOR_ID "device.vendor.id" /**< vendor ID if applicable */ -+#define SPA_KEY_DEVICE_VENDOR_NAME "device.vendor.name" /**< vendor name if applicable */ -+#define SPA_KEY_DEVICE_PRODUCT_ID "device.product.id" /**< product ID if applicable */ -+#define SPA_KEY_DEVICE_PRODUCT_NAME "device.product.name" /**< product name if applicable */ -+#define SPA_KEY_DEVICE_SERIAL "device.serial" /**< Serial number if applicable */ -+#define SPA_KEY_DEVICE_CLASS "device.class" /**< device class */ -+#define SPA_KEY_DEVICE_CAPABILITIES "device.capabilities" /**< api specific device capabilities */ -+#define SPA_KEY_DEVICE_FORM_FACTOR "device.form-factor" /**< form factor if applicable. One of -+ * "internal", "speaker", "handset", "tv", -+ * "webcam", "microphone", "headset", -+ * "headphone", "hands-free", "car", "hifi", -+ * "computer", "portable" */ -+#define SPA_KEY_DEVICE_PROFILE "device.profile " /**< profile for the device */ -+#define SPA_KEY_DEVICE_PROFILE_SET "device.profile-set" /**< profile set for the device */ -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEVICE_H */ -diff --git a/third_party/pipewire/spa/monitor/event.h b/third_party/pipewire/spa/monitor/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/event.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2020 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_DEVICE_H -+#define SPA_EVENT_DEVICE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_EVENT_Device */ -+enum spa_device_event { -+ SPA_DEVICE_EVENT_ObjectConfig, -+}; -+ -+#define SPA_DEVICE_EVENT_ID(ev) SPA_EVENT_ID(ev, SPA_TYPE_EVENT_Device) -+#define SPA_DEVICE_EVENT_INIT(id) SPA_EVENT_INIT(SPA_TYPE_EVENT_Device, id) -+ -+/* properties for SPA_TYPE_EVENT_Device */ -+enum spa_event_device { -+ SPA_EVENT_DEVICE_START, -+ -+ SPA_EVENT_DEVICE_Object, /* an object id (Int) */ -+ SPA_EVENT_DEVICE_Props, /* properties for an object (SPA_TYPE_OBJECT_Props) */ -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_DEVICE */ -diff --git a/third_party/pipewire/spa/monitor/utils.h b/third_party/pipewire/spa/monitor/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/monitor/utils.h -@@ -0,0 +1,95 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DEVICE_UTILS_H -+#define SPA_DEVICE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_result_device_params_data { -+ struct spa_pod_builder *builder; -+ struct spa_result_device_params data; -+}; -+ -+static inline void spa_result_func_device_params(void *data, int seq, int res, -+ uint32_t type, const void *result) -+{ -+ struct spa_result_device_params_data *d = -+ (struct spa_result_device_params_data *)data; -+ const struct spa_result_device_params *r = -+ (const struct spa_result_device_params *)result; -+ uint32_t offset = d->builder->state.offset; -+ spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param)); -+ d->data.next = r->next; -+ d->data.param = SPA_MEMBER(d->builder->data, offset, struct spa_pod); -+} -+ -+static inline int spa_device_enum_params_sync(struct spa_device *device, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_device_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_device_events device_events = { -+ SPA_VERSION_DEVICE_EVENTS, -+ .result = spa_result_func_device_params, -+ }; -+ int res; -+ -+ spa_device_add_listener(device, &listener, &device_events, &data); -+ res = spa_device_enum_params(device, 0, id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+#define spa_device_emit(hooks,method,version,...) \ -+ spa_hook_list_call_simple(hooks, struct spa_device_events, \ -+ method, version, ##__VA_ARGS__) -+ -+#define spa_device_emit_info(hooks,i) spa_device_emit(hooks,info, 0, i) -+#define spa_device_emit_result(hooks,s,r,t,res) spa_device_emit(hooks,result, 0, s, r, t, res) -+#define spa_device_emit_event(hooks,e) spa_device_emit(hooks,event, 0, e) -+#define spa_device_emit_object_info(hooks,id,i) spa_device_emit(hooks,object_info, 0, id, i) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DEVICE_UTILS_H */ -diff --git a/third_party/pipewire/spa/node/command.h b/third_party/pipewire/spa/node/command.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/command.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_COMMAND_NODE_H -+#define SPA_COMMAND_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_COMMAND_Node */ -+enum spa_node_command { -+ SPA_NODE_COMMAND_Suspend, -+ SPA_NODE_COMMAND_Pause, -+ SPA_NODE_COMMAND_Start, -+ SPA_NODE_COMMAND_Enable, -+ SPA_NODE_COMMAND_Disable, -+ SPA_NODE_COMMAND_Flush, -+ SPA_NODE_COMMAND_Drain, -+ SPA_NODE_COMMAND_Marker, -+}; -+ -+#define SPA_NODE_COMMAND_ID(cmd) SPA_COMMAND_ID(cmd, SPA_TYPE_COMMAND_Node) -+#define SPA_NODE_COMMAND_INIT(id) SPA_COMMAND_INIT(SPA_TYPE_COMMAND_Node, id) -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_COMMAND_NODE_H */ -diff --git a/third_party/pipewire/spa/node/event.h b/third_party/pipewire/spa/node/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/event.h -@@ -0,0 +1,48 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_NODE_H -+#define SPA_EVENT_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/* object id of SPA_TYPE_EVENT_Node */ -+enum spa_node_event { -+ SPA_NODE_EVENT_Error, -+ SPA_NODE_EVENT_Buffering, -+ SPA_NODE_EVENT_RequestRefresh, -+}; -+ -+#define SPA_NODE_EVENT_ID(ev) SPA_EVENT_ID(ev, SPA_TYPE_EVENT_Node) -+#define SPA_NODE_EVENT_INIT(id) SPA_EVENT_INIT(SPA_TYPE_EVENT_Node, id) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_NODE_H */ -diff --git a/third_party/pipewire/spa/node/io.h b/third_party/pipewire/spa/node/io.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/io.h -@@ -0,0 +1,294 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_IO_H -+#define SPA_IO_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** IO areas -+ * -+ * IO information for a port on a node. This is allocated -+ * by the host and configured on a node or all ports for which -+ * IO is requested. -+ * -+ * The plugin will communicate with the host through the IO -+ * areas. -+ */ -+ -+/** Different IO area types */ -+enum spa_io_type { -+ SPA_IO_Invalid, -+ SPA_IO_Buffers, /**< area to exchange buffers, struct spa_io_buffers */ -+ SPA_IO_Range, /**< expected byte range, struct spa_io_range */ -+ SPA_IO_Clock, /**< area to update clock information, struct spa_io_clock */ -+ SPA_IO_Latency, /**< latency reporting, struct spa_io_latency */ -+ SPA_IO_Control, /**< area for control messages, struct spa_io_sequence */ -+ SPA_IO_Notify, /**< area for notify messages, struct spa_io_sequence */ -+ SPA_IO_Position, /**< position information in the graph, struct spa_io_position */ -+ SPA_IO_RateMatch, /**< rate matching between nodes, struct spa_io_rate_match */ -+ SPA_IO_Memory, /**< memory pointer, struct spa_io_memory */ -+}; -+ -+/** -+ * IO area to exchange buffers. -+ * -+ * A set of buffers should first be configured on the node/port. -+ * Further references to those buffers will be made by using the -+ * id of the buffer. -+ * -+ * If status is SPA_STATUS_OK, the host should ignore -+ * the io area. -+ * -+ * If status is SPA_STATUS_NEED_DATA, the host should: -+ * 1) recycle the buffer in buffer_id, if possible -+ * 2) prepare a new buffer and place the id in buffer_id. -+ * -+ * If status is SPA_STATUS_HAVE_DATA, the host should consume -+ * the buffer in buffer_id and set the state to -+ * SPA_STATUS_NEED_DATA when new data is requested. -+ * -+ * If status is SPA_STATUS_STOPPED, some error occurred on the -+ * port. -+ * -+ * If status is SPA_STATUS_DRAINED, data from the io area was -+ * used to drain. -+ * -+ * Status can also be a negative errno value to indicate errors. -+ * such as: -+ * -EINVAL: buffer_id is invalid -+ * -EPIPE: no more buffers available -+ */ -+struct spa_io_buffers { -+#define SPA_STATUS_OK 0 -+#define SPA_STATUS_NEED_DATA (1<<0) -+#define SPA_STATUS_HAVE_DATA (1<<1) -+#define SPA_STATUS_STOPPED (1<<2) -+#define SPA_STATUS_DRAINED (1<<3) -+ int32_t status; /**< the status code */ -+ uint32_t buffer_id; /**< a buffer id */ -+}; -+ -+#define SPA_IO_BUFFERS_INIT (struct spa_io_buffers) { SPA_STATUS_OK, SPA_ID_INVALID, } -+ -+/** -+ * IO area to exchange a memory region -+ */ -+struct spa_io_memory { -+ int32_t status; /**< the status code */ -+ uint32_t size; /**< the size of \a data */ -+ void *data; /**< a memory pointer */ -+}; -+#define SPA_IO_MEMORY_INIT (struct spa_io_memory) { SPA_STATUS_OK, 0, NULL, } -+ -+/** A range, suitable for input ports that can suggest a range to output ports */ -+struct spa_io_range { -+ uint64_t offset; /**< offset in range */ -+ uint32_t min_size; /**< minimum size of data */ -+ uint32_t max_size; /**< maximum size of data */ -+}; -+ -+/** -+ * Absolute time reporting. -+ * -+ * Nodes that can report clocking information will receive this io block. -+ * The application sets the id. This is usually set as part of the -+ * position information but can also be set separately. -+ * -+ * The clock counts the elapsed time according to the clock provider -+ * since the provider was last started. -+ */ -+struct spa_io_clock { -+ uint32_t flags; /**< clock flags */ -+ uint32_t id; /**< unique clock id, set by application */ -+ char name[64]; /**< clock name prefixed with API, set by node. The clock name -+ * is unique per clock and can be used to check if nodes -+ * share the same clock. */ -+ uint64_t nsec; /**< time in nanoseconds against monotonic clock */ -+ struct spa_fraction rate; /**< rate for position/duration/delay */ -+ uint64_t position; /**< current position */ -+ uint64_t duration; /**< duration of current cycle */ -+ int64_t delay; /**< delay between position and hardware, -+ * positive for capture, negative for playback */ -+ double rate_diff; /**< rate difference between clock and monotonic time */ -+ uint64_t next_nsec; /**< extimated next wakeup time in nanoseconds */ -+ uint32_t padding[8]; -+}; -+ -+/* the size of the video in this cycle */ -+struct spa_io_video_size { -+#define SPA_IO_VIDEO_SIZE_VALID (1<<0) -+ uint32_t flags; /**< optional flags */ -+ uint32_t stride; /**< video stride in bytes */ -+ struct spa_rectangle size; /**< the video size */ -+ struct spa_fraction framerate; /**< the minimum framerate, the cycle duration is -+ * always smaller to ensure there is only one -+ * video frame per cycle. */ -+ uint32_t padding[4]; -+}; -+ -+/** latency reporting */ -+struct spa_io_latency { -+ struct spa_fraction rate; /**< rate for min/max */ -+ uint64_t min; /**< min latency */ -+ uint64_t max; /**< max latency */ -+}; -+ -+/** control stream, io area for SPA_IO_Control and SPA_IO_Notify */ -+struct spa_io_sequence { -+ struct spa_pod_sequence sequence; /**< sequence of timed events */ -+}; -+ -+/** bar and beat segment */ -+struct spa_io_segment_bar { -+#define SPA_IO_SEGMENT_BAR_FLAG_VALID (1<<0) -+ uint32_t flags; /**< extra flags */ -+ uint32_t offset; /**< offset in segment of this beat */ -+ float signature_num; /**< time signature numerator */ -+ float signature_denom; /**< time signature denominator */ -+ double bpm; /**< beats per minute */ -+ double beat; /**< current beat in segment */ -+ uint32_t padding[8]; -+}; -+ -+/** video frame segment */ -+struct spa_io_segment_video { -+#define SPA_IO_SEGMENT_VIDEO_FLAG_VALID (1<<0) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_DROP_FRAME (1<<1) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_PULL_DOWN (1<<2) -+#define SPA_IO_SEGMENT_VIDEO_FLAG_INTERLACED (1<<3) -+ uint32_t flags; /**< flags */ -+ uint32_t offset; /**< offset in segment */ -+ struct spa_fraction framerate; -+ uint32_t hours; -+ uint32_t minutes; -+ uint32_t seconds; -+ uint32_t frames; -+ uint32_t field_count; /**< 0 for progressive, 1 and 2 for interlaced */ -+ uint32_t padding[11]; -+}; -+ -+/** -+ * A segment converts a running time to a segment (stream) position. -+ * -+ * The segment position is valid when the current running time is between -+ * start and start + duration. The position is then -+ * calculated as: -+ * -+ * (running time - start) * rate + position; -+ * -+ * Support for looping is done by specifying the LOOPING flags with a -+ * non-zero duration. When the running time reaches start + duration, -+ * duration is added to start and the loop repeats. -+ * -+ * Care has to be taken when the running time + clock.duration extends -+ * past the start + duration from the segment; the user should correctly -+ * wrap around and partially repeat the loop in the current cycle. -+ * -+ * Extra information can be placed in the segment by setting the valid flags -+ * and filling up the corresponding structures. -+ */ -+struct spa_io_segment { -+ uint32_t version; -+#define SPA_IO_SEGMENT_FLAG_LOOPING (1<<0) /**< after the duration, the segment repeats */ -+#define SPA_IO_SEGMENT_FLAG_NO_POSITION (1<<1) /**< position is invalid. The position can be invalid -+ * after a seek, for example, when the exact mapping -+ * of the extra segment info (bar, video, ...) to -+ * position has not been determined yet */ -+ uint32_t flags; /**< extra flags */ -+ uint64_t start; /**< value of running time when this -+ * info is active. Can be in the future for -+ * pending changes. It does not have to be in -+ * exact multiples of the clock duration. */ -+ uint64_t duration; /**< duration when this info becomes invalid expressed -+ * in running time. If the duration is 0, this -+ * segment extends to the next segment. If the -+ * segment becomes invalid and the looping flag is -+ * set, the segment repeats. */ -+ double rate; /**< overal rate of the segment, can be negative for -+ * backwards time reporting. */ -+ uint64_t position; /**< The position when the running time == start. -+ * can be invalid when the owner of the extra segment -+ * information has not yet made the mapping. */ -+ -+ struct spa_io_segment_bar bar; -+ struct spa_io_segment_video video; -+}; -+ -+enum spa_io_position_state { -+ SPA_IO_POSITION_STATE_STOPPED, -+ SPA_IO_POSITION_STATE_STARTING, -+ SPA_IO_POSITION_STATE_RUNNING, -+}; -+ -+/** the maximum number of segments visible in the future */ -+#define SPA_IO_POSITION_MAX_SEGMENTS 8 -+ -+/** -+ * The position information adds extra meaning to the raw clock times. -+ * -+ * It is set on all nodes and the clock id will contain the clock of the -+ * driving node in the graph. -+ * -+ * The position information contains 1 or more segments that convert the -+ * raw clock times to a stream time. They are sorted based on their -+ * start times, and thus the order in which they will activate in -+ * the future. This makes it possible to look ahead in the scheduled -+ * segments and anticipate the changes in the timeline. -+ */ -+struct spa_io_position { -+ struct spa_io_clock clock; /**< clock position of driver, always valid and -+ * read only */ -+ struct spa_io_video_size video; /**< size of the video in the current cycle */ -+ int64_t offset; /**< an offset to subtract from the clock position -+ * to get a running time. This is the time that -+ * the state has been in the RUNNING state and the -+ * time that should be used to compare the segment -+ * start values against. */ -+ uint32_t state; /**< one of enum spa_io_position_state */ -+ -+ uint32_t n_segments; /**< number of segments */ -+ struct spa_io_segment segments[SPA_IO_POSITION_MAX_SEGMENTS]; /**< segments */ -+}; -+ -+/** rate matching */ -+struct spa_io_rate_match { -+ uint32_t delay; /**< extra delay in samples for resampler */ -+ uint32_t size; /**< requested input size for resampler */ -+ double rate; /**< rate for resampler */ -+#define SPA_IO_RATE_MATCH_FLAG_ACTIVE (1 << 0) -+ uint32_t flags; /**< extra flags */ -+ uint32_t padding[7]; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_IO_H */ -diff --git a/third_party/pipewire/spa/node/keys.h b/third_party/pipewire/spa/node/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/keys.h -@@ -0,0 +1,54 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_KEYS_H -+#define SPA_NODE_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** node keys */ -+#define SPA_KEY_NODE_NAME "node.name" /**< a node name */ -+#define SPA_KEY_NODE_LATENCY "node.latency" /**< the requested node latency */ -+ -+#define SPA_KEY_NODE_DRIVER "node.driver" /**< the node can be a driver */ -+#define SPA_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< call the process function even if -+ * not linked. */ -+#define SPA_KEY_NODE_PAUSE_ON_IDLE "node.pause-on-idle" /**< if the node should be paused -+ * immediately when idle. */ -+#define SPA_KEY_NODE_MONITOR "node.monitor" /**< the node has monitor ports */ -+ -+ -+/** port keys */ -+#define SPA_KEY_PORT_NAME "port.name" /**< a port name */ -+#define SPA_KEY_PORT_ALIAS "port.alias" /**< a port alias */ -+#define SPA_KEY_PORT_MONITOR "port.monitor" /**< this port is a monitor port */ -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_KEYS_H */ -diff --git a/third_party/pipewire/spa/node/node.h b/third_party/pipewire/spa/node/node.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/node.h -@@ -0,0 +1,662 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_H -+#define SPA_NODE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+ -+/** -+ * A spa_node is a component that can consume and produce buffers. -+ */ -+#define SPA_TYPE_INTERFACE_Node SPA_TYPE_INFO_INTERFACE_BASE "Node" -+ -+#define SPA_VERSION_NODE 0 -+struct spa_node { struct spa_interface iface; }; -+ -+/** -+ * Node information structure -+ * -+ * Contains the basic node information. -+ */ -+struct spa_node_info { -+ uint32_t max_input_ports; -+ uint32_t max_output_ports; -+#define SPA_NODE_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_NODE_CHANGE_MASK_PROPS (1u<<1) -+#define SPA_NODE_CHANGE_MASK_PARAMS (1u<<2) -+ uint64_t change_mask; -+ -+#define SPA_NODE_FLAG_RT (1u<<0) /**< node can do real-time processing */ -+#define SPA_NODE_FLAG_IN_DYNAMIC_PORTS (1u<<1) /**< input ports can be added/removed */ -+#define SPA_NODE_FLAG_OUT_DYNAMIC_PORTS (1u<<2) /**< output ports can be added/removed */ -+#define SPA_NODE_FLAG_IN_PORT_CONFIG (1u<<3) /**< input ports can be reconfigured with -+ * PortConfig parameter */ -+#define SPA_NODE_FLAG_OUT_PORT_CONFIG (1u<<4) /**< output ports can be reconfigured with -+ * PortConfig parameter */ -+#define SPA_NODE_FLAG_NEED_CONFIGURE (1u<<5) /**< node needs configuration before it can -+ * be started. */ -+#define SPA_NODE_FLAG_ASYNC (1u<<6) /**< the process function might not -+ * immediateley produce or consume data -+ * but might offload the work to a worker -+ * thread. */ -+ uint64_t flags; -+ struct spa_dict *props; /**< extra node properties */ -+ struct spa_param_info *params; /**< parameter information */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+#define SPA_NODE_INFO_INIT() (struct spa_node_info) { 0, } -+ -+/** -+ * Port information structure -+ * -+ * Contains the basic port information. -+ */ -+struct spa_port_info { -+#define SPA_PORT_CHANGE_MASK_FLAGS (1u<<0) -+#define SPA_PORT_CHANGE_MASK_RATE (1u<<1) -+#define SPA_PORT_CHANGE_MASK_PROPS (1u<<2) -+#define SPA_PORT_CHANGE_MASK_PARAMS (1u<<3) -+ uint64_t change_mask; -+ -+#define SPA_PORT_FLAG_REMOVABLE (1u<<0) /**< port can be removed */ -+#define SPA_PORT_FLAG_OPTIONAL (1u<<1) /**< processing on port is optional */ -+#define SPA_PORT_FLAG_CAN_ALLOC_BUFFERS (1u<<2) /**< the port can allocate buffer data */ -+#define SPA_PORT_FLAG_IN_PLACE (1u<<3) /**< the port can process data in-place and -+ * will need a writable input buffer */ -+#define SPA_PORT_FLAG_NO_REF (1u<<4) /**< the port does not keep a ref on the buffer. -+ * This means the node will always completely -+ * consume the input buffer and it will be -+ * recycled after process. */ -+#define SPA_PORT_FLAG_LIVE (1u<<5) /**< output buffers from this port are -+ * timestamped against a live clock. */ -+#define SPA_PORT_FLAG_PHYSICAL (1u<<6) /**< connects to some device */ -+#define SPA_PORT_FLAG_TERMINAL (1u<<7) /**< data was not created from this port -+ * or will not be made available on another -+ * port */ -+#define SPA_PORT_FLAG_DYNAMIC_DATA (1u<<8) /**< data pointer on buffers can be changed. -+ * Only the buffer data marked as DYNAMIC -+ * can be changed. */ -+ uint64_t flags; /**< port flags */ -+ struct spa_fraction rate; /**< rate of sequence numbers on port */ -+ const struct spa_dict *props; /**< extra port properties */ -+ struct spa_param_info *params; /**< parameter information */ -+ uint32_t n_params; /**< number of items in \a params */ -+}; -+ -+#define SPA_PORT_INFO_INIT() (struct spa_port_info) { 0, } -+ -+#define SPA_RESULT_TYPE_NODE_ERROR 1 -+#define SPA_RESULT_TYPE_NODE_PARAMS 2 -+ -+/** an error result */ -+struct spa_result_node_error { -+ const char *message; -+}; -+ -+/** the result of enum_params or port_enum_params. */ -+struct spa_result_node_params { -+ uint32_t id; /**< id of parameter */ -+ uint32_t index; /**< index of parameter */ -+ uint32_t next; /**< next index of iteration */ -+ struct spa_pod *param; /**< the result param */ -+}; -+ -+#define SPA_NODE_EVENT_INFO 0 -+#define SPA_NODE_EVENT_PORT_INFO 1 -+#define SPA_NODE_EVENT_RESULT 2 -+#define SPA_NODE_EVENT_EVENT 3 -+#define SPA_NODE_EVENT_NUM 4 -+ -+/** events from the spa_node. -+ * -+ * All event are called from the main thread and multiple -+ * listeners can be registered for the events with -+ * spa_node_add_listener(). -+ */ -+struct spa_node_events { -+#define SPA_VERSION_NODE_EVENTS 0 -+ uint32_t version; /**< version of this structure */ -+ -+ /** Emitted when info changes */ -+ void (*info) (void *data, const struct spa_node_info *info); -+ -+ /** Emitted when port info changes, NULL when port is removed */ -+ void (*port_info) (void *data, -+ enum spa_direction direction, uint32_t port, -+ const struct spa_port_info *info); -+ -+ /** notify a result. -+ * -+ * Some methods will trigger a result event with an optional -+ * result of the given type. Look at the documentation of the -+ * method to know when to expect a result event. -+ * -+ * The result event can be called synchronously, as an event -+ * called from inside the method itself, in which case the seq -+ * number passed to the method will be passed unchanged. -+ * -+ * The result event will be called asynchronously when the -+ * method returned an async return value. In this case, the seq -+ * number in the result will match the async return value of -+ * the method call. Users should match the seq number from -+ * request to the reply. -+ */ -+ void (*result) (void *data, int seq, int res, -+ uint32_t type, const void *result); -+ -+ /** -+ * \param node a spa_node -+ * \param event the event that was emitted -+ * -+ * This will be called when an out-of-bound event is notified -+ * on \a node. -+ */ -+ void (*event) (void *data, const struct spa_event *event); -+}; -+ -+#define SPA_NODE_CALLBACK_READY 0 -+#define SPA_NODE_CALLBACK_REUSE_BUFFER 1 -+#define SPA_NODE_CALLBACK_XRUN 2 -+#define SPA_NODE_CALLBACK_NUM 3 -+ -+/** Node callbacks -+ * -+ * Callbacks are called from the real-time data thread. Only -+ * one callback structure can be set on an spa_node. -+ */ -+struct spa_node_callbacks { -+#define SPA_VERSION_NODE_CALLBACKS 0 -+ uint32_t version; -+ /** -+ * \param node a spa_node -+ * -+ * The node is ready for processing. -+ * -+ * When this function is NULL, synchronous operation is requested -+ * on the ports. -+ */ -+ int (*ready) (void *data, int state); -+ -+ /** -+ * \param node a spa_node -+ * \param port_id an input port_id -+ * \param buffer_id the buffer id to be reused -+ * -+ * The node has a buffer that can be reused. -+ * -+ * When this function is NULL, the buffers to reuse will be set in -+ * the io area of the input ports. -+ */ -+ int (*reuse_buffer) (void *data, -+ uint32_t port_id, -+ uint32_t buffer_id); -+ -+ /** -+ * \param data user data -+ * \param trigger the timestamp in microseconds when the xrun happened -+ * \param delay the amount of microseconds of xrun. -+ * \param info an object with extra info (NULL for now) -+ * -+ * The node has encountered an over or underrun -+ * -+ * The info contains an object with more information -+ */ -+ int (*xrun) (void *data, uint64_t trigger, uint64_t delay, -+ struct spa_pod *info); -+}; -+ -+ -+/** flags that can be passed to set_param and port_set_param functions */ -+#define SPA_NODE_PARAM_FLAG_TEST_ONLY (1 << 0) /**< Just check if the param is accepted */ -+#define SPA_NODE_PARAM_FLAG_FIXATE (1 << 1) /**< Fixate the non-optional unset fields */ -+#define SPA_NODE_PARAM_FLAG_NEAREST (1 << 2) /**< Allow set fields to be rounded to the -+ * nearest allowed field value. */ -+ -+/** flags to pass to the use_buffers functions */ -+#define SPA_NODE_BUFFERS_FLAG_ALLOC (1 << 0) /**< Allocate memory for the buffers. This flag -+ * is ignored when the port does not have the -+ * SPA_PORT_FLAG_CAN_ALLOC_BUFFERS set. */ -+ -+ -+#define SPA_NODE_METHOD_ADD_LISTENER 0 -+#define SPA_NODE_METHOD_SET_CALLBACKS 1 -+#define SPA_NODE_METHOD_SYNC 2 -+#define SPA_NODE_METHOD_ENUM_PARAMS 3 -+#define SPA_NODE_METHOD_SET_PARAM 4 -+#define SPA_NODE_METHOD_SET_IO 5 -+#define SPA_NODE_METHOD_SEND_COMMAND 6 -+#define SPA_NODE_METHOD_ADD_PORT 7 -+#define SPA_NODE_METHOD_REMOVE_PORT 8 -+#define SPA_NODE_METHOD_PORT_ENUM_PARAMS 9 -+#define SPA_NODE_METHOD_PORT_SET_PARAM 10 -+#define SPA_NODE_METHOD_PORT_USE_BUFFERS 11 -+#define SPA_NODE_METHOD_PORT_SET_IO 12 -+#define SPA_NODE_METHOD_PORT_REUSE_BUFFER 13 -+#define SPA_NODE_METHOD_PROCESS 14 -+#define SPA_NODE_METHOD_NUM 15 -+ -+/** -+ * Node methods -+ */ -+struct spa_node_methods { -+ /* the version of the node methods. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_NODE_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Adds an event listener on \a node. -+ * -+ * Setting the events will trigger the info event and a -+ * port_info event for each managed port on the new -+ * listener. -+ * -+ * \param node a #spa_node -+ * \param listener a listener -+ * \param events a #struct spa_node_events -+ * \param data data passed as first argument in functions of \a events -+ * \return 0 on success -+ * < 0 errno on error -+ */ -+ int (*add_listener) (void *object, -+ struct spa_hook *listener, -+ const struct spa_node_events *events, -+ void *data); -+ /** -+ * Set callbacks to on \a node. -+ * if \a callbacks is NULL, the current callbacks are removed. -+ * -+ * This function must be called from the main thread. -+ * -+ * All callbacks are called from the data thread. -+ * -+ * \param node a spa_node -+ * \param callbacks callbacks to set -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*set_callbacks) (void *object, -+ const struct spa_node_callbacks *callbacks, -+ void *data); -+ /** -+ * Perform a sync operation. -+ * -+ * This method will emit the result event with the given sequence -+ * number synchronously or with the returned async return value -+ * asynchronously. -+ * -+ * Because all methods are serialized in the node, this can be used -+ * to wait for completion of all previous method calls. -+ * -+ * \param seq a sequence number -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * an async result -+ */ -+ int (*sync) (void *object, int seq); -+ -+ /** -+ * Enumerate the parameters of a node. -+ * -+ * Parameters are identified with an \a id. Some parameters can have -+ * multiple values, see the documentation of the parameter id. -+ * -+ * Parameters can be filtered by passing a non-NULL \a filter. -+ * -+ * The function will emit the result event up to \a max times with -+ * the result value. The seq in the result will either be the \a seq -+ * number when executed synchronously or the async return value of -+ * this function when executed asynchronously. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a \ref spa_node -+ * \param seq a sequence number to pass to the result event when -+ * this method is executed synchronously. -+ * \param id the param id to enumerate -+ * \param start the index of enumeration, pass 0 for the first item -+ * \param max the maximum number of parameters to enumerate -+ * \param filter and optional filter to use -+ * -+ * \return 0 when no more items can be iterated. -+ * -EINVAL when invalid arguments are given -+ * -ENOENT the parameter \a id is unknown -+ * -ENOTSUP when there are no parameters -+ * implemented on \a node -+ * an async return value when the result event will be -+ * emitted later. -+ */ -+ int (*enum_params) (void *object, int seq, -+ uint32_t id, uint32_t start, uint32_t max, -+ const struct spa_pod *filter); -+ -+ /** -+ * Set the configurable parameter in \a node. -+ * -+ * Usually, \a param will be obtained from enum_params and then -+ * modified but it is also possible to set another spa_pod -+ * as long as its keys and types match a supported object. -+ * -+ * Objects with property keys that are not known are ignored. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a \ref spa_node -+ * \param id the parameter id to configure -+ * \param flags additional flags -+ * \param param the parameter to configure -+ * -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ * -ENOTSUP when there are no parameters implemented on \a node -+ * -ENOENT the parameter is unknown -+ */ -+ int (*set_param) (void *object, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Configure the given memory area with \a id on \a node. This -+ * structure is allocated by the host and is used to exchange -+ * data and parameters with the node. -+ * -+ * Setting an \a io of NULL will disable the node io. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param id the id of the io area, the available ids can be -+ * enumerated with the node parameters. -+ * \param data a io area memory -+ * \param size the size of \a data -+ * \return 0 on success -+ * -EINVAL when invalid input is given -+ * -ENOENT when \a id is unknown -+ * -ENOSPC when \a size is too small -+ */ -+ int (*set_io) (void *object, -+ uint32_t id, void *data, size_t size); -+ -+ /** -+ * Send a command to a node. -+ * -+ * Upon completion, a command might change the state of a node. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param command a spa_command -+ * \return 0 on success -+ * -EINVAL when node or command is NULL -+ * -ENOTSUP when this node can't process commands -+ * -EINVAL \a command is an invalid command -+ */ -+ int (*send_command) (void *object, const struct spa_command *command); -+ -+ /** -+ * Make a new port with \a port_id. The caller should use the lowest unused -+ * port id for the given \a direction. -+ * -+ * Port ids should be between 0 and max_ports as obtained from the info -+ * event. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id an unused port id -+ * \param props extra properties -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*add_port) (void *object, -+ enum spa_direction direction, uint32_t port_id, -+ const struct spa_dict *props); -+ -+ /** -+ * Remove a port with \a port_id. -+ * -+ * \param node a spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id a port id -+ * \return 0 on success -+ * -EINVAL when node is NULL or when port_id is unknown or -+ * when the port can't be removed. -+ */ -+ int (*remove_port) (void *object, -+ enum spa_direction direction, uint32_t port_id); -+ -+ /** -+ * Enumerate all possible parameters of \a id on \a port_id of \a node -+ * that are compatible with \a filter. -+ * -+ * The result parameters can be queried and modified and ultimately be used -+ * to call port_set_param. -+ * -+ * The function will emit the result event up to \a max times with -+ * the result value. The seq in the result event will either be the -+ * \a seq number when executed synchronously or the async return -+ * value of this function when executed asynchronously. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a spa_node -+ * \param seq a sequence number to pass to the result event when -+ * this method is executed synchronously. -+ * \param direction an spa_direction -+ * \param port_id the port to query -+ * \param id the parameter id to query -+ * \param start the first index to query, 0 to get the first item -+ * \param max the maximum number of params to query -+ * \param filter a parameter filter or NULL for no filter -+ * -+ * \return 0 when no more items can be iterated. -+ * -EINVAL when invalid parameters are given -+ * -ENOENT when \a id is unknown -+ * an async return value when the result event will be -+ * emitted later. -+ */ -+ int (*port_enum_params) (void *object, int seq, -+ enum spa_direction direction, uint32_t port_id, -+ uint32_t id, uint32_t start, uint32_t max, -+ const struct spa_pod *filter); -+ /** -+ * Set a parameter on \a port_id of \a node. -+ * -+ * When \a param is NULL, the parameter will be unset. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param node a #struct spa_node -+ * \param direction a #enum spa_direction -+ * \param port_id the port to configure -+ * \param id the parameter id to set -+ * \param flags optional flags -+ * \param param a #struct spa_pod with the parameter to set -+ * \return 0 on success -+ * 1 on success, the value of \a param might have been -+ * changed depending on \a flags and the final value can be found by -+ * doing port_enum_params. -+ * -EINVAL when node is NULL or invalid arguments are given -+ * -ESRCH when one of the mandatory param -+ * properties is not specified and SPA_NODE_PARAM_FLAG_FIXATE was -+ * not set in \a flags. -+ * -ESRCH when the type or size of a property is not correct. -+ * -ENOENT when the param id is not found -+ */ -+ int (*port_set_param) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t id, uint32_t flags, -+ const struct spa_pod *param); -+ -+ /** -+ * Tell the port to use the given buffers -+ * -+ * When \a flags contains SPA_NODE_BUFFERS_FLAG_ALLOC, the data -+ * in the buffers should point to an array of at least 1 data entry -+ * with the desired supported type that will be filled by this function. -+ * -+ * The port should also have a spa_io_buffers io area configured to exchange -+ * the buffers with the port. -+ * -+ * For an input port, all the buffers will remain dequeued. -+ * Once a buffer has been queued on a port in the spa_io_buffers, -+ * it should not be reused until the reuse_buffer callback is notified -+ * or when the buffer has been returned in the spa_io_buffers of -+ * the port. -+ * -+ * For output ports, all buffers will be queued in the port. When process -+ * returns SPA_STATUS_HAVE_DATA, buffers are available in one or more -+ * of the spa_io_buffers areas. -+ * -+ * When a buffer can be reused, port_reuse_buffer() should be called or the -+ * buffer_id should be placed in the spa_io_buffers area before calling -+ * process. -+ * -+ * Passing NULL as \a buffers will remove the reference that the port has -+ * on the buffers. -+ * -+ * When this function returns async, use the spa_node_sync operation to -+ * wait for completion. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param object an object implementing the interface -+ * \param direction a port direction -+ * \param port_id a port id -+ * \param flags extra flags -+ * \param buffers an array of buffer pointers -+ * \param n_buffers number of elements in \a buffers -+ * \return 0 on success -+ */ -+ int (*port_use_buffers) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t flags, -+ struct spa_buffer **buffers, -+ uint32_t n_buffers); -+ -+ /** -+ * Configure the given memory area with \a id on \a port_id. This -+ * structure is allocated by the host and is used to exchange -+ * data and parameters with the port. -+ * -+ * Setting an \a io of NULL will disable the port io. -+ * -+ * This function must be called from the main thread. -+ * -+ * \param direction a spa_direction -+ * \param port_id a port id -+ * \param id the id of the io area, the available ids can be -+ * enumerated with the port parameters. -+ * \param data a io area memory -+ * \param size the size of \a data -+ * \return 0 on success -+ * -EINVAL when invalid input is given -+ * -ENOENT when \a id is unknown -+ * -ENOSPC when \a size is too small -+ */ -+ int (*port_set_io) (void *object, -+ enum spa_direction direction, -+ uint32_t port_id, -+ uint32_t id, -+ void *data, size_t size); -+ -+ /** -+ * Tell an output port to reuse a buffer. -+ * -+ * This function must be called from the data thread. -+ * -+ * \param node a spa_node -+ * \param port_id a port id -+ * \param buffer_id a buffer id to reuse -+ * \return 0 on success -+ * -EINVAL when node is NULL -+ */ -+ int (*port_reuse_buffer) (void *object, uint32_t port_id, uint32_t buffer_id); -+ -+ /** -+ * Process the node -+ * -+ * This function must be called from the data thread. -+ * -+ * Output io areas with SPA_STATUS_NEED_DATA will recycle the -+ * buffers if any. -+ * -+ * Input areas with SPA_STATUS_HAVE_DATA are consumed if possible -+ * and the status is set to SPA_STATUS_NEED_DATA or SPA_STATUS_OK. -+ * -+ * When the node has new output buffers, the SPA_STATUS_HAVE_DATA -+ * bit will be set. -+ * -+ * When the node can accept new input in the next cycle, the -+ * SPA_STATUS_NEED_DATA bit will be set. -+ */ -+ int (*process) (void *object); -+}; -+ -+#define spa_node_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_node *_n = o; \ -+ spa_interface_call_res(&_n->iface, \ -+ struct spa_node_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_node_add_listener(n,...) spa_node_method(n, add_listener, 0, __VA_ARGS__) -+#define spa_node_set_callbacks(n,...) spa_node_method(n, set_callbacks, 0, __VA_ARGS__) -+#define spa_node_sync(n,...) spa_node_method(n, sync, 0, __VA_ARGS__) -+#define spa_node_enum_params(n,...) spa_node_method(n, enum_params, 0, __VA_ARGS__) -+#define spa_node_set_param(n,...) spa_node_method(n, set_param, 0, __VA_ARGS__) -+#define spa_node_set_io(n,...) spa_node_method(n, set_io, 0, __VA_ARGS__) -+#define spa_node_send_command(n,...) spa_node_method(n, send_command, 0, __VA_ARGS__) -+#define spa_node_add_port(n,...) spa_node_method(n, add_port, 0, __VA_ARGS__) -+#define spa_node_remove_port(n,...) spa_node_method(n, remove_port, 0, __VA_ARGS__) -+#define spa_node_port_enum_params(n,...) spa_node_method(n, port_enum_params, 0, __VA_ARGS__) -+#define spa_node_port_set_param(n,...) spa_node_method(n, port_set_param, 0, __VA_ARGS__) -+#define spa_node_port_use_buffers(n,...) spa_node_method(n, port_use_buffers, 0, __VA_ARGS__) -+#define spa_node_port_set_io(n,...) spa_node_method(n, port_set_io, 0, __VA_ARGS__) -+ -+#define spa_node_port_reuse_buffer(n,...) spa_node_method(n, port_reuse_buffer, 0, __VA_ARGS__) -+#define spa_node_process(n) spa_node_method(n, process, 0) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_H */ -diff --git a/third_party/pipewire/spa/node/type-info.h b/third_party/pipewire/spa/node/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/type-info.h -@@ -0,0 +1,94 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_TYPES_H -+#define SPA_NODE_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INFO_IO SPA_TYPE_INFO_ENUM_BASE "IO" -+#define SPA_TYPE_INFO_IO_BASE SPA_TYPE_INFO_IO ":" -+ -+static const struct spa_type_info spa_type_io[] = { -+ { SPA_IO_Invalid, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Invalid", NULL }, -+ { SPA_IO_Buffers, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Buffers", NULL }, -+ { SPA_IO_Range, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Range", NULL }, -+ { SPA_IO_Clock, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Clock", NULL }, -+ { SPA_IO_Latency, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Latency", NULL }, -+ { SPA_IO_Control, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Control", NULL }, -+ { SPA_IO_Notify, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Notify", NULL }, -+ { SPA_IO_Position, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Position", NULL }, -+ { SPA_IO_RateMatch, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "RateMatch", NULL }, -+ { SPA_IO_Memory, SPA_TYPE_Int, SPA_TYPE_INFO_IO_BASE "Memory", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_NodeEvent SPA_TYPE_INFO_EVENT_BASE "Node" -+#define SPA_TYPE_INFO_NODE_EVENT_BASE SPA_TYPE_INFO_NodeEvent ":" -+ -+static const struct spa_type_info spa_type_node_event_id[] = { -+ { SPA_NODE_EVENT_Error, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL }, -+ { SPA_NODE_EVENT_Buffering, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL }, -+ { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+static const struct spa_type_info spa_type_node_event[] = { -+ { 0, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_EVENT_BASE, spa_type_node_event_id }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_NodeCommand SPA_TYPE_INFO_COMMAND_BASE "Node" -+#define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":" -+ -+static const struct spa_type_info spa_type_node_command_id[] = { -+ { SPA_NODE_COMMAND_Suspend, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL }, -+ { SPA_NODE_COMMAND_Pause, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL }, -+ { SPA_NODE_COMMAND_Start, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL }, -+ { SPA_NODE_COMMAND_Enable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL }, -+ { SPA_NODE_COMMAND_Disable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL }, -+ { SPA_NODE_COMMAND_Flush, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL }, -+ { SPA_NODE_COMMAND_Drain, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL }, -+ { SPA_NODE_COMMAND_Marker, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+static const struct spa_type_info spa_type_node_command[] = { -+ { 0, SPA_TYPE_Id, SPA_TYPE_INFO_NODE_COMMAND_BASE, spa_type_node_command_id }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_TYPES_H */ -diff --git a/third_party/pipewire/spa/node/utils.h b/third_party/pipewire/spa/node/utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/node/utils.h -@@ -0,0 +1,144 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_NODE_UTILS_H -+#define SPA_NODE_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+struct spa_result_node_params_data { -+ struct spa_pod_builder *builder; -+ struct spa_result_node_params data; -+}; -+ -+static inline void spa_result_func_node_params(void *data, -+ int seq, int res, uint32_t type, const void *result) -+{ -+ struct spa_result_node_params_data *d = -+ (struct spa_result_node_params_data *) data; -+ const struct spa_result_node_params *r = -+ (const struct spa_result_node_params *) result; -+ uint32_t offset = d->builder->state.offset; -+ spa_pod_builder_raw_padded(d->builder, r->param, SPA_POD_SIZE(r->param)); -+ d->data.next = r->next; -+ d->data.param = SPA_MEMBER(d->builder->data, offset, struct spa_pod); -+} -+ -+static inline int spa_node_enum_params_sync(struct spa_node *node, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_node_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_node_events node_events = { -+ SPA_VERSION_NODE_EVENTS, -+ .result = spa_result_func_node_params, -+ }; -+ int res; -+ -+ res = spa_node_add_listener(node, &listener, &node_events, &data); -+ if (res >= 0) { -+ res = spa_node_enum_params(node, 0, id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ } -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+static inline int spa_node_port_enum_params_sync(struct spa_node *node, -+ enum spa_direction direction, uint32_t port_id, -+ uint32_t id, uint32_t *index, -+ const struct spa_pod *filter, -+ struct spa_pod **param, -+ struct spa_pod_builder *builder) -+{ -+ struct spa_result_node_params_data data = { builder, }; -+ struct spa_hook listener = { 0 }; -+ static const struct spa_node_events node_events = { -+ SPA_VERSION_NODE_EVENTS, -+ .result = spa_result_func_node_params, -+ }; -+ int res; -+ -+ res = spa_node_add_listener(node, &listener, &node_events, &data); -+ if (res >= 0) { -+ res = spa_node_port_enum_params(node, 0, direction, port_id, -+ id, *index, 1, filter); -+ spa_hook_remove(&listener); -+ } -+ -+ if (data.data.param == NULL) { -+ if (res > 0) -+ res = 0; -+ } else { -+ *index = data.data.next; -+ *param = data.data.param; -+ res = 1; -+ } -+ return res; -+} -+ -+#define spa_node_emit(hooks,method,version,...) \ -+ spa_hook_list_call_simple(hooks, struct spa_node_events, \ -+ method, version, ##__VA_ARGS__) -+ -+#define spa_node_emit_info(hooks,...) spa_node_emit(hooks,info, 0, __VA_ARGS__) -+#define spa_node_emit_port_info(hooks,...) spa_node_emit(hooks,port_info, 0, __VA_ARGS__) -+#define spa_node_emit_result(hooks,...) spa_node_emit(hooks,result, 0, __VA_ARGS__) -+#define spa_node_emit_event(hooks,...) spa_node_emit(hooks,event, 0, __VA_ARGS__) -+ -+ -+#define spa_node_call(callbacks,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ spa_callbacks_call_res(callbacks, struct spa_node_callbacks, \ -+ _res, method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_node_call_ready(hook,...) spa_node_call(hook, ready, 0, __VA_ARGS__) -+#define spa_node_call_reuse_buffer(hook,...) spa_node_call(hook, reuse_buffer, 0, __VA_ARGS__) -+#define spa_node_call_xrun(hook,...) spa_node_call(hook, xrun, 0, __VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_NODE_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/audio/format-utils.h b/third_party/pipewire/spa/param/audio/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/format-utils.h -@@ -0,0 +1,105 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_AUDIO_FORMAT_UTILS_H -+#define SPA_PARAM_AUDIO_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info) -+{ -+ struct spa_pod *position = NULL; -+ int res; -+ info->flags = 0; -+ res = spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info->rate), -+ SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info->channels), -+ SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); -+ if (position == NULL || -+ !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) -+ SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); -+ -+ return res; -+} -+ -+static inline int -+spa_format_audio_dsp_parse(const struct spa_pod *format, struct spa_audio_info_dsp *info) -+{ -+ int res; -+ res = spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info->format)); -+ return res; -+} -+ -+static inline struct spa_pod * -+spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_raw *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(info->format), -+ SPA_FORMAT_AUDIO_rate, SPA_POD_Int(info->rate), -+ SPA_FORMAT_AUDIO_channels, SPA_POD_Int(info->channels), -+ 0); -+ -+ if (!SPA_FLAG_IS_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { -+ spa_pod_builder_prop(builder, SPA_FORMAT_AUDIO_position, 0); -+ spa_pod_builder_array(builder, sizeof(uint32_t), SPA_TYPE_Id, -+ info->channels, info->position); -+ } -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline struct spa_pod * -+spa_format_audio_dsp_build(struct spa_pod_builder *builder, uint32_t id, struct spa_audio_info_dsp *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), -+ SPA_FORMAT_AUDIO_format, SPA_POD_Id(info->format), -+ 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_AUDIO_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/audio/format.h b/third_party/pipewire/spa/param/audio/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/format.h -@@ -0,0 +1,48 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_AUDIO_FORMAT_H -+#define SPA_PARAM_AUDIO_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_audio_info { -+ uint32_t media_type; -+ uint32_t media_subtype; -+ union { -+ struct spa_audio_info_raw raw; -+ struct spa_audio_info_dsp dsp; -+ } info; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_AUDIO_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/audio/layout.h b/third_party/pipewire/spa/param/audio/layout.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/layout.h -@@ -0,0 +1,184 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_LAYOUT_H -+#define SPA_AUDIO_LAYOUT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#ifndef __FreeBSD__ -+#include -+#endif -+ -+#include -+ -+struct spa_audio_layout_info { -+ uint32_t n_channels; -+ uint32_t position[SPA_AUDIO_MAX_CHANNELS]; -+}; -+ -+#define SPA_AUDIO_LAYOUT_Mono 1, { SPA_AUDIO_CHANNEL_MONO, } -+#define SPA_AUDIO_LAYOUT_Stereo 2, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, } -+#define SPA_AUDIO_LAYOUT_Quad 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_Pentagonal 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_Hexagonal 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_Octagonal 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_Cube 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR }, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, \ -+ SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR, } -+ -+ -+#define SPA_AUDIO_LAYOUT_MPEG_1_0 SPA_AUDIO_LAYOUT_MONO -+#define SPA_AUDIO_LAYOUT_MPEG_2_0 SPA_AUDIO_LAYOUT_STEREO -+#define SPA_AUDIO_LAYOUT_MPEG_3_0A 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_MPEG_3_0B 3, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, } -+#define SPA_AUDIO_LAYOUT_MPEG_4_0A 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_4_0B 4, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0A 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0B 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0C 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FC, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_0D 5, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1A 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1B 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1C 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FC, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_5_1D 6, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_6_1A 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1A 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1B 8, { SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_FL, \ -+ SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_MPEG_7_1C 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+ -+ -+#define SPA_AUDIO_LAYOUT_2_1 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_LFE, } -+ -+#define SPA_AUDIO_LAYOUT_2RC 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_2FC 3, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, } -+ -+#define SPA_AUDIO_LAYOUT_3_1 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, } -+#define SPA_AUDIO_LAYOUT_4_0 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_2_2 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+ -+#define SPA_AUDIO_LAYOUT_4_1 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_5_0 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_5_0R 5, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_5_1 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_5_1R 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, } -+#define SPA_AUDIO_LAYOUT_6_0 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_0F 6, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_1 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_6_1F 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_RC, } -+#define SPA_AUDIO_LAYOUT_7_0 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RL, \ -+ SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_0F 7, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_FLC, \ -+ SPA_AUDIO_CHANNEL_FRC, SPA_AUDIO_CHANNEL_SL, \ -+ SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1W 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, \ -+ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -+#define SPA_AUDIO_LAYOUT_7_1WR 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ -+ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, \ -+ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ -+ SPA_AUDIO_CHANNEL_FLC, SPA_AUDIO_CHANNEL_FRC, } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_LAYOUT_H */ -diff --git a/third_party/pipewire/spa/param/audio/raw.h b/third_party/pipewire/spa/param/audio/raw.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/raw.h -@@ -0,0 +1,237 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_RAW_H -+#define SPA_AUDIO_RAW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef __FreeBSD__ -+#include -+#endif -+ -+#define SPA_AUDIO_MAX_CHANNELS 64u -+ -+enum spa_audio_format { -+ SPA_AUDIO_FORMAT_UNKNOWN, -+ SPA_AUDIO_FORMAT_ENCODED, -+ -+ /* interleaved formats */ -+ SPA_AUDIO_FORMAT_START_Interleaved = 0x100, -+ SPA_AUDIO_FORMAT_S8, -+ SPA_AUDIO_FORMAT_U8, -+ SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64_LE, -+ SPA_AUDIO_FORMAT_F64_BE, -+ -+ /* planar formats */ -+ SPA_AUDIO_FORMAT_START_Planar = 0x200, -+ SPA_AUDIO_FORMAT_U8P, -+ SPA_AUDIO_FORMAT_S16P, -+ SPA_AUDIO_FORMAT_S24_32P, -+ SPA_AUDIO_FORMAT_S32P, -+ SPA_AUDIO_FORMAT_S24P, -+ SPA_AUDIO_FORMAT_F32P, -+ SPA_AUDIO_FORMAT_F64P, -+ -+ /* other formats start here */ -+ SPA_AUDIO_FORMAT_START_Other = 0x400, -+ -+ /* Aliases */ -+ -+ /* DSP formats */ -+ SPA_AUDIO_FORMAT_DSP_S32 = SPA_AUDIO_FORMAT_S24_32P, -+ SPA_AUDIO_FORMAT_DSP_F32 = SPA_AUDIO_FORMAT_F32P, -+ SPA_AUDIO_FORMAT_DSP_F64 = SPA_AUDIO_FORMAT_F64P, -+ -+ /* native endian */ -+#if __BYTE_ORDER == __BIG_ENDIAN -+ SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32 = SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32 = SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32 = SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32 = SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24 = SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24 = SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20 = SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20 = SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18 = SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18 = SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32 = SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64 = SPA_AUDIO_FORMAT_F64_BE, -+ SPA_AUDIO_FORMAT_S16_OE = SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_U16_OE = SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_S24_32_OE = SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32_OE = SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_S32_OE = SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_U32_OE = SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_S24_OE = SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_U24_OE = SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_S20_OE = SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_U20_OE = SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_S18_OE = SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_U18_OE = SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_F32_OE = SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F64_OE = SPA_AUDIO_FORMAT_F64_LE, -+#elif __BYTE_ORDER == __LITTLE_ENDIAN -+ SPA_AUDIO_FORMAT_S16 = SPA_AUDIO_FORMAT_S16_LE, -+ SPA_AUDIO_FORMAT_U16 = SPA_AUDIO_FORMAT_U16_LE, -+ SPA_AUDIO_FORMAT_S24_32 = SPA_AUDIO_FORMAT_S24_32_LE, -+ SPA_AUDIO_FORMAT_U24_32 = SPA_AUDIO_FORMAT_U24_32_LE, -+ SPA_AUDIO_FORMAT_S32 = SPA_AUDIO_FORMAT_S32_LE, -+ SPA_AUDIO_FORMAT_U32 = SPA_AUDIO_FORMAT_U32_LE, -+ SPA_AUDIO_FORMAT_S24 = SPA_AUDIO_FORMAT_S24_LE, -+ SPA_AUDIO_FORMAT_U24 = SPA_AUDIO_FORMAT_U24_LE, -+ SPA_AUDIO_FORMAT_S20 = SPA_AUDIO_FORMAT_S20_LE, -+ SPA_AUDIO_FORMAT_U20 = SPA_AUDIO_FORMAT_U20_LE, -+ SPA_AUDIO_FORMAT_S18 = SPA_AUDIO_FORMAT_S18_LE, -+ SPA_AUDIO_FORMAT_U18 = SPA_AUDIO_FORMAT_U18_LE, -+ SPA_AUDIO_FORMAT_F32 = SPA_AUDIO_FORMAT_F32_LE, -+ SPA_AUDIO_FORMAT_F64 = SPA_AUDIO_FORMAT_F64_LE, -+ SPA_AUDIO_FORMAT_S16_OE = SPA_AUDIO_FORMAT_S16_BE, -+ SPA_AUDIO_FORMAT_U16_OE = SPA_AUDIO_FORMAT_U16_BE, -+ SPA_AUDIO_FORMAT_S24_32_OE = SPA_AUDIO_FORMAT_S24_32_BE, -+ SPA_AUDIO_FORMAT_U24_32_OE = SPA_AUDIO_FORMAT_U24_32_BE, -+ SPA_AUDIO_FORMAT_S32_OE = SPA_AUDIO_FORMAT_S32_BE, -+ SPA_AUDIO_FORMAT_U32_OE = SPA_AUDIO_FORMAT_U32_BE, -+ SPA_AUDIO_FORMAT_S24_OE = SPA_AUDIO_FORMAT_S24_BE, -+ SPA_AUDIO_FORMAT_U24_OE = SPA_AUDIO_FORMAT_U24_BE, -+ SPA_AUDIO_FORMAT_S20_OE = SPA_AUDIO_FORMAT_S20_BE, -+ SPA_AUDIO_FORMAT_U20_OE = SPA_AUDIO_FORMAT_U20_BE, -+ SPA_AUDIO_FORMAT_S18_OE = SPA_AUDIO_FORMAT_S18_BE, -+ SPA_AUDIO_FORMAT_U18_OE = SPA_AUDIO_FORMAT_U18_BE, -+ SPA_AUDIO_FORMAT_F32_OE = SPA_AUDIO_FORMAT_F32_BE, -+ SPA_AUDIO_FORMAT_F64_OE = SPA_AUDIO_FORMAT_F64_BE, -+#endif -+}; -+ -+#define SPA_AUDIO_FORMAT_IS_INTERLEAVED(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Interleaved && (fmt) < SPA_AUDIO_FORMAT_START_Planar) -+#define SPA_AUDIO_FORMAT_IS_PLANAR(fmt) ((fmt) > SPA_AUDIO_FORMAT_START_Planar && (fmt) < SPA_AUDIO_FORMAT_START_Other) -+ -+enum spa_audio_channel { -+ SPA_AUDIO_CHANNEL_UNKNOWN, /**< unspecified */ -+ SPA_AUDIO_CHANNEL_NA, /**< N/A, silent */ -+ -+ SPA_AUDIO_CHANNEL_MONO, /**< mono stream */ -+ -+ SPA_AUDIO_CHANNEL_FL, /**< front left */ -+ SPA_AUDIO_CHANNEL_FR, /**< front right */ -+ SPA_AUDIO_CHANNEL_FC, /**< front center */ -+ SPA_AUDIO_CHANNEL_LFE, /**< LFE */ -+ SPA_AUDIO_CHANNEL_SL, /**< side left */ -+ SPA_AUDIO_CHANNEL_SR, /**< side right */ -+ SPA_AUDIO_CHANNEL_FLC, /**< front left center */ -+ SPA_AUDIO_CHANNEL_FRC, /**< front right center */ -+ SPA_AUDIO_CHANNEL_RC, /**< rear center */ -+ SPA_AUDIO_CHANNEL_RL, /**< rear left */ -+ SPA_AUDIO_CHANNEL_RR, /**< rear right */ -+ SPA_AUDIO_CHANNEL_TC, /**< top center */ -+ SPA_AUDIO_CHANNEL_TFL, /**< top front left */ -+ SPA_AUDIO_CHANNEL_TFC, /**< top front center */ -+ SPA_AUDIO_CHANNEL_TFR, /**< top front right */ -+ SPA_AUDIO_CHANNEL_TRL, /**< top rear left */ -+ SPA_AUDIO_CHANNEL_TRC, /**< top rear center */ -+ SPA_AUDIO_CHANNEL_TRR, /**< top rear right */ -+ SPA_AUDIO_CHANNEL_RLC, /**< rear left center */ -+ SPA_AUDIO_CHANNEL_RRC, /**< rear right center */ -+ SPA_AUDIO_CHANNEL_FLW, /**< front left wide */ -+ SPA_AUDIO_CHANNEL_FRW, /**< front right wide */ -+ SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 */ -+ SPA_AUDIO_CHANNEL_FLH, /**< front left high */ -+ SPA_AUDIO_CHANNEL_FCH, /**< front center high */ -+ SPA_AUDIO_CHANNEL_FRH, /**< front right high */ -+ SPA_AUDIO_CHANNEL_TFLC, /**< top front left center */ -+ SPA_AUDIO_CHANNEL_TFRC, /**< top front right center */ -+ SPA_AUDIO_CHANNEL_TSL, /**< top side left */ -+ SPA_AUDIO_CHANNEL_TSR, /**< top side right */ -+ SPA_AUDIO_CHANNEL_LLFE, /**< left LFE */ -+ SPA_AUDIO_CHANNEL_RLFE, /**< right LFE */ -+ SPA_AUDIO_CHANNEL_BC, /**< bottom center */ -+ SPA_AUDIO_CHANNEL_BLC, /**< bottom left center */ -+ SPA_AUDIO_CHANNEL_BRC, /**< bottom right center */ -+ -+ SPA_AUDIO_CHANNEL_CUSTOM_START = 0x10000, -+}; -+ -+/** Extra audio flags */ -+#define SPA_AUDIO_FLAG_NONE (0) /*< no valid flag */ -+#define SPA_AUDIO_FLAG_UNPOSITIONED (1 << 0) /*< the position array explicitly -+ * contains unpositioned channels. */ -+/** Audio information description */ -+struct spa_audio_info_raw { -+ enum spa_audio_format format; /*< format, one of enum spa_audio_format */ -+ uint32_t flags; /*< extra flags */ -+ uint32_t rate; /*< sample rate */ -+ uint32_t channels; /*< number of channels */ -+ uint32_t position[SPA_AUDIO_MAX_CHANNELS]; /*< channel position from enum spa_audio_channel */ -+}; -+ -+#define SPA_AUDIO_INFO_RAW_INIT(...) (struct spa_audio_info_raw) { __VA_ARGS__ } -+ -+#define SPA_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel as string, -+ * Ex. "FL" */ -+#define SPA_KEY_AUDIO_CHANNELS "audio.channels" /**< an audio channel count as int */ -+#define SPA_KEY_AUDIO_RATE "audio.rate" /**< an audio sample rate as int */ -+ -+struct spa_audio_info_dsp { -+ enum spa_audio_format format; /*< format, one of the DSP formats in enum spa_audio_format_dsp */ -+}; -+ -+#define SPA_AUDIO_INFO_DSP_INIT(...) (struct spa_audio_info_dsp) { __VA_ARGS__ } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_RAW_H */ -diff --git a/third_party/pipewire/spa/param/audio/type-info.h b/third_party/pipewire/spa/param/audio/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/audio/type-info.h -@@ -0,0 +1,140 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_AUDIO_TYPES_H -+#define SPA_AUDIO_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INFO_AudioFormat SPA_TYPE_INFO_ENUM_BASE "AudioFormat" -+#define SPA_TYPE_INFO_AUDIO_FORMAT_BASE SPA_TYPE_INFO_AudioFormat ":" -+ -+static const struct spa_type_info spa_type_audio_format[] = { -+ { SPA_AUDIO_FORMAT_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "UNKNOWN", NULL }, -+ { SPA_AUDIO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "ENCODED", NULL }, -+ { SPA_AUDIO_FORMAT_S8, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S8", NULL }, -+ { SPA_AUDIO_FORMAT_U8, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U8", NULL }, -+ { SPA_AUDIO_FORMAT_S16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16LE", NULL }, -+ { SPA_AUDIO_FORMAT_S16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16BE", NULL }, -+ { SPA_AUDIO_FORMAT_U16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U16LE", NULL }, -+ { SPA_AUDIO_FORMAT_U16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U16BE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32LE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32BE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24_32LE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24_32BE", NULL }, -+ { SPA_AUDIO_FORMAT_S32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32LE", NULL }, -+ { SPA_AUDIO_FORMAT_S32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32BE", NULL }, -+ { SPA_AUDIO_FORMAT_U32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U32LE", NULL }, -+ { SPA_AUDIO_FORMAT_U32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U32BE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24LE", NULL }, -+ { SPA_AUDIO_FORMAT_S24_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24BE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24LE", NULL }, -+ { SPA_AUDIO_FORMAT_U24_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U24BE", NULL }, -+ { SPA_AUDIO_FORMAT_S20_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S20LE", NULL }, -+ { SPA_AUDIO_FORMAT_S20_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S20BE", NULL }, -+ { SPA_AUDIO_FORMAT_U20_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U20LE", NULL }, -+ { SPA_AUDIO_FORMAT_U20_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U20BE", NULL }, -+ { SPA_AUDIO_FORMAT_S18_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S18LE", NULL }, -+ { SPA_AUDIO_FORMAT_S18_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S18BE", NULL }, -+ { SPA_AUDIO_FORMAT_U18_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U18LE", NULL }, -+ { SPA_AUDIO_FORMAT_U18_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U18BE", NULL }, -+ { SPA_AUDIO_FORMAT_F32_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32LE", NULL }, -+ { SPA_AUDIO_FORMAT_F32_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32BE", NULL }, -+ { SPA_AUDIO_FORMAT_F64_LE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64LE", NULL }, -+ { SPA_AUDIO_FORMAT_F64_BE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64BE", NULL }, -+ -+ { SPA_AUDIO_FORMAT_U8P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "U8P", NULL }, -+ { SPA_AUDIO_FORMAT_S16P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S16P", NULL }, -+ { SPA_AUDIO_FORMAT_S24_32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24_32P", NULL }, -+ { SPA_AUDIO_FORMAT_S32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S32P", NULL }, -+ { SPA_AUDIO_FORMAT_S24P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "S24P", NULL }, -+ { SPA_AUDIO_FORMAT_F32P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F32P", NULL }, -+ { SPA_AUDIO_FORMAT_F64P, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FORMAT_BASE "F64P", NULL }, -+ -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_AudioFlags SPA_TYPE_INFO_FLAGS_BASE "AudioFlags" -+#define SPA_TYPE_INFO_AUDIO_FLAGS_BASE SPA_TYPE_INFO_AudioFlags ":" -+ -+static const struct spa_type_info spa_type_audio_flags[] = { -+ { SPA_AUDIO_FLAG_NONE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FLAGS_BASE "none", NULL }, -+ { SPA_AUDIO_FLAG_UNPOSITIONED, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_FLAGS_BASE "unpositioned", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_AudioChannel SPA_TYPE_INFO_ENUM_BASE "AudioChannel" -+#define SPA_TYPE_INFO_AUDIO_CHANNEL_BASE SPA_TYPE_INFO_AudioChannel ":" -+ -+static const struct spa_type_info spa_type_audio_channel[] = { -+ { SPA_AUDIO_CHANNEL_UNKNOWN, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "UNK", NULL }, -+ { SPA_AUDIO_CHANNEL_NA, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "NA", NULL }, -+ { SPA_AUDIO_CHANNEL_MONO, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "MONO", NULL }, -+ { SPA_AUDIO_CHANNEL_FL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FL", NULL }, -+ { SPA_AUDIO_CHANNEL_FR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FR", NULL }, -+ { SPA_AUDIO_CHANNEL_FC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FC", NULL }, -+ { SPA_AUDIO_CHANNEL_LFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LFE", NULL }, -+ { SPA_AUDIO_CHANNEL_SL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "SL", NULL }, -+ { SPA_AUDIO_CHANNEL_SR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "SR", NULL }, -+ { SPA_AUDIO_CHANNEL_FLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLC", NULL }, -+ { SPA_AUDIO_CHANNEL_FRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRC", NULL }, -+ { SPA_AUDIO_CHANNEL_RC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RC", NULL }, -+ { SPA_AUDIO_CHANNEL_RL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RL", NULL }, -+ { SPA_AUDIO_CHANNEL_RR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RR", NULL }, -+ { SPA_AUDIO_CHANNEL_TC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFL", NULL }, -+ { SPA_AUDIO_CHANNEL_TFC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFR", NULL }, -+ { SPA_AUDIO_CHANNEL_TRL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRL", NULL }, -+ { SPA_AUDIO_CHANNEL_TRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRC", NULL }, -+ { SPA_AUDIO_CHANNEL_TRR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TRR", NULL }, -+ { SPA_AUDIO_CHANNEL_RLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RLC", NULL }, -+ { SPA_AUDIO_CHANNEL_RRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RRC", NULL }, -+ { SPA_AUDIO_CHANNEL_FLW, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLW", NULL }, -+ { SPA_AUDIO_CHANNEL_FRW, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRW", NULL }, -+ { SPA_AUDIO_CHANNEL_LFE2, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LFE2", NULL }, -+ { SPA_AUDIO_CHANNEL_FLH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FLH", NULL }, -+ { SPA_AUDIO_CHANNEL_FCH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FCH", NULL }, -+ { SPA_AUDIO_CHANNEL_FRH, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "FRH", NULL }, -+ { SPA_AUDIO_CHANNEL_TFLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFLC", NULL }, -+ { SPA_AUDIO_CHANNEL_TFRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TFRC", NULL }, -+ { SPA_AUDIO_CHANNEL_TSL, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TSL", NULL }, -+ { SPA_AUDIO_CHANNEL_TSR, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "TSR", NULL }, -+ { SPA_AUDIO_CHANNEL_LLFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "LLFR", NULL }, -+ { SPA_AUDIO_CHANNEL_RLFE, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "RLFE", NULL }, -+ { SPA_AUDIO_CHANNEL_BC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BC", NULL }, -+ { SPA_AUDIO_CHANNEL_BLC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BLC", NULL }, -+ { SPA_AUDIO_CHANNEL_BRC, SPA_TYPE_Int, SPA_TYPE_INFO_AUDIO_CHANNEL_BASE "BRC", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_AUDIO_RAW_TYPES_H */ -diff --git a/third_party/pipewire/spa/param/format-utils.h b/third_party/pipewire/spa/param/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/format-utils.h -@@ -0,0 +1,49 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_FORMAT_UTILS_H -+#define SPA_PARAM_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+ -+#include -+#include -+ -+static inline int -+spa_format_parse(const struct spa_pod *format, uint32_t *media_type, uint32_t *media_subtype) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_mediaType, SPA_POD_Id(media_type), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(media_subtype)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/format.h b/third_party/pipewire/spa/param/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/format.h -@@ -0,0 +1,147 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_FORMAT_H -+#define SPA_PARAM_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** media type for SPA_TYPE_OBJECT_Format */ -+enum spa_media_type { -+ SPA_MEDIA_TYPE_unknown, -+ SPA_MEDIA_TYPE_audio, -+ SPA_MEDIA_TYPE_video, -+ SPA_MEDIA_TYPE_image, -+ SPA_MEDIA_TYPE_binary, -+ SPA_MEDIA_TYPE_stream, -+ SPA_MEDIA_TYPE_application, -+}; -+ -+/** media subtype for SPA_TYPE_OBJECT_Format */ -+enum spa_media_subtype { -+ SPA_MEDIA_SUBTYPE_unknown, -+ SPA_MEDIA_SUBTYPE_raw, -+ SPA_MEDIA_SUBTYPE_dsp, -+ -+ SPA_MEDIA_SUBTYPE_START_Audio = 0x10000, -+ SPA_MEDIA_SUBTYPE_mp3, -+ SPA_MEDIA_SUBTYPE_aac, -+ SPA_MEDIA_SUBTYPE_vorbis, -+ SPA_MEDIA_SUBTYPE_wma, -+ SPA_MEDIA_SUBTYPE_ra, -+ SPA_MEDIA_SUBTYPE_sbc, -+ SPA_MEDIA_SUBTYPE_adpcm, -+ SPA_MEDIA_SUBTYPE_g723, -+ SPA_MEDIA_SUBTYPE_g726, -+ SPA_MEDIA_SUBTYPE_g729, -+ SPA_MEDIA_SUBTYPE_amr, -+ SPA_MEDIA_SUBTYPE_gsm, -+ -+ SPA_MEDIA_SUBTYPE_START_Video = 0x20000, -+ SPA_MEDIA_SUBTYPE_h264, -+ SPA_MEDIA_SUBTYPE_mjpg, -+ SPA_MEDIA_SUBTYPE_dv, -+ SPA_MEDIA_SUBTYPE_mpegts, -+ SPA_MEDIA_SUBTYPE_h263, -+ SPA_MEDIA_SUBTYPE_mpeg1, -+ SPA_MEDIA_SUBTYPE_mpeg2, -+ SPA_MEDIA_SUBTYPE_mpeg4, -+ SPA_MEDIA_SUBTYPE_xvid, -+ SPA_MEDIA_SUBTYPE_vc1, -+ SPA_MEDIA_SUBTYPE_vp8, -+ SPA_MEDIA_SUBTYPE_vp9, -+ SPA_MEDIA_SUBTYPE_bayer, -+ -+ SPA_MEDIA_SUBTYPE_START_Image = 0x30000, -+ SPA_MEDIA_SUBTYPE_jpeg, -+ -+ SPA_MEDIA_SUBTYPE_START_Binary = 0x40000, -+ -+ SPA_MEDIA_SUBTYPE_START_Stream = 0x50000, -+ SPA_MEDIA_SUBTYPE_midi, -+ -+ SPA_MEDIA_SUBTYPE_START_Application = 0x60000, -+ SPA_MEDIA_SUBTYPE_control, /**< control stream, data contains -+ * spa_pod_sequence with control info. */ -+}; -+ -+/** properties for audio SPA_TYPE_OBJECT_Format */ -+enum spa_format { -+ SPA_FORMAT_START, -+ -+ SPA_FORMAT_mediaType, /**< media type (Id enum spa_media_type) */ -+ SPA_FORMAT_mediaSubtype, /**< media subtype (Id enum spa_media_subtype) */ -+ -+ /* Audio format keys */ -+ SPA_FORMAT_START_Audio = 0x10000, -+ SPA_FORMAT_AUDIO_format, /**< audio format, (Id enum spa_audio_format) */ -+ SPA_FORMAT_AUDIO_flags, /**< optional flags (Int) */ -+ SPA_FORMAT_AUDIO_rate, /**< sample rate (Int) */ -+ SPA_FORMAT_AUDIO_channels, /**< number of audio channels (Int) */ -+ SPA_FORMAT_AUDIO_position, /**< channel positions (Id enum spa_audio_position) */ -+ -+ /* Video Format keys */ -+ SPA_FORMAT_START_Video = 0x20000, -+ SPA_FORMAT_VIDEO_format, /**< video format (Id enum spa_video_format) */ -+ SPA_FORMAT_VIDEO_modifier, /**< format modifier (Long) */ -+ SPA_FORMAT_VIDEO_size, /**< size (Rectangle) */ -+ SPA_FORMAT_VIDEO_framerate, /**< frame rate (Fraction) */ -+ SPA_FORMAT_VIDEO_maxFramerate, /**< maximum frame rate (Fraction) */ -+ SPA_FORMAT_VIDEO_views, /**< number of views (Int) */ -+ SPA_FORMAT_VIDEO_interlaceMode, /**< (Id enum spa_video_interlace_mode) */ -+ SPA_FORMAT_VIDEO_pixelAspectRatio, /**< (Rectangle) */ -+ SPA_FORMAT_VIDEO_multiviewMode, /**< (Id enum spa_video_multiview_mode) */ -+ SPA_FORMAT_VIDEO_multiviewFlags, /**< (Id enum spa_video_multiview_flags) */ -+ SPA_FORMAT_VIDEO_chromaSite, /**< /Id enum spa_video_chroma_site) */ -+ SPA_FORMAT_VIDEO_colorRange, /**< /Id enum spa_video_color_range) */ -+ SPA_FORMAT_VIDEO_colorMatrix, /**< /Id enum spa_video_color_matrix) */ -+ SPA_FORMAT_VIDEO_transferFunction, /**< /Id enum spa_video_transfer_function) */ -+ SPA_FORMAT_VIDEO_colorPrimaries, /**< /Id enum spa_video_color_primaries) */ -+ SPA_FORMAT_VIDEO_profile, /**< (Int) */ -+ SPA_FORMAT_VIDEO_level, /**< (Int) */ -+ SPA_FORMAT_VIDEO_H264_streamFormat, /**< (Id enum spa_h264_stream_format) */ -+ SPA_FORMAT_VIDEO_H264_alignment, /**< (Id enum spa_h264_alignment) */ -+ -+ /* Image Format keys */ -+ SPA_FORMAT_START_Image = 0x30000, -+ /* Binary Format keys */ -+ SPA_FORMAT_START_Binary = 0x40000, -+ /* Stream Format keys */ -+ SPA_FORMAT_START_Stream = 0x50000, -+ /* Application Format keys */ -+ SPA_FORMAT_START_Application = 0x60000, -+}; -+ -+#define SPA_KEY_FORMAT_DSP "format.dsp" /**< a predefined DSP format, -+ * Ex. "32 bit float mono audio" */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/param.h b/third_party/pipewire/spa/param/param.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/param.h -@@ -0,0 +1,166 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_H -+#define SPA_PARAM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** different parameter types that can be queried */ -+enum spa_param_type { -+ SPA_PARAM_Invalid, /**< invalid */ -+ SPA_PARAM_PropInfo, /**< property information as SPA_TYPE_OBJECT_PropInfo */ -+ SPA_PARAM_Props, /**< properties as SPA_TYPE_OBJECT_Props */ -+ SPA_PARAM_EnumFormat, /**< available formats as SPA_TYPE_OBJECT_Format */ -+ SPA_PARAM_Format, /**< configured format as SPA_TYPE_OBJECT_Format */ -+ SPA_PARAM_Buffers, /**< buffer configurations as SPA_TYPE_OBJECT_ParamBuffers*/ -+ SPA_PARAM_Meta, /**< allowed metadata for buffers as SPA_TYPE_OBJECT_ParamMeta*/ -+ SPA_PARAM_IO, /**< configurable IO areas as SPA_TYPE_OBJECT_ParamIO */ -+ SPA_PARAM_EnumProfile, /**< profile enumeration as SPA_TYPE_OBJECT_ParamProfile */ -+ SPA_PARAM_Profile, /**< profile configuration as SPA_TYPE_OBJECT_ParamProfile */ -+ SPA_PARAM_EnumPortConfig, /**< port configuration enumeration as SPA_TYPE_OBJECT_ParamPortConfig */ -+ SPA_PARAM_PortConfig, /**< port configuration as SPA_TYPE_OBJECT_ParamPortConfig */ -+ SPA_PARAM_EnumRoute, /**< routing enumeration as SPA_TYPE_OBJECT_ParamRoute */ -+ SPA_PARAM_Route, /**< routing configuration as SPA_TYPE_OBJECT_ParamRoute */ -+ SPA_PARAM_Control, /**< Control parameter, a SPA_TYPE_Sequence */ -+}; -+ -+/** information about a parameter */ -+struct spa_param_info { -+ uint32_t id; /**< enum spa_param_type */ -+#define SPA_PARAM_INFO_SERIAL (1<<0) /**< bit to signal update even when the -+ * read/write flags don't change */ -+#define SPA_PARAM_INFO_READ (1<<1) -+#define SPA_PARAM_INFO_WRITE (1<<2) -+#define SPA_PARAM_INFO_READWRITE (SPA_PARAM_INFO_WRITE|SPA_PARAM_INFO_READ) -+ uint32_t flags; -+ uint32_t user; /**< private user field. You can use this to keep -+ * state. */ -+ uint32_t padding[5]; -+}; -+ -+#define SPA_PARAM_INFO(id,flags) (struct spa_param_info){ (id), (flags) } -+ -+/** properties for SPA_TYPE_OBJECT_ParamBuffers */ -+enum spa_param_buffers { -+ SPA_PARAM_BUFFERS_START, -+ SPA_PARAM_BUFFERS_buffers, /**< number of buffers (Int) */ -+ SPA_PARAM_BUFFERS_blocks, /**< number of data blocks per buffer (Int) */ -+ SPA_PARAM_BUFFERS_size, /**< size of a data block memory (Int)*/ -+ SPA_PARAM_BUFFERS_stride, /**< stride of data block memory (Int) */ -+ SPA_PARAM_BUFFERS_align, /**< alignment of data block memory (Int) */ -+ SPA_PARAM_BUFFERS_dataType, /**< possible memory types (Int, mask of enum spa_data_type) */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamMeta */ -+enum spa_param_meta { -+ SPA_PARAM_META_START, -+ SPA_PARAM_META_type, /**< the metadata, one of enum spa_meta_type (Id enum spa_meta_type) */ -+ SPA_PARAM_META_size, /**< the expected maximum size the meta (Int) */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamIO */ -+enum spa_param_io { -+ SPA_PARAM_IO_START, -+ SPA_PARAM_IO_id, /**< type ID, uniquely identifies the io area (Id enum spa_io_type) */ -+ SPA_PARAM_IO_size, /**< size of the io area (Int) */ -+}; -+ -+enum spa_param_availability { -+ SPA_PARAM_AVAILABILITY_unknown, /**< unknown availability */ -+ SPA_PARAM_AVAILABILITY_no, /**< not available */ -+ SPA_PARAM_AVAILABILITY_yes, /**< available */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamProfile */ -+enum spa_param_profile { -+ SPA_PARAM_PROFILE_START, -+ SPA_PARAM_PROFILE_index, /**< profile index (Int) */ -+ SPA_PARAM_PROFILE_name, /**< profile name (String) */ -+ SPA_PARAM_PROFILE_description, /**< profile description (String) */ -+ SPA_PARAM_PROFILE_priority, /**< profile priority (Int) */ -+ SPA_PARAM_PROFILE_available, /**< availability of the profile -+ * (Id enum spa_param_availability) */ -+ SPA_PARAM_PROFILE_info, /**< info (Struct( -+ * Int : n_items, -+ * (String : key, -+ * String : value)*)) */ -+ SPA_PARAM_PROFILE_classes, /**< node classes provided by this profile -+ * (Struct( -+ * Int : number of items following -+ * Struct( -+ * String : class name (eg. "Audio/Source"), -+ * Int : number of nodes)*)) */ -+}; -+ -+enum spa_param_port_config_mode { -+ SPA_PARAM_PORT_CONFIG_MODE_none, /**< no configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_passthrough, /**< passthrough configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_convert, /**< convert configuration */ -+ SPA_PARAM_PORT_CONFIG_MODE_dsp, /**< dsp configuration, depending on the external -+ * format. For audio, ports will be configured for -+ * the given number of channels with F32 format. */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamPortConfig */ -+enum spa_param_port_config { -+ SPA_PARAM_PORT_CONFIG_START, -+ SPA_PARAM_PORT_CONFIG_direction, /**< direction, input/output (Id enum spa_direction) */ -+ SPA_PARAM_PORT_CONFIG_mode, /**< (Id enum spa_param_port_config_mode) mode */ -+ SPA_PARAM_PORT_CONFIG_monitor, /**< (Bool) enable monitor output ports on input ports */ -+ SPA_PARAM_PORT_CONFIG_control, /**< (Bool) enable control ports */ -+ SPA_PARAM_PORT_CONFIG_format, /**< (Object) format filter */ -+}; -+ -+/** properties for SPA_TYPE_OBJECT_ParamRoute */ -+enum spa_param_route { -+ SPA_PARAM_ROUTE_START, -+ SPA_PARAM_ROUTE_index, /**< index of the routing destination (Int) */ -+ SPA_PARAM_ROUTE_direction, /**< direction, input/output (Id enum spa_direction) */ -+ SPA_PARAM_ROUTE_device, /**< device id (Int) */ -+ SPA_PARAM_ROUTE_name, /**< name of the routing destination (String) */ -+ SPA_PARAM_ROUTE_description, /**< description of the destination (String) */ -+ SPA_PARAM_ROUTE_priority, /**< priority of the destination (Int) */ -+ SPA_PARAM_ROUTE_available, /**< availability of the destination -+ * (Id enum spa_param_availability) */ -+ SPA_PARAM_ROUTE_info, /**< info (Struct( -+ * Int : n_items, -+ * (String : key, -+ * String : value)*)) */ -+ SPA_PARAM_ROUTE_profiles, /**< associated profile indexes (Array of Int) */ -+ SPA_PARAM_ROUTE_props, /**< properties SPA_TYPE_OBJECT_Props */ -+ SPA_PARAM_ROUTE_devices, /**< associated device indexes (Array of Int) */ -+ SPA_PARAM_ROUTE_profile, /**< profile id (Int) */ -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_H */ -diff --git a/third_party/pipewire/spa/param/profiler.h b/third_party/pipewire/spa/param/profiler.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/profiler.h -@@ -0,0 +1,84 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2020 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_PROFILER_H -+#define SPA_PARAM_PROFILER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** properties for SPA_TYPE_OBJECT_Profiler */ -+enum spa_profiler { -+ SPA_PROFILER_START, -+ -+ SPA_PROFILER_START_Driver = 0x10000, /**< driver related profiler properties */ -+ SPA_PROFILER_info, /**< Generic info, counter and CPU load, -+ * (Struct( -+ * Long : counter, -+ * Float : cpu_load fast, -+ * Float : cpu_load medium, -+ * Float : cpu_load slow)) */ -+ SPA_PROFILER_clock, /**< clock information -+ * (Struct( -+ * Int : clock flags, -+ * Int : clock id, -+ * String: clock name, -+ * Long : clock nsec, -+ * Fraction : clock rate, -+ * Long : clock position, -+ * Long : clock duration, -+ * Long : clock delay, -+ * Double : clock rate_diff, -+ * Long : clock next_nsec)) */ -+ SPA_PROFILER_driverBlock, /**< generic driver info block -+ * (Struct( -+ * Int : driver_id, -+ * String : name, -+ * Long : driver prev_signal, -+ * Long : driver signal, -+ * Long : driver awake, -+ * Long : driver finish, -+ * Int : driver status)) */ -+ -+ SPA_PROFILER_START_Follower = 0x20000, /**< follower related profiler properties */ -+ SPA_PROFILER_followerBlock, /**< generic follower info block -+ * (Struct( -+ * Int : id, -+ * String : name, -+ * Long : prev_signal, -+ * Long : signal, -+ * Long : awake, -+ * Long : finish, -+ * Int : status)) */ -+ SPA_PROFILER_START_CUSTOM = 0x1000000, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_PROFILER_H */ -diff --git a/third_party/pipewire/spa/param/props.h b/third_party/pipewire/spa/param/props.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/props.h -@@ -0,0 +1,99 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_PROPS_H -+#define SPA_PARAM_PROPS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+/** properties of SPA_TYPE_OBJECT_PropInfo */ -+enum spa_prop_info { -+ SPA_PROP_INFO_START, -+ SPA_PROP_INFO_id, /**< associated id of the property */ -+ SPA_PROP_INFO_name, /**< name of the property */ -+ SPA_PROP_INFO_type, /**< type and range/enums of property */ -+ SPA_PROP_INFO_labels, /**< labels of property if any, this is a -+ * struct with pairs of values, the first one -+ * is of the type of the property, the second -+ * one is a string with a user readable label -+ * for the value. */ -+}; -+ -+/** predefined properties for SPA_TYPE_OBJECT_Props */ -+enum spa_prop { -+ SPA_PROP_START, -+ -+ SPA_PROP_unknown, /**< an unknown property */ -+ -+ SPA_PROP_START_Device = 0x100, /**< device related properties */ -+ SPA_PROP_device, -+ SPA_PROP_deviceName, -+ SPA_PROP_deviceFd, -+ SPA_PROP_card, -+ SPA_PROP_cardName, -+ -+ SPA_PROP_minLatency, -+ SPA_PROP_maxLatency, -+ SPA_PROP_periods, -+ SPA_PROP_periodSize, -+ SPA_PROP_periodEvent, -+ SPA_PROP_live, -+ SPA_PROP_rate, -+ SPA_PROP_quality, -+ -+ SPA_PROP_START_Audio = 0x10000, /**< audio related properties */ -+ SPA_PROP_waveType, -+ SPA_PROP_frequency, -+ SPA_PROP_volume, /**< a volume (Float), 0.0 silence, 1.0 normal */ -+ SPA_PROP_mute, /**< mute (Bool) */ -+ SPA_PROP_patternType, -+ SPA_PROP_ditherType, -+ SPA_PROP_truncate, -+ SPA_PROP_channelVolumes, /**< a volume array, one volume per -+ * channel (Array of Float) */ -+ SPA_PROP_volumeBase, /**< a volume base (Float) */ -+ SPA_PROP_volumeStep, /**< a volume step (Float) */ -+ -+ SPA_PROP_START_Video = 0x20000, /**< video related properties */ -+ SPA_PROP_brightness, -+ SPA_PROP_contrast, -+ SPA_PROP_saturation, -+ SPA_PROP_hue, -+ SPA_PROP_gamma, -+ SPA_PROP_exposure, -+ SPA_PROP_gain, -+ SPA_PROP_sharpness, -+ -+ SPA_PROP_START_CUSTOM = 0x1000000, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_PROPS_H */ -diff --git a/third_party/pipewire/spa/param/type-info.h b/third_party/pipewire/spa/param/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/type-info.h -@@ -0,0 +1,362 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_TYPES_H -+#define SPA_PARAM_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_ParamId SPA_TYPE_INFO_ENUM_BASE "ParamId" -+#define SPA_TYPE_INFO_PARAM_ID_BASE SPA_TYPE_INFO_ParamId ":" -+ -+static const struct spa_type_info spa_type_param[] = { -+ { SPA_PARAM_Invalid, SPA_TYPE_None, SPA_TYPE_INFO_PARAM_ID_BASE "Invalid", NULL }, -+ { SPA_PARAM_PropInfo, SPA_TYPE_OBJECT_Props, SPA_TYPE_INFO_PARAM_ID_BASE "PropInfo", NULL }, -+ { SPA_PARAM_Props, SPA_TYPE_OBJECT_Props, SPA_TYPE_INFO_PARAM_ID_BASE "Props", NULL }, -+ { SPA_PARAM_EnumFormat, SPA_TYPE_OBJECT_Format, SPA_TYPE_INFO_PARAM_ID_BASE "EnumFormat", NULL }, -+ { SPA_PARAM_Format, SPA_TYPE_OBJECT_Format, SPA_TYPE_INFO_PARAM_ID_BASE "Format", NULL }, -+ { SPA_PARAM_Buffers, SPA_TYPE_OBJECT_ParamBuffers, SPA_TYPE_INFO_PARAM_ID_BASE "Buffers", NULL }, -+ { SPA_PARAM_Meta, SPA_TYPE_OBJECT_ParamMeta, SPA_TYPE_INFO_PARAM_ID_BASE "Meta", NULL }, -+ { SPA_PARAM_IO, SPA_TYPE_OBJECT_ParamIO, SPA_TYPE_INFO_PARAM_ID_BASE "IO", NULL }, -+ { SPA_PARAM_EnumProfile, SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_INFO_PARAM_ID_BASE "EnumProfile", NULL }, -+ { SPA_PARAM_Profile, SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_INFO_PARAM_ID_BASE "Profile", NULL }, -+ { SPA_PARAM_EnumPortConfig, SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_INFO_PARAM_ID_BASE "EnumPortConfig", NULL }, -+ { SPA_PARAM_PortConfig, SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_INFO_PARAM_ID_BASE "PortConfig", NULL }, -+ { SPA_PARAM_EnumRoute, SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_INFO_PARAM_ID_BASE "EnumRoute", NULL }, -+ { SPA_PARAM_Route, SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_INFO_PARAM_ID_BASE "Route", NULL }, -+ { SPA_PARAM_Control, SPA_TYPE_Sequence, SPA_TYPE_INFO_PARAM_ID_BASE "Control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/* base for parameter objects */ -+#define SPA_TYPE_INFO_Param SPA_TYPE_INFO_OBJECT_BASE "Param" -+#define SPA_TYPE_INFO_PARAM_BASE SPA_TYPE_INFO_Param ":" -+ -+#define SPA_TYPE_INFO_Props SPA_TYPE_INFO_PARAM_BASE "Props" -+#define SPA_TYPE_INFO_PROPS_BASE SPA_TYPE_INFO_Props ":" -+ -+static const struct spa_type_info spa_type_props[] = { -+ { SPA_PROP_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE, spa_type_param, }, -+ { SPA_PROP_unknown, SPA_TYPE_None, SPA_TYPE_INFO_PROPS_BASE "unknown", NULL }, -+ { SPA_PROP_device, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "device", NULL }, -+ { SPA_PROP_deviceName, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "deviceName", NULL }, -+ { SPA_PROP_deviceFd, SPA_TYPE_Fd, SPA_TYPE_INFO_PROPS_BASE "deviceFd", NULL }, -+ { SPA_PROP_card, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "card", NULL }, -+ { SPA_PROP_cardName, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "cardName", NULL }, -+ { SPA_PROP_minLatency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "minLatency", NULL }, -+ { SPA_PROP_maxLatency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "maxLatency", NULL }, -+ { SPA_PROP_periods, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "periods", NULL }, -+ { SPA_PROP_periodSize, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "periodSize", NULL }, -+ { SPA_PROP_periodEvent, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "periodEvent", NULL }, -+ { SPA_PROP_live, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "live", NULL }, -+ { SPA_PROP_rate, SPA_TYPE_Double, SPA_TYPE_INFO_PROPS_BASE "rate", NULL }, -+ { SPA_PROP_quality, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "quality", NULL }, -+ -+ { SPA_PROP_waveType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "waveType", NULL }, -+ { SPA_PROP_frequency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "frequency", NULL }, -+ { SPA_PROP_volume, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volume", NULL }, -+ { SPA_PROP_mute, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "mute", NULL }, -+ { SPA_PROP_patternType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "patternType", NULL }, -+ { SPA_PROP_ditherType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "ditherType", NULL }, -+ { SPA_PROP_truncate, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "truncate", NULL }, -+ { SPA_PROP_channelVolumes, SPA_TYPE_Array, SPA_TYPE_INFO_PROPS_BASE "channelVolumes", NULL }, -+ { SPA_PROP_volumeBase, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volumeBase", NULL }, -+ { SPA_PROP_volumeStep, SPA_TYPE_Float, SPA_TYPE_INFO_PROPS_BASE "volumeStep", NULL }, -+ -+ { SPA_PROP_brightness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "brightness", NULL }, -+ { SPA_PROP_contrast, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "contrast", NULL }, -+ { SPA_PROP_saturation, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "saturation", NULL }, -+ { SPA_PROP_hue, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "hue", NULL }, -+ { SPA_PROP_gamma, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gamma", NULL }, -+ { SPA_PROP_exposure, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "exposure", NULL }, -+ { SPA_PROP_gain, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "gain", NULL }, -+ { SPA_PROP_sharpness, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "sharpness", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/** Enum Property info */ -+#define SPA_TYPE_INFO_PropInfo SPA_TYPE_INFO_PARAM_BASE "PropInfo" -+#define SPA_TYPE_INFO_PROP_INFO_BASE SPA_TYPE_INFO_PropInfo ":" -+ -+static const struct spa_type_info spa_type_prop_info[] = { -+ { SPA_PROP_INFO_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROP_INFO_BASE, spa_type_param, }, -+ { SPA_PROP_INFO_id, SPA_TYPE_Id, SPA_TYPE_INFO_PROP_INFO_BASE "id", spa_type_props }, -+ { SPA_PROP_INFO_name, SPA_TYPE_String, SPA_TYPE_INFO_PROP_INFO_BASE "name", NULL }, -+ { SPA_PROP_INFO_type, SPA_TYPE_Pod, SPA_TYPE_INFO_PROP_INFO_BASE "type", NULL }, -+ { SPA_PROP_INFO_labels, SPA_TYPE_Struct, SPA_TYPE_INFO_PROP_INFO_BASE "labels", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Meta SPA_TYPE_INFO_PARAM_BASE "Meta" -+#define SPA_TYPE_INFO_PARAM_META_BASE SPA_TYPE_INFO_PARAM_Meta ":" -+ -+static const struct spa_type_info spa_type_param_meta[] = { -+ { SPA_PARAM_META_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_META_BASE, spa_type_param }, -+ { SPA_PARAM_META_type, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_META_BASE "type", spa_type_meta_type }, -+ { SPA_PARAM_META_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_META_BASE "size", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+/** Base for parameters that describe IO areas to exchange data, -+ * control and properties with a node. -+ */ -+#define SPA_TYPE_INFO_PARAM_IO SPA_TYPE_INFO_PARAM_BASE "IO" -+#define SPA_TYPE_INFO_PARAM_IO_BASE SPA_TYPE_INFO_PARAM_IO ":" -+ -+static const struct spa_type_info spa_type_param_io[] = { -+ { SPA_PARAM_IO_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_IO_BASE, spa_type_param, }, -+ { SPA_PARAM_IO_id, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_IO_BASE "id", spa_type_io }, -+ { SPA_PARAM_IO_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_IO_BASE "size", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_Format SPA_TYPE_INFO_PARAM_BASE "Format" -+#define SPA_TYPE_INFO_FORMAT_BASE SPA_TYPE_INFO_Format ":" -+ -+#define SPA_TYPE_INFO_MediaType SPA_TYPE_INFO_ENUM_BASE "MediaType" -+#define SPA_TYPE_INFO_MEDIA_TYPE_BASE SPA_TYPE_INFO_MediaType ":" -+ -+#include -+#include -+ -+static const struct spa_type_info spa_type_media_type[] = { -+ { SPA_MEDIA_TYPE_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "unknown", NULL }, -+ { SPA_MEDIA_TYPE_audio, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "audio", NULL }, -+ { SPA_MEDIA_TYPE_video, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "video", NULL }, -+ { SPA_MEDIA_TYPE_image, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "image", NULL }, -+ { SPA_MEDIA_TYPE_binary, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "binary", NULL }, -+ { SPA_MEDIA_TYPE_stream, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "stream", NULL }, -+ { SPA_MEDIA_TYPE_application, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_TYPE_BASE "application", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_MediaSubtype SPA_TYPE_INFO_ENUM_BASE "MediaSubtype" -+#define SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE SPA_TYPE_INFO_MediaSubtype ":" -+ -+static const struct spa_type_info spa_type_media_subtype[] = { -+ { SPA_MEDIA_SUBTYPE_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "unknown", NULL }, -+ /* generic subtypes */ -+ { SPA_MEDIA_SUBTYPE_raw, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "raw", NULL }, -+ { SPA_MEDIA_SUBTYPE_dsp, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "dsp", NULL }, -+ /* audio subtypes */ -+ { SPA_MEDIA_SUBTYPE_mp3, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mp3", NULL }, -+ { SPA_MEDIA_SUBTYPE_aac, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "aac", NULL }, -+ { SPA_MEDIA_SUBTYPE_vorbis, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vorbis", NULL }, -+ { SPA_MEDIA_SUBTYPE_wma, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "wma", NULL }, -+ { SPA_MEDIA_SUBTYPE_ra, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "ra", NULL }, -+ { SPA_MEDIA_SUBTYPE_sbc, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "sbc", NULL }, -+ { SPA_MEDIA_SUBTYPE_adpcm, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "adpcm", NULL }, -+ { SPA_MEDIA_SUBTYPE_g723, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g723", NULL }, -+ { SPA_MEDIA_SUBTYPE_g726, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g726", NULL }, -+ { SPA_MEDIA_SUBTYPE_g729, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "g729", NULL }, -+ { SPA_MEDIA_SUBTYPE_amr, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "amr", NULL }, -+ { SPA_MEDIA_SUBTYPE_gsm, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "gsm", NULL }, -+ /* video subtypes */ -+ { SPA_MEDIA_SUBTYPE_h264, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "h264", NULL }, -+ { SPA_MEDIA_SUBTYPE_mjpg, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mjpg", NULL }, -+ { SPA_MEDIA_SUBTYPE_dv, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "dv", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpegts, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpegts", NULL }, -+ { SPA_MEDIA_SUBTYPE_h263, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "h263", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg1, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg1", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg2, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg2", NULL }, -+ { SPA_MEDIA_SUBTYPE_mpeg4, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "mpeg4", NULL }, -+ { SPA_MEDIA_SUBTYPE_xvid, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "xvid", NULL }, -+ { SPA_MEDIA_SUBTYPE_vc1, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vc1", NULL }, -+ { SPA_MEDIA_SUBTYPE_vp8, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vp8", NULL }, -+ { SPA_MEDIA_SUBTYPE_vp9, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "vp9", NULL }, -+ { SPA_MEDIA_SUBTYPE_bayer, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "bayer", NULL }, -+ /* image subtypes */ -+ { SPA_MEDIA_SUBTYPE_jpeg, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "jpeg", NULL }, -+ /* stream subtypes */ -+ { SPA_MEDIA_SUBTYPE_midi, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "midi", NULL }, -+ /* application subtypes */ -+ { SPA_MEDIA_SUBTYPE_control, SPA_TYPE_Int, SPA_TYPE_INFO_MEDIA_SUBTYPE_BASE "control", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_FormatAudio SPA_TYPE_INFO_FORMAT_BASE "Audio" -+#define SPA_TYPE_INFO_FORMAT_AUDIO_BASE SPA_TYPE_INFO_FormatAudio ":" -+ -+#define SPA_TYPE_INFO_FormatVideo SPA_TYPE_INFO_FORMAT_BASE "Video" -+#define SPA_TYPE_INFO_FORMAT_VIDEO_BASE SPA_TYPE_INFO_FormatVideo ":" -+ -+#define SPA_TYPE_INFO_FORMAT_VIDEO_H264 SPA_TYPE_INFO_FORMAT_VIDEO_BASE "H264" -+#define SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE SPA_TYPE_INFO_FORMAT_VIDEO_H264 ":" -+ -+static const struct spa_type_info spa_type_format[] = { -+ { SPA_FORMAT_START, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE, spa_type_param, }, -+ -+ { SPA_FORMAT_mediaType, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE "mediaType", -+ spa_type_media_type, }, -+ { SPA_FORMAT_mediaSubtype, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_BASE "mediaSubtype", -+ spa_type_media_subtype, }, -+ -+ { SPA_FORMAT_AUDIO_format, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "format", -+ spa_type_audio_format }, -+ { SPA_FORMAT_AUDIO_flags, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "flags", -+ spa_type_audio_flags }, -+ { SPA_FORMAT_AUDIO_rate, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "rate", NULL }, -+ { SPA_FORMAT_AUDIO_channels, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "channels", NULL }, -+ { SPA_FORMAT_AUDIO_position, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_AUDIO_BASE "position", -+ spa_type_audio_channel }, -+ -+ { SPA_FORMAT_VIDEO_format, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "format", -+ spa_type_video_format, }, -+ { SPA_FORMAT_VIDEO_modifier, SPA_TYPE_Long, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "modifier", NULL }, -+ { SPA_FORMAT_VIDEO_size, SPA_TYPE_Rectangle, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "size", NULL }, -+ { SPA_FORMAT_VIDEO_framerate, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "framerate", NULL }, -+ { SPA_FORMAT_VIDEO_maxFramerate, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "maxFramerate", NULL }, -+ { SPA_FORMAT_VIDEO_views, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "views", NULL }, -+ { SPA_FORMAT_VIDEO_interlaceMode, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "interlaceMode", NULL }, -+ { SPA_FORMAT_VIDEO_pixelAspectRatio, SPA_TYPE_Fraction, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "pixelAspectRatio", NULL }, -+ { SPA_FORMAT_VIDEO_multiviewMode, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "multiviewMode", NULL }, -+ { SPA_FORMAT_VIDEO_multiviewFlags, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "multiviewFlags", NULL }, -+ { SPA_FORMAT_VIDEO_chromaSite, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "chromaSite", NULL }, -+ { SPA_FORMAT_VIDEO_colorRange, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorRange", NULL }, -+ { SPA_FORMAT_VIDEO_colorMatrix, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorMatrix", NULL }, -+ { SPA_FORMAT_VIDEO_transferFunction, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "transferFunction", NULL }, -+ { SPA_FORMAT_VIDEO_colorPrimaries, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "colorPrimaries", NULL }, -+ { SPA_FORMAT_VIDEO_profile, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "profile", NULL }, -+ { SPA_FORMAT_VIDEO_level, SPA_TYPE_Int, SPA_TYPE_INFO_FORMAT_VIDEO_BASE "level", NULL }, -+ -+ { SPA_FORMAT_VIDEO_H264_streamFormat, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "streamFormat", NULL }, -+ { SPA_FORMAT_VIDEO_H264_alignment, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "alignment", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Buffers SPA_TYPE_INFO_PARAM_BASE "Buffers" -+#define SPA_TYPE_INFO_PARAM_BUFFERS_BASE SPA_TYPE_INFO_PARAM_Buffers ":" -+ -+#define SPA_TYPE_INFO_PARAM_BlockInfo SPA_TYPE_INFO_PARAM_BUFFERS_BASE "BlockInfo" -+#define SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE SPA_TYPE_INFO_PARAM_BlockInfo ":" -+ -+static const struct spa_type_info spa_type_param_buffers[] = { -+ { SPA_PARAM_BUFFERS_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_BUFFERS_BASE, spa_type_param, }, -+ { SPA_PARAM_BUFFERS_buffers, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BUFFERS_BASE "buffers", NULL }, -+ { SPA_PARAM_BUFFERS_blocks, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BUFFERS_BASE "blocks", NULL }, -+ { SPA_PARAM_BUFFERS_size, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "size", NULL }, -+ { SPA_PARAM_BUFFERS_stride, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "stride", NULL }, -+ { SPA_PARAM_BUFFERS_align, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "align", NULL }, -+ { SPA_PARAM_BUFFERS_dataType, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_BLOCK_INFO_BASE "dataType", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_ParamAvailability SPA_TYPE_INFO_ENUM_BASE "ParamAvailability" -+#define SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE SPA_TYPE_INFO_ParamAvailability ":" -+ -+static const struct spa_type_info spa_type_param_availability[] = { -+ { SPA_PARAM_AVAILABILITY_unknown, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "unknown", NULL }, -+ { SPA_PARAM_AVAILABILITY_no, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "no", NULL }, -+ { SPA_PARAM_AVAILABILITY_yes, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_AVAILABILITY_BASE "yes", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_Profile SPA_TYPE_INFO_PARAM_BASE "Profile" -+#define SPA_TYPE_INFO_PARAM_PROFILE_BASE SPA_TYPE_INFO_PARAM_Profile ":" -+ -+static const struct spa_type_info spa_type_param_profile[] = { -+ { SPA_PARAM_PROFILE_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PROFILE_BASE, spa_type_param, }, -+ { SPA_PARAM_PROFILE_index, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PROFILE_BASE "index", NULL }, -+ { SPA_PARAM_PROFILE_name, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_PROFILE_BASE "name", NULL }, -+ { SPA_PARAM_PROFILE_description, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_PROFILE_BASE "description", NULL }, -+ { SPA_PARAM_PROFILE_priority, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PROFILE_BASE "priority", NULL }, -+ { SPA_PARAM_PROFILE_available, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PROFILE_BASE "available", spa_type_param_availability, }, -+ { SPA_PARAM_PROFILE_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_PROFILE_BASE "info", NULL, }, -+ { SPA_PARAM_PROFILE_classes, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_PROFILE_BASE "classes", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_ParamPortConfigMode SPA_TYPE_INFO_ENUM_BASE "ParamPortConfigMode" -+#define SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE SPA_TYPE_INFO_ParamPortConfigMode ":" -+ -+static const struct spa_type_info spa_type_param_port_config_mode[] = { -+ { SPA_PARAM_PORT_CONFIG_MODE_none, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "none", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_passthrough, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "passthrough", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_convert, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "convert", NULL }, -+ { SPA_PARAM_PORT_CONFIG_MODE_dsp, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_PORT_CONFIG_MODE_BASE "dsp", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#define SPA_TYPE_INFO_PARAM_PortConfig SPA_TYPE_INFO_PARAM_BASE "PortConfig" -+#define SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE SPA_TYPE_INFO_PARAM_PortConfig ":" -+ -+static const struct spa_type_info spa_type_param_port_config[] = { -+ { SPA_PARAM_PORT_CONFIG_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE, spa_type_param, }, -+ { SPA_PARAM_PORT_CONFIG_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "direction", spa_type_direction, }, -+ { SPA_PARAM_PORT_CONFIG_mode, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "mode", spa_type_param_port_config_mode }, -+ { SPA_PARAM_PORT_CONFIG_monitor, SPA_TYPE_Bool, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "monitor", NULL }, -+ { SPA_PARAM_PORT_CONFIG_control, SPA_TYPE_Bool, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "control", NULL }, -+ { SPA_PARAM_PORT_CONFIG_format, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_PORT_CONFIG_BASE "format", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+ -+#define SPA_TYPE_INFO_PARAM_Route SPA_TYPE_INFO_PARAM_BASE "Route" -+#define SPA_TYPE_INFO_PARAM_ROUTE_BASE SPA_TYPE_INFO_PARAM_Route ":" -+ -+static const struct spa_type_info spa_type_param_route[] = { -+ { SPA_PARAM_ROUTE_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE, spa_type_param, }, -+ { SPA_PARAM_ROUTE_index, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "index", NULL, }, -+ { SPA_PARAM_ROUTE_direction, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE "direction", spa_type_direction, }, -+ { SPA_PARAM_ROUTE_device, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "device", NULL, }, -+ { SPA_PARAM_ROUTE_name, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_ROUTE_BASE "name", NULL, }, -+ { SPA_PARAM_ROUTE_description, SPA_TYPE_String, SPA_TYPE_INFO_PARAM_ROUTE_BASE "description", NULL, }, -+ { SPA_PARAM_ROUTE_priority, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "priority", NULL, }, -+ { SPA_PARAM_ROUTE_available, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_ROUTE_BASE "available", spa_type_param_availability, }, -+ { SPA_PARAM_ROUTE_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_ROUTE_BASE "info", NULL, }, -+ { SPA_PARAM_ROUTE_profiles, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profiles", NULL, }, -+ { SPA_PARAM_ROUTE_props, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ROUTE_BASE "props", NULL, }, -+ { SPA_PARAM_ROUTE_devices, SPA_TYPE_Array, SPA_TYPE_INFO_PARAM_ROUTE_BASE "devices", NULL, }, -+ { SPA_PARAM_ROUTE_profile, SPA_TYPE_Int, SPA_TYPE_INFO_PARAM_ROUTE_BASE "profile", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#include -+ -+#define SPA_TYPE_INFO_Profiler SPA_TYPE_INFO_OBJECT_BASE "Profiler" -+#define SPA_TYPE_INFO_PROFILER_BASE SPA_TYPE_INFO_Profiler ":" -+ -+static const struct spa_type_info spa_type_profiler[] = { -+ { SPA_PROFILER_START, SPA_TYPE_Id, SPA_TYPE_INFO_PROFILER_BASE, spa_type_param, }, -+ { SPA_PROFILER_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "info", NULL, }, -+ { SPA_PROFILER_clock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "clock", NULL, }, -+ { SPA_PROFILER_driverBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "driverBlock", NULL, }, -+ { SPA_PROFILER_followerBlock, SPA_TYPE_Struct, SPA_TYPE_INFO_PROFILER_BASE "followerBlock", NULL, }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_TYPES_H */ -diff --git a/third_party/pipewire/spa/param/video/chroma.h b/third_party/pipewire/spa/param/video/chroma.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/chroma.h -@@ -0,0 +1,60 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_CHROMA_H -+#define SPA_VIDEO_CHROMA_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** Various Chroma sitings. -+ * @SPA_VIDEO_CHROMA_SITE_UNKNOWN: unknown cositing -+ * @SPA_VIDEO_CHROMA_SITE_NONE: no cositing -+ * @SPA_VIDEO_CHROMA_SITE_H_COSITED: chroma is horizontally cosited -+ * @SPA_VIDEO_CHROMA_SITE_V_COSITED: chroma is vertically cosited -+ * @SPA_VIDEO_CHROMA_SITE_ALT_LINE: choma samples are sited on alternate lines -+ * @SPA_VIDEO_CHROMA_SITE_COSITED: chroma samples cosited with luma samples -+ * @SPA_VIDEO_CHROMA_SITE_JPEG: jpeg style cositing, also for mpeg1 and mjpeg -+ * @SPA_VIDEO_CHROMA_SITE_MPEG2: mpeg2 style cositing -+ * @SPA_VIDEO_CHROMA_SITE_DV: DV style cositing -+ */ -+enum spa_video_chroma_site { -+ SPA_VIDEO_CHROMA_SITE_UNKNOWN = 0, -+ SPA_VIDEO_CHROMA_SITE_NONE = (1 << 0), -+ SPA_VIDEO_CHROMA_SITE_H_COSITED = (1 << 1), -+ SPA_VIDEO_CHROMA_SITE_V_COSITED = (1 << 2), -+ SPA_VIDEO_CHROMA_SITE_ALT_LINE = (1 << 3), -+ /* some common chroma cositing */ -+ SPA_VIDEO_CHROMA_SITE_COSITED = (SPA_VIDEO_CHROMA_SITE_H_COSITED | SPA_VIDEO_CHROMA_SITE_V_COSITED), -+ SPA_VIDEO_CHROMA_SITE_JPEG = (SPA_VIDEO_CHROMA_SITE_NONE), -+ SPA_VIDEO_CHROMA_SITE_MPEG2 = (SPA_VIDEO_CHROMA_SITE_H_COSITED), -+ SPA_VIDEO_CHROMA_SITE_DV = (SPA_VIDEO_CHROMA_SITE_COSITED | SPA_VIDEO_CHROMA_SITE_ALT_LINE), -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_CHROMA_H */ -diff --git a/third_party/pipewire/spa/param/video/color.h b/third_party/pipewire/spa/param/video/color.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/color.h -@@ -0,0 +1,162 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_COLOR_H -+#define SPA_VIDEO_COLOR_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * spa_video_color_range: -+ * @SPA_VIDEO_COLOR_RANGE_UNKNOWN: unknown range -+ * @SPA_VIDEO_COLOR_RANGE_0_255: [0..255] for 8 bit components -+ * @SPA_VIDEO_COLOR_RANGE_16_235: [16..235] for 8 bit components. Chroma has -+ * [16..240] range. -+ * -+ * Possible color range values. These constants are defined for 8 bit color -+ * values and can be scaled for other bit depths. -+ */ -+enum spa_video_color_range { -+ SPA_VIDEO_COLOR_RANGE_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_RANGE_0_255, -+ SPA_VIDEO_COLOR_RANGE_16_235 -+}; -+ -+/** -+ * spa_video_color_matrix: -+ * @SPA_VIDEO_COLOR_MATRIX_UNKNOWN: unknown matrix -+ * @SPA_VIDEO_COLOR_MATRIX_RGB: identity matrix -+ * @SPA_VIDEO_COLOR_MATRIX_FCC: FCC color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT709: ITU-R BT.709 color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT601: ITU-R BT.601 color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_SMPTE240M: SMPTE 240M color matrix -+ * @SPA_VIDEO_COLOR_MATRIX_BT2020: ITU-R BT.2020 color matrix. Since: 1.6. -+ * -+ * The color matrix is used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ */ -+enum spa_video_color_matrix { -+ SPA_VIDEO_COLOR_MATRIX_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_MATRIX_RGB, -+ SPA_VIDEO_COLOR_MATRIX_FCC, -+ SPA_VIDEO_COLOR_MATRIX_BT709, -+ SPA_VIDEO_COLOR_MATRIX_BT601, -+ SPA_VIDEO_COLOR_MATRIX_SMPTE240M, -+ SPA_VIDEO_COLOR_MATRIX_BT2020 -+}; -+ -+/** -+ * spa_video_transfer_function: -+ * @SPA_VIDEO_TRANSFER_UNKNOWN: unknown transfer function -+ * @SPA_VIDEO_TRANSFER_GAMMA10: linear RGB, gamma 1.0 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA18: Gamma 1.8 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA20: Gamma 2.0 curve -+ * @SPA_VIDEO_TRANSFER_GAMMA22: Gamma 2.2 curve -+ * @SPA_VIDEO_TRANSFER_BT709: Gamma 2.2 curve with a linear segment in the lower -+ * range -+ * @SPA_VIDEO_TRANSFER_SMPTE240M: Gamma 2.2 curve with a linear segment in the -+ * lower range -+ * @SPA_VIDEO_TRANSFER_SRGB: Gamma 2.4 curve with a linear segment in the lower -+ * range -+ * @SPA_VIDEO_TRANSFER_GAMMA28: Gamma 2.8 curve -+ * @SPA_VIDEO_TRANSFER_LOG100: Logarithmic transfer characteristic -+ * 100:1 range -+ * @SPA_VIDEO_TRANSFER_LOG316: Logarithmic transfer characteristic -+ * 316.22777:1 range -+ * @SPA_VIDEO_TRANSFER_BT2020_12: Gamma 2.2 curve with a linear segment in the lower -+ * range. Used for BT.2020 with 12 bits per -+ * component. Since: 1.6. -+ * @SPA_VIDEO_TRANSFER_ADOBERGB: Gamma 2.19921875. Since: 1.8 -+ * -+ * The video transfer function defines the formula for converting between -+ * non-linear RGB (R'G'B') and linear RGB -+ */ -+enum spa_video_transfer_function { -+ SPA_VIDEO_TRANSFER_UNKNOWN = 0, -+ SPA_VIDEO_TRANSFER_GAMMA10, -+ SPA_VIDEO_TRANSFER_GAMMA18, -+ SPA_VIDEO_TRANSFER_GAMMA20, -+ SPA_VIDEO_TRANSFER_GAMMA22, -+ SPA_VIDEO_TRANSFER_BT709, -+ SPA_VIDEO_TRANSFER_SMPTE240M, -+ SPA_VIDEO_TRANSFER_SRGB, -+ SPA_VIDEO_TRANSFER_GAMMA28, -+ SPA_VIDEO_TRANSFER_LOG100, -+ SPA_VIDEO_TRANSFER_LOG316, -+ SPA_VIDEO_TRANSFER_BT2020_12, -+ SPA_VIDEO_TRANSFER_ADOBERGB -+}; -+ -+/** -+ * spa_video_color_primaries: -+ * @SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN: unknown color primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT709: BT709 primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT470M: BT470M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT470BG: BT470BG primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M: SMPTE170M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M: SMPTE240M primaries -+ * @SPA_VIDEO_COLOR_PRIMARIES_FILM: Generic film -+ * @SPA_VIDEO_COLOR_PRIMARIES_BT2020: BT2020 primaries. Since: 1.6. -+ * @SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB: Adobe RGB primaries. Since: 1.8 -+ * -+ * The color primaries define the how to transform linear RGB values to and from -+ * the CIE XYZ colorspace. -+ */ -+enum spa_video_color_primaries { -+ SPA_VIDEO_COLOR_PRIMARIES_UNKNOWN = 0, -+ SPA_VIDEO_COLOR_PRIMARIES_BT709, -+ SPA_VIDEO_COLOR_PRIMARIES_BT470M, -+ SPA_VIDEO_COLOR_PRIMARIES_BT470BG, -+ SPA_VIDEO_COLOR_PRIMARIES_SMPTE170M, -+ SPA_VIDEO_COLOR_PRIMARIES_SMPTE240M, -+ SPA_VIDEO_COLOR_PRIMARIES_FILM, -+ SPA_VIDEO_COLOR_PRIMARIES_BT2020, -+ SPA_VIDEO_COLOR_PRIMARIES_ADOBERGB -+}; -+ -+/** -+ * spa_video_colorimetry: -+ * @range: the color range. This is the valid range for the samples. -+ * It is used to convert the samples to Y'PbPr values. -+ * @matrix: the color matrix. Used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ * @transfer: the transfer function. used to convert between R'G'B' and RGB -+ * @primaries: color primaries. used to convert between R'G'B' and CIE XYZ -+ * -+ * Structure describing the color info. -+ */ -+struct spa_video_colorimetry { -+ enum spa_video_color_range range; -+ enum spa_video_color_matrix matrix; -+ enum spa_video_transfer_function transfer; -+ enum spa_video_color_primaries primaries; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_COLOR_H */ -diff --git a/third_party/pipewire/spa/param/video/encoded.h b/third_party/pipewire/spa/param/video/encoded.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/encoded.h -@@ -0,0 +1,65 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_ENCODED_H -+#define SPA_VIDEO_ENCODED_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum spa_h264_stream_format { -+ SPA_H264_STREAM_FORMAT_UNKNOWN = 0, -+ SPA_H264_STREAM_FORMAT_AVC, -+ SPA_H264_STREAM_FORMAT_AVC3, -+ SPA_H264_STREAM_FORMAT_BYTESTREAM -+}; -+ -+enum spa_h264_alignment { -+ SPA_H264_ALIGNMENT_UNKNOWN = 0, -+ SPA_H264_ALIGNMENT_AU, -+ SPA_H264_ALIGNMENT_NAL -+}; -+ -+struct spa_video_info_h264 { -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+ enum spa_h264_stream_format stream_format; -+ enum spa_h264_alignment alignment; -+}; -+ -+struct spa_video_info_mjpg { -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_ENCODED_H */ -diff --git a/third_party/pipewire/spa/param/video/format-utils.h b/third_party/pipewire/spa/param/video/format-utils.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/format-utils.h -@@ -0,0 +1,167 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_VIDEO_FORMAT_UTILS_H -+#define SPA_PARAM_VIDEO_FORMAT_UTILS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+static inline int -+spa_format_video_raw_parse(const struct spa_pod *format, -+ struct spa_video_info_raw *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_OPT_Long(&info->modifier), -+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate), -+ SPA_FORMAT_VIDEO_views, SPA_POD_OPT_Int(&info->views), -+ SPA_FORMAT_VIDEO_interlaceMode, SPA_POD_OPT_Id(&info->interlace_mode), -+ SPA_FORMAT_VIDEO_pixelAspectRatio, SPA_POD_OPT_Fraction(&info->pixel_aspect_ratio), -+ SPA_FORMAT_VIDEO_multiviewMode, SPA_POD_OPT_Id(&info->multiview_mode), -+ SPA_FORMAT_VIDEO_multiviewFlags, SPA_POD_OPT_Id(&info->multiview_flags), -+ SPA_FORMAT_VIDEO_chromaSite, SPA_POD_OPT_Id(&info->chroma_site), -+ SPA_FORMAT_VIDEO_colorRange, SPA_POD_OPT_Id(&info->color_range), -+ SPA_FORMAT_VIDEO_colorMatrix, SPA_POD_OPT_Id(&info->color_matrix), -+ SPA_FORMAT_VIDEO_transferFunction, SPA_POD_OPT_Id(&info->transfer_function), -+ SPA_FORMAT_VIDEO_colorPrimaries, SPA_POD_OPT_Id(&info->color_primaries)); -+} -+ -+static inline int -+spa_format_video_dsp_parse(const struct spa_pod *format, -+ struct spa_video_info_dsp *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(&info->format), -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_OPT_Long(&info->modifier)); -+} -+ -+static inline struct spa_pod * -+spa_format_video_raw_build(struct spa_pod_builder *builder, uint32_t id, -+ struct spa_video_info_raw *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), -+ SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), -+ 0); -+ if (info->modifier != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); -+ if (info->max_framerate.denom != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_Fraction(info->max_framerate), 0); -+ if (info->views != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_views, SPA_POD_Int(info->views), 0); -+ if (info->interlace_mode != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_interlaceMode, SPA_POD_Id(info->interlace_mode), 0); -+ if (info->pixel_aspect_ratio.denom != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_pixelAspectRatio,SPA_POD_Fraction(info->pixel_aspect_ratio), 0); -+ if (info->multiview_mode != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_multiviewMode, SPA_POD_Id(info->multiview_mode), 0); -+ if (info->multiview_flags != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_multiviewFlags,SPA_POD_Id(info->multiview_flags), 0); -+ if (info->chroma_site != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_chromaSite, SPA_POD_Id(info->chroma_site), 0); -+ if (info->color_range != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorRange, SPA_POD_Id(info->color_range), 0); -+ if (info->color_matrix != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorMatrix, SPA_POD_Id(info->color_matrix), 0); -+ if (info->transfer_function != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_transferFunction,SPA_POD_Id(info->transfer_function), 0); -+ if (info->color_primaries != 0) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_colorPrimaries,SPA_POD_Id(info->color_primaries), 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline struct spa_pod * -+spa_format_video_dsp_build(struct spa_pod_builder *builder, uint32_t id, -+ struct spa_video_info_dsp *info) -+{ -+ struct spa_pod_frame f; -+ spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), -+ SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_dsp), -+ SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), -+ 0); -+ if (info->modifier) -+ spa_pod_builder_add(builder, -+ SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); -+ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); -+} -+ -+static inline int -+spa_format_video_h264_parse(const struct spa_pod *format, -+ struct spa_video_info_h264 *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_OPT_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate), -+ SPA_FORMAT_VIDEO_H264_streamFormat, SPA_POD_OPT_Id(&info->stream_format), -+ SPA_FORMAT_VIDEO_H264_alignment, SPA_POD_OPT_Id(&info->alignment)); -+} -+ -+static inline int -+spa_format_video_mjpg_parse(const struct spa_pod *format, -+ struct spa_video_info_mjpg *info) -+{ -+ return spa_pod_parse_object(format, -+ SPA_TYPE_OBJECT_Format, NULL, -+ SPA_FORMAT_VIDEO_size, SPA_POD_OPT_Rectangle(&info->size), -+ SPA_FORMAT_VIDEO_framerate, SPA_POD_OPT_Fraction(&info->framerate), -+ SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_OPT_Fraction(&info->max_framerate)); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_VIDEO_FORMAT_UTILS_H */ -diff --git a/third_party/pipewire/spa/param/video/format.h b/third_party/pipewire/spa/param/video/format.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/format.h -@@ -0,0 +1,50 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PARAM_VIDEO_FORMAT_H -+#define SPA_PARAM_VIDEO_FORMAT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_video_info { -+ uint32_t media_type; -+ uint32_t media_subtype; -+ union { -+ struct spa_video_info_raw raw; -+ struct spa_video_info_dsp dsp; -+ struct spa_video_info_h264 h264; -+ struct spa_video_info_mjpg mjpg; -+ } info; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PARAM_VIDEO_FORMAT_H */ -diff --git a/third_party/pipewire/spa/param/video/multiview.h b/third_party/pipewire/spa/param/video/multiview.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/multiview.h -@@ -0,0 +1,140 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_MULTIVIEW_H -+#define SPA_VIDEO_MULTIVIEW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** -+ * spa_video_multiview_mode: -+ * @SPA_VIDEO_MULTIVIEW_MODE_NONE: A special value indicating -+ * no multiview information. Used in spa_video_info and other places to -+ * indicate that no specific multiview handling has been requested or -+ * provided. This value is never carried on caps. -+ * @SPA_VIDEO_MULTIVIEW_MODE_MONO: All frames are monoscopic. -+ * @SPA_VIDEO_MULTIVIEW_MODE_LEFT: All frames represent a left-eye view. -+ * @SPA_VIDEO_MULTIVIEW_MODE_RIGHT: All frames represent a right-eye view. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE: Left and right eye views are -+ * provided in the left and right half of the frame respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX: Left and right eye -+ * views are provided in the left and right half of the frame, but -+ * have been sampled using quincunx method, with half-pixel offset -+ * between the 2 views. -+ * @SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED: Alternating vertical -+ * columns of pixels represent the left and right eye view respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED: Alternating horizontal -+ * rows of pixels represent the left and right eye view respectively. -+ * @SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM: The top half of the frame -+ * contains the left eye, and the bottom half the right eye. -+ * @SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD: Pixels are arranged with -+ * alternating pixels representing left and right eye views in a -+ * checkerboard fashion. -+ * @SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME: Left and right eye views -+ * are provided in separate frames alternately. -+ * @SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME: Multiple -+ * independent views are provided in separate frames in sequence. -+ * This method only applies to raw video buffers at the moment. -+ * Specific view identification is via the #spa_video_multiview_meta -+ * on raw video buffers. -+ * @SPA_VIDEO_MULTIVIEW_MODE_SEPARATED: Multiple views are -+ * provided as separate #spa_data framebuffers attached to each -+ * #spa_buffer, described by the #spa_video_multiview_meta -+ * -+ * All possible stereoscopic 3D and multiview representations. -+ * In conjunction with #soa_video_multiview_flags, describes how -+ * multiview content is being transported in the stream. -+ */ -+enum spa_video_multiview_mode { -+ SPA_VIDEO_MULTIVIEW_MODE_NONE = -1, -+ SPA_VIDEO_MULTIVIEW_MODE_MONO = 0, -+ /* Single view modes */ -+ SPA_VIDEO_MULTIVIEW_MODE_LEFT, -+ SPA_VIDEO_MULTIVIEW_MODE_RIGHT, -+ /* Stereo view modes */ -+ SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE, -+ SPA_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE_QUINCUNX, -+ SPA_VIDEO_MULTIVIEW_MODE_COLUMN_INTERLEAVED, -+ SPA_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED, -+ SPA_VIDEO_MULTIVIEW_MODE_TOP_BOTTOM, -+ SPA_VIDEO_MULTIVIEW_MODE_CHECKERBOARD, -+ /* Padding for new frame packing modes */ -+ -+ SPA_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME = 32, -+ /* Multivew mode(s) */ -+ SPA_VIDEO_MULTIVIEW_MODE_MULTIVIEW_FRAME_BY_FRAME, -+ SPA_VIDEO_MULTIVIEW_MODE_SEPARATED -+ /* future expansion for annotated modes */ -+}; -+ -+/** -+ * spa_video_multiview_flags: -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_NONE: No flags -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST: For stereo streams, the -+ * normal arrangement of left and right views is reversed. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED: The left view is vertically -+ * mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED: The left view is horizontally -+ * mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED: The right view is -+ * vertically mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED: The right view is -+ * horizontally mirrored. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT: For frame-packed -+ * multiview modes, indicates that the individual -+ * views have been encoded with half the true width or height -+ * and should be scaled back up for display. This flag -+ * is used for overriding input layout interpretation -+ * by adjusting pixel-aspect-ratio. -+ * For side-by-side, column interleaved or checkerboard packings, the -+ * pixel width will be doubled. For row interleaved and top-bottom -+ * encodings, pixel height will be doubled. -+ * @SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO: The video stream contains both -+ * mono and multiview portions, signalled on each buffer by the -+ * absence or presence of the @SPA_VIDEO_BUFFER_FLAG_MULTIPLE_VIEW -+ * buffer flag. -+ * -+ * spa_video_multiview_flags are used to indicate extra properties of a -+ * stereo/multiview stream beyond the frame layout and buffer mapping -+ * that is conveyed in the #spa_video_multiview_mode. -+ */ -+enum spa_video_multiview_flags { -+ SPA_VIDEO_MULTIVIEW_FLAGS_NONE = 0, -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST = (1 << 0), -+ SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLIPPED = (1 << 1), -+ SPA_VIDEO_MULTIVIEW_FLAGS_LEFT_FLOPPED = (1 << 2), -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLIPPED = (1 << 3), -+ SPA_VIDEO_MULTIVIEW_FLAGS_RIGHT_FLOPPED = (1 << 4), -+ SPA_VIDEO_MULTIVIEW_FLAGS_HALF_ASPECT = (1 << 14), -+ SPA_VIDEO_MULTIVIEW_FLAGS_MIXED_MONO = (1 << 15) -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_MULTIVIEW_H */ -diff --git a/third_party/pipewire/spa/param/video/raw.h b/third_party/pipewire/spa/param/video/raw.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/raw.h -@@ -0,0 +1,221 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_RAW_H -+#define SPA_VIDEO_RAW_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+ -+#define SPA_VIDEO_MAX_PLANES 4 -+#define SPA_VIDEO_MAX_COMPONENTS 4 -+ -+enum spa_video_format { -+ SPA_VIDEO_FORMAT_UNKNOWN, -+ SPA_VIDEO_FORMAT_ENCODED, -+ -+ SPA_VIDEO_FORMAT_I420, -+ SPA_VIDEO_FORMAT_YV12, -+ SPA_VIDEO_FORMAT_YUY2, -+ SPA_VIDEO_FORMAT_UYVY, -+ SPA_VIDEO_FORMAT_AYUV, -+ SPA_VIDEO_FORMAT_RGBx, -+ SPA_VIDEO_FORMAT_BGRx, -+ SPA_VIDEO_FORMAT_xRGB, -+ SPA_VIDEO_FORMAT_xBGR, -+ SPA_VIDEO_FORMAT_RGBA, -+ SPA_VIDEO_FORMAT_BGRA, -+ SPA_VIDEO_FORMAT_ARGB, -+ SPA_VIDEO_FORMAT_ABGR, -+ SPA_VIDEO_FORMAT_RGB, -+ SPA_VIDEO_FORMAT_BGR, -+ SPA_VIDEO_FORMAT_Y41B, -+ SPA_VIDEO_FORMAT_Y42B, -+ SPA_VIDEO_FORMAT_YVYU, -+ SPA_VIDEO_FORMAT_Y444, -+ SPA_VIDEO_FORMAT_v210, -+ SPA_VIDEO_FORMAT_v216, -+ SPA_VIDEO_FORMAT_NV12, -+ SPA_VIDEO_FORMAT_NV21, -+ SPA_VIDEO_FORMAT_GRAY8, -+ SPA_VIDEO_FORMAT_GRAY16_BE, -+ SPA_VIDEO_FORMAT_GRAY16_LE, -+ SPA_VIDEO_FORMAT_v308, -+ SPA_VIDEO_FORMAT_RGB16, -+ SPA_VIDEO_FORMAT_BGR16, -+ SPA_VIDEO_FORMAT_RGB15, -+ SPA_VIDEO_FORMAT_BGR15, -+ SPA_VIDEO_FORMAT_UYVP, -+ SPA_VIDEO_FORMAT_A420, -+ SPA_VIDEO_FORMAT_RGB8P, -+ SPA_VIDEO_FORMAT_YUV9, -+ SPA_VIDEO_FORMAT_YVU9, -+ SPA_VIDEO_FORMAT_IYU1, -+ SPA_VIDEO_FORMAT_ARGB64, -+ SPA_VIDEO_FORMAT_AYUV64, -+ SPA_VIDEO_FORMAT_r210, -+ SPA_VIDEO_FORMAT_I420_10BE, -+ SPA_VIDEO_FORMAT_I420_10LE, -+ SPA_VIDEO_FORMAT_I422_10BE, -+ SPA_VIDEO_FORMAT_I422_10LE, -+ SPA_VIDEO_FORMAT_Y444_10BE, -+ SPA_VIDEO_FORMAT_Y444_10LE, -+ SPA_VIDEO_FORMAT_GBR, -+ SPA_VIDEO_FORMAT_GBR_10BE, -+ SPA_VIDEO_FORMAT_GBR_10LE, -+ SPA_VIDEO_FORMAT_NV16, -+ SPA_VIDEO_FORMAT_NV24, -+ SPA_VIDEO_FORMAT_NV12_64Z32, -+ SPA_VIDEO_FORMAT_A420_10BE, -+ SPA_VIDEO_FORMAT_A420_10LE, -+ SPA_VIDEO_FORMAT_A422_10BE, -+ SPA_VIDEO_FORMAT_A422_10LE, -+ SPA_VIDEO_FORMAT_A444_10BE, -+ SPA_VIDEO_FORMAT_A444_10LE, -+ SPA_VIDEO_FORMAT_NV61, -+ SPA_VIDEO_FORMAT_P010_10BE, -+ SPA_VIDEO_FORMAT_P010_10LE, -+ SPA_VIDEO_FORMAT_IYU2, -+ SPA_VIDEO_FORMAT_VYUY, -+ SPA_VIDEO_FORMAT_GBRA, -+ SPA_VIDEO_FORMAT_GBRA_10BE, -+ SPA_VIDEO_FORMAT_GBRA_10LE, -+ SPA_VIDEO_FORMAT_GBR_12BE, -+ SPA_VIDEO_FORMAT_GBR_12LE, -+ SPA_VIDEO_FORMAT_GBRA_12BE, -+ SPA_VIDEO_FORMAT_GBRA_12LE, -+ SPA_VIDEO_FORMAT_I420_12BE, -+ SPA_VIDEO_FORMAT_I420_12LE, -+ SPA_VIDEO_FORMAT_I422_12BE, -+ SPA_VIDEO_FORMAT_I422_12LE, -+ SPA_VIDEO_FORMAT_Y444_12BE, -+ SPA_VIDEO_FORMAT_Y444_12LE, -+ -+ SPA_VIDEO_FORMAT_RGBA_F16, -+ SPA_VIDEO_FORMAT_RGBA_F32, -+ -+ /* Aliases */ -+ SPA_VIDEO_FORMAT_DSP_F32 = SPA_VIDEO_FORMAT_RGBA_F32, -+}; -+ -+/** -+ * spa_video_flags: -+ * @SPA_VIDEO_FLAG_NONE: no flags -+ * @SPA_VIDEO_FLAG_VARIABLE_FPS: a variable fps is selected, fps_n and fps_d -+ * denote the maximum fps of the video -+ * @SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA: Each color has been scaled by the alpha -+ * value. -+ * -+ * Extra video flags -+ */ -+enum spa_video_flags { -+ SPA_VIDEO_FLAG_NONE = 0, -+ SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0), -+ SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1) -+}; -+ -+/** -+ * spa_video_interlace_mode: -+ * @SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE: all frames are progressive -+ * @SPA_VIDEO_INTERLACE_MODE_INTERLEAVED: 2 fields are interleaved in one video -+ * frame. Extra buffer flags describe the field order. -+ * @SPA_VIDEO_INTERLACE_MODE_MIXED: frames contains both interlaced and -+ * progressive video, the buffer flags describe the frame and fields. -+ * @SPA_VIDEO_INTERLACE_MODE_FIELDS: 2 fields are stored in one buffer, use the -+ * frame ID to get access to the required field. For multiview (the -+ * 'views' property > 1) the fields of view N can be found at frame ID -+ * (N * 2) and (N * 2) + 1. -+ * Each field has only half the amount of lines as noted in the -+ * height property. This mode requires multiple spa_data -+ * to describe the fields. -+ * -+ * The possible values of the #spa_video_interlace_mode describing the interlace -+ * mode of the stream. -+ */ -+enum spa_video_interlace_mode { -+ SPA_VIDEO_INTERLACE_MODE_PROGRESSIVE = 0, -+ SPA_VIDEO_INTERLACE_MODE_INTERLEAVED, -+ SPA_VIDEO_INTERLACE_MODE_MIXED, -+ SPA_VIDEO_INTERLACE_MODE_FIELDS -+}; -+ -+/** -+ * spa_video_info_raw: -+ * @format: the format -+ * @modifier: format modifier -+ * @size: the frame size of the video -+ * @framerate: the framerate of the video 0/1 means variable rate -+ * @max_framerate: the maximum framerate of the video. This is only valid when -+ * @framerate is 0/1 -+ * @views: the number of views in this video -+ * @interlace_mode: the interlace mode -+ * @pixel_aspect_ratio: The pixel aspect ratio -+ * @multiview_mode: multiview mode -+ * @multiview_flags: multiview flags -+ * @chroma_site: the chroma siting -+ * @color_range: the color range. This is the valid range for the samples. -+ * It is used to convert the samples to Y'PbPr values. -+ * @color_matrix: the color matrix. Used to convert between Y'PbPr and -+ * non-linear RGB (R'G'B') -+ * @transfer_function: the transfer function. used to convert between R'G'B' and RGB -+ * @color_primaries: color primaries. used to convert between R'G'B' and CIE XYZ -+ */ -+struct spa_video_info_raw { -+ enum spa_video_format format; -+ int64_t modifier; -+ struct spa_rectangle size; -+ struct spa_fraction framerate; -+ struct spa_fraction max_framerate; -+ uint32_t views; -+ enum spa_video_interlace_mode interlace_mode; -+ struct spa_fraction pixel_aspect_ratio; -+ enum spa_video_multiview_mode multiview_mode; -+ enum spa_video_multiview_flags multiview_flags; -+ enum spa_video_chroma_site chroma_site; -+ enum spa_video_color_range color_range; -+ enum spa_video_color_matrix color_matrix; -+ enum spa_video_transfer_function transfer_function; -+ enum spa_video_color_primaries color_primaries; -+}; -+ -+#define SPA_VIDEO_INFO_RAW_INIT(...) (struct spa_video_info_raw) { __VA_ARGS__ } -+ -+struct spa_video_info_dsp { -+ enum spa_video_format format; -+ int64_t modifier; -+}; -+ -+#define SPA_VIDEO_INFO_DSP_INIT(...) (struct spa_video_info_dsp) { __VA_ARGS__ } -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_RAW_H */ -diff --git a/third_party/pipewire/spa/param/video/type-info.h b/third_party/pipewire/spa/param/video/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/param/video/type-info.h -@@ -0,0 +1,124 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_VIDEO_TYPES_H -+#define SPA_VIDEO_TYPES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INFO_VideoFormat SPA_TYPE_INFO_ENUM_BASE "VideoFormat" -+#define SPA_TYPE_INFO_VIDEO_FORMAT_BASE SPA_TYPE_INFO_VideoFormat ":" -+ -+static const struct spa_type_info spa_type_video_format[] = { -+ { SPA_VIDEO_FORMAT_ENCODED, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "encoded", NULL }, -+ { SPA_VIDEO_FORMAT_I420, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420", NULL }, -+ { SPA_VIDEO_FORMAT_YV12, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YV12", NULL }, -+ { SPA_VIDEO_FORMAT_YUY2, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUY2", NULL }, -+ { SPA_VIDEO_FORMAT_UYVY, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UYVY", NULL }, -+ { SPA_VIDEO_FORMAT_AYUV, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "AYUV", NULL }, -+ { SPA_VIDEO_FORMAT_RGBx, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBx", NULL }, -+ { SPA_VIDEO_FORMAT_BGRx, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGRx", NULL }, -+ { SPA_VIDEO_FORMAT_xRGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "xRGB", NULL }, -+ { SPA_VIDEO_FORMAT_xBGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "xBGR", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA", NULL }, -+ { SPA_VIDEO_FORMAT_BGRA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGRA", NULL }, -+ { SPA_VIDEO_FORMAT_ARGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ARGB", NULL }, -+ { SPA_VIDEO_FORMAT_ABGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ABGR", NULL }, -+ { SPA_VIDEO_FORMAT_RGB, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB", NULL }, -+ { SPA_VIDEO_FORMAT_BGR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR", NULL }, -+ { SPA_VIDEO_FORMAT_Y41B, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y41B", NULL }, -+ { SPA_VIDEO_FORMAT_Y42B, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y42B", NULL }, -+ { SPA_VIDEO_FORMAT_YVYU, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YVYU", NULL }, -+ { SPA_VIDEO_FORMAT_Y444, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444", NULL }, -+ { SPA_VIDEO_FORMAT_v210, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v210", NULL }, -+ { SPA_VIDEO_FORMAT_v216, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v216", NULL }, -+ { SPA_VIDEO_FORMAT_NV12, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV12", NULL }, -+ { SPA_VIDEO_FORMAT_NV21, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV21", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY8, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY8", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY16_BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY16_BE", NULL }, -+ { SPA_VIDEO_FORMAT_GRAY16_LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GRAY16_LE", NULL }, -+ { SPA_VIDEO_FORMAT_v308, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "v308", NULL }, -+ { SPA_VIDEO_FORMAT_RGB16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB16", NULL }, -+ { SPA_VIDEO_FORMAT_BGR16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR16", NULL }, -+ { SPA_VIDEO_FORMAT_RGB15, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB15", NULL }, -+ { SPA_VIDEO_FORMAT_BGR15, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "BGR15", NULL }, -+ { SPA_VIDEO_FORMAT_UYVP, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "UYVP", NULL }, -+ { SPA_VIDEO_FORMAT_A420, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420", NULL }, -+ { SPA_VIDEO_FORMAT_RGB8P, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGB8P", NULL }, -+ { SPA_VIDEO_FORMAT_YUV9, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YUV9", NULL }, -+ { SPA_VIDEO_FORMAT_YVU9, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "YVU9", NULL }, -+ { SPA_VIDEO_FORMAT_IYU1, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "IYU1", NULL }, -+ { SPA_VIDEO_FORMAT_ARGB64, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "ARGB64", NULL }, -+ { SPA_VIDEO_FORMAT_AYUV64, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "AYUV64", NULL }, -+ { SPA_VIDEO_FORMAT_r210, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "r210", NULL }, -+ { SPA_VIDEO_FORMAT_I420_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_NV16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV16", NULL }, -+ { SPA_VIDEO_FORMAT_NV24, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV24", NULL }, -+ { SPA_VIDEO_FORMAT_NV12_64Z32, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV12_64Z32", NULL }, -+ { SPA_VIDEO_FORMAT_A420_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A420_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A420_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_A422_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A422_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A422_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A422_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_A444_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A444_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_A444_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "A444_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_NV61, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "NV61", NULL }, -+ { SPA_VIDEO_FORMAT_P010_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "P010_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_P010_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "P010_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_IYU2, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "IYU2", NULL }, -+ { SPA_VIDEO_FORMAT_VYUY, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "VYUY", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_10BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_10BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_10LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_10LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBR_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBR_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_GBRA_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "GBRA_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_I420_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I420_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_I422_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "I422_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_12BE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_12BE", NULL }, -+ { SPA_VIDEO_FORMAT_Y444_12LE, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "Y444_12LE", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA_F16, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA_F16", NULL }, -+ { SPA_VIDEO_FORMAT_RGBA_F32, SPA_TYPE_Int, SPA_TYPE_INFO_VIDEO_FORMAT_BASE "RGBA_F32", NULL }, -+ { 0, 0, NULL, NULL }, -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_VIDEO_RAW_TYPES_H */ -diff --git a/third_party/pipewire/spa/pod/builder.h b/third_party/pipewire/spa/pod/builder.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/builder.h -@@ -0,0 +1,671 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_BUILDER_H -+#define SPA_POD_BUILDER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+#include -+ -+struct spa_pod_builder_state { -+ uint32_t offset; -+#define SPA_POD_BUILDER_FLAG_BODY (1<<0) -+#define SPA_POD_BUILDER_FLAG_FIRST (1<<1) -+ uint32_t flags; -+ struct spa_pod_frame *frame; -+}; -+ -+struct spa_pod_builder; -+ -+struct spa_pod_builder_callbacks { -+#define SPA_VERSION_POD_BUILDER_CALLBACKS 0 -+ uint32_t version; -+ -+ int (*overflow) (void *data, uint32_t size); -+}; -+ -+struct spa_pod_builder { -+ void *data; -+ uint32_t size; -+ uint32_t _padding; -+ struct spa_pod_builder_state state; -+ struct spa_callbacks callbacks; -+}; -+ -+#define SPA_POD_BUILDER_INIT(buffer,size) (struct spa_pod_builder){ buffer, size, } -+ -+static inline void -+spa_pod_builder_get_state(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) -+{ -+ *state = builder->state; -+} -+ -+static inline void -+spa_pod_builder_set_callbacks(struct spa_pod_builder *builder, -+ const struct spa_pod_builder_callbacks *callbacks, void *data) -+{ -+ builder->callbacks = SPA_CALLBACKS_INIT(callbacks, data); -+} -+ -+static inline void -+spa_pod_builder_reset(struct spa_pod_builder *builder, struct spa_pod_builder_state *state) -+{ -+ struct spa_pod_frame *f; -+ uint32_t size = builder->state.offset - state->offset; -+ builder->state = *state; -+ for (f = builder->state.frame; f ; f = f->parent) -+ f->pod.size -= size; -+} -+ -+static inline void spa_pod_builder_init(struct spa_pod_builder *builder, void *data, uint32_t size) -+{ -+ *builder = SPA_POD_BUILDER_INIT(data, size); -+} -+ -+static inline struct spa_pod * -+spa_pod_builder_deref(struct spa_pod_builder *builder, uint32_t offset) -+{ -+ uint32_t size = builder->size; -+ if (offset + 8 <= size) { -+ struct spa_pod *pod = SPA_MEMBER(builder->data, offset, struct spa_pod); -+ if (offset + SPA_POD_SIZE(pod) <= size) -+ return pod; -+ } -+ return NULL; -+} -+ -+static inline struct spa_pod * -+spa_pod_builder_frame(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ if (frame->offset + SPA_POD_SIZE(&frame->pod) <= builder->size) -+ return SPA_MEMBER(builder->data, frame->offset, struct spa_pod); -+ return NULL; -+} -+ -+static inline void -+spa_pod_builder_push(struct spa_pod_builder *builder, -+ struct spa_pod_frame *frame, -+ const struct spa_pod *pod, -+ uint32_t offset) -+{ -+ frame->pod = *pod; -+ frame->offset = offset; -+ frame->parent = builder->state.frame; -+ frame->flags = builder->state.flags; -+ builder->state.frame = frame; -+ -+ if (frame->pod.type == SPA_TYPE_Array || frame->pod.type == SPA_TYPE_Choice) -+ builder->state.flags = SPA_POD_BUILDER_FLAG_FIRST | SPA_POD_BUILDER_FLAG_BODY; -+} -+ -+static inline int spa_pod_builder_raw(struct spa_pod_builder *builder, const void *data, uint32_t size) -+{ -+ int res = 0; -+ struct spa_pod_frame *f; -+ uint32_t offset = builder->state.offset; -+ -+ if (offset + size > builder->size) { -+ res = -ENOSPC; -+ spa_callbacks_call_res(&builder->callbacks, struct spa_pod_builder_callbacks, res, -+ overflow, 0, offset + size); -+ } -+ if (res == 0 && data) -+ memcpy(SPA_MEMBER(builder->data, offset, void), data, size); -+ -+ builder->state.offset += size; -+ -+ for (f = builder->state.frame; f ; f = f->parent) -+ f->pod.size += size; -+ -+ return res; -+} -+ -+static inline int spa_pod_builder_pad(struct spa_pod_builder *builder, uint32_t size) -+{ -+ uint64_t zeroes = 0; -+ size = SPA_ROUND_UP_N(size, 8) - size; -+ return size ? spa_pod_builder_raw(builder, &zeroes, size) : 0; -+} -+ -+static inline int -+spa_pod_builder_raw_padded(struct spa_pod_builder *builder, const void *data, uint32_t size) -+{ -+ int r, res = spa_pod_builder_raw(builder, data, size); -+ if ((r = spa_pod_builder_pad(builder, size)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline void *spa_pod_builder_pop(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ struct spa_pod *pod; -+ -+ if ((pod = (struct spa_pod*)spa_pod_builder_frame(builder, frame)) != NULL) -+ *pod = frame->pod; -+ -+ builder->state.frame = frame->parent; -+ builder->state.flags = frame->flags; -+ spa_pod_builder_pad(builder, builder->state.offset); -+ return pod; -+} -+ -+static inline int -+spa_pod_builder_primitive(struct spa_pod_builder *builder, const struct spa_pod *p) -+{ -+ const void *data; -+ uint32_t size; -+ int r, res; -+ -+ if (builder->state.flags == SPA_POD_BUILDER_FLAG_BODY) { -+ data = SPA_POD_BODY_CONST(p); -+ size = SPA_POD_BODY_SIZE(p); -+ } else { -+ data = p; -+ size = SPA_POD_SIZE(p); -+ SPA_FLAG_CLEAR(builder->state.flags, SPA_POD_BUILDER_FLAG_FIRST); -+ } -+ res = spa_pod_builder_raw(builder, data, size); -+ if (builder->state.flags != SPA_POD_BUILDER_FLAG_BODY) -+ if ((r = spa_pod_builder_pad(builder, size)) < 0) -+ res = r; -+ return res; -+} -+ -+#define SPA_POD_INIT(size,type) (struct spa_pod) { size, type } -+ -+#define SPA_POD_INIT_None() SPA_POD_INIT(0, SPA_TYPE_None) -+ -+static inline int spa_pod_builder_none(struct spa_pod_builder *builder) -+{ -+ const struct spa_pod p = SPA_POD_INIT_None(); -+ return spa_pod_builder_primitive(builder, &p); -+} -+ -+#define SPA_POD_INIT_Bool(val) (struct spa_pod_bool){ { sizeof(uint32_t), SPA_TYPE_Bool }, val ? 1 : 0, 0 } -+ -+static inline int spa_pod_builder_bool(struct spa_pod_builder *builder, bool val) -+{ -+ const struct spa_pod_bool p = SPA_POD_INIT_Bool(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Id(val) (struct spa_pod_id){ { sizeof(uint32_t), SPA_TYPE_Id }, (uint32_t)val, 0 } -+ -+static inline int spa_pod_builder_id(struct spa_pod_builder *builder, uint32_t val) -+{ -+ const struct spa_pod_id p = SPA_POD_INIT_Id(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Int(val) (struct spa_pod_int){ { sizeof(int32_t), SPA_TYPE_Int }, (int32_t)val, 0 } -+ -+static inline int spa_pod_builder_int(struct spa_pod_builder *builder, int32_t val) -+{ -+ const struct spa_pod_int p = SPA_POD_INIT_Int(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Long(val) (struct spa_pod_long){ { sizeof(int64_t), SPA_TYPE_Long }, (int64_t)val } -+ -+static inline int spa_pod_builder_long(struct spa_pod_builder *builder, int64_t val) -+{ -+ const struct spa_pod_long p = SPA_POD_INIT_Long(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Float(val) (struct spa_pod_float){ { sizeof(float), SPA_TYPE_Float }, val } -+ -+static inline int spa_pod_builder_float(struct spa_pod_builder *builder, float val) -+{ -+ const struct spa_pod_float p = SPA_POD_INIT_Float(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Double(val) (struct spa_pod_double){ { sizeof(double), SPA_TYPE_Double }, val } -+ -+static inline int spa_pod_builder_double(struct spa_pod_builder *builder, double val) -+{ -+ const struct spa_pod_double p = SPA_POD_INIT_Double(val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_String(len) (struct spa_pod_string){ { len, SPA_TYPE_String } } -+ -+static inline int -+spa_pod_builder_write_string(struct spa_pod_builder *builder, const char *str, uint32_t len) -+{ -+ int r, res; -+ res = spa_pod_builder_raw(builder, str, len); -+ if ((r = spa_pod_builder_raw(builder, "", 1)) < 0) -+ res = r; -+ if ((r = spa_pod_builder_pad(builder, builder->state.offset)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline int -+spa_pod_builder_string_len(struct spa_pod_builder *builder, const char *str, uint32_t len) -+{ -+ const struct spa_pod_string p = SPA_POD_INIT_String(len+1); -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_write_string(builder, str, len)) < 0) -+ res = r; -+ return res; -+} -+ -+static inline int spa_pod_builder_string(struct spa_pod_builder *builder, const char *str) -+{ -+ uint32_t len = str ? strlen(str) : 0; -+ return spa_pod_builder_string_len(builder, str ? str : "", len); -+} -+ -+#define SPA_POD_INIT_Bytes(len) (struct spa_pod_bytes){ { len, SPA_TYPE_Bytes } } -+ -+static inline int -+spa_pod_builder_bytes(struct spa_pod_builder *builder, const void *bytes, uint32_t len) -+{ -+ const struct spa_pod_bytes p = SPA_POD_INIT_Bytes(len); -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_raw_padded(builder, bytes, len)) < 0) -+ res = r; -+ return res; -+} -+static inline void * -+spa_pod_builder_reserve_bytes(struct spa_pod_builder *builder, uint32_t len) -+{ -+ uint32_t offset = builder->state.offset; -+ if (spa_pod_builder_bytes(builder, NULL, len) < 0) -+ return NULL; -+ return SPA_POD_BODY(spa_pod_builder_deref(builder, offset)); -+} -+ -+#define SPA_POD_INIT_Pointer(type,value) (struct spa_pod_pointer){ { sizeof(struct spa_pod_pointer_body), SPA_TYPE_Pointer }, { type, 0, value } } -+ -+static inline int -+spa_pod_builder_pointer(struct spa_pod_builder *builder, uint32_t type, const void *val) -+{ -+ const struct spa_pod_pointer p = SPA_POD_INIT_Pointer(type, val); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Fd(fd) (struct spa_pod_fd){ { sizeof(int64_t), SPA_TYPE_Fd }, fd } -+ -+static inline int spa_pod_builder_fd(struct spa_pod_builder *builder, int64_t fd) -+{ -+ const struct spa_pod_fd p = SPA_POD_INIT_Fd(fd); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Rectangle(val) (struct spa_pod_rectangle){ { sizeof(struct spa_rectangle), SPA_TYPE_Rectangle }, val } -+ -+static inline int -+spa_pod_builder_rectangle(struct spa_pod_builder *builder, uint32_t width, uint32_t height) -+{ -+ const struct spa_pod_rectangle p = SPA_POD_INIT_Rectangle(SPA_RECTANGLE(width, height)); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+#define SPA_POD_INIT_Fraction(val) (struct spa_pod_fraction){ { sizeof(struct spa_fraction), SPA_TYPE_Fraction }, val } -+ -+static inline int -+spa_pod_builder_fraction(struct spa_pod_builder *builder, uint32_t num, uint32_t denom) -+{ -+ const struct spa_pod_fraction p = SPA_POD_INIT_Fraction(SPA_FRACTION(num, denom)); -+ return spa_pod_builder_primitive(builder, &p.pod); -+} -+ -+static inline int -+spa_pod_builder_push_array(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ const struct spa_pod_array p = -+ { {sizeof(struct spa_pod_array_body) - sizeof(struct spa_pod), SPA_TYPE_Array}, -+ {{0, 0}} }; -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+static inline int -+spa_pod_builder_array(struct spa_pod_builder *builder, -+ uint32_t child_size, uint32_t child_type, uint32_t n_elems, const void *elems) -+{ -+ const struct spa_pod_array p = { -+ {(uint32_t)(sizeof(struct spa_pod_array_body) + n_elems * child_size), SPA_TYPE_Array}, -+ {{child_size, child_type}} -+ }; -+ int r, res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ if ((r = spa_pod_builder_raw_padded(builder, elems, child_size * n_elems)) < 0) -+ res = r; -+ return res; -+} -+ -+#define SPA_POD_INIT_CHOICE_BODY(type, flags, child_size, child_type) \ -+ (struct spa_pod_choice_body) { type, flags, { child_size, child_type }} -+ -+#define SPA_POD_INIT_Choice(type, ctype, child_type, n_vals, ...) \ -+ (struct { struct spa_pod_choice choice; ctype vals[n_vals];}) \ -+ { { { n_vals * sizeof(ctype) + sizeof(struct spa_pod_choice_body), SPA_TYPE_Choice }, \ -+ { type, 0, { sizeof(ctype), child_type } } }, { __VA_ARGS__ } } -+ -+static inline int -+spa_pod_builder_push_choice(struct spa_pod_builder *builder, struct spa_pod_frame *frame, -+ uint32_t type, uint32_t flags) -+{ -+ const struct spa_pod_choice p = -+ { {sizeof(struct spa_pod_choice_body) - sizeof(struct spa_pod), SPA_TYPE_Choice}, -+ { type, flags, {0, 0}} }; -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p) - sizeof(struct spa_pod)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Struct(size) (struct spa_pod_struct){ { size, SPA_TYPE_Struct } } -+ -+static inline int -+spa_pod_builder_push_struct(struct spa_pod_builder *builder, struct spa_pod_frame *frame) -+{ -+ const struct spa_pod_struct p = SPA_POD_INIT_Struct(0); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Object(size,type,id,...) (struct spa_pod_object){ { size, SPA_TYPE_Object }, { type, id }, ##__VA_ARGS__ } -+ -+static inline int -+spa_pod_builder_push_object(struct spa_pod_builder *builder, struct spa_pod_frame *frame, -+ uint32_t type, uint32_t id) -+{ -+ const struct spa_pod_object p = -+ SPA_POD_INIT_Object(sizeof(struct spa_pod_object_body), type, id); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+#define SPA_POD_INIT_Prop(key,flags,size,type) \ -+ (struct spa_pod_prop){ key, flags, { size, type } } -+ -+static inline int -+spa_pod_builder_prop(struct spa_pod_builder *builder, uint32_t key, uint32_t flags) -+{ -+ const struct { uint32_t key; uint32_t flags; } p = { key, flags }; -+ return spa_pod_builder_raw(builder, &p, sizeof(p)); -+} -+ -+#define SPA_POD_INIT_Sequence(size,unit) \ -+ (struct spa_pod_sequence){ { size, SPA_TYPE_Sequence}, {unit, 0 } } -+ -+static inline int -+spa_pod_builder_push_sequence(struct spa_pod_builder *builder, struct spa_pod_frame *frame, uint32_t unit) -+{ -+ const struct spa_pod_sequence p = -+ SPA_POD_INIT_Sequence(sizeof(struct spa_pod_sequence_body), unit); -+ uint32_t offset = builder->state.offset; -+ int res = spa_pod_builder_raw(builder, &p, sizeof(p)); -+ spa_pod_builder_push(builder, frame, &p.pod, offset); -+ return res; -+} -+ -+static inline uint32_t -+spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) -+{ -+ const struct { uint32_t offset; uint32_t type; } p = { offset, type }; -+ return spa_pod_builder_raw(builder, &p, sizeof(p)); -+} -+ -+static inline uint32_t spa_choice_from_id(char id) -+{ -+ switch (id) { -+ case 'r': -+ return SPA_CHOICE_Range; -+ case 's': -+ return SPA_CHOICE_Step; -+ case 'e': -+ return SPA_CHOICE_Enum; -+ case 'f': -+ return SPA_CHOICE_Flags; -+ case 'n': -+ default: -+ return SPA_CHOICE_None; -+ } -+} -+ -+#define SPA_POD_BUILDER_COLLECT(builder,type,args) \ -+do { \ -+ switch (type) { \ -+ case 'b': \ -+ spa_pod_builder_bool(builder, !!va_arg(args, int)); \ -+ break; \ -+ case 'I': \ -+ spa_pod_builder_id(builder, va_arg(args, uint32_t)); \ -+ break; \ -+ case 'i': \ -+ spa_pod_builder_int(builder, va_arg(args, int)); \ -+ break; \ -+ case 'l': \ -+ spa_pod_builder_long(builder, va_arg(args, int64_t)); \ -+ break; \ -+ case 'f': \ -+ spa_pod_builder_float(builder, va_arg(args, double)); \ -+ break; \ -+ case 'd': \ -+ spa_pod_builder_double(builder, va_arg(args, double)); \ -+ break; \ -+ case 's': \ -+ { \ -+ char *strval = va_arg(args, char *); \ -+ if (strval != NULL) { \ -+ size_t len = strlen(strval); \ -+ spa_pod_builder_string_len(builder, strval, len); \ -+ } \ -+ else \ -+ spa_pod_builder_none(builder); \ -+ break; \ -+ } \ -+ case 'S': \ -+ { \ -+ char *strval = va_arg(args, char *); \ -+ size_t len = va_arg(args, int); \ -+ spa_pod_builder_string_len(builder, strval, len); \ -+ break; \ -+ } \ -+ case 'y': \ -+ { \ -+ void *ptr = va_arg(args, void *); \ -+ int len = va_arg(args, int); \ -+ spa_pod_builder_bytes(builder, ptr, len); \ -+ break; \ -+ } \ -+ case 'R': \ -+ { \ -+ struct spa_rectangle *rectval = \ -+ va_arg(args, struct spa_rectangle *); \ -+ spa_pod_builder_rectangle(builder, \ -+ rectval->width, rectval->height); \ -+ break; \ -+ } \ -+ case 'F': \ -+ { \ -+ struct spa_fraction *fracval = \ -+ va_arg(args, struct spa_fraction *); \ -+ spa_pod_builder_fraction(builder, fracval->num, fracval->denom);\ -+ break; \ -+ } \ -+ case 'a': \ -+ { \ -+ int child_size = va_arg(args, int); \ -+ int child_type = va_arg(args, int); \ -+ int n_elems = va_arg(args, int); \ -+ void *elems = va_arg(args, void *); \ -+ spa_pod_builder_array(builder, child_size, \ -+ child_type, n_elems, elems); \ -+ break; \ -+ } \ -+ case 'p': \ -+ { \ -+ int t = va_arg(args, uint32_t); \ -+ spa_pod_builder_pointer(builder, t, va_arg(args, void *)); \ -+ break; \ -+ } \ -+ case 'h': \ -+ spa_pod_builder_fd(builder, va_arg(args, int)); \ -+ break; \ -+ case 'P': \ -+ case 'O': \ -+ case 'T': \ -+ case 'V': \ -+ { \ -+ struct spa_pod *pod = va_arg(args, struct spa_pod *); \ -+ if (pod == NULL) \ -+ spa_pod_builder_none(builder); \ -+ else \ -+ spa_pod_builder_primitive(builder, pod); \ -+ break; \ -+ } \ -+ } \ -+} while(false) -+ -+static inline int -+spa_pod_builder_addv(struct spa_pod_builder *builder, va_list args) -+{ -+ int res = 0; -+ struct spa_pod_frame *f = builder->state.frame; -+ uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_None; -+ -+ do { -+ const char *format; -+ int n_values = 1; -+ struct spa_pod_frame f; -+ bool choice; -+ -+ switch (ftype) { -+ case SPA_TYPE_Object: -+ { -+ uint32_t key = va_arg(args, uint32_t); -+ if (key == 0) -+ goto exit; -+ spa_pod_builder_prop(builder, key, 0); -+ break; -+ } -+ case SPA_TYPE_Sequence: -+ { -+ uint32_t offset = va_arg(args, uint32_t); -+ uint32_t type = va_arg(args, uint32_t); -+ if (type == 0) -+ goto exit; -+ spa_pod_builder_control(builder, offset, type); -+ } -+ default: -+ break; -+ } -+ if ((format = va_arg(args, const char *)) == NULL) -+ break; -+ -+ choice = *format == '?'; -+ if (choice) { -+ uint32_t type = spa_choice_from_id(*++format); -+ if (*format != '\0') -+ format++; -+ -+ spa_pod_builder_push_choice(builder, &f, type, 0); -+ -+ n_values = va_arg(args, int); -+ } -+ while (n_values-- > 0) -+ SPA_POD_BUILDER_COLLECT(builder, *format, args); -+ -+ if (choice) -+ spa_pod_builder_pop(builder, &f); -+ } while (true); -+ -+ exit: -+ return res; -+} -+ -+static inline int spa_pod_builder_add(struct spa_pod_builder *builder, ...) -+{ -+ int res; -+ va_list args; -+ -+ va_start(args, builder); -+ res = spa_pod_builder_addv(builder, args); -+ va_end(args); -+ -+ return res; -+} -+ -+#define spa_pod_builder_add_object(b,type,id,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_object(b, &_f, type, id); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, 0); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+#define spa_pod_builder_add_struct(b,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_struct(b, &_f); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, NULL); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+#define spa_pod_builder_add_sequence(b,unit,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ spa_pod_builder_push_sequence(b, &_f, unit); \ -+ spa_pod_builder_add(b, ##__VA_ARGS__, 0, 0); \ -+ spa_pod_builder_pop(b, &_f); \ -+}) -+ -+/** Copy a pod structure */ -+static inline struct spa_pod * -+spa_pod_copy(const struct spa_pod *pod) -+{ -+ size_t size; -+ struct spa_pod *c; -+ -+ size = SPA_POD_SIZE(pod); -+ if ((c = (struct spa_pod *) malloc(size)) == NULL) -+ return NULL; -+ return (struct spa_pod *) memcpy(c, pod, size); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_BUILDER_H */ -diff --git a/third_party/pipewire/spa/pod/command.h b/third_party/pipewire/spa/pod/command.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/command.h -@@ -0,0 +1,61 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_COMMAND_H -+#define SPA_COMMAND_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_command_body { -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_command { -+ struct spa_pod pod; -+ struct spa_command_body body; -+}; -+ -+#define SPA_COMMAND_TYPE(cmd) ((cmd)->body.body.type) -+#define SPA_COMMAND_ID(cmd,type) (SPA_COMMAND_TYPE(cmd) == type ? \ -+ (cmd)->body.body.id : SPA_ID_INVALID) -+ -+#define SPA_COMMAND_INIT_FULL(t,size,type,id,...) (t) \ -+ { { size, SPA_TYPE_Object }, \ -+ { { type, id }, ##__VA_ARGS__ } } \ -+ -+#define SPA_COMMAND_INIT(type,id) \ -+ SPA_COMMAND_INIT_FULL(struct spa_command, \ -+ sizeof(struct spa_command_body), type, id) -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_COMMAND_H */ -diff --git a/third_party/pipewire/spa/pod/compare.h b/third_party/pipewire/spa/pod/compare.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/compare.h -@@ -0,0 +1,181 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_COMPARE_H -+#define SPA_POD_COMPARE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+ -+static inline int spa_pod_compare_value(uint32_t type, const void *r1, const void *r2, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_None: -+ return 0; -+ case SPA_TYPE_Bool: -+ case SPA_TYPE_Id: -+ return *(uint32_t *) r1 == *(uint32_t *) r2 ? 0 : 1; -+ case SPA_TYPE_Int: -+ return *(int32_t *) r1 - *(int32_t *) r2; -+ case SPA_TYPE_Long: -+ return *(int64_t *) r1 - *(int64_t *) r2; -+ case SPA_TYPE_Float: -+ return *(float *) r1 - *(float *) r2; -+ case SPA_TYPE_Double: -+ return *(double *) r1 - *(double *) r2; -+ case SPA_TYPE_String: -+ return strcmp((char *)r1, (char *)r2); -+ case SPA_TYPE_Bytes: -+ return memcmp((char *)r1, (char *)r2, size); -+ case SPA_TYPE_Rectangle: -+ { -+ const struct spa_rectangle *rec1 = (struct spa_rectangle *) r1, -+ *rec2 = (struct spa_rectangle *) r2; -+ if (rec1->width == rec2->width && rec1->height == rec2->height) -+ return 0; -+ else if (rec1->width < rec2->width || rec1->height < rec2->height) -+ return -1; -+ else -+ return 1; -+ } -+ case SPA_TYPE_Fraction: -+ { -+ const struct spa_fraction *f1 = (struct spa_fraction *) r1, -+ *f2 = (struct spa_fraction *) r2; -+ int64_t n1, n2; -+ n1 = ((int64_t) f1->num) * f2->denom; -+ n2 = ((int64_t) f2->num) * f1->denom; -+ if (n1 < n2) -+ return -1; -+ else if (n1 > n2) -+ return 1; -+ else -+ return 0; -+ } -+ default: -+ break; -+ } -+ return 0; -+} -+ -+static inline int spa_pod_compare(const struct spa_pod *pod1, -+ const struct spa_pod *pod2) -+{ -+ int res = 0; -+ uint32_t n_vals1, n_vals2; -+ uint32_t choice1, choice2; -+ -+ spa_return_val_if_fail(pod1 != NULL, -EINVAL); -+ spa_return_val_if_fail(pod2 != NULL, -EINVAL); -+ -+ pod1 = spa_pod_get_values(pod1, &n_vals1, &choice1); -+ pod2 = spa_pod_get_values(pod2, &n_vals2, &choice2); -+ -+ if (n_vals1 != n_vals2) -+ return -EINVAL; -+ -+ if (SPA_POD_TYPE(pod1) != SPA_POD_TYPE(pod2)) -+ return -EINVAL; -+ -+ switch (SPA_POD_TYPE(pod1)) { -+ case SPA_TYPE_Struct: -+ { -+ const struct spa_pod *p1, *p2; -+ size_t p1s, p2s; -+ -+ p1 = (const struct spa_pod*)SPA_POD_BODY_CONST(pod1); -+ p1s = SPA_POD_BODY_SIZE(pod1); -+ p2 = (const struct spa_pod*)SPA_POD_BODY_CONST(pod2); -+ p2s = SPA_POD_BODY_SIZE(pod2); -+ -+ while (true) { -+ if (!spa_pod_is_inside(pod1, p1s, p1) || -+ !spa_pod_is_inside(pod2, p2s, p2)) -+ return -EINVAL; -+ -+ if ((res = spa_pod_compare(p1, p2)) != 0) -+ return res; -+ -+ p1 = (const struct spa_pod*)spa_pod_next(p1); -+ p2 = (const struct spa_pod*)spa_pod_next(p2); -+ } -+ break; -+ } -+ case SPA_TYPE_Object: -+ { -+ const struct spa_pod_prop *p1, *p2; -+ const struct spa_pod_object *o1, *o2; -+ -+ o1 = (const struct spa_pod_object*)pod1; -+ o2 = (const struct spa_pod_object*)pod2; -+ -+ p2 = NULL; -+ SPA_POD_OBJECT_FOREACH(o1, p1) { -+ if ((p2 = spa_pod_object_find_prop(o2, p2, p1->key)) == NULL) -+ return 1; -+ if ((res = spa_pod_compare(&p1->value, &p2->value)) != 0) -+ return res; -+ } -+ p1 = NULL; -+ SPA_POD_OBJECT_FOREACH(o2, p2) { -+ if ((p1 = spa_pod_object_find_prop(o1, p1, p2->key)) == NULL) -+ return -1; -+ } -+ break; -+ } -+ case SPA_TYPE_Array: -+ { -+ if (SPA_POD_BODY_SIZE(pod1) != SPA_POD_BODY_SIZE(pod2)) -+ return -EINVAL; -+ res = memcmp(SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), SPA_POD_BODY_SIZE(pod2)); -+ break; -+ } -+ default: -+ if (SPA_POD_BODY_SIZE(pod1) != SPA_POD_BODY_SIZE(pod2)) -+ return -EINVAL; -+ res = spa_pod_compare_value(SPA_POD_TYPE(pod1), -+ SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), -+ SPA_POD_BODY_SIZE(pod1)); -+ break; -+ } -+ return res; -+} -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif -diff --git a/third_party/pipewire/spa/pod/event.h b/third_party/pipewire/spa/pod/event.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/event.h -@@ -0,0 +1,59 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_EVENT_H -+#define SPA_EVENT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+struct spa_event_body { -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_event { -+ struct spa_pod pod; -+ struct spa_event_body body; -+}; -+ -+#define SPA_EVENT_TYPE(ev) ((ev)->body.body.type) -+#define SPA_EVENT_ID(ev,type) (SPA_EVENT_TYPE(ev) == type ? \ -+ (ev)->body.body.id : SPA_ID_INVALID) -+ -+#define SPA_EVENT_INIT_FULL(t,size,type,id,...) (t) \ -+ { { size, SPA_TYPE_OBJECT }, \ -+ { { type, id }, ##__VA_ARGS__ } } \ -+ -+#define SPA_EVENT_INIT(type,id) \ -+ SPA_EVENT_INIT_FULL(struct spa_event, \ -+ sizeof(struct spa_event_body), type, id) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_EVENT_H */ -diff --git a/third_party/pipewire/spa/pod/filter.h b/third_party/pipewire/spa/pod/filter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/filter.h -@@ -0,0 +1,395 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#include -+#include -+#include -+#include -+#include -+ -+#include -+#include -+#include -+#include -+ -+static inline int spa_pod_choice_fix_default(struct spa_pod_choice *choice) -+{ -+ void *val, *alt; -+ int i, nvals; -+ uint32_t type, size; -+ -+ nvals = SPA_POD_CHOICE_N_VALUES(choice); -+ type = SPA_POD_CHOICE_VALUE_TYPE(choice); -+ size = SPA_POD_CHOICE_VALUE_SIZE(choice); -+ alt = val = SPA_POD_CHOICE_VALUES(choice); -+ -+ switch (choice->body.type) { -+ case SPA_CHOICE_None: -+ break; -+ case SPA_CHOICE_Range: -+ case SPA_CHOICE_Step: -+ if (nvals > 1) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) < 0) -+ memcpy(val, alt, size); -+ } -+ if (nvals > 2) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) > 0) -+ memcpy(val, alt, size); -+ } -+ break; -+ case SPA_CHOICE_Flags: -+ case SPA_CHOICE_Enum: -+ { -+ void *best = NULL; -+ -+ for (i = 1; i < nvals; i++) { -+ alt = SPA_MEMBER(alt, size, void); -+ if (spa_pod_compare_value(type, val, alt, size) == 0) { -+ best = alt; -+ break; -+ } -+ if (best == NULL) -+ best = alt; -+ } -+ if (best) -+ memcpy(val, best, size); -+ -+ if (nvals <= 1) -+ choice->body.type = SPA_CHOICE_None; -+ break; -+ } -+ } -+ return 0; -+} -+ -+static inline int spa_pod_filter_flags_value(struct spa_pod_builder *b, -+ uint32_t type, const void *r1, const void *r2, uint32_t size) -+{ -+ switch (type) { -+ case SPA_TYPE_Int: -+ { -+ int32_t val = (*(int32_t *) r1) & (*(int32_t *) r2); -+ if (val == 0) -+ return 0; -+ spa_pod_builder_int(b, val); -+ break; -+ } -+ case SPA_TYPE_Long: -+ { -+ int64_t val = (*(int64_t *) r1) & (*(int64_t *) r2); -+ if (val == 0) -+ return 0; -+ spa_pod_builder_long(b, val); -+ break; -+ } -+ default: -+ return -ENOTSUP; -+ } -+ return 1; -+} -+ -+ -+static inline int -+spa_pod_filter_prop(struct spa_pod_builder *b, -+ const struct spa_pod_prop *p1, -+ const struct spa_pod_prop *p2) -+{ -+ const struct spa_pod *v1, *v2; -+ struct spa_pod_choice *nc; -+ uint32_t j, k, nalt1, nalt2; -+ void *alt1, *alt2, *a1, *a2; -+ uint32_t type, size, p1c, p2c; -+ struct spa_pod_frame f; -+ -+ v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c); -+ alt1 = SPA_POD_BODY(v1); -+ v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); -+ alt2 = SPA_POD_BODY(v2); -+ -+ type = v1->type; -+ size = v1->size; -+ -+ /* incompatible property types */ -+ if (type != v2->type || size != v2->size || p1->key != p2->key) -+ return -EINVAL; -+ -+ if (p1c == SPA_CHOICE_None || p1c == SPA_CHOICE_Flags) { -+ nalt1 = 1; -+ } else { -+ alt1 = SPA_MEMBER(alt1, size, void); -+ nalt1--; -+ } -+ -+ if (p2c == SPA_CHOICE_None || p2c == SPA_CHOICE_Flags) { -+ nalt2 = 1; -+ } else { -+ alt2 = SPA_MEMBER(alt2, size, void); -+ nalt2--; -+ } -+ -+ /* start with copying the property */ -+ spa_pod_builder_prop(b, p1->key, 0); -+ spa_pod_builder_push_choice(b, &f, 0, 0); -+ nc = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f); -+ -+ /* default value */ -+ spa_pod_builder_primitive(b, v1); -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Enum) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Enum)) { -+ int n_copied = 0; -+ /* copy all equal values but don't copy the default value again */ -+ for (j = 0, a1 = alt1; j < nalt1; j++, a1 = SPA_MEMBER(a1, size, void)) { -+ for (k = 0, a2 = alt2; k < nalt2; k++, a2 = SPA_MEMBER(a2,size,void)) { -+ if (spa_pod_compare_value(type, a1, a2, size) == 0) { -+ if (p1c == SPA_CHOICE_Enum || j > 0) -+ spa_pod_builder_raw(b, a1, size); -+ n_copied++; -+ } -+ } -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Range)) { -+ int n_copied = 0; -+ /* copy all values inside the range */ -+ for (j = 0, a1 = alt1, a2 = alt2; j < nalt1; j++, a1 = SPA_MEMBER(a1,size,void)) { -+ if (spa_pod_compare_value(type, a1, a2, size) < 0) -+ continue; -+ if (spa_pod_compare_value(type, a1, SPA_MEMBER(a2,size,void), size) > 0) -+ continue; -+ spa_pod_builder_raw(b, a1, size); -+ n_copied++; -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Step) || -+ (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Step)) { -+ return -ENOTSUP; -+ } -+ -+ if ((p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Enum)) { -+ int n_copied = 0; -+ /* copy all values inside the range */ -+ for (k = 0, a1 = alt1, a2 = alt2; k < nalt2; k++, a2 = SPA_MEMBER(a2,size,void)) { -+ if (spa_pod_compare_value(type, a2, a1, size) < 0) -+ continue; -+ if (spa_pod_compare_value(type, a2, SPA_MEMBER(a1,size,void), size) > 0) -+ continue; -+ spa_pod_builder_raw(b, a2, size); -+ n_copied++; -+ } -+ if (n_copied == 0) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Enum; -+ } -+ -+ if ((p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Step) || -+ (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Range) || -+ (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Step)) { -+ if (spa_pod_compare_value(type, alt1, alt2, size) < 0) -+ spa_pod_builder_raw(b, alt2, size); -+ else -+ spa_pod_builder_raw(b, alt1, size); -+ -+ alt1 = SPA_MEMBER(alt1,size,void); -+ alt2 = SPA_MEMBER(alt2,size,void); -+ -+ if (spa_pod_compare_value(type, alt1, alt2, size) < 0) -+ spa_pod_builder_raw(b, alt1, size); -+ else -+ spa_pod_builder_raw(b, alt2, size); -+ -+ nc->body.type = SPA_CHOICE_Range; -+ } -+ -+ if ((p1c == SPA_CHOICE_None && p2c == SPA_CHOICE_Flags) || -+ (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_None) || -+ (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Flags)) { -+ if (spa_pod_filter_flags_value(b, type, alt1, alt2, size) != 1) -+ return -EINVAL; -+ nc->body.type = SPA_CHOICE_Flags; -+ } -+ -+ if (p1c == SPA_CHOICE_Range && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Enum && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_None) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Enum) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Step && p2c == SPA_CHOICE_Flags) -+ return -ENOTSUP; -+ -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Range) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Step) -+ return -ENOTSUP; -+ if (p1c == SPA_CHOICE_Flags && p2c == SPA_CHOICE_Enum) -+ return -ENOTSUP; -+ -+ spa_pod_builder_pop(b, &f); -+ spa_pod_choice_fix_default(nc); -+ -+ return 0; -+} -+ -+static inline int spa_pod_filter_part(struct spa_pod_builder *b, -+ const struct spa_pod *pod, uint32_t pod_size, -+ const struct spa_pod *filter, uint32_t filter_size) -+{ -+ const struct spa_pod *pp, *pf; -+ int res = 0; -+ -+ pf = filter; -+ -+ SPA_POD_FOREACH(pod, pod_size, pp) { -+ bool do_copy = false, do_advance = false; -+ uint32_t filter_offset = 0; -+ struct spa_pod_frame f; -+ -+ switch (SPA_POD_TYPE(pp)) { -+ case SPA_TYPE_Object: -+ if (pf != NULL) { -+ struct spa_pod_object *op = (struct spa_pod_object *) pp; -+ struct spa_pod_object *of = (struct spa_pod_object *) pf; -+ const struct spa_pod_prop *p1, *p2; -+ -+ if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp)) -+ return -EINVAL; -+ -+ spa_pod_builder_push_object(b, &f, op->body.type, op->body.id); -+ p2 = NULL; -+ SPA_POD_OBJECT_FOREACH(op, p1) { -+ p2 = spa_pod_object_find_prop(of, p2, p1->key); -+ if (p2 != NULL) -+ res = spa_pod_filter_prop(b, p1, p2); -+ else -+ spa_pod_builder_raw_padded(b, p1, SPA_POD_PROP_SIZE(p1)); -+ if (res < 0) -+ break; -+ } -+ if (res >= 0) { -+ p1 = NULL; -+ SPA_POD_OBJECT_FOREACH(of, p2) { -+ p1 = spa_pod_object_find_prop(op, p1, p2->key); -+ if (p1 != NULL) -+ continue; -+ -+ spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2)); -+ } -+ } -+ spa_pod_builder_pop(b, &f); -+ do_advance = true; -+ } -+ else -+ do_copy = true; -+ break; -+ -+ case SPA_TYPE_Struct: -+ if (pf != NULL) { -+ if (SPA_POD_TYPE(pf) != SPA_POD_TYPE(pp)) -+ return -EINVAL; -+ -+ filter_offset = sizeof(struct spa_pod_struct); -+ spa_pod_builder_push_struct(b, &f); -+ res = spa_pod_filter_part(b, -+ SPA_MEMBER(pp,filter_offset,const struct spa_pod), -+ SPA_POD_SIZE(pp) - filter_offset, -+ SPA_MEMBER(pf,filter_offset,const struct spa_pod), -+ SPA_POD_SIZE(pf) - filter_offset); -+ spa_pod_builder_pop(b, &f); -+ do_advance = true; -+ } -+ else -+ do_copy = true; -+ break; -+ -+ default: -+ if (pf != NULL) { -+ if (SPA_POD_SIZE(pp) != SPA_POD_SIZE(pf)) -+ return -EINVAL; -+ if (memcmp(pp, pf, SPA_POD_SIZE(pp)) != 0) -+ return -EINVAL; -+ do_advance = true; -+ } -+ do_copy = true; -+ break; -+ } -+ if (do_copy) -+ spa_pod_builder_raw_padded(b, pp, SPA_POD_SIZE(pp)); -+ if (do_advance) { -+ pf = (const struct spa_pod*)spa_pod_next(pf); -+ if (!spa_pod_is_inside(filter, filter_size, pf)) -+ pf = NULL; -+ } -+ if (res < 0) -+ break; -+ } -+ return res; -+} -+ -+static inline int -+spa_pod_filter(struct spa_pod_builder *b, -+ struct spa_pod **result, -+ const struct spa_pod *pod, -+ const struct spa_pod *filter) -+{ -+ int res; -+ struct spa_pod_builder_state state; -+ -+ spa_return_val_if_fail(pod != NULL, -EINVAL); -+ spa_return_val_if_fail(b != NULL, -EINVAL); -+ -+ spa_pod_builder_get_state(b, &state); -+ if (filter == NULL) -+ res = spa_pod_builder_raw_padded(b, pod, SPA_POD_SIZE(pod)); -+ else -+ res = spa_pod_filter_part(b, pod, SPA_POD_SIZE(pod), filter, SPA_POD_SIZE(filter)); -+ -+ if (res < 0) { -+ spa_pod_builder_reset(b, &state); -+ } else if (result) { -+ *result = (struct spa_pod*)spa_pod_builder_deref(b, state.offset); -+ if (*result == NULL) -+ res = -ENOSPC; -+ } -+ return res; -+} -diff --git a/third_party/pipewire/spa/pod/iter.h b/third_party/pipewire/spa/pod/iter.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/iter.h -@@ -0,0 +1,446 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_ITER_H -+#define SPA_POD_ITER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+ -+struct spa_pod_frame { -+ struct spa_pod pod; -+ struct spa_pod_frame *parent; -+ uint32_t offset; -+ uint32_t flags; -+}; -+ -+static inline bool spa_pod_is_inside(const void *pod, uint32_t size, const void *iter) -+{ -+ return SPA_POD_BODY(iter) <= SPA_MEMBER(pod, size, void) && -+ SPA_MEMBER(iter, SPA_POD_SIZE(iter), void) <= SPA_MEMBER(pod, size, void); -+} -+ -+static inline void *spa_pod_next(const void *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_SIZE(iter), 8), void); -+} -+ -+static inline struct spa_pod_prop *spa_pod_prop_first(const struct spa_pod_object_body *body) -+{ -+ return SPA_MEMBER(body, sizeof(struct spa_pod_object_body), struct spa_pod_prop); -+} -+ -+static inline bool spa_pod_prop_is_inside(const struct spa_pod_object_body *body, -+ uint32_t size, const struct spa_pod_prop *iter) -+{ -+ return SPA_POD_CONTENTS(struct spa_pod_prop, iter) <= SPA_MEMBER(body, size, void) && -+ SPA_MEMBER(iter, SPA_POD_PROP_SIZE(iter), void) <= SPA_MEMBER(body, size, void); -+} -+ -+static inline struct spa_pod_prop *spa_pod_prop_next(const struct spa_pod_prop *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_PROP_SIZE(iter), 8), struct spa_pod_prop); -+} -+ -+static inline struct spa_pod_control *spa_pod_control_first(const struct spa_pod_sequence_body *body) -+{ -+ return SPA_MEMBER(body, sizeof(struct spa_pod_sequence_body), struct spa_pod_control); -+} -+ -+static inline bool spa_pod_control_is_inside(const struct spa_pod_sequence_body *body, -+ uint32_t size, const struct spa_pod_control *iter) -+{ -+ return SPA_POD_CONTENTS(struct spa_pod_control, iter) <= SPA_MEMBER(body, size, void) && -+ SPA_MEMBER(iter, SPA_POD_CONTROL_SIZE(iter), void) <= SPA_MEMBER(body, size, void); -+} -+ -+static inline struct spa_pod_control *spa_pod_control_next(const struct spa_pod_control *iter) -+{ -+ return SPA_MEMBER(iter, SPA_ROUND_UP_N(SPA_POD_CONTROL_SIZE(iter), 8), struct spa_pod_control); -+} -+ -+#define SPA_POD_ARRAY_BODY_FOREACH(body, _size, iter) \ -+ for ((iter) = (__typeof__(iter))SPA_MEMBER((body), sizeof(struct spa_pod_array_body), void); \ -+ (iter) < (__typeof__(iter))SPA_MEMBER((body), (_size), void); \ -+ (iter) = (__typeof__(iter))SPA_MEMBER((iter), (body)->child.size, void)) -+ -+#define SPA_POD_ARRAY_FOREACH(obj, iter) \ -+ SPA_POD_ARRAY_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_CHOICE_BODY_FOREACH(body, _size, iter) \ -+ for ((iter) = (__typeof__(iter))SPA_MEMBER((body), sizeof(struct spa_pod_choice_body), void); \ -+ (iter) < (__typeof__(iter))SPA_MEMBER((body), (_size), void); \ -+ (iter) = (__typeof__(iter))SPA_MEMBER((iter), (body)->child.size, void)) -+ -+#define SPA_POD_CHOICE_FOREACH(obj, iter) \ -+ SPA_POD_CHOICE_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_FOREACH(pod, size, iter) \ -+ for ((iter) = (pod); \ -+ spa_pod_is_inside(pod, size, iter); \ -+ (iter) = (__typeof__(iter))spa_pod_next(iter)) -+ -+#define SPA_POD_STRUCT_FOREACH(obj, iter) \ -+ SPA_POD_FOREACH(SPA_POD_BODY(obj), SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_OBJECT_BODY_FOREACH(body, size, iter) \ -+ for ((iter) = spa_pod_prop_first(body); \ -+ spa_pod_prop_is_inside(body, size, iter); \ -+ (iter) = spa_pod_prop_next(iter)) -+ -+#define SPA_POD_OBJECT_FOREACH(obj, iter) \ -+ SPA_POD_OBJECT_BODY_FOREACH(&(obj)->body, SPA_POD_BODY_SIZE(obj), iter) -+ -+#define SPA_POD_SEQUENCE_BODY_FOREACH(body, size, iter) \ -+ for ((iter) = spa_pod_control_first(body); \ -+ spa_pod_control_is_inside(body, size, iter); \ -+ (iter) = spa_pod_control_next(iter)) -+ -+#define SPA_POD_SEQUENCE_FOREACH(seq, iter) \ -+ SPA_POD_SEQUENCE_BODY_FOREACH(&(seq)->body, SPA_POD_BODY_SIZE(seq), iter) -+ -+ -+static inline void *spa_pod_from_data(void *data, size_t maxsize, off_t offset, size_t size) -+{ -+ void *pod; -+ if (size < sizeof(struct spa_pod) || offset + size > maxsize) -+ return NULL; -+ pod = SPA_MEMBER(data, offset, void); -+ if (SPA_POD_SIZE(pod) > size) -+ return NULL; -+ return pod; -+} -+ -+static inline int spa_pod_is_none(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_None); -+} -+ -+static inline int spa_pod_is_bool(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Bool && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); -+} -+ -+static inline int spa_pod_get_bool(const struct spa_pod *pod, bool *value) -+{ -+ if (!spa_pod_is_bool(pod)) -+ return -EINVAL; -+ *value = !!SPA_POD_VALUE(struct spa_pod_bool, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_id(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Id && SPA_POD_BODY_SIZE(pod) >= sizeof(uint32_t)); -+} -+ -+static inline int spa_pod_get_id(const struct spa_pod *pod, uint32_t *value) -+{ -+ if (!spa_pod_is_id(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_id, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_int(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Int && SPA_POD_BODY_SIZE(pod) >= sizeof(int32_t)); -+} -+ -+static inline int spa_pod_get_int(const struct spa_pod *pod, int32_t *value) -+{ -+ if (!spa_pod_is_int(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_int, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_long(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Long && SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); -+} -+ -+static inline int spa_pod_get_long(const struct spa_pod *pod, int64_t *value) -+{ -+ if (!spa_pod_is_long(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_long, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_float(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Float && SPA_POD_BODY_SIZE(pod) >= sizeof(float)); -+} -+ -+static inline int spa_pod_get_float(const struct spa_pod *pod, float *value) -+{ -+ if (!spa_pod_is_float(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_float, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_double(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Double && SPA_POD_BODY_SIZE(pod) >= sizeof(double)); -+} -+ -+static inline int spa_pod_get_double(const struct spa_pod *pod, double *value) -+{ -+ if (!spa_pod_is_double(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_double, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_string(const struct spa_pod *pod) -+{ -+ const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_String && -+ SPA_POD_BODY_SIZE(pod) > 0 && -+ s[SPA_POD_BODY_SIZE(pod)-1] == '\0'); -+} -+ -+static inline int spa_pod_get_string(const struct spa_pod *pod, const char **value) -+{ -+ if (!spa_pod_is_string(pod)) -+ return -EINVAL; -+ *value = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ return 0; -+} -+ -+static inline int spa_pod_copy_string(const struct spa_pod *pod, size_t maxlen, char *dest) -+{ -+ const char *s = (const char *)SPA_POD_CONTENTS(struct spa_pod_string, pod); -+ if (!spa_pod_is_string(pod) || maxlen < 1) -+ return -EINVAL; -+ strncpy(dest, s, maxlen-1); -+ dest[maxlen-1]= '\0'; -+ return 0; -+} -+ -+static inline int spa_pod_is_bytes(const struct spa_pod *pod) -+{ -+ return SPA_POD_TYPE(pod) == SPA_TYPE_Bytes; -+} -+ -+static inline int spa_pod_get_bytes(const struct spa_pod *pod, const void **value, uint32_t *len) -+{ -+ if (!spa_pod_is_bytes(pod)) -+ return -EINVAL; -+ *value = (const void *)SPA_POD_CONTENTS(struct spa_pod_bytes, pod); -+ *len = SPA_POD_BODY_SIZE(pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_pointer(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Pointer && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_pointer_body)); -+} -+ -+static inline int spa_pod_get_pointer(const struct spa_pod *pod, uint32_t *type, const void **value) -+{ -+ if (!spa_pod_is_pointer(pod)) -+ return -EINVAL; -+ *type = ((struct spa_pod_pointer*)pod)->body.type; -+ *value = ((struct spa_pod_pointer*)pod)->body.value; -+ return 0; -+} -+ -+static inline int spa_pod_is_fd(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Fd && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(int64_t)); -+} -+ -+static inline int spa_pod_get_fd(const struct spa_pod *pod, int64_t *value) -+{ -+ if (!spa_pod_is_fd(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_fd, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_rectangle(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Rectangle && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_rectangle)); -+} -+ -+static inline int spa_pod_get_rectangle(const struct spa_pod *pod, struct spa_rectangle *value) -+{ -+ if (!spa_pod_is_rectangle(pod)) -+ return -EINVAL; -+ *value = SPA_POD_VALUE(struct spa_pod_rectangle, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_fraction(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Fraction && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_fraction)); -+} -+ -+static inline int spa_pod_get_fraction(const struct spa_pod *pod, struct spa_fraction *value) -+{ -+ spa_return_val_if_fail(spa_pod_is_fraction(pod), -EINVAL); -+ *value = SPA_POD_VALUE(struct spa_pod_fraction, pod); -+ return 0; -+} -+ -+static inline int spa_pod_is_bitmap(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Bitmap && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(uint8_t)); -+} -+ -+static inline int spa_pod_is_array(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Array && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_array_body)); -+} -+ -+static inline void *spa_pod_get_array(const struct spa_pod *pod, uint32_t *n_values) -+{ -+ spa_return_val_if_fail(spa_pod_is_array(pod), NULL); -+ *n_values = SPA_POD_ARRAY_N_VALUES(pod); -+ return SPA_POD_ARRAY_VALUES(pod); -+} -+ -+static inline uint32_t spa_pod_copy_array(const struct spa_pod *pod, uint32_t type, -+ void *values, uint32_t max_values) -+{ -+ uint32_t n_values; -+ void *v = spa_pod_get_array(pod, &n_values); -+ if (v == NULL || max_values == 0 || SPA_POD_ARRAY_VALUE_TYPE(pod) != type) -+ return 0; -+ n_values = SPA_MIN(n_values, max_values); -+ memcpy(values, v, SPA_POD_ARRAY_VALUE_SIZE(pod) * n_values); -+ return n_values; -+} -+ -+static inline int spa_pod_is_choice(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Choice && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_choice_body)); -+} -+ -+static inline struct spa_pod *spa_pod_get_values(const struct spa_pod *pod, uint32_t *n_vals, uint32_t *choice) -+{ -+ if (pod->type == SPA_TYPE_Choice) { -+ *choice = SPA_POD_CHOICE_TYPE(pod); -+ *n_vals = *choice == SPA_CHOICE_None ? 1 : SPA_POD_CHOICE_N_VALUES(pod); -+ return (struct spa_pod*)SPA_POD_CHOICE_CHILD(pod); -+ } else { -+ *n_vals = 1; -+ *choice = SPA_CHOICE_None; -+ return (struct spa_pod*)pod; -+ } -+} -+ -+static inline int spa_pod_is_struct(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Struct); -+} -+ -+static inline int spa_pod_is_object(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Object && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_object_body)); -+} -+ -+static inline bool spa_pod_is_object_type(const struct spa_pod *pod, uint32_t type) -+{ -+ return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_TYPE(pod) == type); -+} -+ -+static inline bool spa_pod_is_object_id(const struct spa_pod *pod, uint32_t id) -+{ -+ return (pod && spa_pod_is_object(pod) && SPA_POD_OBJECT_ID(pod) == id); -+} -+ -+static inline int spa_pod_is_sequence(const struct spa_pod *pod) -+{ -+ return (SPA_POD_TYPE(pod) == SPA_TYPE_Sequence && -+ SPA_POD_BODY_SIZE(pod) >= sizeof(struct spa_pod_sequence_body)); -+} -+ -+static inline const struct spa_pod_prop *spa_pod_object_find_prop(const struct spa_pod_object *pod, -+ const struct spa_pod_prop *start, uint32_t key) -+{ -+ const struct spa_pod_prop *first, *res; -+ -+ first = spa_pod_prop_first(&pod->body); -+ start = start ? spa_pod_prop_next(start) : first; -+ -+ for (res = start; spa_pod_prop_is_inside(&pod->body, pod->pod.size, res); -+ res = spa_pod_prop_next(res)) { -+ if (res->key == key) -+ return res; -+ } -+ for (res = first; res != start; res = spa_pod_prop_next(res)) { -+ if (res->key == key) -+ return res; -+ } -+ return NULL; -+} -+ -+static inline const struct spa_pod_prop *spa_pod_find_prop(const struct spa_pod *pod, -+ const struct spa_pod_prop *start, uint32_t key) -+{ -+ if (!spa_pod_is_object(pod)) -+ return NULL; -+ return spa_pod_object_find_prop((const struct spa_pod_object *)pod, start, key); -+} -+ -+static inline int spa_pod_object_fixate(struct spa_pod_object *pod) -+{ -+ struct spa_pod_prop *res; -+ SPA_POD_OBJECT_FOREACH(pod, res) { -+ if (res->value.type == SPA_TYPE_Choice) -+ ((struct spa_pod_choice*)&res->value)->body.type = SPA_CHOICE_None; -+ } -+ return 0; -+} -+ -+static inline int spa_pod_fixate(struct spa_pod *pod) -+{ -+ if (!spa_pod_is_object(pod)) -+ return -EINVAL; -+ return spa_pod_object_fixate((struct spa_pod_object *)pod); -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_H */ -diff --git a/third_party/pipewire/spa/pod/parser.h b/third_party/pipewire/spa/pod/parser.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/parser.h -@@ -0,0 +1,573 @@ -+/* Spa -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_PARSER_H -+#define SPA_POD_PARSER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#include -+#include -+ -+struct spa_pod_parser_state { -+ uint32_t offset; -+ uint32_t flags; -+ struct spa_pod_frame *frame; -+}; -+ -+struct spa_pod_parser { -+ const void *data; -+ uint32_t size; -+ uint32_t _padding; -+ struct spa_pod_parser_state state; -+}; -+ -+#define SPA_POD_PARSER_INIT(buffer,size) (struct spa_pod_parser){ buffer, size, } -+ -+static inline void spa_pod_parser_init(struct spa_pod_parser *parser, -+ const void *data, uint32_t size) -+{ -+ *parser = SPA_POD_PARSER_INIT(data, size); -+} -+ -+static inline void spa_pod_parser_pod(struct spa_pod_parser *parser, -+ const struct spa_pod *pod) -+{ -+ spa_pod_parser_init(parser, pod, SPA_POD_SIZE(pod)); -+} -+ -+static inline void -+spa_pod_parser_get_state(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) -+{ -+ *state = parser->state; -+} -+ -+static inline void -+spa_pod_parser_reset(struct spa_pod_parser *parser, struct spa_pod_parser_state *state) -+{ -+ parser->state = *state; -+} -+ -+static inline struct spa_pod * -+spa_pod_parser_deref(struct spa_pod_parser *parser, uint32_t offset, uint32_t size) -+{ -+ if (offset + 8 <= size) { -+ struct spa_pod *pod = SPA_MEMBER(parser->data, offset, struct spa_pod); -+ if (offset + SPA_POD_SIZE(pod) <= size) -+ return pod; -+ } -+ return NULL; -+} -+ -+static inline struct spa_pod *spa_pod_parser_frame(struct spa_pod_parser *parser, struct spa_pod_frame *frame) -+{ -+ return SPA_MEMBER(parser->data, frame->offset, struct spa_pod); -+} -+ -+static inline void spa_pod_parser_push(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame, const struct spa_pod *pod, uint32_t offset) -+{ -+ frame->pod = *pod; -+ frame->offset = offset; -+ frame->parent = parser->state.frame; -+ frame->flags = parser->state.flags; -+ parser->state.frame = frame; -+} -+ -+static inline struct spa_pod *spa_pod_parser_current(struct spa_pod_parser *parser) -+{ -+ struct spa_pod_frame *f = parser->state.frame; -+ uint32_t size = f ? f->offset + SPA_POD_SIZE(&f->pod) : parser->size; -+ return spa_pod_parser_deref(parser, parser->state.offset, size); -+} -+ -+static inline void spa_pod_parser_advance(struct spa_pod_parser *parser, const struct spa_pod *pod) -+{ -+ parser->state.offset += SPA_ROUND_UP_N(SPA_POD_SIZE(pod), 8); -+} -+ -+static inline struct spa_pod *spa_pod_parser_next(struct spa_pod_parser *parser) -+{ -+ struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod) -+ spa_pod_parser_advance(parser, pod); -+ return pod; -+} -+ -+static inline int spa_pod_parser_pop(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame) -+{ -+ parser->state.frame = frame->parent; -+ parser->state.offset = frame->offset + SPA_ROUND_UP_N(SPA_POD_SIZE(&frame->pod), 8); -+ return 0; -+} -+ -+static inline int spa_pod_parser_get_bool(struct spa_pod_parser *parser, bool *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_bool(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_id(struct spa_pod_parser *parser, uint32_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_id(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_int(struct spa_pod_parser *parser, int32_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_int(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_long(struct spa_pod_parser *parser, int64_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_long(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_float(struct spa_pod_parser *parser, float *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_float(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_double(struct spa_pod_parser *parser, double *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_double(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_string(struct spa_pod_parser *parser, const char **value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_string(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_bytes(struct spa_pod_parser *parser, const void **value, uint32_t *len) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_bytes(pod, value, len)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_pointer(struct spa_pod_parser *parser, uint32_t *type, const void **value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_pointer(pod, type, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_fd(struct spa_pod_parser *parser, int64_t *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_fd(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_rectangle(struct spa_pod_parser *parser, struct spa_rectangle *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_rectangle(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_fraction(struct spa_pod_parser *parser, struct spa_fraction *value) -+{ -+ int res = -EPIPE; -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod != NULL && (res = spa_pod_get_fraction(pod, value)) >= 0) -+ spa_pod_parser_advance(parser, pod); -+ return res; -+} -+ -+static inline int spa_pod_parser_get_pod(struct spa_pod_parser *parser, struct spa_pod **value) -+{ -+ struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ *value = pod; -+ spa_pod_parser_advance(parser, pod); -+ return 0; -+} -+static inline int spa_pod_parser_push_struct(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame) -+{ -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ if (!spa_pod_is_struct(pod)) -+ return -EINVAL; -+ spa_pod_parser_push(parser, frame, pod, parser->state.offset); -+ parser->state.offset += sizeof(struct spa_pod_struct); -+ return 0; -+} -+ -+static inline int spa_pod_parser_push_object(struct spa_pod_parser *parser, -+ struct spa_pod_frame *frame, uint32_t type, uint32_t *id) -+{ -+ const struct spa_pod *pod = spa_pod_parser_current(parser); -+ if (pod == NULL) -+ return -EPIPE; -+ if (!spa_pod_is_object(pod)) -+ return -EINVAL; -+ if (type != SPA_POD_OBJECT_TYPE(pod)) -+ return -EPROTO; -+ if (id != NULL) -+ *id = SPA_POD_OBJECT_ID(pod); -+ spa_pod_parser_push(parser, frame, pod, parser->state.offset); -+ parser->state.offset = parser->size; -+ return 0; -+} -+ -+static inline bool spa_pod_parser_can_collect(const struct spa_pod *pod, char type) -+{ -+ if (pod == NULL) -+ return false; -+ -+ if (spa_pod_is_choice(pod) && -+ SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None && -+ spa_pod_parser_can_collect(SPA_POD_CHOICE_CHILD(pod), type)) -+ return true; -+ -+ switch (type) { -+ case 'P': -+ return true; -+ case 'b': -+ return spa_pod_is_bool(pod); -+ case 'I': -+ return spa_pod_is_id(pod); -+ case 'i': -+ return spa_pod_is_int(pod); -+ case 'l': -+ return spa_pod_is_long(pod); -+ case 'f': -+ return spa_pod_is_float(pod); -+ case 'd': -+ return spa_pod_is_double(pod); -+ case 's': -+ return spa_pod_is_string(pod) || spa_pod_is_none(pod); -+ case 'S': -+ return spa_pod_is_string(pod); -+ case 'y': -+ return spa_pod_is_bytes(pod); -+ case 'R': -+ return spa_pod_is_rectangle(pod); -+ case 'F': -+ return spa_pod_is_fraction(pod); -+ case 'B': -+ return spa_pod_is_bitmap(pod); -+ case 'a': -+ return spa_pod_is_array(pod); -+ case 'p': -+ return spa_pod_is_pointer(pod); -+ case 'h': -+ return spa_pod_is_fd(pod); -+ case 'T': -+ return spa_pod_is_struct(pod) || spa_pod_is_none(pod); -+ case 'O': -+ return spa_pod_is_object(pod) || spa_pod_is_none(pod); -+ case 'V': -+ return spa_pod_is_choice(pod); -+ default: -+ return false; -+ } -+} -+ -+#define SPA_POD_PARSER_COLLECT(pod,_type,args) \ -+do { \ -+ switch (_type) { \ -+ case 'b': \ -+ *va_arg(args, bool*) = SPA_POD_VALUE(struct spa_pod_bool, pod); \ -+ break; \ -+ case 'I': \ -+ case 'i': \ -+ *va_arg(args, int32_t*) = SPA_POD_VALUE(struct spa_pod_int, pod); \ -+ break; \ -+ case 'l': \ -+ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_long, pod); \ -+ break; \ -+ case 'f': \ -+ *va_arg(args, float*) = SPA_POD_VALUE(struct spa_pod_float, pod); \ -+ break; \ -+ case 'd': \ -+ *va_arg(args, double*) = SPA_POD_VALUE(struct spa_pod_double, pod); \ -+ break; \ -+ case 's': \ -+ *va_arg(args, char**) = \ -+ (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \ -+ ? NULL \ -+ : (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod)); \ -+ break; \ -+ case 'S': \ -+ { \ -+ char *dest = va_arg(args, char*); \ -+ uint32_t maxlen = va_arg(args, uint32_t); \ -+ strncpy(dest, (char *)SPA_POD_CONTENTS(struct spa_pod_string, pod), maxlen-1); \ -+ break; \ -+ } \ -+ case 'y': \ -+ *(va_arg(args, void **)) = SPA_POD_CONTENTS(struct spa_pod_bytes, pod); \ -+ *(va_arg(args, uint32_t *)) = SPA_POD_BODY_SIZE(pod); \ -+ break; \ -+ case 'R': \ -+ *va_arg(args, struct spa_rectangle*) = \ -+ SPA_POD_VALUE(struct spa_pod_rectangle, pod); \ -+ break; \ -+ case 'F': \ -+ *va_arg(args, struct spa_fraction*) = \ -+ SPA_POD_VALUE(struct spa_pod_fraction, pod); \ -+ break; \ -+ case 'B': \ -+ *va_arg(args, uint32_t **) = \ -+ (uint32_t *) SPA_POD_CONTENTS(struct spa_pod_bitmap, pod); \ -+ break; \ -+ case 'a': \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_SIZE(pod); \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_VALUE_TYPE(pod); \ -+ *va_arg(args, uint32_t*) = SPA_POD_ARRAY_N_VALUES(pod); \ -+ *va_arg(args, void**) = SPA_POD_ARRAY_VALUES(pod); \ -+ break; \ -+ case 'p': \ -+ { \ -+ struct spa_pod_pointer_body *b = \ -+ (struct spa_pod_pointer_body *) SPA_POD_BODY(pod); \ -+ *(va_arg(args, uint32_t *)) = b->type; \ -+ *(va_arg(args, const void **)) = b->value; \ -+ break; \ -+ } \ -+ case 'h': \ -+ *va_arg(args, int64_t*) = SPA_POD_VALUE(struct spa_pod_fd, pod); \ -+ break; \ -+ case 'P': \ -+ case 'T': \ -+ case 'O': \ -+ case 'V': \ -+ { \ -+ const struct spa_pod **d = va_arg(args, const struct spa_pod**); \ -+ if (d) \ -+ *d = (pod == NULL || (SPA_POD_TYPE(pod) == SPA_TYPE_None) \ -+ ? NULL : pod); \ -+ break; \ -+ } \ -+ default: \ -+ break; \ -+ } \ -+} while(false) -+ -+#define SPA_POD_PARSER_SKIP(_type,args) \ -+do { \ -+ switch (_type) { \ -+ case 'S': \ -+ va_arg(args, char*); \ -+ va_arg(args, uint32_t); \ -+ break; \ -+ case 'a': \ -+ va_arg(args, void*); \ -+ va_arg(args, void*); \ -+ /* fallthrough */ \ -+ case 'p': \ -+ case 'y': \ -+ va_arg(args, void*); \ -+ /* fallthrough */ \ -+ case 'b': \ -+ case 'I': \ -+ case 'i': \ -+ case 'l': \ -+ case 'f': \ -+ case 'd': \ -+ case 's': \ -+ case 'R': \ -+ case 'F': \ -+ case 'B': \ -+ case 'h': \ -+ case 'V': \ -+ case 'P': \ -+ case 'T': \ -+ case 'O': \ -+ va_arg(args, void*); \ -+ break; \ -+ } \ -+} while(false) -+ -+static inline int spa_pod_parser_getv(struct spa_pod_parser *parser, va_list args) -+{ -+ struct spa_pod_frame *f = parser->state.frame; -+ uint32_t ftype = f ? f->pod.type : (uint32_t)SPA_TYPE_Struct; -+ const struct spa_pod_prop *prop = NULL; -+ int count = 0; -+ -+ do { -+ bool optional; -+ const struct spa_pod *pod = NULL; -+ const char *format; -+ -+ if (ftype == SPA_TYPE_Object) { -+ uint32_t key = va_arg(args, uint32_t); -+ const struct spa_pod_object *object; -+ -+ if (key == 0) -+ break; -+ -+ object = (const struct spa_pod_object *)spa_pod_parser_frame(parser, f); -+ prop = spa_pod_object_find_prop(object, prop, key); -+ pod = prop ? &prop->value : NULL; -+ } -+ -+ if ((format = va_arg(args, char *)) == NULL) -+ break; -+ -+ if (ftype == SPA_TYPE_Struct) -+ pod = spa_pod_parser_next(parser); -+ -+ if ((optional = (*format == '?'))) -+ format++; -+ -+ if (!spa_pod_parser_can_collect(pod, *format)) { -+ if (!optional) { -+ if (pod == NULL) -+ return -ESRCH; -+ else -+ return -EPROTO; -+ } -+ SPA_POD_PARSER_SKIP(*format, args); -+ } else { -+ if (pod->type == SPA_TYPE_Choice && *format != 'V' && -+ SPA_POD_CHOICE_TYPE(pod) == SPA_CHOICE_None) -+ pod = SPA_POD_CHOICE_CHILD(pod); -+ -+ SPA_POD_PARSER_COLLECT(pod, *format, args); -+ count++; -+ } -+ } while (true); -+ -+ return count; -+} -+ -+static inline int spa_pod_parser_get(struct spa_pod_parser *parser, ...) -+{ -+ int res; -+ va_list args; -+ -+ va_start(args, parser); -+ res = spa_pod_parser_getv(parser, args); -+ va_end(args); -+ -+ return res; -+} -+ -+#define SPA_POD_OPT_Bool(val) "?" SPA_POD_Bool(val) -+#define SPA_POD_OPT_Id(val) "?" SPA_POD_Id(val) -+#define SPA_POD_OPT_Int(val) "?" SPA_POD_Int(val) -+#define SPA_POD_OPT_Long(val) "?" SPA_POD_Long(val) -+#define SPA_POD_OPT_Float(val) "?" SPA_POD_Float(val) -+#define SPA_POD_OPT_Double(val) "?" SPA_POD_Double(val) -+#define SPA_POD_OPT_String(val) "?" SPA_POD_String(val) -+#define SPA_POD_OPT_Stringn(val,len) "?" SPA_POD_Stringn(val,len) -+#define SPA_POD_OPT_Bytes(val,len) "?" SPA_POD_Bytes(val,len) -+#define SPA_POD_OPT_Rectangle(val) "?" SPA_POD_Rectangle(val) -+#define SPA_POD_OPT_Fraction(val) "?" SPA_POD_Fraction(val) -+#define SPA_POD_OPT_Array(csize,ctype,n_vals,vals) "?" SPA_POD_Array(csize,ctype,n_vals,vals) -+#define SPA_POD_OPT_Pointer(type,val) "?" SPA_POD_Pointer(type,val) -+#define SPA_POD_OPT_Fd(val) "?" SPA_POD_Fd(val) -+#define SPA_POD_OPT_Pod(val) "?" SPA_POD_Pod(val) -+#define SPA_POD_OPT_PodObject(val) "?" SPA_POD_PodObject(val) -+#define SPA_POD_OPT_PodStruct(val) "?" SPA_POD_PodStruct(val) -+#define SPA_POD_OPT_PodChoice(val) "?" SPA_POD_PodChoice(val) -+ -+#define spa_pod_parser_get_object(p,type,id,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ int _res; \ -+ if ((_res = spa_pod_parser_push_object(p, &_f, type, id)) == 0) { \ -+ _res = spa_pod_parser_get(p,##__VA_ARGS__, 0); \ -+ spa_pod_parser_pop(p, &_f); \ -+ } \ -+ _res; \ -+}) -+ -+#define spa_pod_parser_get_struct(p,...) \ -+({ \ -+ struct spa_pod_frame _f; \ -+ int _res; \ -+ if ((_res = spa_pod_parser_push_struct(p, &_f)) == 0) { \ -+ _res = spa_pod_parser_get(p,##__VA_ARGS__, NULL); \ -+ spa_pod_parser_pop(p, &_f); \ -+ } \ -+ _res; \ -+}) -+ -+#define spa_pod_parse_object(pod,type,id,...) \ -+({ \ -+ struct spa_pod_parser _p; \ -+ spa_pod_parser_pod(&_p, pod); \ -+ spa_pod_parser_get_object(&_p,type,id,##__VA_ARGS__); \ -+}) -+ -+#define spa_pod_parse_struct(pod,...) \ -+({ \ -+ struct spa_pod_parser _p; \ -+ spa_pod_parser_pod(&_p, pod); \ -+ spa_pod_parser_get_struct(&_p,##__VA_ARGS__); \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_PARSER_H */ -diff --git a/third_party/pipewire/spa/pod/pod.h b/third_party/pipewire/spa/pod/pod.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/pod.h -@@ -0,0 +1,231 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_H -+#define SPA_POD_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define SPA_POD_BODY_SIZE(pod) (((struct spa_pod*)(pod))->size) -+#define SPA_POD_TYPE(pod) (((struct spa_pod*)(pod))->type) -+#define SPA_POD_SIZE(pod) (sizeof(struct spa_pod) + SPA_POD_BODY_SIZE(pod)) -+#define SPA_POD_CONTENTS_SIZE(type,pod) (SPA_POD_SIZE(pod)-sizeof(type)) -+ -+#define SPA_POD_CONTENTS(type,pod) SPA_MEMBER((pod),sizeof(type),void) -+#define SPA_POD_CONTENTS_CONST(type,pod) SPA_MEMBER((pod),sizeof(type),const void) -+#define SPA_POD_BODY(pod) SPA_MEMBER((pod),sizeof(struct spa_pod),void) -+#define SPA_POD_BODY_CONST(pod) SPA_MEMBER((pod),sizeof(struct spa_pod),const void) -+ -+struct spa_pod { -+ uint32_t size; /* size of the body */ -+ uint32_t type; /* a basic id of enum spa_type */ -+}; -+ -+#define SPA_POD_VALUE(type,pod) (((type*)pod)->value) -+ -+struct spa_pod_bool { -+ struct spa_pod pod; -+ int32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_id { -+ struct spa_pod pod; -+ uint32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_int { -+ struct spa_pod pod; -+ int32_t value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_long { -+ struct spa_pod pod; -+ int64_t value; -+}; -+ -+struct spa_pod_float { -+ struct spa_pod pod; -+ float value; -+ int32_t _padding; -+}; -+ -+struct spa_pod_double { -+ struct spa_pod pod; -+ double value; -+}; -+ -+struct spa_pod_string { -+ struct spa_pod pod; -+ /* value here */ -+}; -+ -+struct spa_pod_bytes { -+ struct spa_pod pod; -+ /* value here */ -+}; -+ -+struct spa_pod_rectangle { -+ struct spa_pod pod; -+ struct spa_rectangle value; -+}; -+ -+struct spa_pod_fraction { -+ struct spa_pod pod; -+ struct spa_fraction value; -+}; -+ -+struct spa_pod_bitmap { -+ struct spa_pod pod; -+ /* array of uint8_t follows with the bitmap */ -+}; -+ -+#define SPA_POD_ARRAY_CHILD(arr) (&((struct spa_pod_array*)(arr))->body.child) -+#define SPA_POD_ARRAY_VALUE_TYPE(arr) (SPA_POD_TYPE(SPA_POD_ARRAY_CHILD(arr))) -+#define SPA_POD_ARRAY_VALUE_SIZE(arr) (SPA_POD_BODY_SIZE(SPA_POD_ARRAY_CHILD(arr))) -+#define SPA_POD_ARRAY_N_VALUES(arr) ((SPA_POD_BODY_SIZE(arr) - sizeof(struct spa_pod_array_body)) / SPA_POD_ARRAY_VALUE_SIZE(arr)) -+#define SPA_POD_ARRAY_VALUES(arr) SPA_POD_CONTENTS(struct spa_pod_array, arr) -+ -+struct spa_pod_array_body { -+ struct spa_pod child; -+ /* array with elements of child.size follows */ -+}; -+ -+struct spa_pod_array { -+ struct spa_pod pod; -+ struct spa_pod_array_body body; -+}; -+ -+#define SPA_POD_CHOICE_CHILD(choice) (&((struct spa_pod_choice*)(choice))->body.child) -+#define SPA_POD_CHOICE_TYPE(choice) (((struct spa_pod_choice*)(choice))->body.type) -+#define SPA_POD_CHOICE_FLAGS(choice) (((struct spa_pod_choice*)(choice))->body.flags) -+#define SPA_POD_CHOICE_VALUE_TYPE(choice) (SPA_POD_TYPE(SPA_POD_CHOICE_CHILD(choice))) -+#define SPA_POD_CHOICE_VALUE_SIZE(choice) (SPA_POD_BODY_SIZE(SPA_POD_CHOICE_CHILD(choice))) -+#define SPA_POD_CHOICE_N_VALUES(choice) ((SPA_POD_BODY_SIZE(choice) - sizeof(struct spa_pod_choice_body)) / SPA_POD_CHOICE_VALUE_SIZE(choice)) -+#define SPA_POD_CHOICE_VALUES(choice) (SPA_POD_CONTENTS(struct spa_pod_choice, choice)) -+ -+enum spa_choice_type { -+ SPA_CHOICE_None, /**< no choice, first value is current */ -+ SPA_CHOICE_Range, /**< range: default, min, max */ -+ SPA_CHOICE_Step, /**< range with step: default, min, max, step */ -+ SPA_CHOICE_Enum, /**< list: default, alternative,... */ -+ SPA_CHOICE_Flags, /**< flags: default, possible flags,... */ -+}; -+ -+struct spa_pod_choice_body { -+ uint32_t type; /**< type of choice, one of enum spa_choice_type */ -+ uint32_t flags; /**< extra flags */ -+ struct spa_pod child; -+ /* array with elements of child.size follows. Note that there might be more -+ * elements than required by \a type, which should be ignored. */ -+}; -+ -+struct spa_pod_choice { -+ struct spa_pod pod; -+ struct spa_pod_choice_body body; -+}; -+ -+struct spa_pod_struct { -+ struct spa_pod pod; -+ /* one or more spa_pod follow */ -+}; -+ -+#define SPA_POD_OBJECT_TYPE(obj) (((struct spa_pod_object*)(obj))->body.type) -+#define SPA_POD_OBJECT_ID(obj) (((struct spa_pod_object*)(obj))->body.id) -+ -+struct spa_pod_object_body { -+ uint32_t type; /**< one of enum spa_type */ -+ uint32_t id; /**< id of the object, depends on the object type */ -+ /* contents follow, series of spa_pod_prop */ -+}; -+ -+struct spa_pod_object { -+ struct spa_pod pod; -+ struct spa_pod_object_body body; -+}; -+ -+struct spa_pod_pointer_body { -+ uint32_t type; /**< pointer id, one of enum spa_type */ -+ uint32_t _padding; -+ const void *value; -+}; -+ -+struct spa_pod_pointer { -+ struct spa_pod pod; -+ struct spa_pod_pointer_body body; -+}; -+ -+struct spa_pod_fd { -+ struct spa_pod pod; -+ int64_t value; -+}; -+ -+#define SPA_POD_PROP_SIZE(prop) (sizeof(struct spa_pod_prop) + (prop)->value.size) -+ -+/* props can be inside an object */ -+struct spa_pod_prop { -+ uint32_t key; /**< key of property, list of valid keys depends on the -+ * object type */ -+#define SPA_POD_PROP_FLAG_READONLY (1u<<0) /**< is read-only */ -+#define SPA_POD_PROP_FLAG_HARDWARE (1u<<1) /**< some sort of hardware parameter */ -+ uint32_t flags; /**< flags for property */ -+ struct spa_pod value; -+ /* value follows */ -+}; -+ -+#define SPA_POD_CONTROL_SIZE(ev) (sizeof(struct spa_pod_control) + (ev)->value.size) -+ -+/* controls can be inside a sequence and mark timed values */ -+struct spa_pod_control { -+ uint32_t offset; /**< media offset */ -+ uint32_t type; /**< type of control, enum spa_control_type */ -+ struct spa_pod value; /**< control value, depends on type */ -+ /* value contents follow */ -+}; -+ -+struct spa_pod_sequence_body { -+ uint32_t unit; -+ uint32_t pad; -+ /* series of struct spa_pod_control follows */ -+}; -+ -+/** a sequence of timed controls */ -+struct spa_pod_sequence { -+ struct spa_pod pod; -+ struct spa_pod_sequence_body body; -+}; -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_H */ -diff --git a/third_party/pipewire/spa/pod/vararg.h b/third_party/pipewire/spa/pod/vararg.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/pod/vararg.h -@@ -0,0 +1,104 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_POD_VARARG_H -+#define SPA_POD_VARARG_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+#define SPA_POD_Prop(key,...) \ -+ key, ##__VA_ARGS__ -+ -+#define SPA_POD_Control(offset,type,...) \ -+ offset, type, ##__VA_ARGS__ -+ -+#define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max) -+#define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) -+#define SPA_CHOICE_ENUM(n_vals,...) (n_vals),##__VA_ARGS__ -+#define SPA_CHOICE_FLAGS(flags) 1, (flags) -+#define SPA_CHOICE_BOOL(def) 3,(def),(def),!(def) -+ -+#define SPA_POD_Bool(val) "b", val -+#define SPA_POD_CHOICE_Bool(def) "?eb", SPA_CHOICE_BOOL(def) -+ -+#define SPA_POD_Id(val) "I", val -+#define SPA_POD_CHOICE_ENUM_Id(n_vals,...) "?eI", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+ -+#define SPA_POD_Int(val) "i", val -+#define SPA_POD_CHOICE_ENUM_Int(n_vals,...) "?ei", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Int(def,min,max) "?ri", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Int(def,min,max,step) "?si", SPA_CHOICE_STEP(def, min, max, step) -+#define SPA_POD_CHOICE_FLAGS_Int(flags) "?fi", SPA_CHOICE_FLAGS(flags) -+ -+#define SPA_POD_Long(val) "l", val -+#define SPA_POD_CHOICE_ENUM_Long(n_vals,...) "?el", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Long(def,min,max) "?rl", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Long(def,min,max,step) "?sl", SPA_CHOICE_STEP(def, min, max, step) -+#define SPA_POD_CHOICE_FLAGS_Long(flags) "?fl", SPA_CHOICE_FLAGS(flags) -+ -+#define SPA_POD_Float(val) "f", val -+#define SPA_POD_CHOICE_ENUM_Float(n_vals,...) "?ef", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Float(def,min,max) "?rf", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Float(def,min,max,step) "?sf", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_Double(val) "d", val -+#define SPA_POD_CHOICE_ENUM_Double(n_vals,...) "?ed", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Double(def,min,max) "?rd", SPA_CHOICE_RANGE(def, min, max) -+#define SPA_POD_CHOICE_STEP_Double(def,min,max,step) "?sd", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_String(val) "s",val -+#define SPA_POD_Stringn(val,len) "S",val,len -+ -+#define SPA_POD_Bytes(val,len) "y",val,len -+ -+#define SPA_POD_Rectangle(val) "R",val -+#define SPA_POD_CHOICE_ENUM_Rectangle(n_vals,...) "?eR", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Rectangle(def,min,max) "?rR", SPA_CHOICE_RANGE((def),(min),(max)) -+#define SPA_POD_CHOICE_STEP_Rectangle(def,min,max,step) "?sR", SPA_CHOICE_STEP((def),(min),(max),(step)) -+ -+#define SPA_POD_Fraction(val) "F",val -+#define SPA_POD_CHOICE_ENUM_Fraction(n_vals,...) "?eF", SPA_CHOICE_ENUM(n_vals, __VA_ARGS__) -+#define SPA_POD_CHOICE_RANGE_Fraction(def,min,max) "?rF", SPA_CHOICE_RANGE((def),(min),(max)) -+#define SPA_POD_CHOICE_STEP_Fraction(def,min,max,step) "?sF", SPA_CHOICE_STEP(def, min, max, step) -+ -+#define SPA_POD_Array(csize,ctype,n_vals,vals) "a", csize,ctype,n_vals,vals -+#define SPA_POD_Pointer(type,val) "p", type,val -+#define SPA_POD_Fd(val) "h", val -+#define SPA_POD_None() "P", NULL -+#define SPA_POD_Pod(val) "P", val -+#define SPA_POD_PodObject(val) "O", val -+#define SPA_POD_PodStruct(val) "T", val -+#define SPA_POD_PodChoice(val) "V", val -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_POD_VARARG_H */ -diff --git a/third_party/pipewire/spa/support/cpu.h b/third_party/pipewire/spa/support/cpu.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/cpu.h -@@ -0,0 +1,126 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_CPU_H -+#define SPA_CPU_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+/** -+ * The CPU features interface -+ */ -+#define SPA_TYPE_INTERFACE_CPU SPA_TYPE_INFO_INTERFACE_BASE "CPU" -+ -+#define SPA_VERSION_CPU 0 -+struct spa_cpu { struct spa_interface iface; }; -+ -+/* x86 specific */ -+#define SPA_CPU_FLAG_MMX (1<<0) /**< standard MMX */ -+#define SPA_CPU_FLAG_MMXEXT (1<<1) /**< SSE integer or AMD MMX ext */ -+#define SPA_CPU_FLAG_3DNOW (1<<2) /**< AMD 3DNOW */ -+#define SPA_CPU_FLAG_SSE (1<<3) /**< SSE */ -+#define SPA_CPU_FLAG_SSE2 (1<<4) /**< SSE2 */ -+#define SPA_CPU_FLAG_3DNOWEXT (1<<5) /**< AMD 3DNowExt */ -+#define SPA_CPU_FLAG_SSE3 (1<<6) /**< Prescott SSE3 */ -+#define SPA_CPU_FLAG_SSSE3 (1<<7) /**< Conroe SSSE3 */ -+#define SPA_CPU_FLAG_SSE41 (1<<8) /**< Penryn SSE4.1 */ -+#define SPA_CPU_FLAG_SSE42 (1<<9) /**< Nehalem SSE4.2 */ -+#define SPA_CPU_FLAG_AESNI (1<<10) /**< Advanced Encryption Standard */ -+#define SPA_CPU_FLAG_AVX (1<<11) /**< AVX */ -+#define SPA_CPU_FLAG_XOP (1<<12) /**< Bulldozer XOP */ -+#define SPA_CPU_FLAG_FMA4 (1<<13) /**< Bulldozer FMA4 */ -+#define SPA_CPU_FLAG_CMOV (1<<14) /**< supports cmov */ -+#define SPA_CPU_FLAG_AVX2 (1<<15) /**< AVX2 */ -+#define SPA_CPU_FLAG_FMA3 (1<<16) /**< Haswell FMA3 */ -+#define SPA_CPU_FLAG_BMI1 (1<<17) /**< Bit Manipulation Instruction Set 1 */ -+#define SPA_CPU_FLAG_BMI2 (1<<18) /**< Bit Manipulation Instruction Set 2 */ -+#define SPA_CPU_FLAG_AVX512 (1<<19) /**< AVX-512 */ -+#define SPA_CPU_FLAG_SLOW_UNALIGNED (1<<20) /**< unaligned loads/stores are slow */ -+ -+/* PPC specific */ -+#define SPA_CPU_FLAG_ALTIVEC (1<<0) /**< standard */ -+#define SPA_CPU_FLAG_VSX (1<<1) /**< ISA 2.06 */ -+#define SPA_CPU_FLAG_POWER8 (1<<2) /**< ISA 2.07 */ -+ -+/* ARM specific */ -+#define SPA_CPU_FLAG_ARMV5TE (1 << 0) -+#define SPA_CPU_FLAG_ARMV6 (1 << 1) -+#define SPA_CPU_FLAG_ARMV6T2 (1 << 2) -+#define SPA_CPU_FLAG_VFP (1 << 3) -+#define SPA_CPU_FLAG_VFPV3 (1 << 4) -+#define SPA_CPU_FLAG_NEON (1 << 5) -+#define SPA_CPU_FLAG_ARMV8 (1 << 6) -+ -+#define SPA_CPU_FORCE_AUTODETECT ((uint32_t)-1) -+/** -+ * methods -+ */ -+struct spa_cpu_methods { -+ /** the version of the methods. This can be used to expand this -+ structure in the future */ -+#define SPA_VERSION_CPU_METHODS 0 -+ uint32_t version; -+ -+ /** get CPU flags */ -+ uint32_t (*get_flags) (void *object); -+ -+ /** force CPU flags, use SPA_CPU_FORCE_AUTODETECT to autodetect CPU flags */ -+ int (*force_flags) (void *object, uint32_t flags); -+ -+ /** get number of CPU cores */ -+ uint32_t (*get_count) (void *object); -+ -+ /** get maximum required alignment of data */ -+ uint32_t (*get_max_align) (void *object); -+}; -+ -+#define spa_cpu_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_cpu *_c = o; \ -+ spa_interface_call_res(&_c->iface, \ -+ struct spa_cpu_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+#define spa_cpu_get_flags(c) spa_cpu_method(c, get_flags, 0) -+#define spa_cpu_force_flags(c,f) spa_cpu_method(c, force_flags, 0, f) -+#define spa_cpu_get_count(c) spa_cpu_method(c, get_count, 0) -+#define spa_cpu_get_max_align(c) spa_cpu_method(c, get_max_align, 0) -+ -+/** keys can be given when initializing the cpu handle */ -+#define SPA_KEY_CPU_FORCE "cpu.force" /**< force cpu flags */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_CPU_H */ -diff --git a/third_party/pipewire/spa/support/dbus.h b/third_party/pipewire/spa/support/dbus.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/dbus.h -@@ -0,0 +1,100 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DBUS_H -+#define SPA_DBUS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#define SPA_TYPE_INTERFACE_DBus SPA_TYPE_INFO_INTERFACE_BASE "DBus" -+ -+#define SPA_VERSION_DBUS 0 -+struct spa_dbus { struct spa_interface iface; }; -+ -+enum spa_dbus_type { -+ SPA_DBUS_TYPE_SESSION, /**< The login session bus */ -+ SPA_DBUS_TYPE_SYSTEM, /**< The systemwide bus */ -+ SPA_DBUS_TYPE_STARTER /**< The bus that started us, if any */ -+}; -+ -+struct spa_dbus_connection { -+#define SPA_VERSION_DBUS_CONNECTION 0 -+ uint32_t version; -+ /** -+ * Get the DBusConnection from a wrapper -+ * -+ * \param conn the spa_dbus_connection wrapper -+ * \return a pointer of type DBusConnection -+ */ -+ void *(*get) (struct spa_dbus_connection *conn); -+ /** -+ * Destroy a dbus connection wrapper -+ * -+ * \param conn the wrapper to destroy -+ */ -+ void (*destroy) (struct spa_dbus_connection *conn); -+}; -+ -+#define spa_dbus_connection_get(c) (c)->get((c)) -+#define spa_dbus_connection_destroy(c) (c)->destroy((c)) -+ -+struct spa_dbus_methods { -+#define SPA_VERSION_DBUS_METHODS 0 -+ uint32_t version; -+ -+ /** -+ * Get a new connection wrapper for the given bus type. -+ * -+ * The connection wrapper is completely configured to operate -+ * in the main context of the handle that manages the spa_dbus -+ * interface. -+ * -+ * \param dbus the dbus manager -+ * \param type the bus type to wrap -+ * \param error location for the DBusError -+ * \return a new dbus connection wrapper or NULL on error -+ */ -+ struct spa_dbus_connection * (*get_connection) (void *object, -+ enum spa_dbus_type type); -+}; -+ -+static inline struct spa_dbus_connection * -+spa_dbus_get_connection(struct spa_dbus *dbus, enum spa_dbus_type type) -+{ -+ struct spa_dbus_connection *res = NULL; -+ spa_interface_call_res(&dbus->iface, -+ struct spa_dbus_methods, res, -+ get_connection, 0, type); -+ return res; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DBUS_H */ -diff --git a/third_party/pipewire/spa/support/log-impl.h b/third_party/pipewire/spa/support/log-impl.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/log-impl.h -@@ -0,0 +1,86 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOG_IMPL_H -+#define SPA_LOG_IMPL_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+static inline SPA_PRINTF_FUNC(6, 0) void spa_log_impl_logv(void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, -+ va_list args) -+{ -+ char text[512], location[1024]; -+ static const char *levels[] = { "-", "E", "W", "I", "D", "T" }; -+ -+ vsnprintf(text, sizeof(text), fmt, args); -+ snprintf(location, sizeof(location), "[%s][%s:%i %s()] %s\n", -+ levels[level], strrchr(file, '/') + 1, line, func, text); -+ fputs(location, stderr); -+} -+static inline SPA_PRINTF_FUNC(6,7) void spa_log_impl_log(void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, ...) -+{ -+ va_list args; -+ va_start(args, fmt); -+ spa_log_impl_logv(object, level, file, line, func, fmt, args); -+ va_end(args); -+} -+ -+#define SPA_LOG_IMPL_DEFINE(name) \ -+struct { \ -+ struct spa_log log; \ -+ struct spa_log_methods methods; \ -+} name -+ -+#define SPA_LOG_IMPL_INIT(name) \ -+ { { { SPA_TYPE_INTERFACE_Log, SPA_VERSION_LOG, \ -+ SPA_CALLBACKS_INIT(&name.methods, &name) }, \ -+ SPA_LOG_LEVEL_INFO, }, \ -+ { SPA_VERSION_LOG_METHODS, \ -+ spa_log_impl_log, \ -+ spa_log_impl_logv,} } -+ -+#define SPA_LOG_IMPL(name) \ -+ SPA_LOG_IMPL_DEFINE(name) = SPA_LOG_IMPL_INIT(name) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+#endif /* SPA_LOG_IMPL_H */ -diff --git a/third_party/pipewire/spa/support/log.h b/third_party/pipewire/spa/support/log.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/log.h -@@ -0,0 +1,179 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOG_H -+#define SPA_LOG_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+#include -+ -+enum spa_log_level { -+ SPA_LOG_LEVEL_NONE = 0, -+ SPA_LOG_LEVEL_ERROR, -+ SPA_LOG_LEVEL_WARN, -+ SPA_LOG_LEVEL_INFO, -+ SPA_LOG_LEVEL_DEBUG, -+ SPA_LOG_LEVEL_TRACE, -+}; -+ -+/** -+ * The Log interface -+ */ -+#define SPA_TYPE_INTERFACE_Log SPA_TYPE_INFO_INTERFACE_BASE "Log" -+ -+#define SPA_VERSION_LOG 0 -+ -+struct spa_log { -+ /** the version of this log. This can be used to expand this -+ * structure in the future */ -+ struct spa_interface iface; -+ /** -+ * Logging level, everything above this level is not logged -+ */ -+ enum spa_log_level level; -+}; -+ -+struct spa_log_methods { -+#define SPA_VERSION_LOG_METHODS 0 -+ uint32_t version; -+ /** -+ * Log a message with the given log level. -+ * -+ * \param log a spa_log -+ * \param level a spa_log_level -+ * \param file the file name -+ * \param line the line number -+ * \param func the function name -+ * \param fmt printf style format -+ * \param ... format arguments -+ */ -+ void (*log) (void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, ...) SPA_PRINTF_FUNC(6, 7); -+ -+ /** -+ * Log a message with the given log level. -+ * -+ * \param log a spa_log -+ * \param level a spa_log_level -+ * \param file the file name -+ * \param line the line number -+ * \param func the function name -+ * \param fmt printf style format -+ * \param args format arguments -+ */ -+ void (*logv) (void *object, -+ enum spa_log_level level, -+ const char *file, -+ int line, -+ const char *func, -+ const char *fmt, -+ va_list args) SPA_PRINTF_FUNC(6, 0); -+}; -+ -+#define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev)) -+ -+#if defined(__USE_ISOC11) || defined(__USE_ISOC99) || \ -+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) -+ -+#define spa_log_log(l,lev,...) \ -+({ \ -+ struct spa_log *_l = l; \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ -+ spa_interface_call(&_l->iface, \ -+ struct spa_log_methods, log, 0, lev, \ -+ __VA_ARGS__); \ -+}) -+ -+#define spa_log_logv(l,lev,...) \ -+({ \ -+ struct spa_log *_l = l; \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(_l, lev))) \ -+ spa_interface_call(&_l->iface, \ -+ struct spa_log_methods, logv, 0, lev, \ -+ __VA_ARGS__); \ -+}) -+ -+#define spa_log_error(l,...) spa_log_log(l,SPA_LOG_LEVEL_ERROR,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_warn(l,...) spa_log_log(l,SPA_LOG_LEVEL_WARN,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_info(l,...) spa_log_log(l,SPA_LOG_LEVEL_INFO,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_debug(l,...) spa_log_log(l,SPA_LOG_LEVEL_DEBUG,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#define spa_log_trace(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) -+ -+#ifndef FASTPATH -+#define spa_log_trace_fp(l,...) spa_log_log(l,SPA_LOG_LEVEL_TRACE,__FILE__,__LINE__,__func__,__VA_ARGS__) -+#else -+#define spa_log_trace_fp(l,...) -+#endif -+ -+#else -+ -+#define SPA_LOG_FUNC(name,lev) \ -+static inline SPA_PRINTF_FUNC(2,3) void spa_log_##name (struct spa_log *l, const char *format, ...) \ -+{ \ -+ if (SPA_UNLIKELY(spa_log_level_enabled(l, lev))) { \ -+ va_list varargs; \ -+ va_start (varargs, format); \ -+ spa_interface_call(&l->iface, \ -+ struct spa_log_methods, logv, 0, lev, \ -+ __FILE__,__LINE__,__func__,format,varargs); \ -+ va_end (varargs); \ -+ } \ -+} -+ -+SPA_LOG_FUNC(error, SPA_LOG_LEVEL_ERROR) -+SPA_LOG_FUNC(warn, SPA_LOG_LEVEL_WARN) -+SPA_LOG_FUNC(info, SPA_LOG_LEVEL_INFO) -+SPA_LOG_FUNC(debug, SPA_LOG_LEVEL_DEBUG) -+SPA_LOG_FUNC(trace, SPA_LOG_LEVEL_TRACE) -+ -+#ifndef FASTPATH -+SPA_LOG_FUNC(trace_fp, SPA_LOG_LEVEL_TRACE) -+#else -+static inline void spa_log_trace_fp (struct spa_log *l, const char *format, ...) { } -+#endif -+ -+#endif -+ -+/** keys can be given when initializing the logger handle */ -+#define SPA_KEY_LOG_LEVEL "log.level" /**< the default log level */ -+#define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger */ -+#define SPA_KEY_LOG_FILE "log.file" /**< log to the specified file instead of -+ * stderr. */ -+#define SPA_KEY_LOG_TIMESTAMP "log.timestamp" /**< log timestamps */ -+#define SPA_KEY_LOG_LINE "log.line" /**< log file and line numbers */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+#endif /* SPA_LOG_H */ -diff --git a/third_party/pipewire/spa/support/loop.h b/third_party/pipewire/spa/support/loop.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/loop.h -@@ -0,0 +1,312 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LOOP_H -+#define SPA_LOOP_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+#include -+ -+#define SPA_TYPE_INTERFACE_Loop SPA_TYPE_INFO_INTERFACE_BASE "Loop" -+#define SPA_TYPE_INTERFACE_DataLoop SPA_TYPE_INFO_INTERFACE_BASE "DataLoop" -+#define SPA_VERSION_LOOP 0 -+struct spa_loop { struct spa_interface iface; }; -+ -+#define SPA_TYPE_INTERFACE_LoopControl SPA_TYPE_INFO_INTERFACE_BASE "LoopControl" -+#define SPA_VERSION_LOOP_CONTROL 0 -+struct spa_loop_control { struct spa_interface iface; }; -+ -+#define SPA_TYPE_INTERFACE_LoopUtils SPA_TYPE_INFO_INTERFACE_BASE "LoopUtils" -+#define SPA_VERSION_LOOP_UTILS 0 -+struct spa_loop_utils { struct spa_interface iface; }; -+ -+struct spa_source; -+ -+typedef void (*spa_source_func_t) (struct spa_source *source); -+ -+struct spa_source { -+ struct spa_loop *loop; -+ spa_source_func_t func; -+ void *data; -+ int fd; -+ uint32_t mask; -+ uint32_t rmask; -+}; -+ -+typedef int (*spa_invoke_func_t) (struct spa_loop *loop, -+ bool async, -+ uint32_t seq, -+ const void *data, -+ size_t size, -+ void *user_data); -+ -+/** -+ * Register sources and work items to an event loop -+ */ -+struct spa_loop_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_METHODS 0 -+ uint32_t version; -+ -+ /** add a source to the loop */ -+ int (*add_source) (void *object, -+ struct spa_source *source); -+ -+ /** update the source io mask */ -+ int (*update_source) (void *object, -+ struct spa_source *source); -+ -+ /** remove a source from the loop */ -+ int (*remove_source) (void *object, -+ struct spa_source *source); -+ -+ /** invoke a function in the context of this loop */ -+ int (*invoke) (void *object, -+ spa_invoke_func_t func, -+ uint32_t seq, -+ const void *data, -+ size_t size, -+ bool block, -+ void *user_data); -+}; -+ -+#define spa_loop_method(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_loop_add_source(l,...) spa_loop_method(l,add_source,0,##__VA_ARGS__) -+#define spa_loop_update_source(l,...) spa_loop_method(l,update_source,0,##__VA_ARGS__) -+#define spa_loop_remove_source(l,...) spa_loop_method(l,remove_source,0,##__VA_ARGS__) -+#define spa_loop_invoke(l,...) spa_loop_method(l,invoke,0,##__VA_ARGS__) -+ -+ -+/** Control hooks. These hooks can't be removed from their -+ * callbacks and must be removed from a safe place (when the loop -+ * is not running or when it is locked). */ -+struct spa_loop_control_hooks { -+#define SPA_VERSION_LOOP_CONTROL_HOOKS 0 -+ uint32_t version; -+ /** Executed right before waiting for events. It is typically used to -+ * release locks. */ -+ void (*before) (void *data); -+ /** Executed right after waiting for events. It is typically used to -+ * reacquire locks. */ -+ void (*after) (void *data); -+}; -+ -+#define spa_loop_control_hook_before(l) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h; \ -+ spa_list_for_each_reverse(_h, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, before, 0); \ -+}) -+ -+#define spa_loop_control_hook_after(l) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h; \ -+ spa_list_for_each(_h, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb, struct spa_loop_control_hooks, after, 0); \ -+}) -+ -+/** -+ * Control an event loop -+ */ -+struct spa_loop_control_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_CONTROL_METHODS 0 -+ uint32_t version; -+ -+ int (*get_fd) (void *object); -+ -+ /** Add a hook -+ * \param ctrl the control to change -+ * \param hooks the hooks to add -+ * -+ * Adds hooks to the loop controlled by \a ctrl. -+ */ -+ void (*add_hook) (void *object, -+ struct spa_hook *hook, -+ const struct spa_loop_control_hooks *hooks, -+ void *data); -+ -+ /** Enter a loop -+ * \param ctrl the control -+ * -+ * Start an iteration of the loop. This function should be called -+ * before calling iterate and is typically used to capture the thread -+ * that this loop will run in. -+ */ -+ void (*enter) (void *object); -+ /** Leave a loop -+ * \param ctrl the control -+ * -+ * Ends the iteration of a loop. This should be called after calling -+ * iterate. -+ */ -+ void (*leave) (void *object); -+ -+ /** Perform one iteration of the loop. -+ * \param ctrl the control -+ * \param timeout an optional timeout in milliseconds. -+ * 0 for no timeout, -1 for infinite timeout. -+ * -+ * This function will block -+ * up to \a timeout milliseconds and then dispatch the fds with activity. -+ * The number of dispatched fds is returned. -+ */ -+ int (*iterate) (void *object, int timeout); -+}; -+ -+#define spa_loop_control_method_v(o,method,version,...) \ -+({ \ -+ struct spa_loop_control *_o = o; \ -+ spa_interface_call(&_o->iface, \ -+ struct spa_loop_control_methods, \ -+ method, version, ##__VA_ARGS__); \ -+}) -+ -+#define spa_loop_control_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop_control *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_control_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+#define spa_loop_control_get_fd(l) spa_loop_control_method_r(l,get_fd,0) -+#define spa_loop_control_add_hook(l,...) spa_loop_control_method_v(l,add_hook,0,__VA_ARGS__) -+#define spa_loop_control_enter(l) spa_loop_control_method_v(l,enter,0) -+#define spa_loop_control_leave(l) spa_loop_control_method_v(l,leave,0) -+#define spa_loop_control_iterate(l,...) spa_loop_control_method_r(l,iterate,0,__VA_ARGS__) -+ -+typedef void (*spa_source_io_func_t) (void *data, int fd, uint32_t mask); -+typedef void (*spa_source_idle_func_t) (void *data); -+typedef void (*spa_source_event_func_t) (void *data, uint64_t count); -+typedef void (*spa_source_timer_func_t) (void *data, uint64_t expirations); -+typedef void (*spa_source_signal_func_t) (void *data, int signal_number); -+ -+/** -+ * Create sources for an event loop -+ */ -+struct spa_loop_utils_methods { -+ /* the version of this structure. This can be used to expand this -+ * structure in the future */ -+#define SPA_VERSION_LOOP_UTILS_METHODS 0 -+ uint32_t version; -+ -+ struct spa_source *(*add_io) (void *object, -+ int fd, -+ uint32_t mask, -+ bool close, -+ spa_source_io_func_t func, void *data); -+ -+ int (*update_io) (void *object, struct spa_source *source, uint32_t mask); -+ -+ struct spa_source *(*add_idle) (void *object, -+ bool enabled, -+ spa_source_idle_func_t func, void *data); -+ int (*enable_idle) (void *object, struct spa_source *source, bool enabled); -+ -+ struct spa_source *(*add_event) (void *object, -+ spa_source_event_func_t func, void *data); -+ int (*signal_event) (void *object, struct spa_source *source); -+ -+ struct spa_source *(*add_timer) (void *object, -+ spa_source_timer_func_t func, void *data); -+ int (*update_timer) (void *object, -+ struct spa_source *source, -+ struct timespec *value, -+ struct timespec *interval, -+ bool absolute); -+ struct spa_source *(*add_signal) (void *object, -+ int signal_number, -+ spa_source_signal_func_t func, void *data); -+ -+ /** destroy a source allocated with this interface. This function -+ * should only be called when the loop is not running or from the -+ * context of the running loop */ -+ void (*destroy_source) (void *object, struct spa_source *source); -+}; -+ -+#define spa_loop_utils_method_v(o,method,version,...) \ -+({ \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call(&_o->iface, \ -+ struct spa_loop_utils_methods, \ -+ method, version, ##__VA_ARGS__); \ -+}) -+ -+#define spa_loop_utils_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_utils_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+#define spa_loop_utils_method_s(o,method,version,...) \ -+({ \ -+ struct spa_source *_res = NULL; \ -+ struct spa_loop_utils *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_loop_utils_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+ -+#define spa_loop_utils_add_io(l,...) spa_loop_utils_method_s(l,add_io,0,__VA_ARGS__) -+#define spa_loop_utils_update_io(l,...) spa_loop_utils_method_r(l,update_io,0,__VA_ARGS__) -+#define spa_loop_utils_add_idle(l,...) spa_loop_utils_method_s(l,add_idle,0,__VA_ARGS__) -+#define spa_loop_utils_enable_idle(l,...) spa_loop_utils_method_r(l,enable_idle,0,__VA_ARGS__) -+#define spa_loop_utils_add_event(l,...) spa_loop_utils_method_s(l,add_event,0,__VA_ARGS__) -+#define spa_loop_utils_signal_event(l,...) spa_loop_utils_method_r(l,signal_event,0,__VA_ARGS__) -+#define spa_loop_utils_add_timer(l,...) spa_loop_utils_method_s(l,add_timer,0,__VA_ARGS__) -+#define spa_loop_utils_update_timer(l,...) spa_loop_utils_method_r(l,update_timer,0,__VA_ARGS__) -+#define spa_loop_utils_add_signal(l,...) spa_loop_utils_method_s(l,add_signal,0,__VA_ARGS__) -+#define spa_loop_utils_destroy_source(l,...) spa_loop_utils_method_v(l,destroy_source,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_LOOP_H */ -diff --git a/third_party/pipewire/spa/support/plugin.h b/third_party/pipewire/spa/support/plugin.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/plugin.h -@@ -0,0 +1,215 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_PLUGIN_H -+#define SPA_PLUGIN_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+struct spa_handle { -+ /** Version of this struct */ -+#define SPA_VERSION_HANDLE 0 -+ uint32_t version; -+ -+ /** -+ * Get the interface provided by \a handle with \a type. -+ * -+ * \a interface is always a struct spa_interface but depending on -+ * \a type, the struct might contain other information. -+ * -+ * \param handle a spa_handle -+ * \param type the interface type -+ * \param interface result to hold the interface. -+ * \return 0 on success -+ * -ENOTSUP when there are no interfaces -+ * -EINVAL when handle or info is NULL -+ */ -+ int (*get_interface) (struct spa_handle *handle, const char *type, void **interface); -+ /** -+ * Clean up the memory of \a handle. After this, \a handle should not be used -+ * anymore. -+ * -+ * \param handle a pointer to memory -+ * \return 0 on success -+ */ -+ int (*clear) (struct spa_handle *handle); -+}; -+ -+#define spa_handle_get_interface(h,...) (h)->get_interface((h),__VA_ARGS__) -+#define spa_handle_clear(h) (h)->clear((h)) -+ -+/** -+ * This structure lists the information about available interfaces on -+ * handles. -+ */ -+struct spa_interface_info { -+ const char *type; /*< the type of the interface, can be -+ * used to get the interface */ -+}; -+ -+/** -+ * Extra supporting infrastructure passed to the init() function of -+ * a factory. It can be extra information or interfaces such as logging. -+ */ -+struct spa_support { -+ const char *type; /*< the type of the support item */ -+ void *data; /*< specific data for the item */ -+}; -+ -+/** Find a support item of the given type */ -+static inline void *spa_support_find(const struct spa_support *support, -+ uint32_t n_support, -+ const char *type) -+{ -+ uint32_t i; -+ for (i = 0; i < n_support; i++) { -+ if (strcmp(support[i].type, type) == 0) -+ return support[i].data; -+ } -+ return NULL; -+} -+ -+#define SPA_SUPPORT_INIT(type,data) (struct spa_support) { (type), (data) } -+ -+struct spa_handle_factory { -+ /** The version of this structure */ -+#define SPA_VERSION_HANDLE_FACTORY 1 -+ uint32_t version; -+ /** -+ * The name of the factory contains a logical name that describes -+ * the function of the handle. Other plugins might contain an alternative -+ * implementation with the same name. -+ * -+ * See utils/names.h for the list of standard names. -+ * -+ * Examples include: -+ * -+ * api.alsa.pcm.sink: an object to write PCM samples to an alsa PLAYBACK -+ * device -+ * api.v4l2.source: an object to read from a v4l2 source. -+ */ -+ const char *name; -+ /** -+ * Extra information about the handles of this factory. -+ */ -+ const struct spa_dict *info; -+ /** -+ * Get the size of handles from this factory. -+ * -+ * \param factory a spa_handle_factory -+ * \param params extra parameters that determine the size of the -+ * handle. -+ */ -+ size_t (*get_size) (const struct spa_handle_factory *factory, -+ const struct spa_dict *params); -+ -+ /** -+ * Initialize an instance of this factory. The caller should allocate -+ * memory at least size bytes and pass this as \a handle. -+ * -+ * \a support can optionally contain extra interfaces or data items that the -+ * plugin can use such as a logger. -+ * -+ * \param factory a spa_handle_factory -+ * \param handle a pointer to memory -+ * \param info extra handle specific information, usually obtained -+ * from a spa_device. This can be used to configure the handle. -+ * \param support support items -+ * \param n_support number of elements in \a support -+ * \return 0 on success -+ * < 0 errno type error -+ */ -+ int (*init) (const struct spa_handle_factory *factory, -+ struct spa_handle *handle, -+ const struct spa_dict *info, -+ const struct spa_support *support, -+ uint32_t n_support); -+ -+ /** -+ * spa_handle_factory::enum_interface_info: -+ * \param factory: a #spa_handle_factory -+ * \param info: result to hold spa_interface_info. -+ * \param index: index to keep track of the enumeration, 0 for first item -+ * -+ * Enumerate the interface information for \a factory. -+ * -+ * \return 1 when an item is available -+ * 0 when no more items are available -+ * < 0 errno type error -+ */ -+ int (*enum_interface_info) (const struct spa_handle_factory *factory, -+ const struct spa_interface_info **info, -+ uint32_t *index); -+}; -+ -+#define spa_handle_factory_get_size(h,...) (h)->get_size((h),__VA_ARGS__) -+#define spa_handle_factory_init(h,...) (h)->init((h),__VA_ARGS__) -+#define spa_handle_factory_enum_interface_info(h,...) (h)->enum_interface_info((h),__VA_ARGS__) -+ -+/** -+ * The function signature of the entry point in a plugin. -+ * -+ * \param factory a location to hold the factory result -+ * \param index index to keep track of the enumeration -+ * \return 1 on success -+ * 0 when there are no more factories -+ * -EINVAL when factory is NULL -+ */ -+typedef int (*spa_handle_factory_enum_func_t) (const struct spa_handle_factory **factory, -+ uint32_t *index); -+ -+#define SPA_HANDLE_FACTORY_ENUM_FUNC_NAME "spa_handle_factory_enum" -+ -+/** -+ * The entry point in a plugin. -+ * -+ * \param factory a location to hold the factory result -+ * \param index index to keep track of the enumeration -+ * \return 1 on success -+ * 0 when no more items are available -+ * < 0 errno type error -+ */ -+int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index); -+ -+ -+ -+#define SPA_KEY_FACTORY_NAME "factory.name" /**< the name of a factory */ -+#define SPA_KEY_FACTORY_AUTHOR "factory.author" /**< a comma separated list of factory authors */ -+#define SPA_KEY_FACTORY_DESCRIPTION "factory.description" /**< description of a factory */ -+#define SPA_KEY_FACTORY_USAGE "factory.usage" /**< usage of a factory */ -+ -+#define SPA_KEY_LIBRARY_NAME "library.name" /**< the name of a library. This is usually -+ * the filename of the plugin without the -+ * path or the plugin extension. */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_PLUGIN_H */ -diff --git a/third_party/pipewire/spa/support/system.h b/third_party/pipewire/spa/support/system.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/support/system.h -@@ -0,0 +1,152 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_SYSTEM_H -+#define SPA_SYSTEM_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct itimerspec; -+ -+#include -+#include -+ -+#include -+#include -+ -+/** -+ * a collection of core system functions -+ */ -+#define SPA_TYPE_INTERFACE_System SPA_TYPE_INFO_INTERFACE_BASE "System" -+#define SPA_TYPE_INTERFACE_DataSystem SPA_TYPE_INFO_INTERFACE_BASE "DataSystem" -+ -+#define SPA_VERSION_SYSTEM 0 -+struct spa_system { struct spa_interface iface; }; -+ -+/* IO events */ -+#define SPA_IO_IN (1 << 0) -+#define SPA_IO_OUT (1 << 2) -+#define SPA_IO_ERR (1 << 3) -+#define SPA_IO_HUP (1 << 4) -+ -+/* flags */ -+#define SPA_FD_CLOEXEC (1<<0) -+#define SPA_FD_NONBLOCK (1<<1) -+#define SPA_FD_EVENT_SEMAPHORE (1<<2) -+#define SPA_FD_TIMER_ABSTIME (1<<3) -+#define SPA_FD_TIMER_CANCEL_ON_SET (1<<4) -+ -+struct spa_poll_event { -+ uint32_t events; -+ void *data; -+}; -+ -+struct spa_system_methods { -+#define SPA_VERSION_SYSTEM_METHODS 0 -+ uint32_t version; -+ -+ /* read/write/ioctl */ -+ ssize_t (*read) (void *object, int fd, void *buf, size_t count); -+ ssize_t (*write) (void *object, int fd, const void *buf, size_t count); -+ int (*ioctl) (void *object, int fd, unsigned long request, ...); -+ int (*close) (void *object, int fd); -+ -+ /* clock */ -+ int (*clock_gettime) (void *object, -+ int clockid, struct timespec *value); -+ int (*clock_getres) (void *object, -+ int clockid, struct timespec *res); -+ -+ /* poll */ -+ int (*pollfd_create) (void *object, int flags); -+ int (*pollfd_add) (void *object, int pfd, int fd, uint32_t events, void *data); -+ int (*pollfd_mod) (void *object, int pfd, int fd, uint32_t events, void *data); -+ int (*pollfd_del) (void *object, int pfd, int fd); -+ int (*pollfd_wait) (void *object, int pfd, -+ struct spa_poll_event *ev, int n_ev, int timeout); -+ -+ /* timers */ -+ int (*timerfd_create) (void *object, int clockid, int flags); -+ int (*timerfd_settime) (void *object, -+ int fd, int flags, -+ const struct itimerspec *new_value, -+ struct itimerspec *old_value); -+ int (*timerfd_gettime) (void *object, -+ int fd, struct itimerspec *curr_value); -+ int (*timerfd_read) (void *object, int fd, uint64_t *expirations); -+ -+ /* events */ -+ int (*eventfd_create) (void *object, int flags); -+ int (*eventfd_write) (void *object, int fd, uint64_t count); -+ int (*eventfd_read) (void *object, int fd, uint64_t *count); -+ -+ /* signals */ -+ int (*signalfd_create) (void *object, int signal, int flags); -+ int (*signalfd_read) (void *object, int fd, int *signal); -+}; -+ -+#define spa_system_method_r(o,method,version,...) \ -+({ \ -+ int _res = -ENOTSUP; \ -+ struct spa_system *_o = o; \ -+ spa_interface_call_res(&_o->iface, \ -+ struct spa_system_methods, _res, \ -+ method, version, ##__VA_ARGS__); \ -+ _res; \ -+}) -+ -+ -+#define spa_system_read(s,...) spa_system_method_r(s,read,0,__VA_ARGS__) -+#define spa_system_write(s,...) spa_system_method_r(s,write,0,__VA_ARGS__) -+#define spa_system_ioctl(s,...) spa_system_method_r(s,ioctl,0,__VA_ARGS__) -+#define spa_system_close(s,...) spa_system_method_r(s,close,0,__VA_ARGS__) -+ -+#define spa_system_clock_gettime(s,...) spa_system_method_r(s,clock_gettime,0,__VA_ARGS__) -+#define spa_system_clock_getres(s,...) spa_system_method_r(s,clock_getres,0,__VA_ARGS__) -+ -+#define spa_system_pollfd_create(s,...) spa_system_method_r(s,pollfd_create,0,__VA_ARGS__) -+#define spa_system_pollfd_add(s,...) spa_system_method_r(s,pollfd_add,0,__VA_ARGS__) -+#define spa_system_pollfd_mod(s,...) spa_system_method_r(s,pollfd_mod,0,__VA_ARGS__) -+#define spa_system_pollfd_del(s,...) spa_system_method_r(s,pollfd_del,0,__VA_ARGS__) -+#define spa_system_pollfd_wait(s,...) spa_system_method_r(s,pollfd_wait,0,__VA_ARGS__) -+ -+#define spa_system_timerfd_create(s,...) spa_system_method_r(s,timerfd_create,0,__VA_ARGS__) -+#define spa_system_timerfd_settime(s,...) spa_system_method_r(s,timerfd_settime,0,__VA_ARGS__) -+#define spa_system_timerfd_gettime(s,...) spa_system_method_r(s,timerfd_gettime,0,__VA_ARGS__) -+#define spa_system_timerfd_read(s,...) spa_system_method_r(s,timerfd_read,0,__VA_ARGS__) -+ -+#define spa_system_eventfd_create(s,...) spa_system_method_r(s,eventfd_create,0,__VA_ARGS__) -+#define spa_system_eventfd_write(s,...) spa_system_method_r(s,eventfd_write,0,__VA_ARGS__) -+#define spa_system_eventfd_read(s,...) spa_system_method_r(s,eventfd_read,0,__VA_ARGS__) -+ -+#define spa_system_signalfd_create(s,...) spa_system_method_r(s,signalfd_create,0,__VA_ARGS__) -+#define spa_system_signalfd_read(s,...) spa_system_method_r(s,signalfd_read,0,__VA_ARGS__) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_SYSTEM_H */ -diff --git a/third_party/pipewire/spa/utils/defs.h b/third_party/pipewire/spa/utils/defs.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/defs.h -@@ -0,0 +1,265 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_DEFS_H -+#define SPA_UTILS_DEFS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#else -+#include -+#endif -+#include -+#include -+#include -+#include -+#include -+ -+#define SPA_FLAG_MASK(field,mask,flag) (((field) & (mask)) == (flag)) -+#define SPA_FLAG_IS_SET(field,flag) SPA_FLAG_MASK(field,flag,flag) -+#define SPA_FLAG_SET(field,flag) ((field) |= (flag)) -+#define SPA_FLAG_CLEAR(field,flag) ((field) &= ~(flag)) -+#define SPA_FLAG_UPDATE(field,flag,val) ((val) ? SPA_FLAG_SET(field,flag) : SPA_FLAG_CLEAR(field,flag)) -+ -+enum spa_direction { -+ SPA_DIRECTION_INPUT = 0, -+ SPA_DIRECTION_OUTPUT = 1, -+}; -+ -+#define SPA_DIRECTION_REVERSE(d) ((d) ^ 1) -+ -+#define SPA_RECTANGLE(width,height) (struct spa_rectangle){ width, height } -+struct spa_rectangle { -+ uint32_t width; -+ uint32_t height; -+}; -+ -+#define SPA_POINT(x,y) (struct spa_point){ x, y } -+struct spa_point { -+ int32_t x; -+ int32_t y; -+}; -+ -+#define SPA_REGION(x,y,width,height) (struct spa_region){ SPA_POINT(x,y), SPA_RECTANGLE(width,height) } -+struct spa_region { -+ struct spa_point position; -+ struct spa_rectangle size; -+}; -+ -+#define SPA_FRACTION(num,denom) (struct spa_fraction){ num, denom } -+struct spa_fraction { -+ uint32_t num; -+ uint32_t denom; -+}; -+ -+#define SPA_N_ELEMENTS(arr) (sizeof(arr) / sizeof((arr)[0])) -+ -+#define SPA_MIN(a,b) \ -+({ \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ -+ SPA_LIKELY(_a < _b) ? _a : _b; \ -+}) -+#define SPA_MAX(a,b) \ -+({ \ -+ __typeof__(a) _a = (a); \ -+ __typeof__(b) _b = (b); \ -+ SPA_LIKELY(_a > _b) ? _a : _b; \ -+}) -+#define SPA_CLAMP(v,low,high) \ -+({ \ -+ __typeof__(v) _v = (v); \ -+ __typeof__(low) _low = (low); \ -+ __typeof__(high) _high = (high); \ -+ SPA_MIN(SPA_MAX(_v, _low), _high); \ -+}) -+ -+#define SPA_SWAP(a,b) \ -+({ \ -+ __typeof__(a) _t = (a); \ -+ a = b; b = _t; \ -+}) -+ -+#define SPA_TYPECHECK(type,x) \ -+({ type _dummy; \ -+ typeof(x) _dummy2; \ -+ (void)(&_dummy == &_dummy2); \ -+ x; \ -+}) -+ -+#define SPA_MEMBER(b,o,t) ((t*)((uint8_t*)(b) + (int)(o))) -+#define SPA_MEMBER_ALIGN(b,o,a,t) SPA_PTR_ALIGN(SPA_MEMBER(b,o,t),a,t) -+ -+#define SPA_CONTAINER_OF(p,t,m) (t*)((uint8_t*)p - offsetof (t,m)) -+ -+#define SPA_PTRDIFF(p1,p2) ((uint8_t*)(p1) - (uint8_t*)(p2)) -+ -+#define SPA_PTR_TO_INT(p) ((int) ((intptr_t) (p))) -+#define SPA_INT_TO_PTR(u) ((void*) ((intptr_t) (u))) -+ -+#define SPA_PTR_TO_UINT32(p) ((uint32_t) ((uintptr_t) (p))) -+#define SPA_UINT32_TO_PTR(u) ((void*) ((uintptr_t) (u))) -+ -+#define SPA_TIME_INVALID ((int64_t)INT64_MIN) -+#define SPA_IDX_INVALID ((unsigned int)-1) -+#define SPA_ID_INVALID ((uint32_t)0xffffffff) -+ -+#define SPA_NSEC_PER_SEC (1000000000ll) -+#define SPA_NSEC_PER_MSEC (1000000ll) -+#define SPA_NSEC_PER_USEC (1000ll) -+#define SPA_USEC_PER_SEC (1000000ll) -+#define SPA_USEC_PER_MSEC (1000ll) -+#define SPA_MSEC_PER_SEC (1000ll) -+ -+#define SPA_TIMESPEC_TO_NSEC(ts) ((ts)->tv_sec * SPA_NSEC_PER_SEC + (ts)->tv_nsec) -+#define SPA_TIMESPEC_TO_USEC(ts) ((ts)->tv_sec * SPA_USEC_PER_SEC + (ts)->tv_nsec / SPA_NSEC_PER_USEC) -+#define SPA_TIMEVAL_TO_NSEC(tv) ((tv)->tv_sec * SPA_NSEC_PER_SEC + (tv)->tv_usec * SPA_NSEC_PER_USEC) -+#define SPA_TIMEVAL_TO_USEC(tv) ((tv)->tv_sec * SPA_USEC_PER_SEC + (tv)->tv_usec) -+ -+#ifdef __GNUC__ -+#define SPA_PRINTF_FUNC(fmt, arg1) __attribute__((format(printf, fmt, arg1))) -+#define SPA_ALIGNED(align) __attribute__((aligned(align))) -+#define SPA_DEPRECATED __attribute__ ((deprecated)) -+#define SPA_EXPORT __attribute__((visibility("default"))) -+#define SPA_SENTINEL __attribute__((__sentinel__)) -+#define SPA_UNUSED __attribute__ ((unused)) -+#else -+#define SPA_PRINTF_FUNC(fmt, arg1) -+#define SPA_ALIGNED(align) -+#define SPA_DEPRECATED -+#define SPA_EXPORT -+#define SPA_SENTINEL -+#define SPA_UNUSED -+#endif -+ -+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L -+#define SPA_RESTRICT restrict -+#elif defined(__GNUC__) && __GNUC__ >= 4 -+#define SPA_RESTRICT __restrict__ -+#else -+#define SPA_RESTRICT -+#endif -+ -+#define SPA_ROUND_DOWN_N(num,align) ((num) & ~((align) - 1)) -+#define SPA_ROUND_UP_N(num,align) SPA_ROUND_DOWN_N((num) + ((align) - 1),align) -+ -+#define SPA_PTR_ALIGNMENT(p,align) ((intptr_t)(p) & ((align)-1)) -+#define SPA_IS_ALIGNED(p,align) (SPA_PTR_ALIGNMENT(p,align) == 0) -+#define SPA_PTR_ALIGN(p,align,type) (type*)SPA_ROUND_UP_N((intptr_t)(p), (intptr_t)(align)) -+ -+#ifndef SPA_LIKELY -+#ifdef __GNUC__ -+#define SPA_LIKELY(x) (__builtin_expect(!!(x),1)) -+#define SPA_UNLIKELY(x) (__builtin_expect(!!(x),0)) -+#else -+#define SPA_LIKELY(x) (x) -+#define SPA_UNLIKELY(x) (x) -+#endif -+#endif -+ -+#define SPA_STRINGIFY_1(...) #__VA_ARGS__ -+#define SPA_STRINGIFY(...) SPA_STRINGIFY_1(__VA_ARGS__) -+ -+#define spa_return_if_fail(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ return; \ -+ } \ -+ } while(false) -+ -+#define spa_return_val_if_fail(expr, val) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ return (val); \ -+ } \ -+ } while(false) -+ -+/* spa_assert_se() is an assert which guarantees side effects of x, -+ * i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */ -+#define spa_assert_se(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } \ -+ } while (false) -+ -+#define spa_assert(expr) \ -+ do { \ -+ if (SPA_UNLIKELY(!(expr))) { \ -+ fprintf(stderr, "'%s' failed at %s:%u %s()\n", \ -+ #expr , __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } \ -+ } while (false) -+ -+#define spa_assert_not_reached() \ -+ do { \ -+ fprintf(stderr, "Code should not be reached at %s:%u %s()\n", \ -+ __FILE__, __LINE__, __func__); \ -+ abort(); \ -+ } while (false) -+ -+/* Does exactly nothing */ -+#define spa_nop() do {} while (false) -+ -+#define spa_memzero(x,l) (memset((x), 0, (l))) -+#define spa_zero(x) (spa_memzero(&(x), sizeof(x))) -+ -+#ifdef SPA_DEBUG_MEMCPY -+#define spa_memcpy(d,s,n) \ -+({ \ -+ fprintf(stderr, "%s:%u %s() memcpy(%p, %p, %zd)\n", \ -+ __FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \ -+ memcpy(d,s,n); \ -+}) -+#define spa_memmove(d,s,n) \ -+({ \ -+ fprintf(stderr, "%s:%u %s() memmove(%p, %p, %zd)\n", \ -+ __FILE__, __LINE__, __func__, (d), (s), (size_t)(n)); \ -+ memmove(d,s,n); \ -+}) -+#else -+#define spa_memcpy(d,s,n) memcpy(d,s,n) -+#define spa_memmove(d,s,n) memmove(d,s,n) -+#endif -+ -+#define spa_aprintf(_fmt, ...) \ -+({ \ -+ char *_strp; \ -+ if (asprintf(&(_strp), (_fmt), ## __VA_ARGS__ ) == -1) \ -+ _strp = NULL; \ -+ _strp; \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_DEFS_H */ -diff --git a/third_party/pipewire/spa/utils/dict.h b/third_party/pipewire/spa/utils/dict.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/dict.h -@@ -0,0 +1,104 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_DICT_H -+#define SPA_DICT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#include -+ -+struct spa_dict_item { -+ const char *key; -+ const char *value; -+}; -+ -+#define SPA_DICT_ITEM_INIT(key,value) (struct spa_dict_item) { key, value } -+ -+struct spa_dict { -+#define SPA_DICT_FLAG_SORTED (1<<0) /**< items are sorted */ -+ uint32_t flags; -+ uint32_t n_items; -+ const struct spa_dict_item *items; -+}; -+ -+#define SPA_DICT_INIT(items,n_items) (struct spa_dict) { 0, n_items, items } -+#define SPA_DICT_INIT_ARRAY(items) (struct spa_dict) { 0, SPA_N_ELEMENTS(items), items } -+ -+#define spa_dict_for_each(item, dict) \ -+ for ((item) = (dict)->items; \ -+ (item) < &(dict)->items[(dict)->n_items]; \ -+ (item)++) -+ -+static inline int spa_dict_item_compare(const void *i1, const void *i2) -+{ -+ const struct spa_dict_item *it1 = (const struct spa_dict_item *)i1, -+ *it2 = (const struct spa_dict_item *)i2; -+ return strcmp(it1->key, it2->key); -+} -+ -+static inline void spa_dict_qsort(struct spa_dict *dict) -+{ -+ qsort((void*)dict->items, dict->n_items, sizeof(struct spa_dict_item), -+ spa_dict_item_compare); -+ SPA_FLAG_SET(dict->flags, SPA_DICT_FLAG_SORTED); -+} -+ -+static inline const struct spa_dict_item *spa_dict_lookup_item(const struct spa_dict *dict, -+ const char *key) -+{ -+ const struct spa_dict_item *item; -+ -+ if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED)) { -+ struct spa_dict_item k = SPA_DICT_ITEM_INIT(key, NULL); -+ item = (const struct spa_dict_item *)bsearch(&k, -+ (const void *) dict->items, dict->n_items, -+ sizeof(struct spa_dict_item), -+ spa_dict_item_compare); -+ if (item != NULL) -+ return item; -+ } else { -+ spa_dict_for_each(item, dict) { -+ if (!strcmp(item->key, key)) -+ return item; -+ } -+ } -+ return NULL; -+} -+ -+static inline const char *spa_dict_lookup(const struct spa_dict *dict, const char *key) -+{ -+ const struct spa_dict_item *item = spa_dict_lookup_item(dict, key); -+ return item ? item->value : NULL; -+} -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_DICT_H */ -diff --git a/third_party/pipewire/spa/utils/hook.h b/third_party/pipewire/spa/utils/hook.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/hook.h -@@ -0,0 +1,198 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_HOOK_H -+#define SPA_HOOK_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+/** \class spa_hook -+ * -+ * \brief a list of hooks -+ * -+ * The hook list provides a way to keep track of hooks. -+ */ -+/** A list of hooks */ -+struct spa_hook_list { -+ struct spa_list list; -+}; -+ -+/** Callbacks, contains the structure with functions and the data passed -+ * to the functions. The structure should also contain a version field that -+ * is checked. */ -+struct spa_callbacks { -+ const void *funcs; -+ void *data; -+}; -+ -+/** Check if a callback \c has method \m of version \v */ -+#define SPA_CALLBACK_CHECK(c,m,v) ((c) && ((v) == 0 || (c)->version > (v)-1) && (c)->m) -+ -+#define SPA_CALLBACKS_INIT(_funcs,_data) (struct spa_callbacks){ _funcs, _data, } -+ -+struct spa_interface { -+ const char *type; -+ uint32_t version; -+ struct spa_callbacks cb; -+}; -+ -+#define SPA_INTERFACE_INIT(_type,_version,_funcs,_data) \ -+ (struct spa_interface){ _type, _version, SPA_CALLBACKS_INIT(_funcs,_data), } -+ -+/** A hook, contains the structure with functions and the data passed -+ * to the functions. */ -+struct spa_hook { -+ struct spa_list link; -+ struct spa_callbacks cb; -+ /** callback and data for the hook list */ -+ void (*removed) (struct spa_hook *hook); -+ void *priv; -+}; -+ -+/** Initialize a hook list */ -+static inline void spa_hook_list_init(struct spa_hook_list *list) -+{ -+ spa_list_init(&list->list); -+} -+ -+static inline bool spa_hook_list_is_empty(struct spa_hook_list *list) -+{ -+ return spa_list_is_empty(&list->list); -+} -+ -+/** Append a hook \memberof spa_hook */ -+static inline void spa_hook_list_append(struct spa_hook_list *list, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ hook->cb = SPA_CALLBACKS_INIT(funcs, data); -+ spa_list_append(&list->list, &hook->link); -+} -+ -+/** Prepend a hook \memberof spa_hook */ -+static inline void spa_hook_list_prepend(struct spa_hook_list *list, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ hook->cb = SPA_CALLBACKS_INIT(funcs, data); -+ spa_list_prepend(&list->list, &hook->link); -+} -+ -+/** Remove a hook \memberof spa_hook */ -+static inline void spa_hook_remove(struct spa_hook *hook) -+{ -+ spa_list_remove(&hook->link); -+ if (hook->removed) -+ hook->removed(hook); -+} -+ -+static inline void -+spa_hook_list_isolate(struct spa_hook_list *list, -+ struct spa_hook_list *save, -+ struct spa_hook *hook, -+ const void *funcs, void *data) -+{ -+ /* init save list and move hooks to it */ -+ spa_hook_list_init(save); -+ spa_list_insert_list(&save->list, &list->list); -+ /* init hooks and add single hook */ -+ spa_hook_list_init(list); -+ spa_hook_list_append(list, hook, funcs, data); -+} -+ -+static inline void -+spa_hook_list_join(struct spa_hook_list *list, -+ struct spa_hook_list *save) -+{ -+ spa_list_insert_list(&list->list, &save->list); -+} -+ -+#define spa_callbacks_call(callbacks,type,method,vers,...) \ -+({ \ -+ const type *_f = (const type *) (callbacks)->funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \ -+ _f->method((callbacks)->data, ## __VA_ARGS__); \ -+}) -+ -+#define spa_callbacks_call_res(callbacks,type,res,method,vers,...) \ -+({ \ -+ const type *_f = (const type *) (callbacks)->funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) \ -+ res = _f->method((callbacks)->data, ## __VA_ARGS__); \ -+ res; \ -+}) -+ -+#define spa_interface_call(iface,type,method,vers,...) \ -+ spa_callbacks_call(&(iface)->cb,type,method,vers,##__VA_ARGS__) -+ -+#define spa_interface_call_res(iface,type,res,method,vers,...) \ -+ spa_callbacks_call_res(&(iface)->cb,type,res,method,vers,##__VA_ARGS__) -+ -+#define spa_hook_list_call_simple(l,type,method,vers,...) \ -+({ \ -+ struct spa_hook_list *_l = l; \ -+ struct spa_hook *_h, *_t; \ -+ spa_list_for_each_safe(_h, _t, &_l->list, link) \ -+ spa_callbacks_call(&_h->cb,type,method,vers, ## __VA_ARGS__); \ -+}) -+ -+/** Call all hooks in a list, starting from the given one and optionally stopping -+ * after calling the first non-NULL function, returns the number of methods -+ * called */ -+#define spa_hook_list_do_call(l,start,type,method,vers,once,...) \ -+({ \ -+ struct spa_hook_list *list = l; \ -+ struct spa_list *s = start ? (struct spa_list *)start : &list->list; \ -+ struct spa_hook cursor = { 0 }, *ci; \ -+ int count = 0; \ -+ spa_list_cursor_start(cursor, s, link); \ -+ spa_list_for_each_cursor(ci, cursor, &list->list, link) { \ -+ const type *_f = (const type *)ci->cb.funcs; \ -+ if (SPA_LIKELY(SPA_CALLBACK_CHECK(_f,method,vers))) { \ -+ _f->method(ci->cb.data, ## __VA_ARGS__); \ -+ count++; \ -+ if (once) \ -+ break; \ -+ } \ -+ } \ -+ spa_list_cursor_end(cursor, link); \ -+ count; \ -+}) -+ -+#define spa_hook_list_call(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,false,##__VA_ARGS__) -+#define spa_hook_list_call_once(l,t,m,v,...) spa_hook_list_do_call(l,NULL,t,m,v,true,##__VA_ARGS__) -+ -+#define spa_hook_list_call_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,false,##__VA_ARGS__) -+#define spa_hook_list_call_once_start(l,s,t,m,v,...) spa_hook_list_do_call(l,s,t,m,v,true,##__VA_ARGS__) -+ -+#ifdef __cplusplus -+} -+#endif -+ -+#endif /* SPA_HOOK_H */ -diff --git a/third_party/pipewire/spa/utils/keys.h b/third_party/pipewire/spa/utils/keys.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/keys.h -@@ -0,0 +1,124 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_KEYS_H -+#define SPA_UTILS_KEYS_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** for objects */ -+#define SPA_KEY_OBJECT_PATH "object.path" /**< a unique path to -+ * identity the object */ -+ -+#define SPA_KEY_MEDIA_CLASS "media.class" /**< Media class -+ * Ex. "Audio/Device", -+ * "Video/Source",... */ -+#define SPA_KEY_MEDIA_ROLE "media.role" /**< Role: Movie, Music, Camera, -+ * Screen, Communication, Game, -+ * Notification, DSP, Production, -+ * Accessibility, Test */ -+/** keys for udev api */ -+#define SPA_KEY_API_UDEV "api.udev" /**< key for the udev api */ -+#define SPA_KEY_API_UDEV_MATCH "api.udev.match" /**< udev subsystem match */ -+ -+/** keys for alsa api */ -+#define SPA_KEY_API_ALSA "api.alsa" /**< key for the alsa api */ -+#define SPA_KEY_API_ALSA_PATH "api.alsa.path" /**< alsa device path as can be -+ * used in snd_pcm_open() and -+ * snd_ctl_open(). */ -+#define SPA_KEY_API_ALSA_CARD "api.alsa.card" /**< alsa card number */ -+#define SPA_KEY_API_ALSA_USE_UCM "api.alsa.use-ucm" /**< if UCM should be used */ -+#define SPA_KEY_API_ALSA_IGNORE_DB "api.alsa.ignore-dB" /**< if decibel info should be ignored */ -+ -+/** info from alsa card_info */ -+#define SPA_KEY_API_ALSA_CARD_ID "api.alsa.card.id" /**< id from card_info */ -+#define SPA_KEY_API_ALSA_CARD_COMPONENTS \ -+ "api.alsa.card.components" /**< components from card_info */ -+#define SPA_KEY_API_ALSA_CARD_DRIVER "api.alsa.card.driver" /**< driver from card_info */ -+#define SPA_KEY_API_ALSA_CARD_NAME "api.alsa.card.name" /**< name from card_info */ -+#define SPA_KEY_API_ALSA_CARD_LONGNAME "api.alsa.card.longname" /**< longname from card_info */ -+#define SPA_KEY_API_ALSA_CARD_MIXERNAME "api.alsa.card.mixername" /**< mixername from card_info */ -+ -+/** info from alsa pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_ID "api.alsa.pcm.id" /**< id from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_CARD "api.alsa.pcm.card" /**< card from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_NAME "api.alsa.pcm.name" /**< name from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBNAME "api.alsa.pcm.subname" /**< subdevice_name from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_STREAM "api.alsa.pcm.stream" /**< stream type from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_CLASS "api.alsa.pcm.class" /**< class from pcm_info as string */ -+#define SPA_KEY_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< device from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBDEVICE "api.alsa.pcm.subdevice" /**< subdevice from pcm_info */ -+#define SPA_KEY_API_ALSA_PCM_SUBCLASS "api.alsa.pcm.subclass" /**< subclass from pcm_info as string */ -+#define SPA_KEY_API_ALSA_PCM_SYNC_ID "api.alsa.pcm.sync-id" /**< sync id */ -+ -+/** keys for v4l2 api */ -+#define SPA_KEY_API_V4L2 "api.v4l2" /**< key for the v4l2 api */ -+#define SPA_KEY_API_V4L2_PATH "api.v4l2.path" /**< v4l2 device path as can be -+ * used in open() */ -+ -+/** keys for libcamera api */ -+#define SPA_KEY_API_LIBCAMERA "api.libcamera" /**< key for the libcamera api */ -+#define SPA_KEY_API_LIBCAMERA_PATH "api.libcamera.path" /**< libcamera device path as can be -+ * used in open() */ -+ -+/** info from libcamera_capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_DRIVER "api.libcamera.cap.driver" /**< driver from capbility */ -+#define SPA_KEY_API_LIBCAMERA_CAP_CARD "api.libcamera.cap.card" /**< caps from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_BUS_INFO "api.libcamera.cap.bus_info"/**< bus_info from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_VERSION "api.libcamera.cap.version" /**< version from capability as %u.%u.%u */ -+#define SPA_KEY_API_LIBCAMERA_CAP_CAPABILITIES \ -+ "api.libcamera.cap.capabilities" /**< capabilities from capability */ -+#define SPA_KEY_API_LIBCAMERA_CAP_DEVICE_CAPS \ -+ "api.libcamera.cap.device-caps" /**< device_caps from capability */ -+/** info from v4l2_capability */ -+#define SPA_KEY_API_V4L2_CAP_DRIVER "api.v4l2.cap.driver" /**< driver from capbility */ -+#define SPA_KEY_API_V4L2_CAP_CARD "api.v4l2.cap.card" /**< caps from capability */ -+#define SPA_KEY_API_V4L2_CAP_BUS_INFO "api.v4l2.cap.bus_info" /**< bus_info from capability */ -+#define SPA_KEY_API_V4L2_CAP_VERSION "api.v4l2.cap.version" /**< version from capability as %u.%u.%u */ -+#define SPA_KEY_API_V4L2_CAP_CAPABILITIES \ -+ "api.v4l2.cap.capabilities" /**< capabilities from capability */ -+#define SPA_KEY_API_V4L2_CAP_DEVICE_CAPS \ -+ "api.v4l2.cap.device-caps" /**< device_caps from capability */ -+ -+ -+/** keys for bluez5 api */ -+#define SPA_KEY_API_BLUEZ5 "api.bluez5" /**< key for the bluez5 api */ -+#define SPA_KEY_API_BLUEZ5_PATH "api.bluez5.path" /**< a bluez5 path */ -+#define SPA_KEY_API_BLUEZ5_DEVICE "api.bluez5.device" /**< an internal bluez5 device */ -+#define SPA_KEY_API_BLUEZ5_TRANSPORT "api.bluez5.transport" /**< an internal bluez5 transport */ -+#define SPA_KEY_API_BLUEZ5_PROFILE "api.bluez5.profile" /**< a bluetooth profile */ -+#define SPA_KEY_API_BLUEZ5_ADDRESS "api.bluez5.address" /**< a bluetooth address */ -+ -+/** keys for jack api */ -+#define SPA_KEY_API_JACK "api.jack" /**< key for the JACK api */ -+#define SPA_KEY_API_JACK_SERVER "api.jack.server" /**< a jack server name */ -+#define SPA_KEY_API_JACK_CLIENT "api.jack.client" /**< an internal jack client */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_KEYS_H */ -diff --git a/third_party/pipewire/spa/utils/list.h b/third_party/pipewire/spa/utils/list.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/list.h -@@ -0,0 +1,138 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_LIST_H -+#define SPA_LIST_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct spa_list { -+ struct spa_list *next; -+ struct spa_list *prev; -+}; -+ -+#define SPA_LIST_INIT(list) (struct spa_list){ list, list }; -+ -+static inline void spa_list_init(struct spa_list *list) -+{ -+ *list = SPA_LIST_INIT(list); -+} -+ -+#define spa_list_is_empty(l) ((l)->next == (l)) -+ -+static inline void spa_list_insert(struct spa_list *list, struct spa_list *elem) -+{ -+ elem->prev = list; -+ elem->next = list->next; -+ list->next = elem; -+ elem->next->prev = elem; -+} -+ -+static inline void spa_list_insert_list(struct spa_list *list, struct spa_list *other) -+{ -+ if (spa_list_is_empty(other)) -+ return; -+ other->next->prev = list; -+ other->prev->next = list->next; -+ list->next->prev = other->prev; -+ list->next = other->next; -+} -+ -+static inline void spa_list_remove(struct spa_list *elem) -+{ -+ elem->prev->next = elem->next; -+ elem->next->prev = elem->prev; -+} -+ -+#define spa_list_first(head, type, member) \ -+ SPA_CONTAINER_OF((head)->next, type, member) -+ -+#define spa_list_last(head, type, member) \ -+ SPA_CONTAINER_OF((head)->prev, type, member) -+ -+#define spa_list_append(list, item) \ -+ spa_list_insert((list)->prev, item) -+ -+#define spa_list_prepend(list, item) \ -+ spa_list_insert(list, item) -+ -+#define spa_list_is_end(pos, head, member) \ -+ (&(pos)->member == (head)) -+ -+#define spa_list_next(pos, member) \ -+ SPA_CONTAINER_OF((pos)->member.next, __typeof__(*pos), member) -+ -+#define spa_list_prev(pos, member) \ -+ SPA_CONTAINER_OF((pos)->member.prev, __typeof__(*pos), member) -+ -+#define spa_list_consume(pos, head, member) \ -+ for (pos = spa_list_first(head, __typeof__(*pos), member); \ -+ !spa_list_is_empty(head); \ -+ pos = spa_list_first(head, __typeof__(*pos), member)) -+ -+#define spa_list_for_each_next(pos, head, curr, member) \ -+ for (pos = spa_list_first(curr, __typeof__(*pos), member); \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_next(pos, member)) -+ -+#define spa_list_for_each_prev(pos, head, curr, member) \ -+ for (pos = spa_list_last(curr, __typeof__(*pos), member); \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_prev(pos, member)) -+ -+#define spa_list_for_each(pos, head, member) \ -+ spa_list_for_each_next(pos, head, head, member) -+ -+#define spa_list_for_each_reverse(pos, head, member) \ -+ spa_list_for_each_prev(pos, head, head, member) -+ -+#define spa_list_for_each_safe_next(pos, tmp, head, curr, member) \ -+ for (pos = spa_list_first(curr, __typeof__(*pos), member); \ -+ tmp = spa_list_next(pos, member), \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = tmp) -+ -+#define spa_list_for_each_safe(pos, tmp, head, member) \ -+ spa_list_for_each_safe_next(pos, tmp, head, head, member) -+ -+#define spa_list_cursor_start(cursor, head, member) \ -+ spa_list_prepend(head, &(cursor).member) -+ -+#define spa_list_for_each_cursor(pos, cursor, head, member) \ -+ for(pos = spa_list_first(&(cursor).member, __typeof__(*(pos)), member); \ -+ spa_list_remove(&(pos)->member), \ -+ spa_list_append(&(cursor).member, &(pos)->member), \ -+ !spa_list_is_end(pos, head, member); \ -+ pos = spa_list_next(&cursor, member)) -+ -+#define spa_list_cursor_end(cursor, member) \ -+ spa_list_remove(&(cursor).member) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_LIST_H */ -diff --git a/third_party/pipewire/spa/utils/names.h b/third_party/pipewire/spa/utils/names.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/names.h -@@ -0,0 +1,137 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2019 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_NAMES_H -+#define SPA_UTILS_NAMES_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+/** for factory names */ -+#define SPA_NAME_SUPPORT_CPU "support.cpu" /**< A CPU interface */ -+#define SPA_NAME_SUPPORT_DBUS "support.dbus" /**< A DBUS interface */ -+#define SPA_NAME_SUPPORT_LOG "support.log" /**< A Log interface */ -+#define SPA_NAME_SUPPORT_LOOP "support.loop" /**< A Loop/LoopControl/LoopUtils -+ * interface */ -+#define SPA_NAME_SUPPORT_SYSTEM "support.system" /**< A System interface */ -+ -+#define SPA_NAME_SUPPORT_NODE_DRIVER "support.node.driver" /**< A dummy driver node */ -+ -+/* control mixer */ -+#define SPA_NAME_CONTROL_MIXER "control.mixer" /**< mixes control streams */ -+ -+/* audio mixer */ -+#define SPA_NAME_AUDIO_MIXER "audio.mixer" /**< mixes the raw audio on N input -+ * ports together on the output -+ * port */ -+#define SPA_NAME_AUDIO_MIXER_DSP "audio.mixer.dsp" /**< mixes mono audio with fixed input -+ * and output buffer sizes. supported -+ * formats must include f32 and -+ * optionally f64 and s24_32 */ -+ -+/** audio processing */ -+#define SPA_NAME_AUDIO_PROCESS_FORMAT "audio.process.format" /**< processes raw audio from one format -+ * to another */ -+#define SPA_NAME_AUDIO_PROCESS_CHANNELMIX \ -+ "audio.process.channelmix" /**< mixes raw audio channels and applies -+ * volume change. */ -+#define SPA_NAME_AUDIO_PROCESS_RESAMPLE \ -+ "audio.process.resample" /**< resamples raw audio */ -+#define SPA_NAME_AUDIO_PROCESS_DEINTERLEAVE \ -+ "audio.process.deinterleave" /**< deinterleave raw audio channels */ -+#define SPA_NAME_AUDIO_PROCESS_INTERLEAVE \ -+ "audio.process.interleave" /**< interleave raw audio channels */ -+ -+ -+/** audio convert combines some of the audio processing */ -+#define SPA_NAME_AUDIO_CONVERT "audio.convert" /**< converts raw audio from one format -+ * to another. Must include at least -+ * format, channelmix and resample -+ * processing */ -+#define SPA_NAME_AUDIO_ADAPT "audio.adapt" /**< combination of a node and an -+ * audio.convert. Does clock slaving */ -+ -+/** video processing */ -+#define SPA_NAME_VIDEO_PROCESS_FORMAT "video.process.format" /**< processes raw video from one format -+ * to another */ -+#define SPA_NAME_VIDEO_PROCESS_SCALE "video.process.scale" /**< scales raw video */ -+ -+/** video convert combines some of the video processing */ -+#define SPA_NAME_VIDEO_CONVERT "video.convert" /**< converts raw video from one format -+ * to another. Must include at least -+ * format and scaling */ -+#define SPA_NAME_VIDEO_ADAPT "video.adapt" /**< combination of a node and a -+ * video.convert. */ -+/** keys for alsa factory names */ -+#define SPA_NAME_API_ALSA_ENUM_UDEV "api.alsa.enum.udev" /**< an alsa udev Device interface */ -+#define SPA_NAME_API_ALSA_PCM_DEVICE "api.alsa.pcm.device" /**< an alsa Device interface */ -+#define SPA_NAME_API_ALSA_PCM_SOURCE "api.alsa.pcm.source" /**< an alsa Node interface for -+ * capturing PCM */ -+#define SPA_NAME_API_ALSA_PCM_SINK "api.alsa.pcm.sink" /**< an alsa Node interface for -+ * playback PCM */ -+#define SPA_NAME_API_ALSA_SEQ_DEVICE "api.alsa.seq.device" /**< an alsa Midi device */ -+#define SPA_NAME_API_ALSA_SEQ_SOURCE "api.alsa.seq.source" /**< an alsa Node interface for -+ * capture of midi */ -+#define SPA_NAME_API_ALSA_SEQ_SINK "api.alsa.seq.sink" /**< an alsa Node interface for -+ * playback of midi */ -+#define SPA_NAME_API_ALSA_SEQ_BRIDGE "api.alsa.seq.bridge" /**< an alsa Node interface for -+ * bridging midi ports */ -+#define SPA_NAME_API_ALSA_ACP_DEVICE "api.alsa.acp.device" /**< an alsa ACP Device interface */ -+ -+/** keys for bluez5 factory names */ -+#define SPA_NAME_API_BLUEZ5_ENUM_DBUS "api.bluez5.enum.dbus" /**< a dbus Device interface */ -+#define SPA_NAME_API_BLUEZ5_DEVICE "api.bluez5.device" /**< a Device interface */ -+#define SPA_NAME_API_BLUEZ5_A2DP_SINK "api.bluez5.a2dp.sink" /**< a playback Node interface for A2DP profiles */ -+#define SPA_NAME_API_BLUEZ5_A2DP_SOURCE "api.bluez5.a2dp.source" /**< a capture Node interface for A2DP profiles */ -+#define SPA_NAME_API_BLUEZ5_SCO_SINK "api.bluez5.sco.sink" /**< a playback Node interface for HSP/HFP profiles */ -+#define SPA_NAME_API_BLUEZ5_SCO_SOURCE "api.bluez5.sco.source" /**< a capture Node interface for HSP/HFP profiles */ -+ -+/** keys for v4l2 factory names */ -+#define SPA_NAME_API_V4L2_ENUM_UDEV "api.v4l2.enum.udev" /**< a v4l2 udev Device interface */ -+#define SPA_NAME_API_V4L2_DEVICE "api.v4l2.device" /**< a v4l2 Device interface */ -+#define SPA_NAME_API_V4L2_SOURCE "api.v4l2.source" /**< a v4l2 Node interface for -+ * capturing */ -+ -+/** keys for libcamera factory names */ -+#define SPA_NAME_API_LIBCAMERA_ENUM_CLIENT "api.libcamera.enum.client" /**< a libcamera client Device interface */ -+#define SPA_NAME_API_LIBCAMERA_DEVICE "api.libcamera.device" /**< a libcamera Device interface */ -+#define SPA_NAME_API_LIBCAMERA_SOURCE "api.libcamera.source" /**< a libcamera Node interface for -+ * capturing */ -+ -+/** keys for jack factory names */ -+#define SPA_NAME_API_JACK_DEVICE "api.jack.device" /**< a jack device. This is a -+ * client connected to a server */ -+#define SPA_NAME_API_JACK_SOURCE "api.jack.source" /**< a jack source */ -+#define SPA_NAME_API_JACK_SINK "api.jack.sink" /**< a jack sink */ -+ -+/** keys for vulkan factory names */ -+#define SPA_NAME_API_VULKAN_COMPUTE_SOURCE \ -+ "api.vulkan.compute.source" /**< a vulkan compute source. */ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_NAMES_H */ -diff --git a/third_party/pipewire/spa/utils/result.h b/third_party/pipewire/spa/utils/result.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/result.h -@@ -0,0 +1,58 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_UTILS_RESULT_H -+#define SPA_UTILS_RESULT_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+#include -+ -+#define SPA_ASYNC_BIT (1 << 30) -+#define SPA_ASYNC_MASK (3 << 30) -+#define SPA_ASYNC_SEQ_MASK (SPA_ASYNC_BIT - 1) -+ -+#define SPA_RESULT_IS_OK(res) ((res) >= 0) -+#define SPA_RESULT_IS_ERROR(res) ((res) < 0) -+#define SPA_RESULT_IS_ASYNC(res) (((res) & SPA_ASYNC_MASK) == SPA_ASYNC_BIT) -+ -+#define SPA_RESULT_ASYNC_SEQ(res) ((res) & SPA_ASYNC_SEQ_MASK) -+#define SPA_RESULT_RETURN_ASYNC(seq) (SPA_ASYNC_BIT | SPA_RESULT_ASYNC_SEQ(seq)) -+ -+#define spa_strerror(err) \ -+({ \ -+ int _err = -err; \ -+ if (SPA_RESULT_IS_ASYNC(err)) \ -+ _err = EINPROGRESS; \ -+ strerror(_err); \ -+}) -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_UTILS_RESULT_H */ -diff --git a/third_party/pipewire/spa/utils/ringbuffer.h b/third_party/pipewire/spa/utils/ringbuffer.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/ringbuffer.h -@@ -0,0 +1,174 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_RINGBUFFER_H -+#define SPA_RINGBUFFER_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+struct spa_ringbuffer; -+ -+#include -+ -+#include -+ -+/** -+ * A ringbuffer type. -+ */ -+struct spa_ringbuffer { -+ uint32_t readindex; /*< the current read index */ -+ uint32_t writeindex; /*< the current write index */ -+}; -+ -+#define SPA_RINGBUFFER_INIT() (struct spa_ringbuffer) { 0, 0 } -+ -+/** -+ * Initialize a spa_ringbuffer with \a size. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param size the number of elements in the ringbuffer -+ */ -+static inline void spa_ringbuffer_init(struct spa_ringbuffer *rbuf) -+{ -+ *rbuf = SPA_RINGBUFFER_INIT(); -+} -+ -+/** -+ * Sets the pointers so that the ringbuffer contains \a size bytes. -+ * -+ * \param rbuf a spa_ringbuffer -+ */ -+static inline void spa_ringbuffer_set_avail(struct spa_ringbuffer *rbuf, uint32_t size) -+{ -+ rbuf->readindex = 0; -+ rbuf->writeindex = size; -+} -+ -+/** -+ * Get the read index and available bytes for reading. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index the value of readindex, should be taken modulo the size of the -+ * ringbuffer memory to get the offset in the ringbuffer memory -+ * \return number of available bytes to read. values < 0 mean -+ * there was an underrun. values > rbuf->size means there -+ * was an overrun. -+ */ -+static inline int32_t spa_ringbuffer_get_read_index(struct spa_ringbuffer *rbuf, uint32_t *index) -+{ -+ *index = __atomic_load_n(&rbuf->readindex, __ATOMIC_RELAXED); -+ return (int32_t) (__atomic_load_n(&rbuf->writeindex, __ATOMIC_ACQUIRE) - *index); -+} -+ -+/** -+ * Read \a len bytes from \a rbuf starting \a offset. \a offset must be taken -+ * modulo \a size and len should be smaller than \a size. -+ * -+ * \param rbuf a #struct spa_ringbuffer -+ * \param buffer memory to read from -+ * \param size the size of \a buffer -+ * \param offset offset in \a buffer to read from -+ * \param data destination memory -+ * \param len number of bytes to read -+ */ -+static inline void -+spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf, -+ const void *buffer, uint32_t size, -+ uint32_t offset, void *data, uint32_t len) -+{ -+ uint32_t l0 = SPA_MIN(len, size - offset), l1 = len - l0; -+ spa_memcpy(data, SPA_MEMBER(buffer, offset, void), l0); -+ if (SPA_UNLIKELY(l1 > 0)) -+ spa_memcpy(SPA_MEMBER(data, l0, void), buffer, l1); -+} -+ -+/** -+ * Update the read pointer to \a index. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index new index -+ */ -+static inline void spa_ringbuffer_read_update(struct spa_ringbuffer *rbuf, int32_t index) -+{ -+ __atomic_store_n(&rbuf->readindex, index, __ATOMIC_RELEASE); -+} -+ -+/** -+ * Get the write index and the number of bytes inside the ringbuffer. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index the value of writeindex, should be taken modulo the size of the -+ * ringbuffer memory to get the offset in the ringbuffer memory -+ * \return the fill level of \a rbuf. values < 0 mean -+ * there was an underrun. values > rbuf->size means there -+ * was an overrun. Subtract from the buffer size to get -+ * the number of bytes available for writing. -+ */ -+static inline int32_t spa_ringbuffer_get_write_index(struct spa_ringbuffer *rbuf, uint32_t *index) -+{ -+ *index = __atomic_load_n(&rbuf->writeindex, __ATOMIC_RELAXED); -+ return (int32_t) (*index - __atomic_load_n(&rbuf->readindex, __ATOMIC_ACQUIRE)); -+} -+ -+/** -+ * Write \a len bytes to \a buffer starting \a offset. \a offset must be taken -+ * modulo \a size and len should be smaller than \a size. -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param buffer memory to write to -+ * \param size the size of \a buffer -+ * \param offset offset in \a buffer to write to -+ * \param data source memory -+ * \param len number of bytes to write -+ */ -+static inline void -+spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf, -+ void *buffer, uint32_t size, -+ uint32_t offset, const void *data, uint32_t len) -+{ -+ uint32_t l0 = SPA_MIN(len, size - offset), l1 = len - l0; -+ spa_memcpy(SPA_MEMBER(buffer, offset, void), data, l0); -+ if (SPA_UNLIKELY(l1 > 0)) -+ spa_memcpy(buffer, SPA_MEMBER(data, l0, void), l1); -+} -+ -+/** -+ * Update the write pointer to \a index -+ * -+ * \param rbuf a spa_ringbuffer -+ * \param index new index -+ */ -+static inline void spa_ringbuffer_write_update(struct spa_ringbuffer *rbuf, int32_t index) -+{ -+ __atomic_store_n(&rbuf->writeindex, index, __ATOMIC_RELEASE); -+} -+ -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_RINGBUFFER_H */ -diff --git a/third_party/pipewire/spa/utils/type-info.h b/third_party/pipewire/spa/utils/type-info.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/type-info.h -@@ -0,0 +1,128 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_TYPE_INFO_H -+#define SPA_TYPE_INFO_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+#ifndef SPA_TYPE_ROOT -+#define SPA_TYPE_ROOT spa_types -+#endif -+ -+static inline bool spa_type_is_a(const char *type, const char *parent) -+{ -+ return type != NULL && parent != NULL && strncmp(type, parent, strlen(parent)) == 0; -+} -+ -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Direction SPA_TYPE_INFO_ENUM_BASE "Direction" -+#define SPA_TYPE_INFO_DIRECTION_BASE SPA_TYPE_INFO_Direction ":" -+ -+static const struct spa_type_info spa_type_direction[] = { -+ { SPA_DIRECTION_INPUT, SPA_TYPE_Int, SPA_TYPE_INFO_DIRECTION_BASE "Input", NULL }, -+ { SPA_DIRECTION_OUTPUT, SPA_TYPE_Int, SPA_TYPE_INFO_DIRECTION_BASE "Output", NULL }, -+ { 0, 0, NULL, NULL } -+}; -+ -+#include -+#include -+#include -+ -+/* base for parameter object enumerations */ -+#define SPA_TYPE_INFO_Choice SPA_TYPE_INFO_ENUM_BASE "Choice" -+#define SPA_TYPE_INFO_CHOICE_BASE SPA_TYPE_INFO_Choice ":" -+ -+static const struct spa_type_info spa_type_choice[] = { -+ { SPA_CHOICE_None, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "None", NULL }, -+ { SPA_CHOICE_Range, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Range", NULL }, -+ { SPA_CHOICE_Step, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Step", NULL }, -+ { SPA_CHOICE_Enum, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Enum", NULL }, -+ { SPA_CHOICE_Flags, SPA_TYPE_Int, SPA_TYPE_INFO_CHOICE_BASE "Flags", NULL }, -+ { 0, 0, NULL, NULL } -+}; -+ -+static const struct spa_type_info spa_types[] = { -+ /* Basic types */ -+ { SPA_TYPE_START, SPA_TYPE_START, SPA_TYPE_INFO_BASE, NULL }, -+ { SPA_TYPE_None, SPA_TYPE_None, SPA_TYPE_INFO_BASE "None", NULL }, -+ { SPA_TYPE_Bool, SPA_TYPE_Bool, SPA_TYPE_INFO_BASE "Bool", NULL }, -+ { SPA_TYPE_Id, SPA_TYPE_Int, SPA_TYPE_INFO_BASE "Id", NULL }, -+ { SPA_TYPE_Int, SPA_TYPE_Int, SPA_TYPE_INFO_BASE "Int", NULL }, -+ { SPA_TYPE_Long, SPA_TYPE_Long, SPA_TYPE_INFO_BASE "Long", NULL }, -+ { SPA_TYPE_Float, SPA_TYPE_Float, SPA_TYPE_INFO_BASE "Float", NULL }, -+ { SPA_TYPE_Double, SPA_TYPE_Double, SPA_TYPE_INFO_BASE "Double", NULL }, -+ { SPA_TYPE_String, SPA_TYPE_String, SPA_TYPE_INFO_BASE "String", NULL }, -+ { SPA_TYPE_Bytes, SPA_TYPE_Bytes, SPA_TYPE_INFO_BASE "Bytes", NULL }, -+ { SPA_TYPE_Rectangle, SPA_TYPE_Rectangle, SPA_TYPE_INFO_BASE "Rectangle", NULL }, -+ { SPA_TYPE_Fraction, SPA_TYPE_Fraction, SPA_TYPE_INFO_BASE "Fraction", NULL }, -+ { SPA_TYPE_Bitmap, SPA_TYPE_Bitmap, SPA_TYPE_INFO_BASE "Bitmap", NULL }, -+ { SPA_TYPE_Array, SPA_TYPE_Array, SPA_TYPE_INFO_BASE "Array", NULL }, -+ { SPA_TYPE_Pod, SPA_TYPE_Pod, SPA_TYPE_INFO_Pod, NULL }, -+ { SPA_TYPE_Struct, SPA_TYPE_Pod, SPA_TYPE_INFO_Struct, NULL }, -+ { SPA_TYPE_Object, SPA_TYPE_Pod, SPA_TYPE_INFO_Object, NULL }, -+ { SPA_TYPE_Sequence, SPA_TYPE_Pod, SPA_TYPE_INFO_POD_BASE "Sequence", NULL }, -+ { SPA_TYPE_Pointer, SPA_TYPE_Pointer, SPA_TYPE_INFO_Pointer, NULL }, -+ { SPA_TYPE_Fd, SPA_TYPE_Fd, SPA_TYPE_INFO_BASE "Fd", NULL }, -+ { SPA_TYPE_Choice, SPA_TYPE_Pod, SPA_TYPE_INFO_POD_BASE "Choice", NULL }, -+ -+ { SPA_TYPE_POINTER_START, SPA_TYPE_Pointer, SPA_TYPE_INFO_Pointer, NULL }, -+ { SPA_TYPE_POINTER_Buffer, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Buffer", NULL }, -+ { SPA_TYPE_POINTER_Meta, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Meta", NULL }, -+ { SPA_TYPE_POINTER_Dict, SPA_TYPE_Pointer, SPA_TYPE_INFO_POINTER_BASE "Dict", NULL }, -+ -+ { SPA_TYPE_EVENT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Event, NULL }, -+ { SPA_TYPE_EVENT_Device, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Device", NULL }, -+ { SPA_TYPE_EVENT_Node, SPA_TYPE_Object, SPA_TYPE_INFO_EVENT_BASE "Node", spa_type_node_event }, -+ -+ { SPA_TYPE_COMMAND_START, SPA_TYPE_Object, SPA_TYPE_INFO_Command, NULL }, -+ { SPA_TYPE_COMMAND_Device, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Device", NULL }, -+ { SPA_TYPE_COMMAND_Node, SPA_TYPE_Object, SPA_TYPE_INFO_COMMAND_BASE "Node", spa_type_node_command }, -+ -+ { SPA_TYPE_OBJECT_START, SPA_TYPE_Object, SPA_TYPE_INFO_Object, NULL }, -+ { SPA_TYPE_OBJECT_PropInfo, SPA_TYPE_Object, SPA_TYPE_INFO_PropInfo, spa_type_prop_info, }, -+ { SPA_TYPE_OBJECT_Props, SPA_TYPE_Object, SPA_TYPE_INFO_Props, spa_type_props }, -+ { SPA_TYPE_OBJECT_Format, SPA_TYPE_Object, SPA_TYPE_INFO_Format, spa_type_format }, -+ { SPA_TYPE_OBJECT_ParamBuffers, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Buffers, spa_type_param_buffers, }, -+ { SPA_TYPE_OBJECT_ParamMeta, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Meta, spa_type_param_meta }, -+ { SPA_TYPE_OBJECT_ParamIO, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_IO, spa_type_param_io }, -+ { SPA_TYPE_OBJECT_ParamProfile, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Profile, spa_type_param_profile }, -+ { SPA_TYPE_OBJECT_ParamPortConfig, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_PortConfig, spa_type_param_port_config }, -+ { SPA_TYPE_OBJECT_ParamRoute, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Route, spa_type_param_route }, -+ { SPA_TYPE_OBJECT_Profiler, SPA_TYPE_Object, SPA_TYPE_INFO_Profiler, spa_type_profiler }, -+ -+ { 0, 0, NULL, NULL } -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_TYPE_INFO_H */ -diff --git a/third_party/pipewire/spa/utils/type.h b/third_party/pipewire/spa/utils/type.h -new file mode 100644 ---- /dev/null -+++ b/third_party/pipewire/spa/utils/type.h -@@ -0,0 +1,138 @@ -+/* Simple Plugin API -+ * -+ * Copyright © 2018 Wim Taymans -+ * -+ * Permission is hereby granted, free of charge, to any person obtaining a -+ * copy of this software and associated documentation files (the "Software"), -+ * to deal in the Software without restriction, including without limitation -+ * the rights to use, copy, modify, merge, publish, distribute, sublicense, -+ * and/or sell copies of the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the following conditions: -+ * -+ * The above copyright notice and this permission notice (including the next -+ * paragraph) shall be included in all copies or substantial portions of the -+ * Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER -+ * DEALINGS IN THE SOFTWARE. -+ */ -+ -+#ifndef SPA_TYPE_H -+#define SPA_TYPE_H -+ -+#ifdef __cplusplus -+extern "C" { -+#endif -+ -+#include -+ -+enum { -+ /* Basic types */ -+ SPA_TYPE_START = 0x00000, -+ SPA_TYPE_None, -+ SPA_TYPE_Bool, -+ SPA_TYPE_Id, -+ SPA_TYPE_Int, -+ SPA_TYPE_Long, -+ SPA_TYPE_Float, -+ SPA_TYPE_Double, -+ SPA_TYPE_String, -+ SPA_TYPE_Bytes, -+ SPA_TYPE_Rectangle, -+ SPA_TYPE_Fraction, -+ SPA_TYPE_Bitmap, -+ SPA_TYPE_Array, -+ SPA_TYPE_Struct, -+ SPA_TYPE_Object, -+ SPA_TYPE_Sequence, -+ SPA_TYPE_Pointer, -+ SPA_TYPE_Fd, -+ SPA_TYPE_Choice, -+ SPA_TYPE_Pod, -+ SPA_TYPE_LAST, /**< not part of ABI */ -+ -+ /* Pointers */ -+ SPA_TYPE_POINTER_START = 0x10000, -+ SPA_TYPE_POINTER_Buffer, -+ SPA_TYPE_POINTER_Meta, -+ SPA_TYPE_POINTER_Dict, -+ SPA_TYPE_POINTER_LAST, /**< not part of ABI */ -+ -+ /* Events */ -+ SPA_TYPE_EVENT_START = 0x20000, -+ SPA_TYPE_EVENT_Device, -+ SPA_TYPE_EVENT_Node, -+ SPA_TYPE_EVENT_LAST, /**< not part of ABI */ -+ -+ /* Commands */ -+ SPA_TYPE_COMMAND_START = 0x30000, -+ SPA_TYPE_COMMAND_Device, -+ SPA_TYPE_COMMAND_Node, -+ SPA_TYPE_COMMAND_LAST, /**< not part of ABI */ -+ -+ /* Objects */ -+ SPA_TYPE_OBJECT_START = 0x40000, -+ SPA_TYPE_OBJECT_PropInfo, -+ SPA_TYPE_OBJECT_Props, -+ SPA_TYPE_OBJECT_Format, -+ SPA_TYPE_OBJECT_ParamBuffers, -+ SPA_TYPE_OBJECT_ParamMeta, -+ SPA_TYPE_OBJECT_ParamIO, -+ SPA_TYPE_OBJECT_ParamProfile, -+ SPA_TYPE_OBJECT_ParamPortConfig, -+ SPA_TYPE_OBJECT_ParamRoute, -+ SPA_TYPE_OBJECT_Profiler, -+ SPA_TYPE_OBJECT_LAST, /**< not part of ABI */ -+ -+ /* vendor extensions */ -+ SPA_TYPE_VENDOR_PipeWire = 0x02000000, -+ -+ SPA_TYPE_VENDOR_Other = 0x7f000000, -+}; -+ -+#define SPA_TYPE_INFO_BASE "Spa:" -+ -+#define SPA_TYPE_INFO_Flags SPA_TYPE_INFO_BASE "Flags" -+#define SPA_TYPE_INFO_FLAGS_BASE SPA_TYPE_INFO_Flags ":" -+ -+#define SPA_TYPE_INFO_Enum SPA_TYPE_INFO_BASE "Enum" -+#define SPA_TYPE_INFO_ENUM_BASE SPA_TYPE_INFO_Enum ":" -+ -+#define SPA_TYPE_INFO_Pod SPA_TYPE_INFO_BASE "Pod" -+#define SPA_TYPE_INFO_POD_BASE SPA_TYPE_INFO_Pod ":" -+ -+#define SPA_TYPE_INFO_Struct SPA_TYPE_INFO_POD_BASE "Struct" -+#define SPA_TYPE_INFO_STRUCT_BASE SPA_TYPE_INFO_Struct ":" -+ -+#define SPA_TYPE_INFO_Object SPA_TYPE_INFO_POD_BASE "Object" -+#define SPA_TYPE_INFO_OBJECT_BASE SPA_TYPE_INFO_Object ":" -+ -+#define SPA_TYPE_INFO_Pointer SPA_TYPE_INFO_BASE "Pointer" -+#define SPA_TYPE_INFO_POINTER_BASE SPA_TYPE_INFO_Pointer ":" -+ -+#define SPA_TYPE_INFO_Interface SPA_TYPE_INFO_POINTER_BASE "Interface" -+#define SPA_TYPE_INFO_INTERFACE_BASE SPA_TYPE_INFO_Interface ":" -+ -+#define SPA_TYPE_INFO_Event SPA_TYPE_INFO_OBJECT_BASE "Event" -+#define SPA_TYPE_INFO_EVENT_BASE SPA_TYPE_INFO_Event ":" -+ -+#define SPA_TYPE_INFO_Command SPA_TYPE_INFO_OBJECT_BASE "Command" -+#define SPA_TYPE_INFO_COMMAND_BASE SPA_TYPE_INFO_Command ":" -+ -+struct spa_type_info { -+ uint32_t type; -+ uint32_t parent; -+ const char *name; -+ const struct spa_type_info *values; -+}; -+ -+#ifdef __cplusplus -+} /* extern "C" */ -+#endif -+ -+#endif /* SPA_TYPE_H */ - diff --git a/pw5.patch b/pw5.patch deleted file mode 100644 index bcb004e..0000000 --- a/pw5.patch +++ /dev/null @@ -1,53 +0,0 @@ - -# HG changeset patch -# User stransky -# Date 1605025841 0 -# Node ID e04be7688dfb4fbbe8dee73e366df8bc9a5da580 -# Parent 41d3c1292480de14d05b34aa0cf2d56015994878 -Bug 1675767 [Linux] Use PipeWire on Wayland desktop, r=dminor - -Differential Revision: https://phabricator.services.mozilla.com/D96587 - -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/desktop_capturer.cc -@@ -72,37 +72,21 @@ std::unique_ptr Desktop - if (capturer && options.detect_updated_region()) { - capturer.reset(new DesktopCapturerDifferWrapper(std::move(capturer))); - } - - return capturer; - } - - #if defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) --// Return true if Firefox is actually running with Wayland backend. --static bool IsWaylandDisplayUsed() { -- const auto display = gdk_display_get_default(); -- if (display == nullptr) { -- // We're running in headless mode. -- return false; -- } -- return !GDK_IS_X11_DISPLAY(display); --} -- --// Return true if Firefox is actually running on Wayland enabled session. --// It means some screensharing capabilities may be limited. --static bool IsWaylandSessionUsed() { -+bool DesktopCapturer::IsRunningUnderWayland() { - const char* xdg_session_type = getenv("XDG_SESSION_TYPE"); - if (!xdg_session_type || strncmp(xdg_session_type, "wayland", 7) != 0) - return false; - - if (!(getenv("WAYLAND_DISPLAY"))) - return false; - - return true; - } -- --bool DesktopCapturer::IsRunningUnderWayland() { -- return IsWaylandSessionUsed() ? IsWaylandDisplayUsed() : false; --} - #endif // defined(WEBRTC_USE_PIPEWIRE) || defined(USE_X11) - - } // namespace webrtc - diff --git a/pw6.patch b/pw6.patch deleted file mode 100644 index cc0cd7e..0000000 --- a/pw6.patch +++ /dev/null @@ -1,75 +0,0 @@ -diff --git a/browser/actors/WebRTCParent.jsm b/browser/actors/WebRTCParent.jsm ---- a/browser/actors/WebRTCParent.jsm -+++ b/browser/actors/WebRTCParent.jsm -@@ -45,6 +45,9 @@ - "nsIOSPermissionRequest" - ); - -+const PIPEWIRE_PORTAL_NAME = "####_PIPEWIRE_PORTAL_####"; -+const PIPEWIRE_ID = 0xaffffff; -+ - class WebRTCParent extends JSWindowActorParent { - didDestroy() { - webrtcUI.forgetStreamsFromBrowserContext(this.browsingContext); -@@ -774,6 +777,23 @@ - } - } else { - name = device.name; -+ // When we share content by PipeWire add only one item to the device -+ // list. When it's selected PipeWire portal dialog is opened and -+ // user confirms actual window/screen sharing there. -+ // Don't mark it as scary as there's an extra confirmation step by -+ // PipeWire portal dialog. -+ if (name == PIPEWIRE_PORTAL_NAME && device.id == PIPEWIRE_ID) { -+ let sawcStringId = "getUserMedia.sharePipeWirePortal.label"; -+ let item = addDeviceToList( -+ menupopup, -+ stringBundle.getString(sawcStringId), -+ i, -+ type -+ ); -+ item.deviceId = device.id; -+ item.mediaSource = type; -+ break; -+ } - if (type == "application") { - // The application names returned by the platform are of the form: - // \x1e -diff --git a/browser/locales/en-US/chrome/browser/browser.properties b/browser/locales/en-US/chrome/browser/browser.properties ---- a/browser/locales/en-US/chrome/browser/browser.properties -+++ b/browser/locales/en-US/chrome/browser/browser.properties -@@ -767,6 +767,7 @@ - getUserMedia.selectWindowOrScreen.accesskey=W - getUserMedia.pickWindowOrScreen.label = Select Window or Screen - getUserMedia.shareEntireScreen.label = Entire screen -+getUserMedia.sharePipeWirePortal.label = Use operating system settings - # LOCALIZATION NOTE (getUserMedia.shareMonitor.label): - # %S is screen number (digits 1, 2, etc) - # Example: Screen 1, Screen 2,.. -diff --git a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc ---- a/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -+++ b/third_party/libwebrtc/webrtc/modules/desktop_capture/linux/base_capturer_pipewire.cc -@@ -898,17 +898,17 @@ - callback_->OnCaptureResult(Result::SUCCESS, std::move(result)); - } - -+#define PIPEWIRE_ID 0xaffffff -+#define PIPEWIRE_NAME "####_PIPEWIRE_PORTAL_####" -+ - bool BaseCapturerPipeWire::GetSourceList(SourceList* sources) { -- RTC_DCHECK(sources->size() == 0); -- // List of available screens is already presented by the xdg-desktop-portal. -- // But we have to add an empty source as the code expects it. -- sources->push_back({0}); -+ sources->push_back({PIPEWIRE_ID, 0, PIPEWIRE_NAME}); - return true; - } - - bool BaseCapturerPipeWire::SelectSource(SourceId id) { - // Screen selection is handled by the xdg-desktop-portal. -- return true; -+ return id == PIPEWIRE_ID; - } - - // static - diff --git a/pw7.patch b/pw7.patch deleted file mode 100644 index db75dea..0000000 --- a/pw7.patch +++ /dev/null @@ -1,95 +0,0 @@ -diff --git a/browser/actors/WebRTCParent.jsm b/browser/actors/WebRTCParent.jsm ---- a/browser/actors/WebRTCParent.jsm -+++ b/browser/actors/WebRTCParent.jsm -@@ -756,6 +756,8 @@ - ); - menupopup.appendChild(doc.createXULElement("menuseparator")); - -+ let isPipeWire = false; -+ - // Build the list of 'devices'. - let monitorIndex = 1; - for (let i = 0; i < devices.length; ++i) { -@@ -783,6 +785,7 @@ - // Don't mark it as scary as there's an extra confirmation step by - // PipeWire portal dialog. - if (name == PIPEWIRE_PORTAL_NAME && device.id == PIPEWIRE_ID) { -+ isPipeWire = true; - let sawcStringId = "getUserMedia.sharePipeWirePortal.label"; - let item = addDeviceToList( - menupopup, -@@ -908,39 +911,41 @@ - perms.EXPIRE_SESSION - ); - -- video.deviceId = deviceId; -- let constraints = { -- video: { mediaSource: type, deviceId: { exact: deviceId } }, -- }; -- chromeWin.navigator.mediaDevices.getUserMedia(constraints).then( -- stream => { -- if (video.deviceId != deviceId) { -- // The user has selected a different device or closed the panel -- // before getUserMedia finished. -- stream.getTracks().forEach(t => t.stop()); -- return; -+ if (!isPipeWire) { -+ video.deviceId = deviceId; -+ let constraints = { -+ video: { mediaSource: type, deviceId: { exact: deviceId } }, -+ }; -+ chromeWin.navigator.mediaDevices.getUserMedia(constraints).then( -+ stream => { -+ if (video.deviceId != deviceId) { -+ // The user has selected a different device or closed the panel -+ // before getUserMedia finished. -+ stream.getTracks().forEach(t => t.stop()); -+ return; -+ } -+ video.srcObject = stream; -+ video.stream = stream; -+ doc.getElementById("webRTC-preview").hidden = false; -+ video.onloadedmetadata = function(e) { -+ video.play(); -+ }; -+ }, -+ err => { -+ if ( -+ err.name == "OverconstrainedError" && -+ err.constraint == "deviceId" -+ ) { -+ // Window has disappeared since enumeration, which can happen. -+ // No preview for you. -+ return; -+ } -+ Cu.reportError( -+ `error in preview: ${err.message} ${err.constraint}` -+ ); - } -- video.srcObject = stream; -- video.stream = stream; -- doc.getElementById("webRTC-preview").hidden = false; -- video.onloadedmetadata = function(e) { -- video.play(); -- }; -- }, -- err => { -- if ( -- err.name == "OverconstrainedError" && -- err.constraint == "deviceId" -- ) { -- // Window has disappeared since enumeration, which can happen. -- // No preview for you. -- return; -- } -- Cu.reportError( -- `error in preview: ${err.message} ${err.constraint}` -- ); -- } -- ); -+ ); -+ } - }; - menupopup.addEventListener("command", menupopup._commandEventListener); - } - diff --git a/rhbz-1173156.patch b/rhbz-1173156.patch index c35d901..067b561 100644 --- a/rhbz-1173156.patch +++ b/rhbz-1173156.patch @@ -1,12 +1,12 @@ -diff -up firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156 firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp ---- firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156 2019-01-22 10:36:09.284069020 +0100 -+++ firefox-60.5.0/extensions/auth/nsAuthSambaNTLM.cpp 2019-01-22 10:37:12.669757744 +0100 -@@ -161,7 +161,7 @@ nsresult nsAuthSambaNTLM::SpawnNTLMAuthH - const char* username = PR_GetEnv("USER"); - if (!username) return NS_ERROR_FAILURE; +diff -up firefox-132.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156 firefox-132.0/extensions/auth/nsAuthSambaNTLM.cpp +--- firefox-132.0/extensions/auth/nsAuthSambaNTLM.cpp.rhbz-1173156 2024-10-23 09:26:41.433895188 +0200 ++++ firefox-132.0/extensions/auth/nsAuthSambaNTLM.cpp 2024-10-23 10:05:11.025801336 +0200 +@@ -153,7 +153,7 @@ nsresult nsAuthSambaNTLM::SpawnNTLMAuthH + options.fds_to_remap.push_back( + std::pair{fromChildPipeWrite.get(), STDOUT_FILENO}); + +- std::vector argvVec{"ntlm_auth", "--helper-protocol", ++ std::vector argvVec{"/usr/bin/ntlm_auth", "--helper-protocol", + "ntlmssp-client-1", "--use-cached-creds", + "--username", username}; -- const char* const args[] = {"ntlm_auth", -+ const char* const args[] = {"/usr/bin/ntlm_auth", - "--helper-protocol", - "ntlmssp-client-1", - "--use-cached-creds", 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 diff --git a/rhbz-1400293-fix-mozilla-1324096.patch b/rhbz-1400293-fix-mozilla-1324096.patch deleted file mode 100644 index 4a2691e..0000000 --- a/rhbz-1400293-fix-mozilla-1324096.patch +++ /dev/null @@ -1,72 +0,0 @@ -diff --git a/security/certverifier/CertVerifier.cpp b/security/certverifier/CertVerifier.cpp ---- a/security/certverifier/CertVerifier.cpp -+++ b/security/certverifier/CertVerifier.cpp -@@ -120,16 +120,20 @@ IsCertChainRootBuiltInRoot(const UniqueC - } - CERTCertificate* root = rootNode->cert; - if (!root) { - return Result::FATAL_ERROR_LIBRARY_FAILURE; - } - return IsCertBuiltInRoot(root, result); - } - -+// The term "builtin root" traditionally refers to a root CA certificate that -+// has been added to the NSS trust store, because it has been approved -+// for inclusion according to the Mozilla CA policy, and might be accepted -+// by Mozilla applications as an issuer for certificates seen on the public web. - Result - IsCertBuiltInRoot(CERTCertificate* cert, bool& result) - { - result = false; - #ifdef DEBUG - nsCOMPtr component(do_GetService(PSM_COMPONENT_CONTRACTID)); - if (!component) { - return Result::FATAL_ERROR_LIBRARY_FAILURE; -@@ -142,25 +146,38 @@ IsCertBuiltInRoot(CERTCertificate* cert, - return Success; - } - #endif // DEBUG - AutoSECMODListReadLock lock; - for (SECMODModuleList* list = SECMOD_GetDefaultModuleList(); list; - list = list->next) { - for (int i = 0; i < list->module->slotCount; i++) { - PK11SlotInfo* slot = list->module->slots[i]; -- // PK11_HasRootCerts should return true if and only if the given slot has -- // an object with a CKA_CLASS of CKO_NETSCAPE_BUILTIN_ROOT_LIST, which -- // should be true only of the builtin root list. -- // If we can find a copy of the given certificate on the slot with the -- // builtin root list, that certificate must be a builtin. -- if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot) && -- PK11_FindCertInSlot(slot, cert, nullptr) != CK_INVALID_HANDLE) { -- result = true; -- return Success; -+ // We're searching for the "builtin root module", which is a module that -+ // contains an object with a CKA_CLASS of CKO_NETSCAPE_BUILTIN_ROOT_LIST. -+ // We use PK11_HasRootCerts() to identify a module with that property. -+ // In the past, we exclusively used the PKCS#11 module named nssckbi, -+ // which is provided by the NSS library. -+ // Nowadays, some distributions use a replacement module, which contains -+ // the builtin roots, but which also contains additional CA certificates, -+ // such as CAs trusted in a local deployment. -+ // We want to be able to distinguish between these two categories, -+ // because a CA, which may issue certificates for the public web, -+ // is expected to comply with additional requirements. -+ // If the certificate has attribute CKA_NSS_MOZILLA_CA_POLICY set to true, -+ // then we treat it as a "builtin root". -+ if (PK11_IsPresent(slot) && PK11_HasRootCerts(slot)) { -+ CK_OBJECT_HANDLE handle = PK11_FindCertInSlot(slot, cert, nullptr); -+ if (handle != CK_INVALID_HANDLE && -+ PK11_HasAttributeSet(slot, handle, CKA_NSS_MOZILLA_CA_POLICY, -+ false)) { -+ // Attribute was found, and is set to true -+ result = true; -+ break; -+ } - } - } - } - return Success; - } - - static Result - BuildCertChainForOneKeyUsage(NSSCertDBTrustDomain& trustDomain, Input certDER, diff --git a/run-tests-wayland b/run-tests-wayland new file mode 100755 index 0000000..95ee6f6 --- /dev/null +++ b/run-tests-wayland @@ -0,0 +1,80 @@ +#!/usr/bin/bash +# usage: run-tests-wayland [test flavour] + +set -x + +RUN_XPCSHELL_TEST=1 +RUN_REFTEST=1 +RUN_MOCHITEST=1 +RUN_CRASHTEST=1 + +while (( "$#" )); do + SELECTED_TEST=$1 + if [ "$SELECTED_TEST" = "xpcshell" ] ; then + RUN_XPCSHELL_TEST=1 + elif [ "$SELECTED_TEST" = "reftest" ] ; then + RUN_REFTEST=1 + elif [ "$SELECTED_TEST" = "mochitest" ] ; then + RUN_MOCHITEST=1 + elif [ "$SELECTED_TEST" = "crashtest" ] ; then + RUN_CRASHTEST=1 + fi + shift +done + +export MACH_USE_SYSTEM_PYTHON=1 +export MOZ_NODE_PATH=/usr/bin/node + +MOCHITEST_PARAMS="--timeout 1 --chunk-by-dir 4" +TEST_DIR="test_results" +mkdir $TEST_DIR + +env | grep "DISPLAY" + +# Fix for system nss +ln -s /usr/bin/certutil objdir/dist/bin/certutil +ln -s /usr/bin/pk12util objdir/dist/bin/pk12util + +NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`" + +export MOZ_ENABLE_WAYLAND=1 + +if [ $RUN_XPCSHELL_TEST -ne 0 ] ; then +# ./mach xpcshell-test 2>&1 | cat - | tee $TEST_DIR/xpcshell + ./mach xpcshell-test --enable-webrender 2>&1 | cat - | tee $TEST_DIR/xpcshell-wr + sleep 60 +fi + +# Basic render testing +export TEST_PARAMS="--setpref reftest.ignoreWindowSize=true --setpref widget.wayland.test-workarounds.enabled=true" +#export TEST_FLAVOUR="" +#if [ $RUN_REFTEST -ne 0 ] ; then +# ./mach reftest --marionette localhost:$(($(($RANDOM))+2000)) $TEST_PARAMS 2>&1 | tee $TEST_DIR/reftest$TEST_FLAVOUR +#fi +#if [ $RUN_CRASHTEST -ne 0 ] ; then +# ./mach crashtest --marionette localhost:$(($(($RANDOM))+2000)) $TEST_PARAMS 2>&1 | tee $TEST_DIR/crashtest$TEST_FLAVOUR +#fi +#if [ $RUN_MOCHITEST -ne 0 ] ; then +# ./mach mochitest --marionette localhost:$(($(($RANDOM))+2000)) $MOCHITEST_PARAMS $TEST_PARAMS 2>&1 | tee $TEST_DIR/mochitest$TEST_FLAVOUR +#fi + +# WebRender testing +export TEST_PARAMS="--enable-webrender $TEST_PARAMS" +export TEST_FLAVOUR="-wr" +# Use dom/base/test or dom/base/test/chrome for short version +export MOCHITEST_DIR='dom' +if [ $RUN_REFTEST -ne 0 ] ; then + ./mach reftest $TEST_PARAMS 2>&1 | tee $TEST_DIR/reftest$TEST_FLAVOUR + sleep 60 +fi +if [ $RUN_CRASHTEST -ne 0 ] ; then + ./mach crashtest $TEST_PARAMS 2>&1 | tee $TEST_DIR/crashtest$TEST_FLAVOUR + sleep 60 +fi +if [ $RUN_MOCHITEST -ne 0 ] ; then + ./mach mochitest $MOCHITEST_DIR $MOCHITEST_PARAMS $TEST_PARAMS 2>&1 | tee $TEST_DIR/mochitest$TEST_FLAVOUR + sleep 60 +fi + +rm -f objdir/dist/bin/certutil +rm -f objdir/dist/bin/pk12util diff --git a/run-tests-x11 b/run-tests-x11 new file mode 100755 index 0000000..1d4a1c0 --- /dev/null +++ b/run-tests-x11 @@ -0,0 +1,39 @@ +#!/usr/bin/bash +set -x + +export MACH_USE_SYSTEM_PYTHON=1 +export MOZ_NODE_PATH=/usr/bin/node +export X_PARAMS="-screen 0 1600x1200x24" +export MOCHITEST_PARAMS="--timeout 1 --chunk-by-dir 4" +export TEST_DIR="test_results" + +# Fix for system nss +ln -s /usr/bin/certutil objdir/dist/bin/certutil +ln -s /usr/bin/pk12util objdir/dist/bin/pk12util + +NCPUS="`/usr/bin/getconf _NPROCESSORS_ONLN`" + +# Basic render testing +export TEST_PARAMS="" +export TEST_FLAVOUR="" +#xvfb-run -s "$X_PARAMS" -n 91 ./mach xpcshell-test --sequential $TEST_PARAMS 2>&1 | cat - | tee $TEST_DIR/xpcshell +#xvfb-run -s "$X_PARAMS" -n 92 ./mach reftest --marionette localhost:$(($(($RANDOM))+2000)) $TEST_PARAMS 2>&1 | tee $TEST_DIR/reftest$TEST_FLAVOUR +#xvfb-run -s "$X_PARAMS" -n 93 ./mach crashtest --marionette localhost:$(($(($RANDOM))+2000)) $TEST_PARAMS 2>&1 | tee $TEST_DIR/crashtest$TEST_FLAVOUR +#xvfb-run -s "$X_PARAMS" -n 94 ./mach mochitest --marionette localhost:$(($(($RANDOM))+2000)) $MOCHITEST_PARAMS $TEST_PARAMS 2>&1 | tee $TEST_DIR/mochitest$TEST_FLAVOUR + +# WebRender testing +export TEST_PARAMS="--enable-webrender $TEST_PARAMS" +export TEST_FLAVOUR="-wr" +#xvfb-run -s "$X_PARAMS" -n 95 ./mach xpcshell-test --sequential $TEST_PARAMS 2>&1 | cat - | tee $TEST_DIR/xpcshell-wr +#sleep 60 +#xvfb-run -s "$X_PARAMS" -n 96 ./mach reftest $TEST_PARAMS 2>&1 | tee $TEST_DIR/reftest$TEST_FLAVOUR +#sleep 60 +#xvfb-run -s "$X_PARAMS" -n 97 ./mach crashtest $TEST_PARAMS 2>&1 | tee $TEST_DIR/crashtest$TEST_FLAVOUR +#sleep 60 +#export DISPLAY=:0 +#./mach mochitest dom/base/test/ $MOCHITEST_PARAMS $TEST_PARAMS 2>&1 | tee $TEST_DIR/mochitest$TEST_FLAVOUR +export DISPLAY=:98 +xvfb-run -s "$X_PARAMS" -n 98 ./mach mochitest dom/base/test/ $MOCHITEST_PARAMS $TEST_PARAMS 2>&1 | tee $TEST_DIR/mochitest$TEST_FLAVOUR + +rm -f objdir/dist/bin/certutil +rm -f objdir/dist/bin/pk12util diff --git a/run-wayland-compositor b/run-wayland-compositor new file mode 100755 index 0000000..2ac9f69 --- /dev/null +++ b/run-wayland-compositor @@ -0,0 +1,59 @@ +#!/usr/bin/bash +# Run wayland compositor and set WAYLAND_DISPLAY env variable + +set -x + +echo export DESKTOP_SESSION=gnome > $HOME/.xsessionrc +echo export XDG_CURRENT_DESKTOP=GNOME > $HOME/.xsessionrc +echo export XDG_SESSION_TYPE=wayland >> $HOME/.xsessionrc + +# Turn off the screen saver and screen locking +gsettings set org.gnome.desktop.screensaver idle-activation-enabled false +gsettings set org.gnome.desktop.screensaver lock-enabled false +gsettings set org.gnome.desktop.screensaver lock-delay 3600 + +# Disable the screen saver +# This starts the gnome-keyring-daemon with an unlocked login keyring. libsecret uses this to +# store secrets. Firefox uses libsecret to store a key that protects sensitive information like +# credit card numbers. +if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then + # if not found, launch a new one + eval `dbus-launch --sh-syntax` +fi + +if [ -z "$XDG_RUNTIME_DIR" ]; then + export XDG_RUNTIME_DIR=$HOME +fi + +export WAYLAND_DISPLAY=firefox-pgo-wayland-0 +if [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then + rm -f $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY + rm -f $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY.lock +fi + +echo "Launch mutter for $WAYLAND_DISPLAY" +mutter --headless --virtual-monitor 1920x1080 --wayland-display=$WAYLAND_DISPLAY --no-x11 & MUTTER_PID=$! +export MUTTER_PID +echo "Mutter PID $MUTTER_PID" + +echo "Waiting for mutter to start..." +sleep 5 +retry_count=0 +max_retries=5 +until [ $retry_count -gt $max_retries ]; do + if [ -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then + retry_count=$(($max_retries + 1)) + else + retry_count=$(($retry_count + 1)) + echo "Waiting for Mutter, retry: $retry_count" + sleep 2 + fi +done + +if [ ! -S "$XDG_RUNTIME_DIR/$WAYLAND_DISPLAY" ]; then + echo "Mutter failed to start!" + exit 1 +fi + +echo "Mutter is running, $XDG_RUNTIME_DIR/$WAYLAND_DISPLAY is here." + 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"} diff --git a/sources b/sources index 2752fa7..b87ab2c 100644 --- a/sources +++ b/sources @@ -1,4 +1,7 @@ -SHA512 (cbindgen-vendor.tar.xz) = 3c925c5523246b7dfbcb4ce563483d5b45315a06dc90f2cf07cddef0c263dd15b410afbbe4d86594de96a308e93be3b27ffec01f5f759a42ecba3cc983b1677f -SHA512 (firefox-83.0.source.tar.xz) = 4ac49cefed278d1f898907bbedacf81ea4bb4e5784f567d4c0971d9cbc2cf4a2e4472de81a7ded620bc3a516bc972d600b516b7674319cdfc9734c3824a9a2f6 -SHA512 (firefox-langpacks-83.0-20201116.tar.xz) = 0d26660a7f09481e82d8d88ac43917001301d422a94dc48d3913dff92805f100221ca6db15fea05e895221efe5a9d74c07780a671aebc26a69d7a588e1cd423d -SHA512 (firefox-testing.tar.gz) = 2adda701576ee10b76e623d31f8b73d8ca3008c62dfb5942f77b29f84397bb4ebe42075d9c332f0ae4a115c85933bfaa0b4da03aaa8624cfae561721e03ffaad +SHA512 (mochitest-python.tar.gz) = 089b1593068b76f4572af0086eaccf52a6a1299bfffb58593206d19bf021ae381f2380bbfeb4371586cd53706ff6dde3d240238b2caf19b96c57dfc2f4524e36 +SHA512 (dump_syms-vendor.tar.xz) = ee0ea52aac781b8dd48936a3d13b140bd725a48cc488d23693b68edbe3bcfba5723022dba3c3849d0da1bacf0e37ddd307cfc56304159f91b71495ce8a08b54a +SHA512 (wasi-sdk-25.tar.gz) = 1285981d26aa5eff27f08ed4b409909639ddcd62c94ee0cff7093ef68722f4b024c099ca3aa3ab50411e9aace13b86f1f30c5e08a3fc58b6a46b87369d6904aa +SHA512 (wasm-component-ld-vendor.tar.xz) = 707d942d31455ae0a4f68bf419fb09a20407b6747f831ca554dcd00925b7ea98ef4d03a8652b6d2ae54cf48d7ad15d85aa7eb8d0778ef66b89593eaa8b5c3465 +SHA512 (cbindgen-vendor.tar.xz) = bea420e66bdd1c7c944655dd3e01abd6e7d6ac4b245c7ee190f31d800f7786f21e5cae11715b479bf795f4369d18c40dc12df19e0b643664f2f78e5c8a681415 +SHA512 (firefox-langpacks-147.0-20260106.tar.xz) = 4006c6e8dda8722509c1d1756807373d431d75b20d5a0c3f19e72a2a0dc76df62b15ef871e3fff2d30b2682e6a56b4a4541d8445ea1b83641559a3270e0057b7 +SHA512 (firefox-147.0.source.tar.xz) = ac9017b1a2da7b2f139392c394c36341fd3476e3d4ea1a3c7e5e7bf100dc30d185132ef9256be7e6b0f9dbfc69234ac571ea1fc6db9d84543b15772f4ec85161 diff --git a/wasi.patch b/wasi.patch new file mode 100644 index 0000000..0a83f8c --- /dev/null +++ b/wasi.patch @@ -0,0 +1,35 @@ +diff -up firefox-134.0.1/toolkit/moz.configure.wasi firefox-134.0.1/toolkit/moz.configure +--- firefox-134.0.1/toolkit/moz.configure.wasi 2025-01-13 14:46:04.000000000 +0100 ++++ firefox-134.0.1/toolkit/moz.configure 2025-01-17 08:39:38.870092763 +0100 +@@ -2767,7 +2776,7 @@ with only_when(requires_wasm_sandboxing + def wasi_sysroot_flags(wasi_sysroot): + if wasi_sysroot: + log.info("Using wasi sysroot in %s", wasi_sysroot) +- return ["--sysroot=%s" % wasi_sysroot] ++ return ["--sysroot=%s" % wasi_sysroot, "-nodefaultlibs", "-lc", "-lwasi-emulated-process-clocks", "-lc++", "-lc++abi", "/raid/CVS/firefox/firefox-147.0-build/firefox-147.0/wasi-sdk-25/build/sysroot/install/wasi-resource-dir/lib/wasi/libclang_rt.builtins-wasm32.a"] + return [] + + set_config("WASI_SYSROOT", wasi_sysroot) +diff -up firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake.wasi firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake +--- firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake.wasi 2025-01-17 08:40:23.004159900 +0100 ++++ firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake 2025-01-17 08:40:35.478178790 +0100 +@@ -126,7 +126,7 @@ endif() + add_custom_command( + OUTPUT ${wasm_component_ld} + COMMAND +- cargo install --root ${wasm_component_ld_root} ${rust_target_flag} ++ cargo install --offline --root ${wasm_component_ld_root} ${rust_target_flag} + wasm-component-ld@${wasm_component_ld_version} + COMMAND + cmake -E make_directory ${wasi_tmp_install}/bin +diff -up firefox-134.0.2/wasi-sdk-25/version.py.wasi firefox-134.0.2/wasi-sdk-25/version.py +--- firefox-134.0.2/wasi-sdk-25/version.py.wasi 2025-01-16 08:03:26.042654800 +0100 ++++ firefox-134.0.2/wasi-sdk-25/version.py 2025-01-22 14:08:34.563909971 +0100 +@@ -60,6 +60,7 @@ assert parse_git_version( + + + def git_version(): ++ return 25 + version = exec(['git', 'describe', '--long', '--candidates=999', + '--match=wasi-sdk-*', '--dirty=+m', f'--abbrev={GIT_REF_LEN}'], + os.path.dirname(sys.argv[0])) diff --git a/wasi.patch.template b/wasi.patch.template new file mode 100644 index 0000000..fe4aee9 --- /dev/null +++ b/wasi.patch.template @@ -0,0 +1,35 @@ +diff -up firefox-134.0.1/toolkit/moz.configure.wasi firefox-134.0.1/toolkit/moz.configure +--- firefox-134.0.1/toolkit/moz.configure.wasi 2025-01-13 14:46:04.000000000 +0100 ++++ firefox-134.0.1/toolkit/moz.configure 2025-01-17 08:39:38.870092763 +0100 +@@ -2767,7 +2776,7 @@ with only_when(requires_wasm_sandboxing + def wasi_sysroot_flags(wasi_sysroot): + if wasi_sysroot: + log.info("Using wasi sysroot in %s", wasi_sysroot) +- return ["--sysroot=%s" % wasi_sysroot] ++ return ["--sysroot=%s" % wasi_sysroot, "-nodefaultlibs", "-lc", "-lwasi-emulated-process-clocks", "-lc++", "-lc++abi", "LIBCLANG_RT_PLACEHOLDER"] + return [] + + set_config("WASI_SYSROOT", wasi_sysroot) +diff -up firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake.wasi firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake +--- firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake.wasi 2025-01-17 08:40:23.004159900 +0100 ++++ firefox-134.0.1/wasi-sdk-25/cmake/wasi-sdk-toolchain.cmake 2025-01-17 08:40:35.478178790 +0100 +@@ -126,7 +126,7 @@ endif() + add_custom_command( + OUTPUT ${wasm_component_ld} + COMMAND +- cargo install --root ${wasm_component_ld_root} ${rust_target_flag} ++ cargo install --offline --root ${wasm_component_ld_root} ${rust_target_flag} + wasm-component-ld@${wasm_component_ld_version} + COMMAND + cmake -E make_directory ${wasi_tmp_install}/bin +diff -up firefox-134.0.2/wasi-sdk-25/version.py.wasi firefox-134.0.2/wasi-sdk-25/version.py +--- firefox-134.0.2/wasi-sdk-25/version.py.wasi 2025-01-16 08:03:26.042654800 +0100 ++++ firefox-134.0.2/wasi-sdk-25/version.py 2025-01-22 14:08:34.563909971 +0100 +@@ -60,6 +60,7 @@ assert parse_git_version( + + + def git_version(): ++ return 25 + version = exec(['git', 'describe', '--long', '--candidates=999', + '--match=wasi-sdk-*', '--dirty=+m', f'--abbrev={GIT_REF_LEN}'], + os.path.dirname(sys.argv[0]))