Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package wireplumber for openSUSE:Factory 
checked in at 2022-12-14 14:10:56
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/wireplumber (Old)
 and      /work/SRC/openSUSE:Factory/.wireplumber.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "wireplumber"

Wed Dec 14 14:10:56 2022 rev:20 rq:1042743 version:0.4.13

Changes:
--------
--- /work/SRC/openSUSE:Factory/wireplumber/wireplumber.changes  2022-11-16 
15:42:21.403592705 +0100
+++ /work/SRC/openSUSE:Factory/.wireplumber.new.1835/wireplumber.changes        
2022-12-14 14:11:10.935550031 +0100
@@ -1,0 +2,43 @@
+Tue Dec 13 14:43:46 UTC 2022 - Alexei Sorokin <sor.ale...@meowr.ru>
+
+- Update to version 0.4.13:
+  * Additions
+    - Add bluetooth SCO (HSP/HFP) hardware offload support,
+      together with an example script that enables this
+      functionality on the PinePhone.
+    - Encoded audio (mp3, aac, etc...) can now be passed through,
+      if this mode is supported by both the application and the
+      device.
+    - The v4l2 monitor now also respects the ``node.disabled`` and
+      ``device.disabled`` properties inside rules.
+    - Add "Firefox Developer Edition" to the list of applications
+      that are allowed to trigger a bluetooth profile auto-switch.
+    - Add support in the portal access script to allow newly
+      plugged cameras to be immediately visible to the portal
+      applications.
+  * Fixes
+    - Work around an issue that would prevent streams from properly
+      linking when using effects software like EasyEffects and
+      JamesDSP.
+    - Fix destroying pavucontrol-qt monitor streams after the node
+      that was being monitored is destroyed.
+    - Fix a crash in the alsa.lua monitor that could happen when a
+      disabled device was removed and re-added.
+    - Fix a rare crash in the metadata object.
+    - Fix a bug where a restored node target would override the
+      node target set by the application on the node's properties.
+  * Packaging
+    - Add build options to compile wireplumber's library, daemon
+      and tools independently.
+    - Add a build option to disable unit tests that require the
+      dbus daemon.
+    - Stop using fakesink/fakesrc in the unit tests to be able to
+      run them on default pipewire installations. Compiling the spa
+      ``test`` plugin is no longer necessary.
+    - Add pkg-config and header information in the gir file.
+- Rebase reduce-meson-required-version.patch
+- Drop patches already upstream:
+  * 0001-alsa.lua-remove-the-disabled-entities-from-the-names-table.patch
+  * 0001-policy-node-wait-for-unactivated-links-instead-of-removing.patch
+
+-------------------------------------------------------------------

Old:
----
  0001-alsa.lua-remove-the-disabled-entities-from-the-names-table.patch
  0001-policy-node-wait-for-unactivated-links-instead-of-removing.patch
  wireplumber-0.4.12.obscpio

New:
----
  wireplumber-0.4.13.obscpio

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ wireplumber.spec ++++++
--- /var/tmp/diff_new_pack.NUgeUr/_old  2022-12-14 14:11:11.603553467 +0100
+++ /var/tmp/diff_new_pack.NUgeUr/_new  2022-12-14 14:11:11.607553488 +0100
@@ -22,7 +22,7 @@
 %define sover 0
 %define libwireplumber libwireplumber-%{apiver_str}-%{sover}
 Name:           wireplumber
-Version:        0.4.12
+Version:        0.4.13
 Release:        0
 Summary:        Session / policy manager implementation for PipeWire
 License:        MIT
@@ -32,10 +32,6 @@
 Source1:        split-config-file.py
 # PATCH-FIX-OPENSUSE reduce-meson-required-version.patch
 Patch0:         reduce-meson-required-version.patch
-# PATCH-FIX-UPSTREAM
-Patch1:         
0001-alsa.lua-remove-the-disabled-entities-from-the-names-table.patch
-# PATCH-FIX-UPSTREAM
-Patch2:         
0001-policy-node-wait-for-unactivated-links-instead-of-removing.patch
 # docs
 BuildRequires:  doxygen
 BuildRequires:  graphviz
@@ -141,11 +137,9 @@
 
 %prep
 %autosetup -N
-%if 0%{?sle_version} <= 150300
+%if 0%{?suse_version} <= 1500 && 0%{?sle_version} <= 150300
 %patch0 -p1
 %endif
-%patch1 -p1
-%patch2 -p1
 
 pushd src/config/main.lua.d
 python3 %{SOURCE1}

++++++ _service ++++++
--- /var/tmp/diff_new_pack.NUgeUr/_old  2022-12-14 14:11:11.631553611 +0100
+++ /var/tmp/diff_new_pack.NUgeUr/_new  2022-12-14 14:11:11.635553632 +0100
@@ -3,7 +3,7 @@
   <service name="obs_scm" mode="disabled">
     <param name="scm">git</param>
     <param 
name="url">https://gitlab.freedesktop.org/pipewire/wireplumber.git</param>
-    <param name="revision">0.4.12</param>
+    <param name="revision">0.4.13</param>
     <param name="versionformat">@PARENT_TAG@</param>
 <!--
     <param name="revision">master</param>

++++++ reduce-meson-required-version.patch ++++++
--- /var/tmp/diff_new_pack.NUgeUr/_old  2022-12-14 14:11:11.643553673 +0100
+++ /var/tmp/diff_new_pack.NUgeUr/_new  2022-12-14 14:11:11.647553694 +0100
@@ -4,20 +4,20 @@
 With this, we can build wireplumber in SLE 15 SP3/Leap 15.3
 which only have meson 0.54
 
-Index: wireplumber-0.4.12/meson.build
+Index: wireplumber-0.4.13/meson.build
 ===================================================================
---- wireplumber-0.4.12.orig/meson.build
-+++ wireplumber-0.4.12/meson.build
+--- wireplumber-0.4.13.orig/meson.build
++++ wireplumber-0.4.13/meson.build
 @@ -1,7 +1,7 @@
  project('wireplumber', ['c'],
-   version : '0.4.12',
+   version : '0.4.13',
    license : 'MIT',
 -  meson_version : '>= 0.59.0',
 +  meson_version : '>= 0.54.0',
    default_options : [
      'warning_level=1',
      'buildtype=debugoptimized',
-@@ -42,7 +42,17 @@ spa_dep = dependency('libspa-0.2', versi
+@@ -52,7 +52,17 @@ spa_dep = dependency('libspa-0.2', versi
  pipewire_dep = dependency('libpipewire-0.3', version: '>= 0.3.52')
  mathlib = cc.find_library('m')
  threads_dep = dependency('threads')
@@ -34,9 +34,9 @@
 +  endif
 +endif
  
- system_lua = get_option('system-lua')
- if system_lua
-@@ -129,8 +139,13 @@ if get_option('tests')
+ if build_modules
+   system_lua = get_option('system-lua')
+@@ -145,8 +155,13 @@ if get_option('tests')
    subdir('tests')
  endif
  
@@ -52,7 +52,7 @@
  
  conf_uninstalled = configuration_data()
  conf_uninstalled.set('MESON', '')
-@@ -150,10 +165,12 @@ wireplumber_uninstalled = custom_target(
+@@ -166,10 +181,12 @@ wireplumber_uninstalled = custom_target(
    command : ['cp', '@INPUT@', '@OUTPUT@'],
  )
  

++++++ wireplumber-0.4.12.obscpio -> wireplumber-0.4.13.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/NEWS.rst 
new/wireplumber-0.4.13/NEWS.rst
--- old/wireplumber-0.4.12/NEWS.rst     2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/NEWS.rst     2022-12-13 10:39:14.000000000 +0100
@@ -1,6 +1,58 @@
-WirePlumber 0.4.12
+WirePlumber 0.4.13
 ~~~~~~~~~~~~~~~~~~
 
+Additions:
+
+  - Added bluetooth SCO (HSP/HFP) hardware offload support, together with an
+    example script that enables this functionality on the PinePhone
+
+  - Encoded audio (mp3, aac, etc...) can now be passed through, if this mode is
+    supported by both the application and the device
+
+  - The v4l2 monitor now also respects the ``node.disabled`` and
+    ``device.disabled`` properties inside rules
+
+  - Added "Firefox Developer Edition" to the list of apps that are allowed to
+    trigger a bluetooth profile auto-switch (#381)
+
+  - Added support in the portal access script to allow newly plugged cameras
+    to be immediately visible to the portal apps
+
+Fixes:
+
+  - Worked around an issue that would prevent streams from properly linking
+    when using effects software like EasyEffects and JamesDSP (!450)
+
+  - Fixed destroying pavucontrol-qt monitor streams after the node that was
+    being monitored is destroyed (#388)
+
+  - Fixed a crash in the alsa.lua monitor that could happen when a disabled
+    device was removed and re-added (#361)
+
+  - Fixed a rare crash in the metadata object (#382)
+
+  - Fixed a bug where a restored node target would override the node target
+    set by the application on the node's properties (#335)
+
+Packaging:
+
+  - Added build options to compile wireplumber's library, daemon and tools
+    independently
+
+  - Added a build option to disable unit tests that require the dbus daemon
+
+  - Stopped using fakesink/fakesrc in the unit tests to be able to run them
+    on default pipewire installations. Compiling the spa ``test`` plugin is no
+    longer necessary
+
+  - Added pkg-config and header information in the gir file
+
+Past releases
+~~~~~~~~~~~~~
+
+WirePlumber 0.4.12
+..................
+
 Changes:
 
   - WirePlumber now maintains a stack of previously configured default nodes 
and
@@ -48,9 +100,6 @@
   - Fixed an issue parsing spa-json objects that have a nested object as the
     value of their last property
 
-Past releases
-~~~~~~~~~~~~~
-
 WirePlumber 0.4.11
 ..................
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/docs/meson.build 
new/wireplumber-0.4.13/docs/meson.build
--- old/wireplumber-0.4.12/docs/meson.build     2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/docs/meson.build     2022-12-13 10:39:14.000000000 
+0100
@@ -140,6 +140,8 @@
     dependencies: [wp_dep, dummy_dep],
     namespace: 'Wp',
     nsversion: wireplumber_api_version,
+    export_packages: 'wireplumber-0.4',
+    header: 'wp/wp.h',
     sources: [wpenums_h, wp_gtkdoc_h, wp_lib_headers],
     include_directories: [wpenums_include_dir],
     includes: ['GLib-2.0', 'GObject-2.0', 'Gio-2.0'],
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/wireplumber-0.4.12/docs/rst/installing-wireplumber.rst 
new/wireplumber-0.4.13/docs/rst/installing-wireplumber.rst
--- old/wireplumber-0.4.12/docs/rst/installing-wireplumber.rst  2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/docs/rst/installing-wireplumber.rst  2022-12-13 
10:39:14.000000000 +0100
@@ -64,6 +64,28 @@
   The default value is **auto**, which means that documentation will be built
   if **doxygen**, **sphinx** and **breathe** are found and skipped otherwise.
 
+.. option:: -Dmodules=[true|false]
+
+   Build the wireplumber modules.
+
+   The default value is **true**.
+
+.. option:: -Ddaemon=[true|false]
+
+   Build the session manager daemon.
+
+   The default value is **true**.
+
+   Requires **modules** option to be **true**.
+
+.. option:: -Dtools=[true|false]
+
+   Enable or disable building tools.
+
+   The default value is **true**.
+
+   Requires **modules** option to be **true**.
+
 .. option:: -Dsystem-lua=[enabled|disabled|auto]
 
    Force using lua from the system instead of the bundled one.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/lib/wp/metadata.c 
new/wireplumber-0.4.13/lib/wp/metadata.c
--- old/wireplumber-0.4.12/lib/wp/metadata.c    2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/lib/wp/metadata.c    2022-12-13 10:39:14.000000000 
+0100
@@ -276,7 +276,8 @@
   pw_metadata_add_listener (priv->iface, &priv->listener,
       &metadata_events, self);
   priv->remove_listener = TRUE;
-  wp_core_sync (core, NULL, (GAsyncReadyCallback) initial_sync_done, self);
+  wp_core_sync_closure (core, NULL,
+      g_cclosure_new_object ((GCallback) initial_sync_done, G_OBJECT (self)));
 }
 
 static void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/lib/wp/object-manager.c 
new/wireplumber-0.4.13/lib/wp/object-manager.c
--- old/wireplumber-0.4.12/lib/wp/object-manager.c      2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/lib/wp/object-manager.c      2022-12-13 
10:39:14.000000000 +0100
@@ -381,6 +381,7 @@
 struct om_iterator_data
 {
   WpObjectManager *om;
+  GPtrArray *objects;
   WpObjectInterest *interest;
   guint index;
 };
@@ -396,10 +397,9 @@
 om_iterator_next (WpIterator *it, GValue *item)
 {
   struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
-  GPtrArray *objects = it_data->om->objects;
 
-  while (it_data->index < objects->len) {
-    gpointer obj = g_ptr_array_index (objects, it_data->index++);
+  while (it_data->index < it_data->objects->len) {
+    gpointer obj = g_ptr_array_index (it_data->objects, it_data->index++);
 
     /* take the next object that matches the interest, if any */
     if (!it_data->interest ||
@@ -419,8 +419,8 @@
   gpointer *obj, *base;
   guint len;
 
-  obj = base = it_data->om->objects->pdata;
-  len = it_data->om->objects->len;
+  obj = base = it_data->objects->pdata;
+  len = it_data->objects->len;
 
   while ((obj - base) < len) {
     /* only pass matching objects to the fold func if we have an interest */
@@ -440,6 +440,7 @@
 om_iterator_finalize (WpIterator *it)
 {
   struct om_iterator_data *it_data = wp_iterator_get_user_data (it);
+  g_clear_pointer (&it_data->objects, g_ptr_array_unref);
   g_clear_pointer (&it_data->interest, wp_object_interest_unref);
   g_object_unref (it_data->om);
 }
@@ -470,6 +471,7 @@
   it = wp_iterator_new (&om_iterator_methods, sizeof (struct 
om_iterator_data));
   it_data = wp_iterator_get_user_data (it);
   it_data->om = g_object_ref (self);
+  it_data->objects = g_ptr_array_copy (self->objects, NULL, NULL);
   it_data->index = 0;
   return it;
 }
@@ -537,6 +539,7 @@
   it = wp_iterator_new (&om_iterator_methods, sizeof (struct 
om_iterator_data));
   it_data = wp_iterator_get_user_data (it);
   it_data->om = g_object_ref (self);
+  it_data->objects = g_ptr_array_copy (self->objects, NULL, NULL);
   it_data->interest = interest;
   it_data->index = 0;
   return it;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/meson.build 
new/wireplumber-0.4.13/meson.build
--- old/wireplumber-0.4.12/meson.build  2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/meson.build  2022-12-13 10:39:14.000000000 +0100
@@ -1,5 +1,5 @@
 project('wireplumber', ['c'],
-  version : '0.4.12',
+  version : '0.4.13',
   license : 'MIT',
   meson_version : '>= 0.59.0',
   default_options : [
@@ -33,6 +33,16 @@
   ], language: 'c'
 )
 
+build_modules = get_option('modules')
+build_daemon = get_option('daemon')
+if build_daemon and not build_modules
+  error('\'modules\' option is required to be true when the \'daemon\' option 
is true')
+endif
+build_tools = get_option('tools')
+if build_tools and not build_modules
+  error('\'modules\' option is required to be true when the \'tools\' option 
is enabled')
+endif
+
 glib_dep = dependency('glib-2.0', version : glib_req_version)
 gobject_dep = dependency('gobject-2.0', version : glib_req_version)
 gmodule_dep = dependency('gmodule-2.0', version : glib_req_version)
@@ -44,54 +54,58 @@
 threads_dep = dependency('threads')
 libintl_dep = dependency('intl')
 
-system_lua = get_option('system-lua')
-if system_lua
-  if get_option('system-lua-version') != 'auto'
-    lua_version_requested = get_option('system-lua-version')
-    lua_dep = dependency('lua-' + lua_version_requested, required: false)
-    if not lua_dep.found()
-      lua_dep = dependency('lua' + lua_version_requested, required: false)
-    endif
-
-    if not lua_dep.found()
-      error('Specified Lua version "' + lua_version_requested + '" not found')
+if build_modules
+  system_lua = get_option('system-lua')
+  if system_lua
+    if get_option('system-lua-version') != 'auto'
+      lua_version_requested = get_option('system-lua-version')
+      lua_dep = dependency('lua-' + lua_version_requested, required: false)
+      if not lua_dep.found()
+        lua_dep = dependency('lua' + lua_version_requested, required: false)
+      endif
+
+      if not lua_dep.found()
+        error('Specified Lua version "' + lua_version_requested + '" not 
found')
+      endif
+    else
+      lua_dep = dependency('lua-5.4', required: false)
+      if not lua_dep.found()
+        lua_dep = dependency('lua5.4', required: false)
+      endif
+      if not lua_dep.found()
+        lua_dep = dependency('lua54', required: false)
+      endif
+      if not lua_dep.found()
+        lua_dep = dependency('lua-5.3', required: false)
+      endif
+      if not lua_dep.found()
+        lua_dep = dependency('lua5.3', required: false)
+      endif
+      if not lua_dep.found()
+        lua_dep = dependency('lua53', required: false)
+      endif
+      if not lua_dep.found()
+        lua_dep = dependency('lua', version: ['>=5.3.0'], required: false)
+      endif
+      if not lua_dep.found()
+        error ('Could not find lua. Lua version 5.4 or 5.3 required')
+      endif
     endif
   else
-    lua_dep = dependency('lua-5.4', required: false)
-    if not lua_dep.found()
-      lua_dep = dependency('lua5.4', required: false)
-    endif
-    if not lua_dep.found()
-      lua_dep = dependency('lua54', required: false)
-    endif
-    if not lua_dep.found()
-      lua_dep = dependency('lua-5.3', required: false)
-    endif
-    if not lua_dep.found()
-      lua_dep = dependency('lua5.3', required: false)
-    endif
-    if not lua_dep.found()
-      lua_dep = dependency('lua53', required: false)
-    endif
-    if not lua_dep.found()
-      lua_dep = dependency('lua', version: ['>=5.3.0'], required: false)
-    endif
-    if not lua_dep.found()
-      error ('Could not find lua. Lua version 5.4 or 5.3 required')
-    endif
+    lua_proj = subproject('lua', default_options: ['default_library=static'])
+    lua_dep = lua_proj.get_variable('lua_dep')
   endif
-else
-  lua_proj = subproject('lua', default_options: ['default_library=static'])
-  lua_dep = lua_proj.get_variable('lua_dep')
+  summary({'Lua version': lua_dep.version() + (system_lua ? ' (system)' : ' 
(built-in)')})
 endif
-summary({'Lua version': lua_dep.version() + (system_lua ? ' (system)' : ' 
(built-in)')})
 
-systemd = dependency('systemd', required: get_option('systemd'))
-libsystemd_dep = dependency('libsystemd',required: get_option('systemd'))
-libelogind_dep = dependency('libelogind', required: get_option('elogind'))
-summary({'systemd conf data': systemd.found(),
-         'libsystemd': libsystemd_dep.found(),
-         'libelogind': libelogind_dep.found()}, bool_yn: true)
+if build_modules
+  systemd = dependency('systemd', required: get_option('systemd'))
+  libsystemd_dep = dependency('libsystemd',required: get_option('systemd'))
+  libelogind_dep = dependency('libelogind', required: get_option('elogind'))
+  summary({'systemd conf data': systemd.found(),
+          'libsystemd': libsystemd_dep.found(),
+          'libelogind': libelogind_dep.found()}, bool_yn: true)
+endif
 
 gnome = import('gnome')
 pkgconfig = import('pkgconfig')
@@ -121,7 +135,9 @@
 
 subdir('lib')
 subdir('docs')
-subdir('modules')
+if build_modules
+  subdir('modules')
+endif
 subdir('src')
 subdir('po')
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/meson_options.txt 
new/wireplumber-0.4.13/meson_options.txt
--- old/wireplumber-0.4.12/meson_options.txt    2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/meson_options.txt    2022-12-13 10:39:14.000000000 
+0100
@@ -2,6 +2,12 @@
        description : 'Generate gobject-introspection bindings')
 option('doc', type : 'feature', value : 'auto',
        description: 'Enable documentation.')
+option('modules', type : 'boolean', value: 'true',
+       description : 'Build modules')
+option('daemon', type : 'boolean', value: 'true',
+       description : 'Build session manager daemon')
+option('tools', type : 'boolean', value: 'true',
+       description : 'Build CLI tools')
 option('system-lua', type : 'boolean', value : 'false',
        description : 'Use lua from the system instead of the bundled one')
 option('system-lua-version',
@@ -29,3 +35,5 @@
        description: 'The glib.supp valgrind suppressions file to be used when 
running valgrind')
 option('tests', type : 'boolean', value : 'true',
        description : 'Build the test suite')
+option('dbus-tests', type : 'boolean', value : 'true',
+       description: 'Enable running tests that need a dbus-daemon')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/modules/module-si-audio-adapter.c 
new/wireplumber-0.4.13/modules/module-si-audio-adapter.c
--- old/wireplumber-0.4.12/modules/module-si-audio-adapter.c    2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/modules/module-si-audio-adapter.c    2022-12-13 
10:39:14.000000000 +0100
@@ -199,12 +199,19 @@
           wp_proxy_get_bound_id (WP_PROXY (node)));
       self->have_encoded = TRUE;
       break;
-    default:
+    default: {
+      enum spa_audio_format audio_format;
+      if (spa_pod_parse_object(wp_spa_pod_get_spa_pod (pod),
+                               SPA_TYPE_OBJECT_Format, NULL,
+                               SPA_FORMAT_AUDIO_format,   
SPA_POD_OPT_Id(&audio_format)) >= 0) {
+        self->have_encoded = (audio_format == SPA_AUDIO_FORMAT_ENCODED);
+      }
       break;
     }
+    }
   }
   if (!have_format && self->have_encoded) {
-    wp_info_object (self, ".. passthrough IEC958/DSD only");
+    wp_info_object (self, ".. passthrough IEC958/DSD/encoded only");
     self->encoded_only = TRUE;
     have_format = TRUE;
   }
@@ -350,7 +357,7 @@
   /* position is optional */
   wp_spa_pod_parser_get (parser, "position", "P", &p, NULL);
 
-  if (channels)
+  if (channels && c != 0)
     *channels = c;
   if (position)
     *position = p ? wp_spa_pod_ref (p) : NULL;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/po/cs.po 
new/wireplumber-0.4.13/po/cs.po
--- old/wireplumber-0.4.12/po/cs.po     2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/po/cs.po     2022-12-13 10:39:14.000000000 +0100
@@ -8,10 +8,10 @@
 msgid ""
 msgstr ""
 "Project-Id-Version: pipewire.master-tx\n"
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/";
-"issues/new\n"
-"POT-Creation-Date: 2022-04-09 15:19+0300\n"
-"PO-Revision-Date: 2021-10-12 14:18+0200\n"
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/-/";
+"issues\n"
+"POT-Creation-Date: 2022-07-08 03:32+0000\n"
+"PO-Revision-Date: 2022-10-19 20:52+0200\n"
 "Last-Translator: Daniel Rusek <m...@asciiwolf.com>\n"
 "Language-Team: čeština <gnome-cs-l...@gnome.org>\n"
 "Language: cs\n"
@@ -19,7 +19,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2;\n"
-"X-Generator: Poedit 3.0\n"
+"X-Generator: Poedit 3.1.1\n"
 
 #. WirePlumber
 #.
@@ -29,6 +29,7 @@
 #. SPDX-License-Identifier: MIT
 #. Receive script arguments from config.lua
 #. ensure config.properties is not nil
+#. unique device/node name tables
 #. preprocess rules and create Interest objects
 #. applies properties from config.rules when asked to
 #. set the device id and spa factory name; REQUIRED, do not change
@@ -44,15 +45,64 @@
 #. ensure the node has a description
 #. also sanitize description, replace ':' with ' '
 #. add api.alsa.card.* properties for rule matching purposes
+#. apply VM overrides
 #. apply properties from config.rules
 #. create the node
 #. ensure the device has an appropriate name
 #. deduplicate devices with the same name
 #. ensure the device has a description
-#: src/scripts/monitors/alsa.lua:222
+#: src/scripts/monitors/alsa.lua:228
 msgid "Built-in Audio"
 msgstr "Vnitřní zvukový systém"
 
-#: src/scripts/monitors/alsa.lua:224
+#: src/scripts/monitors/alsa.lua:230
 msgid "Modem"
 msgstr "Modem"
+
+#. ensure the device has a nick
+#. set the icon name
+#. form factor -> icon
+#. apply properties from config.rules
+#. override the device factory to use ACP
+#. use device reservation, if available
+#. unlike pipewire-media-session, this logic here keeps the device
+#. acquired at all times and destroys it if someone else acquires
+#. create the device
+#. attempt to acquire again
+#. destroy the device
+#. TODO enable the jack device
+#. TODO disable the jack device
+#. create the device
+#. handle create-object to prepare device
+#. handle object-removed to destroy device reservations and recycle device name
+#. reset the name tables to make sure names are recycled
+#. activate monitor
+#. create the JACK device (for PipeWire to act as client to a JACK server)
+#. enable device reservation if requested
+#. if the reserve-device plugin is enabled, at the point of script execution
+#. it is expected to be connected. if it is not, assume the d-bus connection
+#. has failed and continue without it
+#. handle rd_plugin state changes to destroy and re-create the ALSA monitor in
+#. case D-Bus service is restarted
+#. create the monitor
+#. WirePlumber
+#.
+#. Copyright © 2021 Collabora Ltd.
+#. @author George Kiagiadakis <george.kiagiada...@collabora.com>
+#.
+#. SPDX-License-Identifier: MIT
+#. preprocess rules and create Interest objects
+#. applies properties from config.rules when asked to
+#. set the device id and spa factory name; REQUIRED, do not change
+#. set the default pause-on-idle setting
+#. set the node name
+#. sanitize name
+#. deduplicate nodes with the same name
+#. set the node description
+#: src/scripts/monitors/libcamera.lua:88
+msgid "Built-in Front Camera"
+msgstr "Vestavěná přední kamera"
+
+#: src/scripts/monitors/libcamera.lua:90
+msgid "Built-in Back Camera"
+msgstr "Vestavěná zadní kamera"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/po/hi.po 
new/wireplumber-0.4.13/po/hi.po
--- old/wireplumber-0.4.12/po/hi.po     2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/po/hi.po     2022-12-13 10:39:14.000000000 +0100
@@ -1,30 +1,23 @@
-# translation of pipewire.master-tx.po to Hindi
+# translation of Wireplumber.master to Hindi
 # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
 # This file is distributed under the same license as the PACKAGE package.
 # Rajesh Ranjan <rajesh...@gmail.com>, 2009, 2012.
-#
+# Hemish <hemish04082...@gmail.com>, 2022
+
 msgid ""
 msgstr ""
 "Project-Id-Version: pipewire.master-tx\n"
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/";
-"issues/new\n"
-"POT-Creation-Date: 2022-04-09 15:19+0300\n"
-"PO-Revision-Date: 2012-01-30 09:54+0000\n"
-"Last-Translator: Rajesh Ranjan <rajesh...@gmail.com>\n"
-"Language-Team: Hindi <hindi.sf.net>\n"
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/-/";
+"issues\n"
+"POT-Creation-Date: 2022-07-08 03:32+0000\n"
+"PO-Revision-Date: 2022-12-04 12:27+0530\n"
+"Last-Translator: Hemish <hemish04082...@gmail.com>\n"
+"Language-Team: Hindi <indlinux-hi...@lists.sourceforge.net> 
https://indlinux.org/hindi\n";
 "Language: hi\n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
-"X-Generator: KBabel 1.11.4\n"
 "Plural-Forms: nplurals=2; plural=(n!=1);\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
-"\n"
 
 #. WirePlumber
 #.
@@ -32,32 +25,19 @@
 #. @author George Kiagiadakis <george.kiagiada...@collabora.com>
 #.
 #. SPDX-License-Identifier: MIT
-#. Receive script arguments from config.lua
-#. ensure config.properties is not nil
-#. preprocess rules and create Interest objects
-#. applies properties from config.rules when asked to
-#. set the device id and spa factory name; REQUIRED, do not change
-#. set the default pause-on-idle setting
-#. try to negotiate the max ammount of channels
-#. set priority
-#. ensure the node has a media class
-#. ensure the node has a name
-#. sanitize name
-#. deduplicate nodes with the same name
-#. and a nick
-#. also sanitize nick, replace ':' with ' '
-#. ensure the node has a description
-#. also sanitize description, replace ':' with ' '
-#. add api.alsa.card.* properties for rule matching purposes
-#. apply properties from config.rules
-#. create the node
-#. ensure the device has an appropriate name
-#. deduplicate devices with the same name
-#. ensure the device has a description
-#: src/scripts/monitors/alsa.lua:222
+
+#: src/scripts/monitors/alsa.lua:228
 msgid "Built-in Audio"
 msgstr "आंतरिक ऑडियो"
 
-#: src/scripts/monitors/alsa.lua:224
+#: src/scripts/monitors/alsa.lua:230
 msgid "Modem"
 msgstr "मॉडेम"
+
+#: src/scripts/monitors/libcamera.lua:88
+msgid "Built-in Front Camera"
+msgstr "आंतरिक आगे का कैमरा"
+
+#: src/scripts/monitors/libcamera.lua:90
+msgid "Built-in Back Camera"
+msgstr "आंतरिक पीछे का कैमरा"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/po/sk.po 
new/wireplumber-0.4.13/po/sk.po
--- old/wireplumber-0.4.12/po/sk.po     2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/po/sk.po     2022-12-13 10:39:14.000000000 +0100
@@ -1,16 +1,16 @@
 # Slovak translation for PipeWire.
 # Copyright (C) 2014 PipeWire's COPYRIGHT HOLDER
 # This file is distributed under the same license as the PipeWire package.
-# Dušan Kazik <prescot...@gmail.com>, 2014, 2015.
+# Dušan Kazik <prescot...@gmail.com>, 2014-2022.
 #
 msgid ""
 msgstr ""
 "Project-Id-Version: PipeWire master\n"
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/";
-"issues/new\n"
-"POT-Creation-Date: 2022-04-09 15:19+0300\n"
-"PO-Revision-Date: 2020-11-25 08:35+0000\n"
-"Last-Translator: Dusan Kazik <prescot...@gmail.com>\n"
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/wireplumber/-/";
+"issues\n"
+"POT-Creation-Date: 2022-07-08 03:32+0000\n"
+"PO-Revision-Date: 2022-11-05 11:45+0100\n"
+"Last-Translator: Dušan Kazik <prescot...@gmail.com>\n"
 "Language-Team: Slovak <https://translate.fedoraproject.org/projects/pipewire/";
 "pipewire/sk/>\n"
 "Language: sk\n"
@@ -18,7 +18,7 @@
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 "Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
-"X-Generator: Weblate 4.3.2\n"
+"X-Generator: Poedit 3.1.1\n"
 
 #. WirePlumber
 #.
@@ -28,6 +28,7 @@
 #. SPDX-License-Identifier: MIT
 #. Receive script arguments from config.lua
 #. ensure config.properties is not nil
+#. unique device/node name tables
 #. preprocess rules and create Interest objects
 #. applies properties from config.rules when asked to
 #. set the device id and spa factory name; REQUIRED, do not change
@@ -43,15 +44,64 @@
 #. ensure the node has a description
 #. also sanitize description, replace ':' with ' '
 #. add api.alsa.card.* properties for rule matching purposes
+#. apply VM overrides
 #. apply properties from config.rules
 #. create the node
 #. ensure the device has an appropriate name
 #. deduplicate devices with the same name
 #. ensure the device has a description
-#: src/scripts/monitors/alsa.lua:222
+#: src/scripts/monitors/alsa.lua:228
 msgid "Built-in Audio"
 msgstr "Vstavaný zvuk"
 
-#: src/scripts/monitors/alsa.lua:224
+#: src/scripts/monitors/alsa.lua:230
 msgid "Modem"
 msgstr "Modem"
+
+#. ensure the device has a nick
+#. set the icon name
+#. form factor -> icon
+#. apply properties from config.rules
+#. override the device factory to use ACP
+#. use device reservation, if available
+#. unlike pipewire-media-session, this logic here keeps the device
+#. acquired at all times and destroys it if someone else acquires
+#. create the device
+#. attempt to acquire again
+#. destroy the device
+#. TODO enable the jack device
+#. TODO disable the jack device
+#. create the device
+#. handle create-object to prepare device
+#. handle object-removed to destroy device reservations and recycle device name
+#. reset the name tables to make sure names are recycled
+#. activate monitor
+#. create the JACK device (for PipeWire to act as client to a JACK server)
+#. enable device reservation if requested
+#. if the reserve-device plugin is enabled, at the point of script execution
+#. it is expected to be connected. if it is not, assume the d-bus connection
+#. has failed and continue without it
+#. handle rd_plugin state changes to destroy and re-create the ALSA monitor in
+#. case D-Bus service is restarted
+#. create the monitor
+#. WirePlumber
+#.
+#. Copyright © 2021 Collabora Ltd.
+#. @author George Kiagiadakis <george.kiagiada...@collabora.com>
+#.
+#. SPDX-License-Identifier: MIT
+#. preprocess rules and create Interest objects
+#. applies properties from config.rules when asked to
+#. set the device id and spa factory name; REQUIRED, do not change
+#. set the default pause-on-idle setting
+#. set the node name
+#. sanitize name
+#. deduplicate nodes with the same name
+#. set the node description
+#: src/scripts/monitors/libcamera.lua:88
+msgid "Built-in Front Camera"
+msgstr "Vstavaná predná kamera"
+
+#: src/scripts/monitors/libcamera.lua:90
+msgid "Built-in Back Camera"
+msgstr "Vstavaná zadná kamera"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/wireplumber-0.4.12/src/config/bluetooth.lua.d/50-bluez-config.lua 
new/wireplumber-0.4.13/src/config/bluetooth.lua.d/50-bluez-config.lua
--- old/wireplumber-0.4.12/src/config/bluetooth.lua.d/50-bluez-config.lua       
2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/config/bluetooth.lua.d/50-bluez-config.lua       
2022-12-13 10:39:14.000000000 +0100
@@ -29,6 +29,14 @@
   -- Available values: any, none, hsphfpd, ofono, native
   --["bluez5.hfphsp-backend"] = "native",
 
+  -- HFP/HSP native backend modem (default: none).
+  -- Available values: none, any or the modem device string as found in
+  --   'Device' property of org.freedesktop.ModemManager1.Modem interface
+  --["bluez5.hfphsp-backend-native-modem"] = "none",
+
+  -- HFP/HSP hardware offload SCO support (default: false).
+  --["bluez5.hw-offload-sco"] = false,
+
   -- Properties for the A2DP codec configuration
   --["bluez5.default.rate"] = 48000,
   --["bluez5.default.channels"] = 2,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/wireplumber-0.4.12/src/config/policy.lua.d/10-default-policy.lua 
new/wireplumber-0.4.13/src/config/policy.lua.d/10-default-policy.lua
--- old/wireplumber-0.4.12/src/config/policy.lua.d/10-default-policy.lua        
2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/config/policy.lua.d/10-default-policy.lua        
2022-12-13 10:39:14.000000000 +0100
@@ -38,7 +38,7 @@
     "Firefox", "Chromium input", "Google Chrome input", "Brave input",
     "Microsoft Edge input", "Vivaldi input", "ZOOM VoiceEngine",
     "Telegram Desktop", "telegram-desktop", "linphone", "Mumble",
-    "WEBRTC VoiceEngine", "Skype"
+    "WEBRTC VoiceEngine", "Skype", "Firefox Developer Edition",
   },
 }
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/main.c 
new/wireplumber-0.4.13/src/main.c
--- old/wireplumber-0.4.12/src/main.c   2022-10-04 15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/main.c   2022-12-13 10:39:14.000000000 +0100
@@ -112,8 +112,9 @@
 on_plugin_added (WpObjectManager * om, WpObject * p, WpInitTransition *self)
 {
   self->pending_plugins++;
-  wp_object_activate (p, WP_PLUGIN_FEATURE_ENABLED, NULL,
-      (GAsyncReadyCallback) on_plugin_activated, self);
+  wp_object_activate_closure (p, WP_PLUGIN_FEATURE_ENABLED, NULL,
+      g_cclosure_new_object (G_CALLBACK (on_plugin_activated),
+      G_OBJECT (self)));
 }
 
 static void
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/meson.build 
new/wireplumber-0.4.13/src/meson.build
--- old/wireplumber-0.4.12/src/meson.build      2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/src/meson.build      2022-12-13 10:39:14.000000000 
+0100
@@ -1,26 +1,31 @@
-wp_sources = [
-  'main.c',
-]
+if build_tools
+  subdir('tools')
+endif
 
-install_subdir('config',
-  install_dir: wireplumber_data_dir,
-  strip_directory : true
-)
-install_subdir('scripts',
-  install_dir: wireplumber_data_dir,
-  strip_directory : false
-)
+if build_daemon
+  subdir('systemd')
 
-subdir('systemd')
-subdir('tools')
+  install_subdir('config',
+    install_dir: wireplumber_data_dir,
+    strip_directory : true
+  )
+  install_subdir('scripts',
+    install_dir: wireplumber_data_dir,
+    strip_directory : false
+  )
 
-wireplumber = executable('wireplumber',
-  wp_sources,
-  c_args : [
-    '-D_GNU_SOURCE',
-    '-DG_LOG_USE_STRUCTURED',
-    '-DG_LOG_DOMAIN="wireplumber"',
-  ],
-  install: true,
-  dependencies : [gobject_dep, gio_dep, wp_dep, pipewire_dep],
-)
+  wp_sources = [
+    'main.c',
+  ]
+
+  wireplumber = executable('wireplumber',
+    wp_sources,
+    c_args : [
+      '-D_GNU_SOURCE',
+      '-DG_LOG_USE_STRUCTURED',
+      '-DG_LOG_DOMAIN="wireplumber"',
+    ],
+    install: true,
+    dependencies : [gobject_dep, gio_dep, wp_dep, pipewire_dep],
+  )
+endif
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/wireplumber-0.4.12/src/scripts/access/access-portal.lua 
new/wireplumber-0.4.13/src/scripts/access/access-portal.lua
--- old/wireplumber-0.4.12/src/scripts/access/access-portal.lua 2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/access/access-portal.lua 2022-12-13 
10:39:14.000000000 +0100
@@ -111,6 +111,13 @@
     updateClientPermissions (client, new_perms)
   end)
 
+  nodes_om:connect("object-added", function (om, node)
+    local new_perms = pps_plugin:call("lookup", "devices", "camera");
+    for client in clients_om:iterate() do
+      updateClientPermissions (client, new_perms)
+    end
+  end)
+
   pps_plugin:connect("changed", function (p, table, id, deleted, permissions)
     if table == "devices" or id == "camera" then
       for app_id, _ in pairs(permissions) do
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/scripts/monitors/alsa.lua 
new/wireplumber-0.4.13/src/scripts/monitors/alsa.lua
--- old/wireplumber-0.4.12/src/scripts/monitors/alsa.lua        2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/monitors/alsa.lua        2022-12-13 
10:39:14.000000000 +0100
@@ -175,6 +175,7 @@
   -- apply properties from config.rules
   rulesApplyProperties(properties)
   if properties["node.disabled"] then
+    node_names_table [properties ["node.name"]] = nil
     return
   end
 
@@ -190,6 +191,10 @@
     device:connect("create-object", createNode)
     device:connect("object-removed", function (parent, id)
       local node = parent:get_managed_object(id)
+      if not node then
+        return
+      end
+
       node_names_table[node.properties["node.name"]] = nil
     end)
     device:activate(Feature.SpaDevice.ENABLED | Feature.Proxy.BOUND)
@@ -269,6 +274,7 @@
   -- apply properties from config.rules
   rulesApplyProperties(properties)
   if properties["device.disabled"] then
+    device_names_table [properties ["device.name"]] = nil
     return
   end
 
@@ -346,6 +352,10 @@
   -- handle object-removed to destroy device reservations and recycle device 
name
   m:connect("object-removed", function (parent, id)
     local device = parent:get_managed_object(id)
+    if not device then
+      return
+    end
+
     if rd_plugin then
       local rd_name = device.properties["api.dbus.ReserveDevice1"]
       if rd_name then
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/scripts/monitors/bluez.lua 
new/wireplumber-0.4.13/src/scripts/monitors/bluez.lua
--- old/wireplumber-0.4.12/src/scripts/monitors/bluez.lua       2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/monitors/bluez.lua       2022-12-13 
10:39:14.000000000 +0100
@@ -7,6 +7,20 @@
 
 local config = ... or {}
 
+devices_om = ObjectManager {
+  Interest {
+    type = "device",
+  }
+}
+
+nodes_om = ObjectManager {
+  Interest {
+    type = "node",
+    Constraint { "node.name", "#", "*.bluez_*put*"},
+    Constraint { "device.id", "+" },
+  }
+}
+
 -- preprocess rules and create Interest objects
 for _, r in ipairs(config.rules or {}) do
   r.interests = {}
@@ -37,9 +51,105 @@
   end
 end
 
+function setOffloadActive(device, value)
+  local pod = Pod.Object {
+    "Spa:Pod:Object:Param:Props", "Props", bluetoothOffloadActive = value
+  }
+  device:set_params("Props", pod)
+end
+
+nodes_om:connect("object-added", function(_, node)
+  node:connect("state-changed", function(node, old_state, cur_state)
+    local interest = Interest {
+      type = "device",
+      Constraint { "object.id", "=", node.properties["device.id"]}
+    }
+    for d in devices_om:iterate (interest) do
+      if cur_state == "running" then
+        setOffloadActive(d, true)
+      else
+        setOffloadActive(d, false)
+      end
+    end
+  end)
+end)
+
+function createOffloadScoNode(parent, id, type, factory, properties)
+  local dev_props = parent.properties
+
+  local args = {
+    ["audio.channels"] = 1,
+    ["audio.position"] = "[MONO]",
+  }
+
+  local desc =
+      dev_props["device.description"]
+      or dev_props["device.name"]
+      or dev_props["device.nick"]
+      or dev_props["device.alias"]
+      or "bluetooth-device"
+  -- sanitize description, replace ':' with ' '
+  args["node.description"] = desc:gsub("(:)", " ")
+
+  if factory:find("sink") then
+    local capture_args = {
+      ["device.id"] = parent["bound-id"],
+      ["media.class"] = "Audio/Sink",
+      ["node.pause-on-idle"] = false,
+    }
+    for k, v in pairs(properties) do
+      capture_args[k] = v
+    end
+
+    local name = "bluez_output" .. "." .. (properties["api.bluez5.address"] or 
dev_props["device.name"]) .. "." .. tostring(id)
+    args["node.name"] = name:gsub("([^%w_%-%.])", "_")
+    args["capture.props"] = Json.Object(capture_args)
+    args["playback.props"] = Json.Object {
+      ["node.passive"] = true,
+      ["node.pause-on-idle"] = false,
+    }
+  elseif factory:find("source") then
+    local playback_args = {
+      ["device.id"] = parent["bound-id"],
+      ["media.class"] = "Audio/Source",
+      ["node.pause-on-idle"] = false,
+    }
+    for k, v in pairs(properties) do
+      playback_args[k] = v
+    end
+
+    local name = "bluez_input" .. "." .. (properties["api.bluez5.address"] or 
dev_props["device.name"]) .. "." .. tostring(id)
+    args["node.name"] = name:gsub("([^%w_%-%.])", "_")
+    args["capture.props"] = Json.Object {
+      ["node.passive"] = true,
+      ["node.pause-on-idle"] = false,
+    }
+    args["playback.props"] = Json.Object(playback_args)
+  else
+    Log.warning(parent, "Unsupported factory: " .. factory)
+    return
+  end
+
+  -- Transform 'args' to a json object here
+  local args_json = Json.Object(args)
+
+  -- and get the final JSON as a string from the json object
+  local args_string = args_json:get_data()
+
+  local loopback_properties = {}
+
+  local loopback = LocalModule("libpipewire-module-loopback", args_string, 
loopback_properties)
+  parent:store_managed_object(id, loopback)
+end
+
 function createNode(parent, id, type, factory, properties)
   local dev_props = parent.properties
 
+  if config.properties["bluez5.hw-offload-sco"] and factory:find("sco") then
+    createOffloadScoNode(parent, id, type, factory, properties)
+    return
+  end
+
   -- set the device id and spa factory name; REQUIRED, do not change
   properties["device.id"] = parent["bound-id"]
   properties["factory.name"] = factory
@@ -192,3 +302,6 @@
 else
   monitor = createMonitor()
 end
+
+nodes_om:activate()
+devices_om:activate()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/scripts/monitors/v4l2.lua 
new/wireplumber-0.4.13/src/scripts/monitors/v4l2.lua
--- old/wireplumber-0.4.12/src/scripts/monitors/v4l2.lua        2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/monitors/v4l2.lua        2022-12-13 
10:39:14.000000000 +0100
@@ -104,6 +104,9 @@
 
   -- apply properties from config.rules
   rulesApplyProperties(properties)
+  if properties["node.disabled"] then
+    return
+  end
 
   -- create the node
   local node = Node("spa-node-factory", properties)
@@ -138,6 +141,9 @@
 
   -- apply properties from config.rules
   rulesApplyProperties(properties)
+  if properties["device.disabled"] then
+    return
+  end
 
   -- create the device
   local device = SpaDevice(factory, properties)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/scripts/policy-node.lua 
new/wireplumber-0.4.13/src/scripts/policy-node.lua
--- old/wireplumber-0.4.12/src/scripts/policy-node.lua  2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/policy-node.lua  2022-12-13 
10:39:14.000000000 +0100
@@ -123,6 +123,7 @@
       end
       Log.info (l, "activated si-standard-link")
     end
+    scheduleRescan()
   end)
 end
 
@@ -696,9 +697,11 @@
       if link ~= nil then
         -- remove old link
         if ((link:get_active_features() & Feature.SessionItem.ACTIVE) == 0) 
then
-          -- remove also not yet activated links: they might never become 
active,
-          -- and we should not loop waiting for them
-          Log.warning (link, "Link was not activated before removing")
+          -- Link not yet activated. We don't want to remove it now, as that
+          -- may cause problems. Instead, give up for now. A rescan is 
scheduled
+          -- once the link activates.
+          Log.info (link, "Link to be moved was not activated, will wait for 
it.")
+          return
         end
         si_flags[si_id].peer_id = nil
         link:remove ()
@@ -961,9 +964,7 @@
 
 linkables_om:connect("object-removed", function (om, si)
   unhandleLinkable (si)
-  if si.properties["item.node.type"] ~= "stream" then
-    scheduleRescan ()
-  end
+  scheduleRescan ()
 end)
 
 devices_om:connect("object-added", function (om, device)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/src/scripts/restore-stream.lua 
new/wireplumber-0.4.13/src/scripts/restore-stream.lua
--- old/wireplumber-0.4.12/src/scripts/restore-stream.lua       2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/src/scripts/restore-stream.lua       2022-12-13 
10:39:14.000000000 +0100
@@ -182,6 +182,24 @@
 end
 
 function restoreTarget(node, target_name)
+
+  local stream_props = node.properties
+  local target_in_props = nil
+
+  if stream_props ["target.object"] ~= nil or
+      stream_props ["node.target"] ~= nil then
+    target_in_props = stream_props ["target.object"] or
+        stream_props ["node.target"]
+
+    Log.debug (string.format ("%s%s%s%s",
+      "Not restoring the target for ",
+      stream_props ["node.name"],
+      " because it is already set to ",
+      target_in_props))
+
+    return
+  end
+
   local target_node = allnodes_om:lookup {
     Constraint { "node.name", "=", target_name, type = "pw" }
   }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/examples/bt-pinephone.lua 
new/wireplumber-0.4.13/tests/examples/bt-pinephone.lua
--- old/wireplumber-0.4.12/tests/examples/bt-pinephone.lua      1970-01-01 
01:00:00.000000000 +0100
+++ new/wireplumber-0.4.13/tests/examples/bt-pinephone.lua      2022-12-13 
10:39:14.000000000 +0100
@@ -0,0 +1,119 @@
+#!/usr/bin/wpexec
+--
+-- WirePlumber
+--
+-- Copyright © 2022 Collabora Ltd.
+--    @author Frédéric Danis <frederic.da...@collabora.com>
+--
+-- SPDX-License-Identifier: MIT
+--
+-- This is an example of the offload SCO nodes platform specific management,
+-- in this case for the PinePhone.
+--
+-- The PinePhone provides specific ALSA ports to route audio to the Bluetooth
+-- chipset. This script selects these ports when the offload SCO nodes state
+-- change to 'running'.
+--
+-- This scriptcan be executed as a standalone executable, or it can be placed
+-- in WirePlumber's scripts directory and loaded together with other scripts.
+-----------------------------------------------------------------------------
+
+devices_om = ObjectManager {
+  Interest {
+    type = "device",
+  }
+}
+
+nodes_om = ObjectManager {
+  Interest {
+    type = "node",
+    Constraint { "node.name", "#", "*.bluez_*put*"},
+    Constraint { "device.id", "+" },
+  }
+}
+
+function parseParam(param, id)
+  local route = param:parse()
+  if route.pod_type == "Object" and route.object_id == id then
+    return route.properties
+  else
+    return nil
+  end
+end
+
+function setPlatformRoute (route_name, direction)
+  local platform_sound = nil
+  local device_id = nil
+  local route_save = nil
+
+  local interest = Interest {
+    type = "device",
+    Constraint { "device.name", "=", "alsa_card.platform-sound"}
+  }
+  for d in devices_om:iterate (interest) do
+    platform_sound = d
+
+    for p in platform_sound:iterate_params("Route") do
+      route = parseParam(p, "Route")
+      if route.direction == direction then
+        device_id = route.device
+        route_save = route.save
+      end
+    end
+
+    for p in platform_sound:iterate_params("EnumRoute") do
+      enum_route = parseParam(p, "EnumRoute")
+
+      if enum_route.name == route_name then
+        route_index = enum_route.index
+      end
+    end
+  end
+
+  if route.index == route_index then
+    return
+  end
+
+  -- default props
+  local props = {
+    "Spa:Pod:Object:Param:Props", "Route",
+    mute = false,
+  }
+
+  -- construct Route param
+  local param = Pod.Object {
+    "Spa:Pod:Object:Param:Route", "Route",
+    index = route_index,
+    device = device_id,
+    props = Pod.Object(props),
+    save = route_save,
+  }
+
+  Log.info(param, "setting route on " .. tostring(platform_sound))
+  platform_sound:set_param("Route", param)
+
+  route.prev_active = true
+  route.active = true
+end
+
+nodes_om:connect("object-added", function(_, node)
+  node:connect("state-changed", function(node, old_state, cur_state)
+    local interest = Interest {
+      type = "device",
+      Constraint { "object.id", "=", node.properties["device.id"]}
+    }
+    for d in devices_om:iterate (interest) do
+      if cur_state == "running" then
+        -- Both direction should be set to allow audio streaming
+        setPlatformRoute("[Out] BluetoothHeadset", "Output")
+        setPlatformRoute("[In] BluetoothHeadset", "Input")
+      else
+        setPlatformRoute("[Out] Earpiece", "Output")
+        setPlatformRoute("[In] DigitalMic", "Input")
+      end
+    end
+  end)
+end)
+
+nodes_om:activate()
+devices_om:activate()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/meson.build 
new/wireplumber-0.4.13/tests/meson.build
--- old/wireplumber-0.4.12/tests/meson.build    2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/tests/meson.build    2022-12-13 10:39:14.000000000 
+0100
@@ -60,6 +60,8 @@
 endif
 
 subdir('wp')
-subdir('wplua')
-subdir('modules')
+if build_modules
+  subdir('wplua')
+  subdir('modules')
+endif
 subdir('examples')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/modules/meson.build 
new/wireplumber-0.4.13/tests/modules/meson.build
--- old/wireplumber-0.4.12/tests/modules/meson.build    2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/tests/modules/meson.build    2022-12-13 
10:39:14.000000000 +0100
@@ -7,12 +7,14 @@
   '-DG_LOG_USE_STRUCTURED',
 ]
 
-test(
-  'test-reserve-device',
-  executable('test-reserve-device', 'reserve-device.c',
-    dependencies: common_deps, c_args: common_args),
-  env: common_env,
-)
+if get_option('dbus-tests')
+  test(
+    'test-reserve-device',
+    executable('test-reserve-device', 'reserve-device.c',
+      dependencies: common_deps, c_args: common_args),
+    env: common_env,
+  )
+endif
 
 test(
   'test-file-monitor',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/modules/si-node.c 
new/wireplumber-0.4.13/tests/modules/si-node.c
--- old/wireplumber-0.4.12/tests/modules/si-node.c      2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/tests/modules/si-node.c      2022-12-13 
10:39:14.000000000 +0100
@@ -31,8 +31,6 @@
         wp_test_server_locker_new (&f->base.server);
 
     g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
-            "fake*", "test/libspa-test"), ==, 0);
-    g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
             "audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
     g_assert_nonnull (pw_context_load_module (f->base.server.context,
             "libpipewire-module-spa-node-factory", NULL, NULL));
@@ -188,11 +186,8 @@
 
   /* data */
 
-  const TestData fakesink_data = {
-    "fakesink", "fakesink0", "Fake/Sink", "Fake/Sink", WP_DIRECTION_INPUT
-  };
-  const TestData fakesrc_data = {
-    "fakesrc", "fakesrc0", "Fake/Source", "Fake/Source", WP_DIRECTION_OUTPUT
+  const TestData nullsink_data = {
+    "support.null-audio-sink", "nullsink0", "Fake/Sink", "Fake/Sink", 
WP_DIRECTION_INPUT
   };
   const TestData audiotestsrc_data = {
     "audiotestsrc", "audiotestsrc0", "Audio/Source", "Audio/Source", 
WP_DIRECTION_OUTPUT
@@ -200,14 +195,8 @@
 
   /* configure-activate */
 
-  g_test_add ("/modules/si-node/configure-activate/fakesink",
-      TestFixture, &fakesink_data,
-      test_si_node_setup,
-      test_si_node_configure_activate,
-      test_si_node_teardown);
-
-  g_test_add ("/modules/si-node/configure-activate/fakesrc",
-      TestFixture, &fakesrc_data,
+  g_test_add ("/modules/si-node/configure-activate/nullsink",
+      TestFixture, &nullsink_data,
       test_si_node_setup,
       test_si_node_configure_activate,
       test_si_node_teardown);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/wp/meson.build 
new/wireplumber-0.4.13/tests/wp/meson.build
--- old/wireplumber-0.4.12/tests/wp/meson.build 2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/tests/wp/meson.build 2022-12-13 10:39:14.000000000 
+0100
@@ -91,13 +91,14 @@
   env: common_env,
 )
 
-test(
-  'test-dbus',
-  executable('test-dbus', 'dbus.c',
-      dependencies: common_deps, c_args: common_args),
-  env: common_env,
-)
-
+if get_option('dbus-tests')
+  test(
+    'test-dbus',
+    executable('test-dbus', 'dbus.c',
+        dependencies: common_deps, c_args: common_args),
+    env: common_env,
+  )
+endif
 
 test(
   'test-transition',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/wp/object-manager.c 
new/wireplumber-0.4.13/tests/wp/object-manager.c
--- old/wireplumber-0.4.12/tests/wp/object-manager.c    2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/tests/wp/object-manager.c    2022-12-13 
10:39:14.000000000 +0100
@@ -8,6 +8,34 @@
 
 #include "../common/base-test-fixture.h"
 
+struct _TestSiDummy
+{
+  WpSessionItem parent;
+};
+
+G_DECLARE_FINAL_TYPE (TestSiDummy, si_dummy, TEST, SI_DUMMY, WpSessionItem)
+G_DEFINE_TYPE (TestSiDummy, si_dummy, WP_TYPE_SESSION_ITEM)
+
+static void
+si_dummy_init (TestSiDummy * self)
+{
+}
+
+static gboolean
+si_dummy_configure (WpSessionItem * item, WpProperties * props)
+{
+  TestSiDummy *self = TEST_SI_DUMMY (item);
+  wp_session_item_set_properties (WP_SESSION_ITEM (self), props);
+  return TRUE;
+}
+
+static void
+si_dummy_class_init (TestSiDummyClass * klass)
+{
+  WpSessionItemClass *si_class = (WpSessionItemClass *) klass;
+  si_class->configure = si_dummy_configure;
+}
+
 typedef struct {
   WpBaseTestFixture base;
   WpObjectManager *om;
@@ -31,28 +59,23 @@
   g_autoptr (WpNode) node = NULL;
   g_autoptr (WpObjectManager) om = NULL;
 
-  /* load audiotestsrc on the server side */
+  /* load modules on the server side */
   {
     g_autoptr (WpTestServerLocker) lock =
         wp_test_server_locker_new (&f->base.server);
 
     g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
-            "fake*", "test/libspa-test"), ==, 0);
-    if (!test_is_spa_lib_installed (&f->base, "fakesink")) {
-      g_test_skip ("The pipewire fakesink factory was not found");
-      return;
-    }
-
+            "audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
     g_assert_nonnull (pw_context_load_module (f->base.server.context,
-            "libpipewire-module-spa-node-factory", NULL, NULL));
+            "libpipewire-module-adapter", NULL, NULL));
   }
 
   /* export node on the client core */
   node = wp_node_new_from_factory (f->base.client_core,
-      "spa-node-factory",
+      "adapter",
       wp_properties_new (
-          "factory.name", "fakesink",
-          "node.name", "Fakesink",
+          "factory.name", "audiotestsrc",
+          "node.name", "Test Source",
           "test.answer", "42",
           NULL));
   g_assert_nonnull (node);
@@ -68,7 +91,7 @@
   /* request that node from the base core */
   om = wp_object_manager_new ();
   wp_object_manager_add_interest (om, WP_TYPE_NODE,
-      WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "node.name", "=s", "Fakesink",
+      WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "node.name", "=s", "Test Source",
       WP_CONSTRAINT_TYPE_PW_PROPERTY, "test.answer", "=s", "42",
       NULL);
   test_ensure_object_manager_is_installed (om, f->base.core, f->base.loop);
@@ -79,7 +102,7 @@
   /* request "test.answer" to be absent... this will not match */
   om = wp_object_manager_new ();
   wp_object_manager_add_interest (om, WP_TYPE_NODE,
-      WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "node.name", "=s", "Fakesink",
+      WP_CONSTRAINT_TYPE_PW_GLOBAL_PROPERTY, "node.name", "=s", "Test Source",
       WP_CONSTRAINT_TYPE_PW_PROPERTY, "test.answer", "-",
       NULL);
   test_ensure_object_manager_is_installed (om, f->base.core, f->base.loop);
@@ -87,6 +110,54 @@
   g_assert_cmpuint (wp_object_manager_get_n_objects (om), ==, 0);
 }
 
+static void
+test_om_iterate_remove (TestFixture *f, gconstpointer user_data)
+{
+  g_autoptr (WpObjectManager) om = NULL;
+  WpSessionItem *si = NULL;
+
+  si = g_object_new (si_dummy_get_type (), "core", f->base.core, NULL);
+  g_assert_true (wp_session_item_configure (si,
+      wp_properties_new ("property1", "4321", NULL)));
+  wp_session_item_register (si);
+
+  si = g_object_new (si_dummy_get_type (), "core", f->base.core, NULL);
+  g_assert_true (wp_session_item_configure (si,
+      wp_properties_new ("property1", "2345", NULL)));
+  wp_session_item_register (si);
+
+  si = g_object_new (si_dummy_get_type (), "core", f->base.core, NULL);
+  g_assert_true (wp_session_item_configure (si,
+      wp_properties_new ("property1", "1234", NULL)));
+  wp_session_item_register (si);
+
+  si = g_object_new (si_dummy_get_type (), "core", f->base.core, NULL);
+  g_assert_true (wp_session_item_configure (si,
+      wp_properties_new ("property1", "1234", NULL)));
+  wp_session_item_register (si);
+
+  om = wp_object_manager_new ();
+  wp_object_manager_add_interest (om, si_dummy_get_type (), NULL);
+  test_ensure_object_manager_is_installed (om, f->base.core, f->base.loop);
+
+  {
+    g_autoptr (WpIterator) it = wp_object_manager_new_iterator (om);
+    g_auto (GValue) value = G_VALUE_INIT;
+    while (wp_iterator_next (it, &value)) {
+      si = g_value_get_object (&value);
+      g_assert_true (WP_IS_SESSION_ITEM (si));
+      if (!g_strcmp0 (wp_session_item_get_property (si, "property1"), "1234")) 
{
+        wp_session_item_remove (si);
+      }
+      g_value_unset (&value);
+    }
+  }
+
+  g_assert_cmpint (wp_object_manager_get_n_objects (om), ==, 2);
+  g_assert_null (wp_object_manager_lookup (om, si_dummy_get_type (),
+      WP_CONSTRAINT_TYPE_PW_PROPERTY, "property1", "=s", "1234", NULL));
+}
+
 gint
 main (gint argc, gchar *argv[])
 {
@@ -95,6 +166,8 @@
 
   g_test_add ("/wp/om/interest-on-pw-props", TestFixture, NULL,
       test_om_setup, test_om_interest_on_pw_props, test_om_teardown);
+  g_test_add ("/wp/om/iterate_remove", TestFixture, NULL,
+      test_om_setup, test_om_iterate_remove, test_om_teardown);
 
   return g_test_run ();
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/wp/proxy.c 
new/wireplumber-0.4.13/tests/wp/proxy.c
--- old/wireplumber-0.4.12/tests/wp/proxy.c     2022-10-04 15:25:09.000000000 
+0200
+++ new/wireplumber-0.4.13/tests/wp/proxy.c     2022-12-13 10:39:14.000000000 
+0100
@@ -262,21 +262,16 @@
         wp_test_server_locker_new (&f->base.server);
 
     g_assert_cmpint (pw_context_add_spa_lib (f->base.server.context,
-            "fake*", "test/libspa-test"), ==, 0);
-    if (!test_is_spa_lib_installed (&f->base, "fakesink")) {
-      g_test_skip ("The pipewire fakesink factory was not found");
-      return;
-    }
-
+            "audiotestsrc", "audiotestsrc/libspa-audiotestsrc"), ==, 0);
     g_assert_nonnull (pw_context_load_module (f->base.server.context,
-            "libpipewire-module-spa-node-factory", NULL, NULL));
+            "libpipewire-module-adapter", NULL, NULL));
   }
 
   node = wp_node_new_from_factory (f->base.core,
-      "spa-node-factory",
+      "adapter",
       wp_properties_new (
-          "factory.name", "fakesink",
-          "node.name", "Fakesink",
+          "factory.name", "audiotestsrc",
+          "node.name", "audiotestsrc",
           NULL));
   g_assert_nonnull (node);
 
@@ -284,7 +279,7 @@
       NULL, (GAsyncReadyCallback) test_object_activate_finish_cb, f);
   g_main_loop_run (f->base.loop);
 
-  /* EnumRoute doesn't exist on fakesink, obviously */
+  /* EnumRoute doesn't exist on audiotestsrc, obviously */
   wp_pipewire_object_enum_params (WP_PIPEWIRE_OBJECT (node), "EnumRoute", NULL,
       NULL, (GAsyncReadyCallback) enum_params_error_cb, f);
   g_main_loop_run (f->base.loop);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/wireplumber-0.4.12/tests/wplua/scripts/json.lua 
new/wireplumber-0.4.13/tests/wplua/scripts/json.lua
--- old/wireplumber-0.4.12/tests/wplua/scripts/json.lua 2022-10-04 
15:25:09.000000000 +0200
+++ new/wireplumber-0.4.13/tests/wplua/scripts/json.lua 2022-12-13 
10:39:14.000000000 +0100
@@ -113,7 +113,8 @@
     key7 = Json.Object {
       key_nested1 = "nested",
       key_nested2 = 8,
-      key_nested3 = Json.Array {false, true, false}
+      key_nested3 = Json.Array {false, true, false},
+      ["Key with spaces and (special % characters)"] = 50.0,
     }
 }
 assert (json:is_object())
@@ -131,6 +132,7 @@
 assert (not val.key7.key_nested3[1])
 assert (val.key7.key_nested3[2])
 assert (not val.key7.key_nested3[3])
+assert (val.key7["Key with spaces and (special % characters)"] == 50.0)
 
 -- Raw
 json = Json.Raw ("[\"foo\", \"bar\"]")

++++++ wireplumber.obsinfo ++++++
--- /var/tmp/diff_new_pack.NUgeUr/_old  2022-12-14 14:11:11.911555051 +0100
+++ /var/tmp/diff_new_pack.NUgeUr/_new  2022-12-14 14:11:11.915555072 +0100
@@ -1,5 +1,5 @@
 name: wireplumber
-version: 0.4.12
-mtime: 1664889909
-commit: 6f6e5df9c1b223907efa8dcbfcd538821d0dabc4
+version: 0.4.13
+mtime: 1670924354
+commit: 7cb1b8b92e96ebd1b7e632cda32715fed713d333
 

Reply via email to