Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sun Jan 30 16:36:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.44 + +------------------------------------------------------------------- Wed Jan 5 16:20:56 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.43
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.43 +Version: 0.3.44 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.43.tar.gz/doc/pipewire-tools.dox
Deleted
@@ -1,4 +0,0 @@ -/** \page page_tools PipeWire Tools - -*/ -
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/mixer/profile-sets/behringer-umc22.conf
Deleted
@@ -1,68 +0,0 @@ -# This file is part of PulseAudio. -# -# PulseAudio is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as -# published by the Free Software Foundation; either version 2.1 of the -# License, or (at your option) any later version. -# -# PulseAudio is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. - -; Behringer U-Phoria UMC22 -; -; Default mapping only allows to use stereo input and sound card has two -; physical input channels. -; -; However in case of only using a single input channel (like condenser -; microphone) only one channel will have any sound, which is often -; inconvenient for casual use. -; -; This config includes mono input options which makes it much more -; friendly in single input configuration. -; -; This config also removes default digital input/output mappings that do -; not physically exist on this card. -; -; Added by Nazar Mokrynskyi <nazar@mokrynskyi.com> - -[General] -auto-profiles = yes - -[Mapping analog-stereo-input] -device-strings = hw:%f -channel-map = left,right -paths-input = analog-input-mic -direction = input -priority = 4 - -[Mapping analog-mono] -device-strings = hw:%f -channel-map = mono,mono -paths-input = analog-input-mic -direction = input -priority = 3 - -[Mapping analog-mono-left] -device-strings = hw:%f -channel-map = mono,aux1 -paths-input = analog-input-mic -direction = input -priority = 2 - -[Mapping analog-mono-right] -device-strings = hw:%f -channel-map = aux1,mono -paths-input = analog-input-mic -direction = input -priority = 1 - -[Mapping analog-stereo-output] -device-strings = front:%f -channel-map = left,right -paths-output = analog-output -direction = output
View file
pipewire-0.3.43.tar.gz/src/modules/module-rtkit.c
Deleted
@@ -1,730 +0,0 @@ -/* 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. - */ - -#include <stdlib.h> -#include <stdbool.h> -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <sys/stat.h> -#ifdef __FreeBSD__ -#include <sys/thr.h> -#endif -#include <fcntl.h> -#include <unistd.h> -#include <pthread.h> -#include <sys/resource.h> - -#include "config.h" - -#include <spa/support/dbus.h> -#include <spa/utils/result.h> -#include <spa/utils/string.h> - -#include <pipewire/impl.h> -#include <pipewire/thread.h> - -/** \page page_module_rtkit PipeWire Module: RTKit - */ - -#define NAME "rtkit" - -PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); -#define PW_LOG_TOPIC_DEFAULT mod_topic - -#define DEFAULT_NICE_LEVEL -11 -#define DEFAULT_RT_PRIO 88 -#define DEFAULT_RT_TIME_SOFT 2000000 -#define DEFAULT_RT_TIME_HARD 2000000 - -#define MODULE_USAGE "[nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL) ">] " \ - "[rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO) ">] " \ - "[rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] " \ - "[rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] " - -static const struct spa_dict_item module_props[] = { - { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, - { PW_KEY_MODULE_DESCRIPTION, "Use RTKit to raise thread priorities" }, - { PW_KEY_MODULE_USAGE, MODULE_USAGE }, - { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, -}; - -struct pw_rtkit_bus; - -struct thread { - struct impl *impl; - struct spa_list link; - pthread_t thread; - pid_t pid; - void *(*start)(void*); - void *arg; -}; - -struct impl { - struct pw_context *context; - - struct pw_properties *props; - - struct pw_rtkit_bus *system_bus; - - pthread_mutex_t lock; - pthread_cond_t cond; - - struct spa_list threads_list; - struct spa_thread_utils thread_utils; - - int nice_level; - int rt_prio; - rlim_t rt_time_soft; - rlim_t rt_time_hard; - - struct spa_hook module_listener; -}; - -/*** - Copyright 2009 Lennart Poettering - Copyright 2010 David Henningsson <diwic@ubuntu.com> - - 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 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 <dbus/dbus.h> - -#include "config.h" - -#include <sys/syscall.h> - -#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" -#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" - -#ifndef RLIMIT_RTTIME -#define RLIMIT_RTTIME 15 -#endif - -/** \cond */ -struct pw_rtkit_bus { - DBusConnection *bus; -}; -/** \endcond */ - -struct pw_rtkit_bus *pw_rtkit_bus_get_system(void) -{ - struct pw_rtkit_bus *bus; - DBusError error; - - if (getenv("DISABLE_RTKIT")) { - errno = ENOTSUP; - return NULL; - } - - dbus_error_init(&error); - - bus = calloc(1, sizeof(struct pw_rtkit_bus)); - if (bus == NULL) - return NULL; - - bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); - if (bus->bus == NULL) - goto error; - - dbus_connection_set_exit_on_disconnect(bus->bus, false); - - return bus; - -error: - free(bus); - pw_log_error("Failed to connect to system bus: %s", error.message); - dbus_error_free(&error); - errno = ECONNREFUSED; - return NULL; -} - -void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus) -{ - dbus_connection_close(system_bus->bus); - dbus_connection_unref(system_bus->bus); - free(system_bus); -} - -static pid_t _gettid(void) -{ -#if defined(HAVE_GETTID) - return (pid_t) gettid(); -#elif defined(__linux__) - return syscall(SYS_gettid); -#elif defined(__FreeBSD__) - long pid; - thr_self(&pid); - return (pid_t)pid; -#else -#error "No gettid impl"
View file
pipewire-0.3.43.tar.gz/.cirrus.yml -> pipewire-0.3.44.tar.gz/.cirrus.yml
Changed
@@ -17,7 +17,7 @@ build_script: - mkdir build - cd build - - meson setup -Dalsa=enabled -Draop=enabled -Dv4l2=enabled -Dpipewire-alsa=enabled -Dbluez5=disabled -Djack=disabled -Dpipewire-jack=disabled -Dpw-cat=enabled -Dpipewire-v4l2=disabled -Dsdl2=enabled -Dsystemd=disabled -Dsession-managers=media-session .. + - meson setup -Dalsa=enabled -Draop=enabled -Dv4l2=enabled -Dpipewire-alsa=enabled -Dbluez5=disabled -Djack=disabled -Dpipewire-jack=enabled -Dpw-cat=enabled -Dpipewire-v4l2=disabled -Dsdl2=enabled -Dsystemd=disabled -Dsession-managers=media-session .. - ninja test_script: - cd build
View file
pipewire-0.3.43.tar.gz/.gitlab-ci.yml -> pipewire-0.3.44.tar.gz/.gitlab-ci.yml
Changed
@@ -8,8 +8,8 @@ variables: FDO_UPSTREAM_REPO: 'pipewire/pipewire' -# ci-templates as of March 19th 2021 -.templates_sha: &templates_sha 290b79e0e78eab67a83766f4e9691be554fc4afd +# ci-templates as of Jan 27th 2022 +.templates_sha: &templates_sha 0c312d9c7255f46e741d43bcd1930f09cd12efe7 include: - project: 'freedesktop/ci-templates' @@ -22,8 +22,8 @@ .fedora: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2021-10-12.1' - FDO_DISTRIBUTION_VERSION: '34' + FDO_DISTRIBUTION_TAG: '2022-01-27.1' + FDO_DISTRIBUTION_VERSION: '35' FDO_DISTRIBUTION_PACKAGES: >- alsa-lib-devel bluez-libs-devel @@ -62,7 +62,7 @@ .ubuntu: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2021-10-15.0' + FDO_DISTRIBUTION_TAG: '2022-01-27.0' FDO_DISTRIBUTION_VERSION: '20.04' FDO_DISTRIBUTION_PACKAGES: >- debhelper-compat
View file
pipewire-0.3.43.tar.gz/NEWS -> pipewire-0.3.44.tar.gz/NEWS
Changed
@@ -1,4 +1,142 @@ -# PipeWire 0.3.43 (2021-01-05) +# PipeWire 0.3.44 (2022-01-27) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - It is now possible to run a minimal PipeWire server without a session + manager, enough to run JACK clients. + - The maximum buffer size is now configurable and can be larger than + the previously hardcoded limit of 8192 samples. When using high sample + rates, the larger buffer size can avoid xruns. + - The default maximum latency was reduced from 170ms to 42ms. This should + improve overall latency for application that ask for a large latency, + such as notifications. + - Better JACK compatibility. Patchbays should now get less confused about + ports appearing and disappearing. + - Fix some bluetooth crashes. + - Fix some races in ALSA device detection. + - Many bug fixes and improvements all over the place. + +## PipeWire + - Bump the meson requirement to 0.59.0. + - pw-top now reports correct times for filter-chain and loopback. + - max-quantum is now also scaled with the rate. A new quantum-limit + property was added as a hard limit for the quantum. This makes it + possible to configure for larger than 8192 buffer sizes. Note + than many JACK applications have a hardcoded 8192 limit. (#1931) + - The max-quantum was reduced to 2048, This gives a 42ms default + latency. (#1908) + - pw-filter can now return a NULL buffer from _get_dsp_buffer(). + - Add a PIPEWIRE_RATE and PIPEWIRE_QUANTUM env variable to set the + graph rate and the graph quantum and rate respectively. + - Fix a potential file descriptor leak in the connection. + - A new minimal.conf file was added to demonstrate a static setup + of a daemon that doesn't require a session manager and is able to + run JACK applicaions. + - Nice levels are now only changed on the servers, not the clients. + - Add an option to suspend nodes when idle. + - Make it possible to avoid quantum and rate changes with + pw-metadata. This is essential in a locked down system. + - Handle mixer port errors better and fail to create the link instead + of silently not working. + - Nodes that are moved to a driver now have all the linked nodes moved + as well. This makes it possible to run some graphs without a + driver, such as paplay -> zita-j2n. + - pw-cli and pw-dump can now also list objects by name, serial and + object.path using glob style pattern matching. + + +## modules + - filter-chain can now also configure parameters by index. + - Fix the client name of module-protocol-simple. (#2017) + - module-rtkit was merged into module-rt. This makes it easier to + ship a default config that works on more systems by default. + - module-adapter can now configure the adapter node from the config. + Previously, this was a task only performed by the session manager. + - module-metadata can now also create metadata object from the + config file. + - The ROC module should now work again. (#2045) + - An X11-bell module was added to handle X11 bell events. (#1668) + - filter-chain and loopback modules now have better unique default + names for the streams, which makes it possible to save and restore + their volumes independently. (#1983) + - module-echo-cancel now has properties to control the delay and + buffer size. + +## ALSA + - The monitor names are now correctly parsed. + - The default period size for batch devices is limited now to avoid + large latency. + - The unused min/max-latency properties were removed. + - Internal latency is now also configurable with params at runtime. + - The udev rule for TI2902 was removed because it causes problems. + - Fix a race where some devices would sometimes be missing. (#2046) + - Add some more timeouts to work around a race in udev device + permission changes when switching VTs. + +## SPA + - Fix potential infinite loop in audioconvert. + - The spa-resample tools can now also use optimized implementations. + - Fix a potential crash in resampler. (#1994) + - audioconvert can now also handle F64 formats. (#1990) + - The channelmixer now does normalization by default to avoid clipping + when downmixing is active. + - The channelmixer will now generate LFE channels when the lfe_cutoff + frequency is set, even when upmix is disabled. + - The channelmixer will now always generate FC when the target has it. + - Adapter now reports latency correctly, even after linking the monitor + ports. + - Reduce memory usage and preallocated memory in some of the + audioconvert nodes. + - Many properties are now exposed in adapter, such as the resample + quality. + - The resampler and channelmixer can now be disabled. + +## V4L2 + - pw-v4l2 now also works for ffplay. (#2029) + - Take product names from udev now that the kernel returns a generic + name. + +## JACK + - The jack pkgconfig file now has the `jack_implementation=pipewire` + variable to be able to distinguish jack implementations. (#1666) + - jconvolver now starts correctly again. (#1989) + - The object.serial is now used for the port_id. This makes it easier + to track old objects in the cache. + - Add a dummy jacknet implementation. (#2043) + - A bug in the port allocation was fixed that would make it impossible + to allocate ports at some point. (#1714) + +## Bluetooth + - Bluetooth profiles are now saved properly by the session manager. + - Improved profile detections, increased timeouts for slow devices. + - Implement HFP call indicator for improved compatibility. + - Handle the case where bluez does not set the adapter or address + properties on the device instead of crashing. + - Improved support for setting the profile from the session manager. + +## pulse-server + - Monitor sources now have the device.class=monitor for better + compatibility. + - Behaviour after seeking is improved. The algorithm for requesting + bytes from the client was simplified and improved. (#1981) + - module-ladspa-sink implements the control argument now. (#1987) + - A potential memory leak in the message queue was fixed. (#1840) + - Use the object.serial for the pulseaudio object index. The index is + not supposed to be reused and this would cause problems with some + clients. + - Servers should now again be able to listen in IPv4. (#2047) + - module-x11-bell was added. (#1668) + - There is now support for per-application quirks and properties in + the pipewire-pulse.conf file. Per-application latency and buffering + properties can also be configured. + - Fix a regression in telegram sounds not playing. + + +Older versions: + +# PipeWire 0.3.43 (2022-01-05) This is a bugfix release that is API and ABI compatible with previous 0.3.x releases. @@ -81,10 +219,6 @@ - Add command access control. This avoids execution of commands without proper authentication. - -Older versions: - - # PipeWire 0.3.42 (2021-12-16) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.43.tar.gz/README.md -> pipewire-0.3.44.tar.gz/README.md
Changed
@@ -48,6 +48,13 @@ expressed as a fraction of the samplerate, like 256/48000, which uses 256 samples at a samplerate of 48KHz for a latency of 5.33ms. + This function does not attempt to configure + the samplerate. +* `PIPEWIRE_RATE=<num/denom>` to configure a rate for the graph. +* `PIPEWIRE_QUANTUM=<num/denom>` to configure latency as a fraction and a + samplerate. This function will attempt to change + the graph samplerate to `denom` and use the + specified `num` as the buffer size. * `PIPEWIRE_NODE=<id>` to request a link to the specified node ### Using tools
View file
pipewire-0.3.44.tar.gz/doc/manpage.dox.in
Added
@@ -0,0 +1,5 @@ +/** \page @pagename@ @title@ + +\verbinclude @filename@ + +*/
View file
pipewire-0.3.43.tar.gz/doc/meson.build -> pipewire-0.3.44.tar.gz/doc/meson.build
Changed
@@ -26,7 +26,6 @@ 'pipewire-daemon.dox', 'pipewire-library.dox', 'pipewire-modules.dox', - 'pipewire-tools.dox', 'pipewire-session-manager.dox', 'pipewire-objects-design.dox', 'pipewire-audio.dox', @@ -115,6 +114,30 @@ input_dirs += [ 'doc/examples.dox' ] +man_doxygen = [] +man_subpages = [] +foreach m : manpages + manconf = configuration_data() + pagename = 'page_man_' + m.split('.rst.in').get(0).replace('.', '_').replace('-', '_') + filename = m.split('.rst.in').get(0) + '.dox' + manconf.set('pagename', pagename) + manconf.set('title', m.split('.rst.in').get(0).replace('.1','').replace('.5','')) + manconf.set('filename', meson.project_source_root() / 'man' / m) + manfile = configure_file(input: 'manpage.dox.in', + output: filename, + configuration: manconf) + man_doxygen += [manfile] + man_subpages += ['- \subpage ' + pagename] + input_dirs += [ 'doc/' + filename ] +endforeach + +pw_tools_dox_conf = configuration_data() +pw_tools_dox_conf.set('man_subpages', '\n'.join(man_subpages)) +pw_tools_dox = configure_file(input: 'pipewire-tools.dox.in', + output: 'pipewire-tools.dox', + configuration: pw_tools_dox_conf) +input_dirs += [ 'doc/pipewire-tools.dox' ] + doxyfile_conf.set('inputs', ' '.join(inputs + input_dirs)) doxyfile_conf.set('cssfiles', ' '.join(cssfiles)) doxyfile_conf.set('path_prefixes', ' '.join(path_prefixes)) @@ -131,7 +154,7 @@ endif html_target = custom_target('pipewire-docs', - input: [ doxyfile, examples_dox ] + inputs + cssfiles, + input: [ doxyfile, examples_dox, pw_tools_dox ] + inputs + cssfiles + man_doxygen, output: [ 'html' ], command: [ doxygen, doxyfile ], install: true,
View file
pipewire-0.3.43.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.44.tar.gz/doc/pipewire-modules.dox
Changed
@@ -74,8 +74,8 @@ - \subpage page_module_roc_sink - \subpage page_module_roc_source - \subpage page_module_rt -- \subpage page_module_rtkit - \subpage page_module_session_manager +- \subpage page_module_x11_bell - \subpage page_module_zeroconf_discover
View file
pipewire-0.3.44.tar.gz/doc/pipewire-tools.dox.in
Added
@@ -0,0 +1,7 @@ +/** \page page_tools PipeWire Tools + +Manual pages: + +@man_subpages@ + +*/
View file
pipewire-0.3.43.tar.gz/man/meson.build -> pipewire-0.3.44.tar.gz/man/meson.build
Changed
@@ -23,6 +23,10 @@ manpages += 'pw-jack.1.rst.in' endif +if not generate_manpages + subdir_done() +endif + foreach m : manpages file = m.split('.rst.in').get(0) rst = configure_file(input : m,
View file
pipewire-0.3.43.tar.gz/man/pipewire-pulse.1.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire-pulse.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pipewire-pulse ##############
View file
pipewire-0.3.43.tar.gz/man/pipewire.1.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pipewire ########
View file
pipewire-0.3.43.tar.gz/man/pipewire.conf.5.rst.in -> pipewire-0.3.44.tar.gz/man/pipewire.conf.5.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pipewire.conf #############
View file
pipewire-0.3.43.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-cat.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-cat ###### @@ -44,13 +42,16 @@ a connection is made to the default PipeWire instance. -p | --playback - Playback mode. Read data from the specified file, and play it back. If the tool is called under the name **pw-play** or **pw-midiplay** this is the default. + Playback mode. Read data from the specified file, and play it back. If the tool + is called under the name **pw-play** or **pw-midiplay** this is the default. -r | --record - Recording mode. Capture data and write it to the specified file. If the tool is called under the name **pw-record** or **pw-midirecord** this is the default. + Recording mode. Capture data and write it to the specified file. If the tool is + called under the name **pw-record** or **pw-midirecord** this is the default. -m | --midi - MIDI mode. *FILE* is a MIDI file. If the tool is called under the name **pw-midiplay** or **pw-midirecord** this is the default. + MIDI mode. *FILE* is a MIDI file. If the tool is called under the name + **pw-midiplay** or **pw-midirecord** this is the default. --media-type=VALUE Set the media type property (default Audio/Midi depending on mode).
View file
pipewire-0.3.43.tar.gz/man/pw-cli.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-cli.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-cli ###### @@ -45,7 +43,8 @@ MODULE MANAGEMENT ================= -| Modules are loaded and unloaded in the local instance and can add functionality or objects to the local instance. +| Modules are loaded and unloaded in the local instance and can add +| functionality or objects to the local instance. load-module *name* [*arguments...*] Load a module specified by its name and arguments. For most
View file
pipewire-0.3.43.tar.gz/man/pw-dot.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-dot.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-dot ######
View file
pipewire-0.3.43.tar.gz/man/pw-jack.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-jack.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-jack #######
View file
pipewire-0.3.43.tar.gz/man/pw-metadata.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-metadata.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-metadata ###########
View file
pipewire-0.3.43.tar.gz/man/pw-mididump.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-mididump.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-mididump ###########
View file
pipewire-0.3.43.tar.gz/man/pw-mon.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-mon.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-mon ######
View file
pipewire-0.3.43.tar.gz/man/pw-profiler.1.rst.in -> pipewire-0.3.44.tar.gz/man/pw-profiler.1.rst.in
Changed
@@ -1,5 +1,3 @@ -.. This file is part of PipeWire. - pw-profiler ###########
View file
pipewire-0.3.43.tar.gz/meson.build -> pipewire-0.3.44.tar.gz/meson.build
Changed
@@ -1,7 +1,7 @@ project('pipewire', ['c' ], - version : '0.3.43', + version : '0.3.44', license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ], - meson_version : '>= 0.56.0', + meson_version : '>= 0.59.0', default_options : [ 'warning_level=3', 'c_std=gnu99', 'cpp_std=c++17', @@ -323,12 +323,12 @@ dl_lib = cc.find_library('dl', required : false) pthread_lib = dependency('threads') dbus_dep = dependency('dbus-1', required : get_option('dbus')) -summary({'dbus (Bluetooth, rtkit, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies') +summary({'dbus (Bluetooth, rt, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies') if dbus_dep.found() cdata.set('HAVE_DBUS', 1) endif sdl_dep = dependency('sdl2', required : get_option('sdl2')) -summary({'SDL 2': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies') +summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies') drm_dep = dependency('libdrm', required : false) readline_dep = dependency('readline', required : false) @@ -349,6 +349,14 @@ summary({'Avahi DNS-SD (Zeroconf)': avahi_dep.found()}, bool_yn: true, section: 'Streaming between daemons') +x11_dep = dependency('x11-xcb', required : get_option('x11')) +summary({'X11 (x11-bell)': x11_dep.found()}, bool_yn: true, + section: 'Misc dependencies') + +canberra_dep = dependency('libcanberra', required : get_option('libcanberra')) +summary({'libcanberra (x11-bell)': canberra_dep.found()}, bool_yn: true, + section: 'Misc dependencies') + libusb_dep = dependency('libusb-1.0', required : get_option('libusb')) summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend') if libusb_dep.found() @@ -479,22 +487,25 @@ subdir('pipewire-alsa/tests') endif -doxygen = find_program('doxygen', required : get_option('docs')) -if doxygen.found() - subdir('doc') -endif - +generate_manpages = false if not get_option('man').disabled() rst2man = find_program('rst2man', required: false) if not rst2man.found() rst2man = find_program('rst2man.py', required: get_option('man')) endif - summary({'Manpage generation': rst2man.found()}, bool_yn: true) if rst2man.found() - subdir('man') + generate_manpages = true endif endif +summary({'Manpage generation': generate_manpages}, bool_yn: true) +subdir('man') + +doxygen = find_program('doxygen', required : get_option('docs')) +if doxygen.found() + subdir('doc') +endif + setenv = find_program('pw-uninstalled.sh') run_target('pw-uninstalled', command : [setenv, @@ -502,27 +513,25 @@ '-v@0@'.format(pipewire_version)] ) -if meson.version().version_compare('>=0.58.0') - devenv = environment() +devenv = environment() - builddir = meson.project_build_root() - srcdir = meson.project_source_root() +builddir = meson.project_build_root() +srcdir = meson.project_source_root() - devenv.set('PIPEWIRE_CONFIG_DIR', pipewire_dep.get_variable(internal: 'confdatadir')) - devenv.set('PIPEWIRE_MODULE_DIR', pipewire_dep.get_variable(internal: 'moduledir')) +devenv.set('PIPEWIRE_CONFIG_DIR', pipewire_dep.get_variable('confdatadir')) +devenv.set('PIPEWIRE_MODULE_DIR', pipewire_dep.get_variable('moduledir')) - devenv.set('SPA_PLUGIN_DIR', spa_dep.get_variable(internal: 'plugindir')) - devenv.set('SPA_DATA_DIR', spa_dep.get_variable(internal: 'datadir')) +devenv.set('SPA_PLUGIN_DIR', spa_dep.get_variable('plugindir')) +devenv.set('SPA_DATA_DIR', spa_dep.get_variable('datadir')) - devenv.set('GST_PLUGIN_PATH', builddir / 'src'/ 'gst') +devenv.set('GST_PLUGIN_PATH', builddir / 'src'/ 'gst') - devenv.set('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins') - devenv.set('ACP_PATHS_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'paths') - devenv.set('ACP_PROFILES_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'profile-sets') +devenv.set('ALSA_PLUGIN_DIR', builddir / 'pipewire-alsa' / 'alsa-plugins') +devenv.set('ACP_PATHS_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'paths') +devenv.set('ACP_PROFILES_DIR', srcdir / 'spa' / 'plugins' / 'alsa' / 'mixer' / 'profile-sets') - devenv.set('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src') +devenv.set('LD_LIBRARY_PATH', builddir / 'pipewire-jack' / 'src') - devenv.set('PW_UNINSTALLED', '1') +devenv.set('PW_UNINSTALLED', '1') - meson.add_devenv(devenv) -endif +meson.add_devenv(devenv)
View file
pipewire-0.3.43.tar.gz/meson_options.txt -> pipewire-0.3.44.tar.gz/meson_options.txt
Changed
@@ -179,6 +179,9 @@ option('udevrulesdir', type : 'string', description : 'Directory for udev rules (defaults to /lib/udev/rules.d)') +option('systemd-system-unit-dir', + type : 'string', + description : 'Directory for system systemd units (defaults to /usr/lib/systemd/system)') option('systemd-user-unit-dir', type : 'string', description : 'Directory for user systemd units (defaults to /usr/lib/systemd/user)') @@ -222,3 +225,11 @@ description: 'Enable loading of LV2 plugins', type: 'feature', value: 'auto') +option('x11', + description: 'Enable code that depends on X11', + type: 'feature', + value: 'auto') +option('libcanberra', + description: 'Enable code that depends on libcanberra', + type: 'feature', + value: 'auto')
View file
pipewire-0.3.43.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.44.tar.gz/pipewire-jack/src/meson.build
Changed
@@ -11,10 +11,9 @@ 'control.c', ] -pipewire_dummy_sources = [ - 'dummy.c', +pipewire_net_sources = [ + 'net.c', ] - pipewire_jack_c_args = [ '-DPIC', ] @@ -57,8 +56,8 @@ install_dir : libjack_path, ) -pipewire_jackserver = shared_library('jacknet', - pipewire_dummy_sources, +pipewire_jacknet = shared_library('jacknet', + pipewire_net_sources, soversion : soversion, version : libversion, c_args : pipewire_jack_c_args, @@ -85,7 +84,7 @@ description : 'PipeWire JACK API', version : '1.9.17', extra_cflags : '-D_REENTRANT', - unescaped_variables: ['server_libs=-L${libdir} -ljackserver']) + unescaped_variables: ['server_libs=-L${libdir} -ljackserver', 'jack_implementation=pipewire']) endif if sdl_dep.found()
View file
pipewire-0.3.43.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.44.tar.gz/pipewire-jack/src/metadata.c
Changed
@@ -213,7 +213,8 @@ const char* type) { struct client *c = (struct client *) client; - uint32_t id; + struct object *o; + uint32_t serial; int res = -1; spa_return_val_if_fail(c != NULL, -EINVAL); @@ -227,14 +228,16 @@ if (subject & (1<<30)) goto done; - id = jack_uuid_to_index(subject); + serial = jack_uuid_to_index(subject); + if ((o = find_by_serial(c, serial)) == NULL) + goto done; if (type == NULL) type = ""; - pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", id, subject, key, value, type); + pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", o->id, subject, key, value, type); if (update_property(c, subject, key, type, value)) - pw_metadata_set_property(c->metadata->proxy, id, key, type, value); + pw_metadata_set_property(c->metadata->proxy, o->id, key, type, value); res = 0; done: pw_thread_loop_unlock(c->context.loop);
View file
pipewire-0.3.44.tar.gz/pipewire-jack/src/net.c
Added
@@ -0,0 +1,169 @@ +/* PipeWire + * + * Copyright © 2022 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 "config.h" + +#include <stdio.h> +#include <unistd.h> +#include <errno.h> + +#include <jack/net.h> + +#include <pipewire/pipewire.h> + +SPA_EXPORT +jack_net_slave_t* jack_net_slave_open(const char* ip, int port, const char* name, + jack_slave_t* request, jack_master_t* result) +{ + return NULL; +} + +SPA_EXPORT +int jack_net_slave_close(jack_net_slave_t* net) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_set_net_slave_process_callback(jack_net_slave_t * net, JackNetSlaveProcessCallback net_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_slave_activate(jack_net_slave_t* net) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_slave_deactivate(jack_net_slave_t* net) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_slave_is_active(jack_net_slave_t* net) +{ + return false; +} + +SPA_EXPORT +int jack_set_net_slave_buffer_size_callback(jack_net_slave_t *net, JackNetSlaveBufferSizeCallback bufsize_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_set_net_slave_sample_rate_callback(jack_net_slave_t *net, JackNetSlaveSampleRateCallback samplerate_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_set_net_slave_shutdown_callback(jack_net_slave_t *net, JackNetSlaveShutdownCallback shutdown_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_set_net_slave_restart_callback(jack_net_slave_t *net, JackNetSlaveRestartCallback restart_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_set_net_slave_error_callback(jack_net_slave_t *net, JackNetSlaveErrorCallback error_callback, void *arg) +{ + return ENOTSUP; +} + +SPA_EXPORT +jack_net_master_t* jack_net_master_open(const char* ip, int port, jack_master_t* request, jack_slave_t* result) +{ + return NULL; +} + +SPA_EXPORT +int jack_net_master_close(jack_net_master_t* net) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_master_recv(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_master_recv_slice(jack_net_master_t* net, int audio_input, float** audio_input_buffer, int midi_input, void** midi_input_buffer, int frames) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_master_send(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_net_master_send_slice(jack_net_master_t* net, int audio_output, float** audio_output_buffer, int midi_output, void** midi_output_buffer, int frames) +{ + return ENOTSUP; +} + +SPA_EXPORT +jack_adapter_t* jack_create_adapter(int input, int output, + jack_nframes_t host_buffer_size, + jack_nframes_t host_sample_rate, + jack_nframes_t adapted_buffer_size, + jack_nframes_t adapted_sample_rate) +{ + return NULL; +} + +SPA_EXPORT +int jack_destroy_adapter(jack_adapter_t* adapter) +{ + return ENOTSUP; +} + +SPA_EXPORT +void jack_flush_adapter(jack_adapter_t* adapter) +{ +} + +SPA_EXPORT +int jack_adapter_push_and_pull(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) +{ + return ENOTSUP; +} + +SPA_EXPORT +int jack_adapter_pull_and_push(jack_adapter_t* adapter, float** input, float** output, unsigned int frames) +{ + return ENOTSUP; +}
View file
pipewire-0.3.43.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.44.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -99,14 +99,14 @@ jack_thread_creator_t creator; pthread_mutex_t lock; struct pw_array descriptions; - struct spa_list free_objects[3]; - struct pw_map cache; + struct spa_list free_objects; }; static struct globals globals; static bool mlock_warned = false; -#define OBJECT_CHUNK 8 +#define OBJECT_CHUNK 8 +#define RECYCLE_THRESHOLD 128 typedef void (*mix2_func) (float *dst, float *src1, float *src2, int n_samples); @@ -122,7 +122,7 @@ #define INTERFACE_Link 2 uint32_t type; uint32_t id; - uint32_t idx; + uint32_t serial; union { struct { @@ -134,11 +134,11 @@ struct { uint32_t src; uint32_t dst; + uint32_t src_serial; + uint32_t dst_serial; bool src_ours; bool dst_ours; bool is_complete; - uint32_t src_idx; - uint32_t dst_idx; struct port *our_input; struct port *our_output; } port_link; @@ -151,7 +151,6 @@ uint32_t system_id; uint32_t type_id; uint32_t node_id; - uint32_t port_id; uint32_t monitor_requests; int32_t priority; struct port *port; @@ -164,6 +163,7 @@ struct spa_hook proxy_listener; struct spa_hook object_listener; unsigned int removing:1; + unsigned int removed:1; }; struct midi_buffer { @@ -223,7 +223,7 @@ struct client *client; enum spa_direction direction; - uint32_t id; + uint32_t port_id; struct object *object; struct pw_properties *props; struct spa_port_info info; @@ -264,15 +264,13 @@ struct pw_context *context; pthread_mutex_t lock; /* protects map and lists below, in addition to thread_lock */ - struct pw_map globals; - struct spa_list ports; - struct spa_list nodes; - struct spa_list links; + struct spa_list objects; + uint32_t free_count; }; #define GET_DIRECTION(f) ((f) & JackPortIsInput ? SPA_DIRECTION_INPUT : SPA_DIRECTION_OUTPUT) -#define GET_PORT(c,d,p) ((d >= 0 && d <=1 && p < c->n_port_pool[d]) ? c->port_pool[d][p] : NULL) +#define GET_PORT(c,d,p) (pw_map_lookup(&c->ports[d], p)) struct metadata { struct pw_metadata *proxy; @@ -315,6 +313,7 @@ struct metadata *metadata; uint32_t node_id; + uint32_t serial; struct spa_source *socket_source; JackThreadCallback thread_callback; @@ -362,10 +361,8 @@ struct spa_list mix; struct spa_list free_mix; - uint32_t n_port_pool[2]; - struct port *port_pool[2][MAX_PORTS]; - struct spa_list ports[2]; - struct spa_list free_ports[2]; + struct spa_list free_ports; + struct pw_map ports[2]; struct spa_list links; uint32_t driver_id; @@ -406,6 +403,7 @@ }; static int do_sync(struct client *client); +static struct object *find_by_serial(struct client *c, uint32_t serial); #include "metadata.c" @@ -413,64 +411,66 @@ int (*matched) (void *data, const char *action, const char *val, int len), void *data); -static void init_port_pool(struct client *c, enum spa_direction direction) -{ - spa_list_init(&c->ports[direction]); - spa_list_init(&c->free_ports[direction]); - c->n_port_pool[direction] = 0; -} - -static struct object * find_cache(uint32_t type, uint32_t idx) -{ - struct object *o; - pthread_mutex_lock(&globals.lock); - o = pw_map_lookup(&globals.cache, idx); - if (o != NULL && o->type != type) - o = NULL; - pthread_mutex_unlock(&globals.lock); - return o; -} - static struct object * alloc_object(struct client *c, int type) { struct object *o; int i; pthread_mutex_lock(&globals.lock); - if (spa_list_is_empty(&globals.free_objects[type])) { + if (spa_list_is_empty(&globals.free_objects)) { o = calloc(OBJECT_CHUNK, sizeof(struct object)); if (o == NULL) { pthread_mutex_unlock(&globals.lock); return NULL; } - for (i = 0; i < OBJECT_CHUNK; i++) { - o[i].idx = pw_map_insert_new(&globals.cache, &o[i]); - spa_list_append(&globals.free_objects[type], &o[i].link); - } + for (i = 0; i < OBJECT_CHUNK; i++) + spa_list_append(&globals.free_objects, &o[i].link); } - o = spa_list_first(&globals.free_objects[type], struct object, link); + o = spa_list_first(&globals.free_objects, struct object, link); spa_list_remove(&o->link); pthread_mutex_unlock(&globals.lock); o->client = c; + o->removed = false; o->type = type; pw_log_debug("%p: object:%p type:%d", c, o, type); return o; } +static void recycle_objects(struct client *c, uint32_t remain) +{ + struct object *o, *t; + pthread_mutex_lock(&globals.lock); + spa_list_for_each_safe(o, t, &c->context.objects, link) { + if (o->removed) { + pw_log_info("%p: recycle object:%p type:%d id:%u/%u", + c, o, o->type, o->id, o->serial); + spa_list_remove(&o->link); + memset(o, 0, sizeof(struct object)); + spa_list_append(&globals.free_objects, &o->link); + if (--c->context.free_count == remain) + break; + } + } + pthread_mutex_unlock(&globals.lock); +} + +/* JACK clients expect the objects to hang around after + * they are unregistered and freed. We mark the object removed and + * move it to the end of the queue. */ static void free_object(struct client *c, struct object *o) { + pw_log_debug("%p: object:%p type:%d", c, o, o->type); pthread_mutex_lock(&c->context.lock); spa_list_remove(&o->link); + o->removed = true; + o->id = SPA_ID_INVALID; + spa_list_append(&c->context.objects, &o->link); + if (++c->context.free_count > RECYCLE_THRESHOLD) + recycle_objects(c, RECYCLE_THRESHOLD / 2);
View file
pipewire-0.3.43.tar.gz/pipewire-jack/src/pw-jack.in -> pipewire-0.3.44.tar.gz/pipewire-jack/src/pw-jack.in
Changed
@@ -24,7 +24,7 @@ # DEALINGS IN THE SOFTWARE. # -SAMPLERATE=48000 +DEFAULT_SAMPLERATE=48000 while getopts 'hr:vs:p:' param ; do case $param in @@ -55,7 +55,7 @@ echo " -h show brief help" echo " -r <remote> remote daemon name" echo " -v verbose debug info" - echo " -s samplerate (default \"$SAMPLERATE\")" + echo " -s samplerate (default \"$DEFAULT_SAMPLERATE\")" echo " -p period in samples" exit 0 ;; @@ -65,8 +65,12 @@ shift $(( OPTIND - 1 )) if [ -n "$PERIOD" ]; then - PIPEWIRE_LATENCY="$PERIOD/$SAMPLERATE" - export PIPEWIRE_LATENCY + if [ -n "$SAMPLERATE" ]; then + PIPEWIRE_QUANTUM="$PERIOD/$SAMPLERATE" + else + PIPEWIRE_QUANTUM="$PERIOD/$DEFAULT_SAMPLERATE" + fi + export PIPEWIRE_QUANTUM fi LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}" export LD_LIBRARY_PATH
View file
pipewire-0.3.43.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c -> pipewire-0.3.44.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c
Changed
@@ -1119,12 +1119,13 @@ file->v4l2_format = fmt; - buffers = file->reqbufs; + buffers = SPA_CLAMP(file->reqbufs, 2u, MAX_BUFFERS); size = 0; params[n_params++] = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_ParamBuffers, SPA_PARAM_Buffers, - SPA_PARAM_BUFFERS_buffers, SPA_POD_Int(buffers), + SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(buffers, + 2, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int(size, 0, INT_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_CHOICE_RANGE_Int(0, 0, INT_MAX),
View file
pipewire-0.3.43.tar.gz/spa/include/spa/buffer/meta.h -> pipewire-0.3.44.tar.gz/spa/include/spa/buffer/meta.h
Changed
@@ -81,7 +81,7 @@ #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 pts; /**< presentation timestamp in nanoseconds */ int64_t dts_offset; /**< decoding timestamp as a difference with pts */ uint64_t seq; /**< sequence number, increments with a * media specific frequency */
View file
pipewire-0.3.43.tar.gz/spa/include/spa/debug/types.h -> pipewire-0.3.44.tar.gz/spa/include/spa/debug/types.h
Changed
@@ -96,6 +96,26 @@ return SPA_ID_INVALID; } +static inline const struct spa_type_info *spa_debug_type_find_short(const struct spa_type_info *info, const char *name) +{ + while (info && info->name) { + if (strcmp(spa_debug_type_short_name(info->name), name) == 0) + return info; + if (strcmp(info->name, name) == 0) + return info; + if (info->type != 0 && info->type == (uint32_t)atoi(name)) + return info; + info++; + } + return NULL; +} + +static inline uint32_t spa_debug_type_find_type_short(const struct spa_type_info *info, const char *name) +{ + if ((info = spa_debug_type_find_short(info, name)) == NULL) + return SPA_ID_INVALID; + return info->type; +} /** * \} */
View file
pipewire-0.3.43.tar.gz/spa/include/spa/support/thread.h -> pipewire-0.3.44.tar.gz/spa/include/spa/support/thread.h
Changed
@@ -68,7 +68,9 @@ /** get realtime priority range for threads created with \a props */ int (*get_rt_range) (void *data, const struct spa_dict *props, int *min, int *max); - /** acquire realtime priority */ + /** acquire realtime priority, a priority of -1 refers to the priority + * configured in the realtime module + */ int (*acquire_rt) (void *data, struct spa_thread *thread, int priority); /** drop realtime priority */ int (*drop_rt) (void *data, struct spa_thread *thread);
View file
pipewire-0.3.43.tar.gz/spa/include/spa/utils/dict.h -> pipewire-0.3.44.tar.gz/spa/include/spa/utils/dict.h
Changed
@@ -74,8 +74,9 @@ 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); + if (dict->n_items > 0) + 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); } @@ -84,7 +85,8 @@ { const struct spa_dict_item *item; - if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED)) { + if (SPA_FLAG_IS_SET(dict->flags, SPA_DICT_FLAG_SORTED) && + dict->n_items > 0) { 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,
View file
pipewire-0.3.44.tar.gz/spa/include/spa/utils/json-pod.h
Added
@@ -0,0 +1,177 @@ +/* Simple Plugin API + * + * Copyright © 2022 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_JSON_POD_H +#define SPA_UTILS_JSON_POD_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/utils/string.h> +#include <spa/utils/json.h> +#include <spa/pod/pod.h> +#include <spa/pod/builder.h> +#include <spa/debug/types.h> + +/** \defgroup spa_json_pod JSON to POD + * JSON to POD conversion + */ + +/** + * \addtogroup spa_json_pod + * \{ + */ + +static inline int spa_json_to_pod_part(struct spa_pod_builder *b, uint32_t flags, uint32_t id, + const struct spa_type_info *info, struct spa_json *iter, const char *value, int len) +{ + const struct spa_type_info *ti; + char key[256]; + struct spa_pod_frame f[1]; + struct spa_json it[1]; + int l, res; + const char *v; + uint32_t type; + + if (spa_json_is_object(value, len) && info != NULL) { + if ((ti = spa_debug_type_find(NULL, info->parent)) == NULL) + return -EINVAL; + + spa_pod_builder_push_object(b, &f[0], info->parent, id); + + spa_json_enter(iter, &it[0]); + while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { + const struct spa_type_info *pi; + if ((l = spa_json_next(&it[0], &v)) <= 0) + break; + if ((pi = spa_debug_type_find_short(ti->values, key)) != NULL) + type = pi->type; + else if (!spa_atou32(key, &type, 0)) + continue; + spa_pod_builder_prop(b, type, 0); + if ((res = spa_json_to_pod_part(b, flags, id, pi, &it[0], v, l)) < 0) + return res; + } + spa_pod_builder_pop(b, &f[0]); + } + else if (spa_json_is_array(value, len)) { + if (info == NULL || info->parent == SPA_TYPE_Struct) { + spa_pod_builder_push_struct(b, &f[0]); + } else { + spa_pod_builder_push_array(b, &f[0]); + info = info->values; + } + spa_json_enter(iter, &it[0]); + while ((l = spa_json_next(&it[0], &v)) > 0) + if ((res = spa_json_to_pod_part(b, flags, id, info, &it[0], v, l)) < 0) + return res; + spa_pod_builder_pop(b, &f[0]); + } + else if (spa_json_is_float(value, len)) { + float val = 0.0f; + spa_json_parse_float(value, len, &val); + switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) { + case SPA_TYPE_Bool: + spa_pod_builder_bool(b, val >= 0.5f); + break; + case SPA_TYPE_Id: + spa_pod_builder_id(b, val); + break; + case SPA_TYPE_Int: + spa_pod_builder_int(b, val); + break; + case SPA_TYPE_Long: + spa_pod_builder_long(b, val); + break; + case SPA_TYPE_Struct: + if (spa_json_is_int(value, len)) + spa_pod_builder_int(b, val); + else + spa_pod_builder_float(b, val); + break; + case SPA_TYPE_Float: + spa_pod_builder_float(b, val); + break; + case SPA_TYPE_Double: + spa_pod_builder_double(b, val); + break; + default: + spa_pod_builder_none(b); + break; + } + } + else if (spa_json_is_bool(value, len)) { + bool val = false; + spa_json_parse_bool(value, len, &val); + spa_pod_builder_bool(b, val); + } + else if (spa_json_is_null(value, len)) { + spa_pod_builder_none(b); + } + else { + char *val = (char*)alloca(len+1); + spa_json_parse_stringn(value, len, val, len+1); + switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) { + case SPA_TYPE_Id: + if ((ti = spa_debug_type_find_short(info->values, val)) != NULL) + type = ti->type; + else if (!spa_atou32(val, &type, 0)) + return -EINVAL; + spa_pod_builder_id(b, type); + break; + case SPA_TYPE_Struct: + case SPA_TYPE_String: + spa_pod_builder_string(b, val); + break; + default: + spa_pod_builder_none(b); + break; + } + } + return 0; +} + +static inline int spa_json_to_pod(struct spa_pod_builder *b, uint32_t flags, + const struct spa_type_info *info, const char *value, int len) +{ + struct spa_json iter; + const char *val; + + spa_json_init(&iter, value, len); + if ((len = spa_json_next(&iter, &val)) <= 0) + return -EINVAL; + + return spa_json_to_pod_part(b, flags, info->type, info, &iter, val, len); +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_UTILS_JSON_POD_H */
View file
pipewire-0.3.43.tar.gz/spa/meson.build -> pipewire-0.3.44.tar.gz/spa/meson.build
Changed
@@ -9,6 +9,7 @@ include_directories : [ include_directories('include'), ], + dependencies : [atomic_dep], version : spaversion, variables : { 'plugindir' : meson.current_build_dir() / 'plugins',
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules
Changed
@@ -113,8 +113,7 @@ ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{ACP_PROFILE_SET}="sb-omni-surround-5.1.conf" ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf" ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="402e", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf" -ATTRS{idVendor}=="1397", ATTRS{idProduct}=="0507", ENV{ACP_PROFILE_SET}="behringer-umc22.conf" -ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf" +#ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf" ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0269", ENV{ACP_PROFILE_SET}="hp-tbt-dock-120w-g2.conf" ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0567", ENV{ACP_PROFILE_SET}="hp-tbt-dock-audio-module.conf"
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/acp/compat.h -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/acp/compat.h
Changed
@@ -34,6 +34,9 @@ #include <inttypes.h> #include <stdlib.h> #include <unistd.h> +#include <math.h> + +#include <spa/utils/string.h> typedef struct pa_core pa_core; @@ -545,25 +548,35 @@ static inline int pa_atod(const char *s, double *ret_d) { - char *x; - *ret_d = strtod(s, &x); - return 0; + if (spa_atod(s, ret_d) && !isnan(*ret_d)) + return 0; + errno = EINVAL; + return -1; } static inline int pa_atoi(const char *s, int32_t *ret_i) { - *ret_i = (int32_t) atoi(s); - return 0; + if (spa_atoi32(s, ret_i, 0)) + return 0; + errno = EINVAL; + return -1; } static inline int pa_atou(const char *s, uint32_t *ret_u) { - *ret_u = (uint32_t) atoi(s); - return 0; + if (spa_atou32(s, ret_u, 0)) + return 0; + errno = EINVAL; + return -1; } static inline int pa_atol(const char *s, long *ret_l) { - char *x; - *ret_l = strtol(s, &x, 0); - return 0; + int64_t res; + if (spa_atoi64(s, &res, 0)) { + *ret_l = res; + if (*ret_l == res) + return 0; + } + errno = EINVAL; + return -1; } static inline int pa_parse_boolean(const char *v)
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -42,14 +42,10 @@ #define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0) static const char default_device[] = "hw:0"; -static const uint32_t default_min_latency = MIN_LATENCY; -static const uint32_t default_max_latency = MAX_LATENCY; static void reset_props(struct props *props) { strncpy(props->device, default_device, 64); - props->min_latency = default_min_latency; - props->max_latency = default_max_latency; props->use_chmap = DEFAULT_USE_CHMAP; } @@ -68,7 +64,7 @@ items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Sink"); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true"); if (this->have_format) { - snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 4, this->rate); + snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency); } this->info.props = &SPA_DICT_INIT(items, n_items); @@ -162,25 +158,11 @@ case 3: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); - break; - case 4: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); - break; - case 5: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX)); break; - case 6: + case 4: if (!this->is_iec958 && !this->is_hdmi) goto next; param = spa_pod_builder_add_object(&b, @@ -193,7 +175,7 @@ SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; default: - param = spa_alsa_enum_propinfo(this, result.index - 7, &b); + param = spa_alsa_enum_propinfo(this, result.index - 5, &b); if (param == NULL) return 0; } @@ -213,8 +195,6 @@ SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)), SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)), SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), - SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), - SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns), 0); @@ -343,8 +323,6 @@ spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, SPA_PROP_device, SPA_POD_OPT_Stringn(p->device, sizeof(p->device)), - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&info.ns), SPA_PROP_iec958Codecs, SPA_POD_OPT_Pod(&iec958_codecs), SPA_PROP_params, SPA_POD_OPT_Pod(¶ms)); @@ -363,8 +341,8 @@ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_params[PORT_EnumFormat].user++; } - handle_process_latency(this, &info); spa_alsa_parse_prop_params(this, params); + handle_process_latency(this, &info); emit_node_info(this, false); emit_port_info(this, false); @@ -551,8 +529,8 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - this->props.max_latency * this->frame_size, - this->props.min_latency * this->frame_size, + this->quantum_limit * this->frame_size, + 16 * this->frame_size, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->frame_size)); break;
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -44,14 +44,10 @@ #define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0) static const char default_device[] = "hw:0"; -static const uint32_t default_min_latency = MIN_LATENCY; -static const uint32_t default_max_latency = MAX_LATENCY; static void reset_props(struct props *props) { strncpy(props->device, default_device, 64); - props->min_latency = default_min_latency; - props->max_latency = default_max_latency; props->use_chmap = DEFAULT_USE_CHMAP; } @@ -69,7 +65,7 @@ items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Source"); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true"); if (this->have_format) { - snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 4, this->rate); + snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate); items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency); } this->info.props = &SPA_DICT_INIT(items, n_items); @@ -162,26 +158,12 @@ case 3: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_minLatency), - SPA_PROP_INFO_description, SPA_POD_String("The minimum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->min_latency, 1, INT32_MAX)); - break; - case 4: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_maxLatency), - SPA_PROP_INFO_description, SPA_POD_String("The maximum latency"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->max_latency, 1, INT32_MAX)); - break; - case 5: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, INT64_MAX)); break; default: - param = spa_alsa_enum_propinfo(this, result.index - 6, &b); + param = spa_alsa_enum_propinfo(this, result.index - 4, &b); if (param == NULL) return 0; } @@ -199,8 +181,6 @@ SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)), SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)), SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), - SPA_PROP_minLatency, SPA_POD_Int(p->min_latency), - SPA_PROP_maxLatency, SPA_POD_Int(p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns), 0); spa_alsa_add_prop_params(this, &b); @@ -323,13 +303,11 @@ spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, SPA_PROP_device, SPA_POD_OPT_Stringn(p->device, sizeof(p->device)), - SPA_PROP_minLatency, SPA_POD_OPT_Int(&p->min_latency), - SPA_PROP_maxLatency, SPA_POD_OPT_Int(&p->max_latency), SPA_PROP_latencyOffsetNsec, SPA_POD_OPT_Long(&info.ns), SPA_PROP_params, SPA_POD_OPT_Pod(¶ms)); - handle_process_latency(this, &info); spa_alsa_parse_prop_params(this, params); + handle_process_latency(this, &info); emit_node_info(this, false); emit_port_info(this, false); @@ -500,8 +478,8 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - this->props.max_latency * this->frame_size, - this->props.min_latency * this->frame_size, + this->quantum_limit * this->frame_size, + 16 * this->frame_size, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->frame_size)); break;
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -125,6 +125,10 @@ state->props.use_chmap = spa_atob(s); } else if (spa_streq(k, "api.alsa.multi-rate")) { state->multi_rate = spa_atob(s); + } else if (spa_streq(k, "latency.internal.rate")) { + state->process_latency.rate = atoi(s); + } else if (spa_streq(k, "latency.internal.ns")) { + state->process_latency.ns = atoi(s); } else if (spa_streq(k, "clock.name")) { spa_scnprintf(state->clock_name, sizeof(state->clock_name), "%s", s); @@ -295,6 +299,22 @@ case 13: param = spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String("latency.internal.rate"), + SPA_PROP_INFO_description, SPA_POD_String("Internal latency in samples"), + SPA_PROP_INFO_type, SPA_POD_Int(state->process_latency.rate), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 14: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String("latency.internal.ns"), + SPA_PROP_INFO_description, SPA_POD_String("Internal latency in nanoseconds"), + SPA_PROP_INFO_type, SPA_POD_Long(state->process_latency.ns), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 15: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_name, SPA_POD_String("clock.name"), SPA_PROP_INFO_description, SPA_POD_String("The name of the clock"), SPA_PROP_INFO_type, SPA_POD_String(state->clock_name), @@ -358,6 +378,12 @@ spa_pod_builder_string(b, "api.alsa.multi-rate"); spa_pod_builder_bool(b, state->multi_rate); + spa_pod_builder_string(b, "latency.internal.rate"); + spa_pod_builder_int(b, state->process_latency.rate); + + spa_pod_builder_string(b, "latency.internal.ns"); + spa_pod_builder_long(b, state->process_latency.ns); + spa_pod_builder_string(b, "clock.name"); spa_pod_builder_string(b, state->clock_name); @@ -391,8 +417,11 @@ if (spa_pod_is_string(pod)) { spa_pod_copy_string(pod, sizeof(value), value); } else if (spa_pod_is_int(pod)) { - snprintf(value, sizeof(value), "%u", + snprintf(value, sizeof(value), "%d", SPA_POD_VALUE(struct spa_pod_int, pod)); + } else if (spa_pod_is_long(pod)) { + snprintf(value, sizeof(value), "%"PRIi64, + SPA_POD_VALUE(struct spa_pod_long, pod)); } else if (spa_pod_is_bool(pod)) { snprintf(value, sizeof(value), "%s", SPA_POD_VALUE(struct spa_pod_bool, pod) ? @@ -427,10 +456,8 @@ state->card_index = atoi(s); } else if (spa_streq(k, SPA_KEY_API_ALSA_OPEN_UCM)) { state->open_ucm = spa_atob(s); - } else if (spa_streq(k, "latency.internal.rate")) { - state->process_latency.rate = atoi(s); - } else if (spa_streq(k, "latency.internal.ns")) { - state->process_latency.ns = atoi(s); + } else if (spa_streq(k, "clock.quantum-limit")) { + spa_atou32(s, &state->quantum_limit, 0); } else { alsa_set_param(state, k, s); } @@ -732,31 +759,32 @@ CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min"); CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max"); - rate = state->default_rate; if (!state->multi_rate && state->card->format_ref > 0) rate = state->card->rate; + else + rate = state->default_rate; - if (rate != 0 && !all) { - if (min < rate) - min = rate; - if (max > rate) - max = rate; - } + if (rate < min || rate > max) + rate = 0; + + if (rate != 0 && !all) + min = max = rate; + + if (rate == 0) + rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE; + + rate = SPA_CLAMP(rate, min, max); spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_rate, 0); spa_pod_builder_push_choice(b, &f[0], SPA_CHOICE_None, 0); choice = (struct spa_pod_choice*)spa_pod_builder_frame(b, &f[0]); - if (rate == 0) - rate = state->position ? state->position->clock.rate.denom : DEFAULT_RATE; - if (state->n_allowed_rates > 0) { uint32_t i, v, last = 0, count = 0; - v = SPA_CLAMP(rate, min, max); - if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, v)) { - spa_pod_builder_int(b, v * scale); + if (uint32_array_contains(state->allowed_rates, state->n_allowed_rates, rate)) { + spa_pod_builder_int(b, rate * scale); count++; } for (i = 0; i < state->n_allowed_rates; i++) { @@ -773,7 +801,7 @@ if (count > 1) choice->body.type = SPA_CHOICE_Enum; } else { - spa_pod_builder_int(b, SPA_CLAMP(rate, min, max) * scale); + spa_pod_builder_int(b, rate * scale); if (min != max) { spa_pod_builder_int(b, min * scale); @@ -1419,9 +1447,13 @@ if (is_batch) { if (period_size == 0) period_size = state->position ? state->position->clock.duration : DEFAULT_PERIOD; + if (period_size == 0) + period_size = DEFAULT_PERIOD; /* batch devices get their hw pointers updated every period. Make - * the period smaller and add one period of headroom */ - period_size /= 2; + * the period smaller and add one period of headroom. Limit the + * period size to our default so that we don't create too much + * headroom. */ + period_size = SPA_MIN(period_size, DEFAULT_PERIOD) / 2; spa_log_info(state->log, "%s: batch mode, period_size:%ld", state->props.device, period_size); } else { @@ -2306,7 +2338,7 @@ else { spa_log_warn(state->log, "%s: no position set, using defaults", state->props.device); - state->duration = state->props.min_latency; + state->duration = 1024; state->rate_denom = state->rate; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -52,9 +52,6 @@ #include "dll.h" -#define MIN_LATENCY 16 -#define MAX_LATENCY 8192 - #define MAX_RATES 16 #define DEFAULT_PERIOD 1024u @@ -66,8 +63,6 @@ char device[64]; char device_name[128]; char card_name[128]; - uint32_t min_latency; - uint32_t max_latency; bool use_chmap; }; @@ -148,6 +143,7 @@ unsigned int disable_mmap; unsigned int disable_batch; char clock_name[64]; + uint32_t quantum_limit; snd_pcm_uframes_t buffer_frames; snd_pcm_uframes_t period_frames;
View file
pipewire-0.3.43.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-udev.c
Changed
@@ -47,6 +47,9 @@ #define MAX_DEVICES 64 +#define RETRY_COUNT 1 +#define RETRY_MSEC 2000 + #define ACTION_ADD 0 #define ACTION_REMOVE 1 #define ACTION_DISABLE 2 @@ -54,6 +57,7 @@ struct device { uint32_t id; struct udev_device *dev; + uint8_t retry; unsigned int accessible:1; unsigned int ignored:1; unsigned int emitted:1; @@ -65,6 +69,7 @@ struct spa_log *log; struct spa_loop *main_loop; + struct spa_system *main_system; struct spa_hook_list hooks; @@ -79,6 +84,7 @@ struct spa_source source; struct spa_source notify; + struct spa_source retry_timer; unsigned int use_acp:1; }; @@ -243,6 +249,39 @@ *d = 0; } +static int check_device_busy(struct impl *this, struct device *device, snd_ctl_t *ctl_hndl) +{ + int dev; + + /* Check if some pcm devices of the card cannot be opened because they are busy */ + + for (dev = -1; snd_ctl_pcm_next_device(ctl_hndl, &dev) >= 0 && dev >= 0;) { + char devpath[64]; + int i; + + snprintf(devpath, sizeof(devpath), "hw:%u,%u", device->id, dev); + + for (i = 0; i < 2; ++i) { + snd_pcm_t *handle; + int res; + + res = snd_pcm_open(&handle, devpath, + (i == 0) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, + SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | + SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT); + if (res == -EBUSY) { + spa_log_debug(this->log, "pcm device %s busy", devpath); + return -EBUSY; + } else if (res >= 0) { + snd_pcm_close(handle); + } + } + spa_log_debug(this->log, "pcm device %s free", devpath); + } + + return 0; +} + static int emit_object_info(struct impl *this, struct device *device) { struct spa_device_object_info info; @@ -267,20 +306,24 @@ pcm = -1; res = snd_ctl_pcm_next_device(ctl_hndl, &pcm); - spa_log_debug(this->log, "close card %s", path); - snd_ctl_close(ctl_hndl); - if (res < 0) { spa_log_error(this->log, "error iterating devices: %s", snd_strerror(res)); device->ignored = true; - return res; - } - if (pcm < 0) { + } else if (pcm < 0) { spa_log_debug(this->log, "no pcm devices for %s", path); device->ignored = true; - return 0; + res = 0; + } else if (device->retry > 0) { + /* Check if we can open all PCM devices (retry later if not) */ + res = check_device_busy(this, device, ctl_hndl); } + spa_log_debug(this->log, "close card %s", path); + snd_ctl_close(ctl_hndl); + + if (res < 0 || device->ignored) + return res; + info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Device; @@ -393,6 +436,82 @@ return 1; } +static void start_retry(struct impl *this); + +static void stop_retry(struct impl *this); + +static void retry_timer_event(struct spa_source *source) +{ + struct impl *this = source->data; + bool have_retry = false; + size_t i; + + stop_retry(this); + + for (i = 0; i < this->n_devices; ++i) { + struct device *device = &this->devices[i]; + if (device->ignored) + device->retry = 0; + if (device->retry > 0) { + --device->retry; + + spa_log_debug(this->log, "retrying device %u", device->id); + + if (emit_object_info(this, device) == -EBUSY) { + spa_log_debug(this->log, "device %u busy (remaining retries %u)", + device->id, device->retry); + } else { + device->retry = 0; + } + } + if (device->retry > 0) + have_retry = true; + } + + if (have_retry) + start_retry(this); +} + +static void start_retry(struct impl *this) +{ + struct itimerspec ts; + + spa_log_debug(this->log, "start retry"); + + if (this->retry_timer.data == NULL) { + this->retry_timer.data = this; + this->retry_timer.func = retry_timer_event; + this->retry_timer.mask = SPA_IO_IN; + this->retry_timer.rmask = 0; + spa_loop_add_source(this->main_loop, &this->retry_timer); + } + + ts.it_value.tv_sec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) / SPA_NSEC_PER_SEC; + ts.it_value.tv_nsec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) % SPA_NSEC_PER_SEC; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL); +} + +static void stop_retry(struct impl *this) +{ + struct itimerspec ts; + + if (this->retry_timer.data == NULL) + return; + + spa_log_debug(this->log, "stop retry"); + + spa_loop_remove_source(this->main_loop, &this->retry_timer); + this->retry_timer.data = NULL; + + ts.it_value.tv_sec = 0; + ts.it_value.tv_nsec = 0; + ts.it_interval.tv_sec = 0; + ts.it_interval.tv_nsec = 0; + spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL); +} + static bool check_access(struct impl *this, struct device *device) { char path[128]; @@ -425,7 +544,14 @@ return; if (!check_access(this, device)) return; - emit_object_info(this, device); + device->retry = RETRY_COUNT; + if (emit_object_info(this, device) == -EBUSY) { + spa_log_debug(this->log, "device %u busy (remaining retries %u)", + device->id, device->retry); + start_retry(this); + } else {
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -118,19 +118,20 @@ struct spa_pod_builder *builder) { int res; - if (result->next < 0x10000) { + if (result->next < 0x100000) { if ((res = spa_node_enum_params_sync(this->convert, id, &result->next, filter, &result->param, builder)) == 1) return res; - result->next = 0x10000; + result->next = 0x100000; } - if (result->next >= 0x10000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) { - result->next &= 0xffff; + if (result->next < 0x200000 && this->follower_params_flags[idx] & SPA_PARAM_INFO_READ) { + result->next &= 0xfffff; if ((res = spa_node_enum_params_sync(this->follower, id, &result->next, filter, &result->param, builder)) == 1) { - result->next |= 0x10000; + result->next |= 0x100000; return res; } + result->next = 0x200000; } return 0; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -472,13 +472,22 @@ } result->next = 0x1000; } - if (result->next >= 0x1000) { + if (result->next < 0x2000) { result->next &= 0xfff; if ((res = spa_node_enum_params_sync(this->channelmix, id, &result->next, filter, &result->param, builder)) == 1) { result->next |= 0x1000; return res; } + result->next = 0x2000; + } + if (result->next >= 0x2000) { + result->next &= 0xfff; + if ((res = spa_node_enum_params_sync(this->resample, + id, &result->next, filter, &result->param, builder)) == 1) { + result->next |= 0x2000; + return res; + } } return 0; } @@ -881,6 +890,7 @@ if (this->fmt[SPA_DIRECTION_INPUT] == this->merger) res = spa_node_set_param(this->merger, id, flags, param); res = spa_node_set_param(this->channelmix, id, flags, param); + res = spa_node_set_param(this->resample, id, flags, param); break; } default: @@ -1112,11 +1122,12 @@ switch (id) { case SPA_PARAM_Latency: - target = this->fmt[SPA_DIRECTION_REVERSE(direction)]; - port_id = 0; - if ((res = spa_node_port_set_param(target, - direction, port_id, id, flags, param)) < 0) - return res; + if (port_id == 0) { + target = this->fmt[SPA_DIRECTION_REVERSE(direction)]; + if ((res = spa_node_port_set_param(target, + direction, port_id, id, flags, param)) < 0) + return res; + } break; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
@@ -149,17 +149,16 @@ float matrix[SPA_AUDIO_MAX_CHANNELS][SPA_AUDIO_MAX_CHANNELS] = {{ 0.0f }}; uint64_t src_mask = mix->src_mask; uint64_t dst_mask = mix->dst_mask; - uint64_t unassigned; + uint64_t unassigned, keep; uint32_t i, j, ic, jc, matrix_encoding = MATRIX_NORMAL; float clev = SQRT1_2; float slev = SQRT1_2; float llev = 0.5f; float maxsum = 0.0f; - bool do_upmix = SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX); #define _MATRIX(s,d) matrix[_CH(s)][_CH(d)] - spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64, - src_mask, dst_mask); + spa_log_debug(mix->log, "src-mask:%08"PRIx64" dst-mask:%08"PRIx64 + " options:%08x", src_mask, dst_mask, mix->options); /* move the MONO mask to FRONT so that the lower bits can be shifted * away. */ @@ -207,6 +206,14 @@ } unassigned = src_mask & ~dst_mask; + keep = dst_mask & ~src_mask; + + if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX)) + keep = 0; + + keep |= FRONT; + if (mix->lfe_cutoff > 0.0f) + keep |= _MASK(LFE); spa_log_debug(mix->log, "unassigned downmix %08" PRIx64, unassigned); @@ -232,6 +239,7 @@ _MATRIX(FC,FR) += SQRT1_2; if (src_mask & FRONT) _MATRIX(FC,FC) = clev * SQRT2; + keep &= ~FRONT; } else { spa_log_warn(mix->log, "can't assign STEREO"); } @@ -374,12 +382,10 @@ } } - if (!do_upmix) - goto done; - - unassigned = dst_mask & ~src_mask; + unassigned = dst_mask & ~src_mask & keep; - spa_log_debug(mix->log, "unassigned upmix %08" PRIx64, unassigned); + spa_log_debug(mix->log, "unassigned upmix %08"PRIx64" lfe:%f", + unassigned, mix->lfe_cutoff); if (unassigned & FRONT) { if ((src_mask & STEREO) == STEREO) { @@ -390,7 +396,7 @@ spa_log_warn(mix->log, "can't produce FC"); } } - if (unassigned & _MASK(LFE) && mix->lfe_cutoff > 0.0f) { + if (unassigned & _MASK(LFE)) { if ((src_mask & STEREO) == STEREO) { spa_log_debug(mix->log, "produce LFE from STEREO"); _MATRIX(LFE,FL) += llev; @@ -445,7 +451,7 @@ sum += fabs(matrix[i][j]); } maxsum = SPA_MAX(maxsum, sum); - if (i == _CH(LFE) && do_upmix && mix->lfe_cutoff > 0.0f) { + if (i == _CH(LFE) && mix->lfe_cutoff > 0.0f) { spa_log_debug(mix->log, "channel %d is LFE", ic); lr4_set(&mix->lr4[ic], BQ_LOWPASS, mix->lfe_cutoff / mix->freq); mix->lr4_info[ic] = 1; @@ -456,6 +462,7 @@ } if (SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE) && maxsum > 1.0f) { + spa_log_debug(mix->log, "normalize %f", maxsum); for (i = 0; i < ic; i++) for (j = 0; j < jc; j++) mix->matrix_orig[i][j] /= maxsum;
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix.c
Changed
@@ -48,7 +48,6 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define DEFAULT_SAMPLES 8192 #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS @@ -82,6 +81,7 @@ struct volumes soft; struct volumes monitor; unsigned int have_soft_volume:1; + unsigned int disabled:1; }; static void props_reset(struct props *props) @@ -142,6 +142,7 @@ struct spa_log *log; struct spa_cpu *cpu; + uint32_t quantum_limit; struct spa_io_position *io_position; @@ -363,6 +364,8 @@ emit_props_changed(this); this->is_passthrough = SPA_FLAG_IS_SET(this->mix.flags, CHANNELMIX_FLAG_IDENTITY); + if (!this->is_passthrough && this->props.disabled) + return -EINVAL; spa_log_debug(this->log, "%p: got channelmix features %08x:%08x flags:%08x passthrough:%d", this, this->cpu_flags, this->mix.cpu_flags, @@ -495,6 +498,14 @@ this->mix.lfe_cutoff, 0.0, 1000.0), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; + case 12: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"), + SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; default: return 0; } @@ -544,6 +555,8 @@ CHANNELMIX_OPTION_UPMIX)); spa_pod_builder_string(&b, "channelmix.lfe-cutoff"); spa_pod_builder_float(&b, this->mix.lfe_cutoff); + spa_pod_builder_string(&b, "channelmix.disable"); + spa_pod_builder_bool(&b, this->props.disabled); spa_pod_builder_pop(&b, &f[1]); param = spa_pod_builder_pop(&b, &f[0]); break; @@ -577,6 +590,8 @@ SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_UPMIX, spa_atob(s)); else if (spa_streq(k, "channelmix.lfe-cutoff")) this->mix.lfe_cutoff = atoi(s); + else if (spa_streq(k, "channelmix.disable")) + this->props.disabled = spa_atob(s); return 0; } @@ -634,6 +649,9 @@ if (param == NULL) return 0; + if (this->props.disabled) + return 0; + SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_volume: @@ -716,6 +734,9 @@ if (size < 3) return -EINVAL; + if (this->props.disabled) + return 0; + if ((val[0] & 0xf0) != 0xb0 || val[1] != 7) return 0; @@ -863,6 +884,7 @@ } else { struct spa_pod_frame f; struct port *other; + int32_t channels, min = 1, max = INT32_MAX; other = GET_PORT(this, SPA_DIRECTION_REVERSE(direction), 0); @@ -875,19 +897,24 @@ 0); if (other->have_format) { + channels = other->format.info.raw.channels; + if (this->props.disabled) + min = max = channels; + spa_pod_builder_add(builder, SPA_FORMAT_AUDIO_rate, SPA_POD_Int(other->format.info.raw.rate), SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( - other->format.info.raw.channels, 1, INT32_MAX), + channels, min, max), 0); } else { uint32_t rate = this->io_position ? this->io_position->clock.rate.denom : DEFAULT_RATE; + channels = DEFAULT_CHANNELS; spa_pod_builder_add(builder, SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(rate, 0, INT32_MAX), SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( - DEFAULT_CHANNELS, 1, INT32_MAX), + channels, min, max), 0); } *param = spa_pod_builder_pop(builder, &f); @@ -978,7 +1005,7 @@ size = other->size / other->stride; } else { buffers = 1; - size = DEFAULT_SAMPLES; + size = this->quantum_limit; } param = spa_pod_builder_add_object(&b, @@ -1539,11 +1566,15 @@ props_reset(&this->props); + this->mix.options = CHANNELMIX_OPTION_NORMALIZE; + for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; const char *s = info->items[i].value; if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s)); + else if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); else channelmix_set_param(this, k, s);
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops-c.c
Changed
@@ -99,6 +99,22 @@ } void +conv_copy64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + for (i = 0; i < n_channels; i++) + spa_memcpy(dst[i], src[i], n_samples * sizeof(int64_t)); +} + +void +conv_copy64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + spa_memcpy(dst[0], src[0], n_samples * sizeof(int64_t) * conv->n_channels); +} + +void conv_u8d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) { @@ -650,6 +666,77 @@ } void +conv_f64d_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, j, n_channels = conv->n_channels; + + for (i = 0; i < n_channels; i++) { + const double *s = src[i]; + float *d = dst[i]; + + for (j = 0; j < n_samples; j++) + d[j] = s[j]; + } +} + +void +conv_f64_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const double *s = src[0]; + float *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = s[i]; +} + +void +conv_f64_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const double *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = *s++; + } +} + +void +conv_f64s_to_f32d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const double *s = src[0]; + float **d = (float **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = bswap_64(*s++); + } +} + +void +conv_f64d_to_f32_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const double **s = (const double **) src; + float *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = s[i][j]; + } +} + +void conv_f32d_to_u8d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) { @@ -989,6 +1076,77 @@ } void +conv_f32d_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, j, n_channels = conv->n_channels; + + for (i = 0; i < n_channels; i++) { + const float *s = src[i]; + double *d = dst[i]; + + for (j = 0; j < n_samples; j++) + d[j] = s[j]; + } +} + +void +conv_f32_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + uint32_t i, n_channels = conv->n_channels; + const float *s = src[0]; + double *d = dst[0]; + + n_samples *= n_channels; + + for (i = 0; i < n_samples; i++) + d[i] = s[i]; +} + +void +conv_f32_to_f64d_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float *s = src[0]; + double **d = (double **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = *s++; + } +} + +void +conv_f32d_to_f64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + double *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = s[i][j]; + } +} + +void +conv_f32d_to_f64s_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const float **s = (const float **) src; + double *d = dst[0]; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + *d++ = bswap_32(s[i][j]); + } +} + +void conv_f32_to_u24_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) { @@ -1273,6 +1431,20 @@ } void +conv_deinterleave_64_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], + uint32_t n_samples) +{ + const uint64_t *s = src[0]; + uint64_t **d = (uint64_t **) dst; + uint32_t i, j, n_channels = conv->n_channels; + + for (j = 0; j < n_samples; j++) { + for (i = 0; i < n_channels; i++) + d[i][j] = *s++; + } +} + +void conv_interleave_8_c(struct convert *conv, void * SPA_RESTRICT dst[], const void * SPA_RESTRICT src[], uint32_t n_samples) {
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops.c
Changed
@@ -138,6 +138,13 @@ { SPA_AUDIO_FORMAT_S24_32_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_s24_32s_to_f32d_c }, + { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F32, 0, 0, conv_f64_to_f32_c }, + { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64d_to_f32d_c }, + { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64_to_f32d_c }, + { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F32, 0, 0, conv_f64d_to_f32_c }, + + { SPA_AUDIO_FORMAT_F64_OE, SPA_AUDIO_FORMAT_F32P, 0, 0, conv_f64s_to_f32d_c }, + /* from f32 */ { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_U8, 0, 0, conv_f32_to_u8_c }, { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_f32d_to_u8d_c }, @@ -219,6 +226,13 @@ { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_S24_32_OE, 0, 0, conv_f32d_to_s24_32s_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64, 0, 0, conv_f32_to_f64_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_f32d_to_f64d_c }, + { SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_f32_to_f64d_c }, + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64, 0, 0, conv_f32d_to_f64_c }, + + { SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F64_OE, 0, 0, conv_f32d_to_f64s_c }, + /* u8 */ { SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_U8, 0, 0, conv_copy8_c }, { SPA_AUDIO_FORMAT_U8P, SPA_AUDIO_FORMAT_U8P, 0, 0, conv_copy8d_c }, @@ -259,6 +273,12 @@ { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_copy32d_c }, { SPA_AUDIO_FORMAT_S24_32, SPA_AUDIO_FORMAT_S24_32P, 0, 0, conv_deinterleave_32_c }, { SPA_AUDIO_FORMAT_S24_32P, SPA_AUDIO_FORMAT_S24_32, 0, 0, conv_interleave_32_c }, + + /* F64 */ + { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F64, 0, 0, conv_copy64_c }, + { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_copy64d_c }, + { SPA_AUDIO_FORMAT_F64, SPA_AUDIO_FORMAT_F64P, 0, 0, conv_deinterleave_64_c }, + { SPA_AUDIO_FORMAT_F64P, SPA_AUDIO_FORMAT_F64, 0, 0, conv_interleave_64_c }, }; #define MATCH_CHAN(a,b) ((a) == 0 || (a) == (b))
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops.h
Changed
@@ -27,6 +27,7 @@ #include <sys/endian.h> #define bswap_16 bswap16 #define bswap_32 bswap32 +#define bswap_64 bswap64 #else #include <byteswap.h> #endif @@ -207,6 +208,8 @@ DEFINE_FUNCTION(copy24, c); DEFINE_FUNCTION(copy32d, c); DEFINE_FUNCTION(copy32, c); +DEFINE_FUNCTION(copy64d, c); +DEFINE_FUNCTION(copy64, c); DEFINE_FUNCTION(u8d_to_f32d, c); DEFINE_FUNCTION(u8_to_f32, c); DEFINE_FUNCTION(u8_to_f32d, c); @@ -245,6 +248,11 @@ DEFINE_FUNCTION(s24_32_to_f32d, c); DEFINE_FUNCTION(s24_32s_to_f32d, c); DEFINE_FUNCTION(s24_32d_to_f32, c); +DEFINE_FUNCTION(f64d_to_f32d, c); +DEFINE_FUNCTION(f64_to_f32, c); +DEFINE_FUNCTION(f64_to_f32d, c); +DEFINE_FUNCTION(f64s_to_f32d, c); +DEFINE_FUNCTION(f64d_to_f32, c); DEFINE_FUNCTION(f32d_to_u8d, c); DEFINE_FUNCTION(f32_to_u8, c); DEFINE_FUNCTION(f32_to_u8d, c); @@ -283,16 +291,25 @@ DEFINE_FUNCTION(f32_to_s24_32d, c); DEFINE_FUNCTION(f32d_to_s24_32, c); DEFINE_FUNCTION(f32d_to_s24_32s, c); +DEFINE_FUNCTION(f32d_to_f64d, c); +DEFINE_FUNCTION(f32_to_f64, c); +DEFINE_FUNCTION(f32_to_f64d, c); +DEFINE_FUNCTION(f32d_to_f64, c); +DEFINE_FUNCTION(f32d_to_f64s, c); DEFINE_FUNCTION(deinterleave_8, c); DEFINE_FUNCTION(deinterleave_16, c); DEFINE_FUNCTION(deinterleave_24, c); DEFINE_FUNCTION(deinterleave_32, c); DEFINE_FUNCTION(deinterleave_32s, c); +DEFINE_FUNCTION(deinterleave_64, c); +DEFINE_FUNCTION(deinterleave_64s, c); DEFINE_FUNCTION(interleave_8, c); DEFINE_FUNCTION(interleave_16, c); DEFINE_FUNCTION(interleave_24, c); DEFINE_FUNCTION(interleave_32, c); DEFINE_FUNCTION(interleave_32s, c); +DEFINE_FUNCTION(interleave_64, c); +DEFINE_FUNCTION(interleave_64s, c); #if defined(HAVE_NEON) DEFINE_FUNCTION(s16_to_f32d_2, neon);
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/fmtconvert.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmtconvert.c
Changed
@@ -52,7 +52,6 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 32 #define MAX_ALIGN 16 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS @@ -118,6 +117,8 @@ struct spa_log *log; struct spa_cpu *cpu; + uint32_t cpu_flags; + uint32_t quantum_limit; struct spa_io_position *io_position; @@ -136,7 +137,6 @@ struct spa_latency_info latency[2]; - uint32_t cpu_flags; struct convert conv; unsigned int started:1; unsigned int is_passthrough:1; @@ -400,11 +400,14 @@ info.info.raw.format == SPA_AUDIO_FORMAT_F32P || info.info.raw.format == SPA_AUDIO_FORMAT_F32) { spa_pod_builder_add(builder, - SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(26, + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(29, info.info.raw.format, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32_OE, + SPA_AUDIO_FORMAT_F64P, + SPA_AUDIO_FORMAT_F64, + SPA_AUDIO_FORMAT_F64_OE, SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32_OE, @@ -542,7 +545,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(port->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * 2 * port->stride, + this->quantum_limit * 2 * port->stride, 16 * port->stride, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->stride)); @@ -619,6 +622,10 @@ case SPA_AUDIO_FORMAT_S24_OE: case SPA_AUDIO_FORMAT_U24: return 3; + case SPA_AUDIO_FORMAT_F64P: + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return 8; default: return 4; } @@ -1070,6 +1077,7 @@ uint32_t n_support) { struct impl *this; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -1086,6 +1094,13 @@ if (this->cpu) this->cpu_flags = spa_cpu_get_flags(this->cpu); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + this->node.iface = SPA_INTERFACE_INIT( SPA_TYPE_INTERFACE_Node, SPA_VERSION_NODE,
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/merger.c
Changed
@@ -55,7 +55,6 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define MAX_SAMPLES 8192 #define MAX_ALIGN 16 #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS @@ -146,6 +145,9 @@ struct spa_log *log; struct spa_cpu *cpu; + uint32_t cpu_flags; + uint32_t quantum_limit; + struct spa_io_position *io_position; uint64_t info_all; @@ -167,7 +169,6 @@ unsigned int have_profile:1; struct convert conv; - uint32_t cpu_flags; unsigned int is_passthrough:1; unsigned int started:1; unsigned int monitor:1; @@ -181,7 +182,8 @@ struct spa_latency_info latency[2]; - float empty[MAX_SAMPLES + MAX_ALIGN]; + uint32_t empty_size; + float *empty; }; #define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < this->port_count) @@ -622,7 +624,9 @@ info.info.raw.rate = 0; - if (this->have_profile && memcmp(&this->format, &info, sizeof(info)) == 0) + if (this->have_profile && + memcmp(&this->format, &info, sizeof(info)) == 0 && + this->monitor == monitor) return 0; spa_log_debug(this->log, "%p: port config %d/%d %d", this, @@ -775,11 +779,14 @@ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, 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_CHOICE_ENUM_Id(22, + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(25, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32_OE, + SPA_AUDIO_FORMAT_F64P, + SPA_AUDIO_FORMAT_F64, + SPA_AUDIO_FORMAT_F64_OE, SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32_OE, @@ -869,7 +876,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(port->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * port->stride, + this->quantum_limit * port->stride, 16 * port->stride, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->stride)); @@ -1008,6 +1015,10 @@ case SPA_AUDIO_FORMAT_S24: case SPA_AUDIO_FORMAT_S24_OE: return 3; + case SPA_AUDIO_FORMAT_F64P: + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return 8; default: return 4; } @@ -1024,7 +1035,11 @@ enum spa_direction other = SPA_DIRECTION_REVERSE(direction); uint32_t i; - spa_log_debug(this->log, "%p: set latency direction:%d", this, direction); + spa_log_debug(this->log, "%p: set latency direction:%d id:%d", + this, direction, port_id); + + if (direction == SPA_DIRECTION_OUTPUT && port_id != 0) + return 0; if (latency == NULL) { this->latency[other] = SPA_LATENCY_INFO(other); @@ -1212,7 +1227,7 @@ { struct impl *this = object; struct port *port; - uint32_t i, j; + uint32_t i, j, maxsize; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -1227,6 +1242,7 @@ clear_buffers(this, port); + maxsize = 0; for (i = 0; i < n_buffers; i++) { struct buffer *b; uint32_t n_datas = buffers[i]->n_datas; @@ -1257,11 +1273,19 @@ if (direction == SPA_DIRECTION_OUTPUT && !SPA_FLAG_IS_SET(d[j].flags, SPA_DATA_FLAG_DYNAMIC)) this->is_passthrough = false; - } + maxsize = SPA_MAX(maxsize, d[j].maxsize); + } if (direction == SPA_DIRECTION_OUTPUT) queue_buffer(this, port, i); } + if (maxsize > this->empty_size) { + this->empty = realloc(this->empty, maxsize + MAX_ALIGN); + if (this->empty == NULL) + return -errno; + memset(this->empty, 0, maxsize + MAX_ALIGN); + this->empty_size = maxsize; + } port->n_buffers = n_buffers; return 0; @@ -1519,6 +1543,7 @@ free(this->in_ports[i]); for (i = 0; i < MAX_PORTS+1; i++) free(this->out_ports[i]); + free(this->empty); return 0; } @@ -1557,7 +1582,10 @@ for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; const char *s = info->items[i].value; - merger_set_param(this, k, s); + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + else + merger_set_param(this, k, s); } this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/meson.build -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/meson.build
Changed
@@ -140,7 +140,7 @@ install : installed_tests_enabled, install_dir : installed_tests_execdir / 'audioconvert'), env : [ - 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')), + 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')), ]) if installed_tests_enabled @@ -170,7 +170,7 @@ install : installed_tests_enabled, install_dir : installed_tests_execdir / 'audioconvert'), env : [ - 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')), + 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')), ]) if installed_tests_enabled @@ -191,7 +191,6 @@ ] executable('spa-resample', sparesample_sources, - c_args : [ simd_cargs ], link_with : [ test_lib ], dependencies : [ spa_dep, sndfile_dep, mathlib, audioconvert_dep ], install : true,
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h
Changed
@@ -31,7 +31,7 @@ struct peaks_data { uint32_t o_count; uint32_t i_count; - float max_f[0]; + float max_f[]; }; #if defined (HAVE_SSE)
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample-peaks.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample-peaks.c
Changed
@@ -146,7 +146,7 @@ r->delay = impl_peaks_delay; r->in_len = impl_peaks_in_len; - d = r->data = calloc(1, sizeof(struct peaks_data) * sizeof(float) * r->channels); + d = r->data = calloc(1, sizeof(struct peaks_data) + sizeof(float) * r->channels); if (r->data == NULL) return -errno;
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/resample.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample.c
Changed
@@ -48,7 +48,6 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define MAX_SAMPLES 8192u #define MAX_ALIGN 16 #define MAX_BUFFERS 32 @@ -57,12 +56,14 @@ struct props { double rate; int quality; + bool disabled; }; static void props_reset(struct props *props) { props->rate = 1.0; props->quality = RESAMPLE_DEFAULT_QUALITY; + props->disabled = false; } struct buffer { @@ -104,6 +105,8 @@ struct spa_log *log; struct spa_cpu *cpu; + uint32_t quantum_limit; + struct spa_io_position *io_position; struct spa_io_rate_match *io_rate_match; @@ -127,8 +130,6 @@ struct resample resample; double rate_scale; - - float empty[MAX_SAMPLES + MAX_ALIGN]; }; #define CHECK_PORT(this,d,id) (id == 0) @@ -183,7 +184,147 @@ uint32_t id, uint32_t start, uint32_t num, const struct spa_pod *filter) { - return -ENOTSUP; + struct impl *this = object; + struct spa_pod *param; + struct spa_pod_builder b = { 0 }; + uint8_t buffer[4096]; + struct spa_result_node_params result; + uint32_t count = 0; + + spa_return_val_if_fail(this != NULL, -EINVAL); + spa_return_val_if_fail(num != 0, -EINVAL); + + result.id = id; + result.next = start; + next: + result.index = result.next++; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + switch (id) { + case SPA_PARAM_PropInfo: + { + struct props *p = &this->props; + + switch (result.index) { + case 0: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate), + SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0)); + break; + case 1: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality), + SPA_PROP_INFO_name, SPA_POD_String("resample.quality"), + SPA_PROP_INFO_description, SPA_POD_String("Resample Quality"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->quality, 0, 14), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 2: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("resample.disable"), + SPA_PROP_INFO_description, SPA_POD_String("Disable Resampling"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + default: + return 0; + } + break; + } + case SPA_PARAM_Props: + { + struct props *p = &this->props; + struct spa_pod_frame f[2]; + + switch (result.index) { + case 0: + spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Props, id); + spa_pod_builder_add(&b, + SPA_PROP_rate, SPA_POD_Double(p->rate), + SPA_PROP_quality, SPA_POD_Int(p->quality), + 0); + spa_pod_builder_prop(&b, SPA_PROP_params, 0); + spa_pod_builder_push_struct(&b, &f[1]); + spa_pod_builder_string(&b, "resample.quality"); + spa_pod_builder_int(&b, p->quality); + spa_pod_builder_string(&b, "resample.disable"); + spa_pod_builder_bool(&b, p->disabled); + spa_pod_builder_pop(&b, &f[1]); + param = spa_pod_builder_pop(&b, &f[0]); + break; + default: + return 0; + } + break; + } + default: + return -ENOENT; + } + + if (spa_pod_filter(&b, &result.param, param, filter) < 0) + goto next; + + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + + if (++count != num) + goto next; + + return 0; +} + +static int resample_set_param(struct impl *this, const char *k, const char *s) +{ + if (spa_streq(k, "resample.quality")) + this->props.quality = atoi(s); + else if (spa_streq(k, "resample.disable")) + this->props.disabled = spa_atob(s); + return 0; +} + +static int parse_prop_params(struct impl *this, struct spa_pod *params) +{ + struct spa_pod_parser prs; + struct spa_pod_frame f; + + spa_pod_parser_pod(&prs, params); + if (spa_pod_parser_push_struct(&prs, &f) < 0) + return 0; + + while (true) { + const char *name; + struct spa_pod *pod; + char value[512]; + + if (spa_pod_parser_get_string(&prs, &name) < 0) + break; + + if (spa_pod_parser_get_pod(&prs, &pod) < 0) + break; + + if (spa_pod_is_string(pod)) { + spa_pod_copy_string(pod, sizeof(value), value); + } else if (spa_pod_is_float(pod)) { + snprintf(value, sizeof(value), "%f", + SPA_POD_VALUE(struct spa_pod_float, pod)); + } else if (spa_pod_is_int(pod)) { + snprintf(value, sizeof(value), "%d", + SPA_POD_VALUE(struct spa_pod_int, pod)); + } else if (spa_pod_is_bool(pod)) { + snprintf(value, sizeof(value), "%s", + SPA_POD_VALUE(struct spa_pod_bool, pod) ? + "true" : "false"); + } else + continue; + + spa_log_info(this->log, "key:'%s' val:'%s'", name, value); + resample_set_param(this, name, value); + } + return 0; } static int apply_props(struct impl *this, const struct spa_pod *param) @@ -191,22 +332,28 @@ struct spa_pod_prop *prop; struct spa_pod_object *obj = (struct spa_pod_object *) param; struct props *p = &this->props; + int changed = 0; SPA_POD_OBJECT_FOREACH(obj, prop) { switch (prop->key) { case SPA_PROP_rate: if (spa_pod_get_double(&prop->value, &p->rate) == 0) {
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/spa-resample.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/spa-resample.c
Changed
@@ -49,6 +49,7 @@ int rate; int format; int quality; + int cpu_flags; const char *iname; SF_INFO iinfo; @@ -61,7 +62,7 @@ #define STR_FMTS "(s8|s16|s32|f32|f64)" -#define OPTIONS "hvr:f:q:" +#define OPTIONS "hvr:f:q:c:" static const struct option long_options[] = { { "help", no_argument, NULL, 'h'}, { "verbose", no_argument, NULL, 'v'}, @@ -69,6 +70,7 @@ { "rate", required_argument, NULL, 'r' }, { "format", required_argument, NULL, 'f' }, { "quality", required_argument, NULL, 'q' }, + { "cpuflags", required_argument, NULL, 'c' }, { NULL, 0, NULL, 0 } }; @@ -88,6 +90,7 @@ " -r --rate Output sample rate (default as input)\n" " -f --format Output sample format %s (default as input)\n" " -q --quality Resampler quality (default %u)\n" + " -c --cpuflags CPU flags (default 0)\n" "\n", STR_FMTS, DEFAULT_QUALITY); } @@ -191,6 +194,7 @@ bool flushing = false; spa_zero(r); + r.cpu_flags = d->cpu_flags; r.log = &logger.log; r.channels = channels; r.i_rate = d->iinfo.samplerate; @@ -297,6 +301,9 @@ } data.quality = ret; break; + case 'c': + data.cpu_flags = strtol(optarg, NULL, 0); + break; default: fprintf(stderr, "error: unknown option '%c'\n", c); goto error_usage;
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/splitter.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/splitter.c
Changed
@@ -53,7 +53,6 @@ #define DEFAULT_CHANNELS 2 #define DEFAULT_MASK (1LL << SPA_AUDIO_CHANNEL_FL) | (1LL << SPA_AUDIO_CHANNEL_FR) -#define MAX_SAMPLES 8192 #define MAX_ALIGN 16 #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS @@ -107,6 +106,9 @@ struct spa_log *log; struct spa_cpu *cpu; + uint32_t cpu_flags; + uint32_t quantum_limit; + struct spa_io_position *io_position; uint64_t info_all; @@ -124,7 +126,6 @@ struct spa_audio_info format; unsigned int have_profile:1; - uint32_t cpu_flags; struct convert conv; unsigned int is_passthrough:1; unsigned int started:1; @@ -134,7 +135,8 @@ uint32_t src_remap[SPA_AUDIO_MAX_CHANNELS]; uint32_t dst_remap[SPA_AUDIO_MAX_CHANNELS]; - float empty[MAX_SAMPLES + MAX_ALIGN]; + uint32_t empty_size; + float *empty; }; #define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < this->port_count) @@ -456,11 +458,14 @@ SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, 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_CHOICE_ENUM_Id(22, + SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(25, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32P, SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F32_OE, + SPA_AUDIO_FORMAT_F64P, + SPA_AUDIO_FORMAT_F64, + SPA_AUDIO_FORMAT_F64_OE, SPA_AUDIO_FORMAT_S32P, SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_S32_OE, @@ -550,9 +555,9 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(port->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * port->stride, + this->quantum_limit * port->stride, 16 * port->stride, - MAX_SAMPLES * port->stride), + INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->stride)); break; @@ -690,6 +695,10 @@ case SPA_AUDIO_FORMAT_S24: case SPA_AUDIO_FORMAT_S24_OE: return 3; + case SPA_AUDIO_FORMAT_F64P: + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return 8; default: return 4; } @@ -877,7 +886,7 @@ { struct impl *this = object; struct port *port; - uint32_t i, j; + uint32_t i, j, maxsize; spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); @@ -890,6 +899,7 @@ clear_buffers(this, port); + maxsize = 0; for (i = 0; i < n_buffers; i++) { struct buffer *b; uint32_t n_datas = buffers[i]->n_datas; @@ -917,11 +927,19 @@ spa_log_debug(this->log, "%p: buffer %d data %d flags:%08x %p", this, i, j, d[j].flags, b->datas[j]); - } + maxsize = SPA_MAX(maxsize, d[j].maxsize); + } if (direction == SPA_DIRECTION_OUTPUT) queue_buffer(this, port, i); } + if (maxsize > this->empty_size) { + this->empty = realloc(this->empty, maxsize + MAX_ALIGN); + if (this->empty == NULL) + return -errno; + memset(this->empty, 0, maxsize + MAX_ALIGN); + this->empty_size = maxsize; + } port->n_buffers = n_buffers; return 0; @@ -975,7 +993,6 @@ uint32_t n_src_datas, n_dst_datas; const void **src_datas; void **dst_datas; - int res = 0; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -1063,10 +1080,8 @@ convert_process(&this->conv, dst_datas, src_datas, n_samples); inio->status = SPA_STATUS_NEED_DATA; - res |= SPA_STATUS_NEED_DATA; - res |= SPA_STATUS_HAVE_DATA; - return res; + return SPA_STATUS_NEED_DATA | SPA_STATUS_HAVE_DATA; } static const struct spa_node_methods impl_node = { @@ -1115,6 +1130,7 @@ for (i = 0; i < MAX_PORTS; i++) free(this->out_ports[i]); + free(this->empty); return 0; } @@ -1134,6 +1150,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -1150,6 +1167,13 @@ if (this->cpu) this->cpu_flags = spa_cpu_get_flags(this->cpu); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + spa_hook_list_init(&this->hooks); this->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT);
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-channelmix.c
Changed
@@ -162,7 +162,7 @@ test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), MATRIX(1.0, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.0, 0.707107, - 0.0, 0.0, 0.0, 0.0, + 0.707107, 0.707107, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0)); }
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-fmt-ops.c
Changed
@@ -41,10 +41,10 @@ static uint32_t cpu_flags; -static uint8_t samp_in[N_SAMPLES * 4]; -static uint8_t samp_out[N_SAMPLES * 4]; -static uint8_t temp_in[N_SAMPLES * N_CHANNELS * 4]; -static uint8_t temp_out[N_SAMPLES * N_CHANNELS * 4]; +static uint8_t samp_in[N_SAMPLES * 8]; +static uint8_t samp_out[N_SAMPLES * 8]; +static uint8_t temp_in[N_SAMPLES * N_CHANNELS * 8]; +static uint8_t temp_out[N_SAMPLES * N_CHANNELS * 8]; static void compare_mem(int i, int j, const void *m1, const void *m2, size_t size) { @@ -92,6 +92,9 @@ case 4: conv_interleave_32_c(&conv, tp, ip, N_SAMPLES); break; + case 8: + conv_interleave_64_c(&conv, tp, ip, N_SAMPLES); + break; default: fprintf(stderr, "unknown size %zd\n", in_size); return; @@ -430,6 +433,35 @@ false, false, conv_s24_32d_to_f32d_c); } +static void test_f64_f32(void) +{ + static const double in[] = { 0.0, 1.0, -1.0, 0.4999999404, -0.4999999404, }; + static const float out[] = { 0.0f, 1.0f, -1.0f, 0.4999999404f, -0.4999999404f, }; + + run_test("test_f64_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_f64_to_f32d_c); + run_test("test_f64d_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, true, conv_f64d_to_f32_c); + run_test("test_f64_f32", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_f64_to_f32_c); + run_test("test_f64d_f32d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, false, conv_f64d_to_f32d_c); +} + +static void test_f32_f64(void) +{ + static const float in[] = { 0.0f, 1.0f, -1.0f, 0.5f, -0.5f, 1.1f, -1.1f }; + static const double out[] = { 0.0, 1.0, -1.0, 0.5, -0.5, 1.1, -1.1 }; + + run_test("test_f32_f64", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, true, conv_f32_to_f64_c); + run_test("test_f32d_f64", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, true, conv_f32d_to_f64_c); + run_test("test_f32_f64d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + true, false, conv_f32_to_f64d_c); + run_test("test_f32d_f64d", in, sizeof(in[0]), out, sizeof(out[0]), SPA_N_ELEMENTS(out), + false, false, conv_f32d_to_f64d_c); +} int main(int argc, char *argv[]) { cpu_flags = get_cpu_flags(); @@ -453,5 +485,7 @@ test_u24_32_f32(); test_f32_s24_32(); test_s24_32_f32(); + test_f32_f64(); + test_f64_f32(); return 0; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/audioconvert/test-source.c -> pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/test-source.c
Changed
@@ -45,7 +45,6 @@ #define DEFAULT_RATE 44100 #define DEFAULT_CHANNELS 2 -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 32 struct impl; @@ -101,6 +100,8 @@ struct spa_log *log; + uint32_t quantum_limit; + struct spa_hook_list hooks; uint64_t info_all; @@ -458,7 +459,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(port->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * port->stride, + this->quantum_limit * port->stride, 16 * port->stride, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->stride)); @@ -830,6 +831,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -841,6 +843,13 @@ this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + spa_log_debug(this->log, NAME " %p: init", this); spa_hook_list_init(&this->hooks);
View file
pipewire-0.3.43.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -45,11 +45,9 @@ #define SPA_LOG_TOPIC_DEFAULT log_topic static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer"); -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 64 #define MAX_PORTS 128 #define MAX_CHANNELS 64 -#define MAX_BUFFER_SIZE (MAX_SAMPLES * MAX_CHANNELS * 8) #define PORT_DEFAULT_VOLUME 1.0 #define PORT_DEFAULT_MUTE false @@ -74,8 +72,6 @@ struct spa_buffer *buffer; struct spa_meta_header *h; struct spa_buffer buf; - struct spa_data datas[1]; - struct spa_chunk chunk[1]; }; struct port { @@ -107,6 +103,7 @@ struct spa_log *log; struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t quantum_limit; struct mix_ops ops; @@ -128,9 +125,6 @@ unsigned int started:1; uint32_t stride; uint32_t blocks; - - uint8_t empty[MAX_BUFFER_SIZE]; - }; #define PORT_VALID(p) ((p) != NULL && (p)->valid) @@ -421,7 +415,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * this->stride, + this->quantum_limit * this->stride, 16 * this->stride, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->stride)); @@ -520,6 +514,10 @@ case SPA_AUDIO_FORMAT_S24_OE: case SPA_AUDIO_FORMAT_U24: return 3; + case SPA_AUDIO_FORMAT_F64P: + case SPA_AUDIO_FORMAT_F64: + case SPA_AUDIO_FORMAT_F64_OE: + return 8; default: return 4; } @@ -653,6 +651,7 @@ b->flags = 0; b->id = i; b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h)); + b->buf = *buffers[i]; if (d[0].data == NULL) { spa_log_error(this->log, "%p: invalid memory on buffer %p", this, @@ -721,9 +720,9 @@ struct impl *this = object; struct port *outport; struct spa_io_buffers *outio; - uint32_t n_samples, n_buffers, i, maxsize; + uint32_t n_buffers, i, maxsize; struct buffer **buffers; - struct buffer *outb; + struct buffer *outb; const void **datas; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -748,7 +747,7 @@ datas = alloca(MAX_PORTS * sizeof(void *)); n_buffers = 0; - maxsize = MAX_SAMPLES * this->stride; + maxsize = UINT32_MAX; for (i = 0; i < this->last_port; i++) { struct port *inport = GET_IN_PORT(this, i); @@ -785,22 +784,22 @@ return -EPIPE; } - n_samples = maxsize / this->stride; - if (n_buffers == 1) { *outb->buffer = *buffers[0]->buffer; } else { - outb->buffer->n_datas = 1; - outb->buffer->datas = outb->datas; - outb->datas[0].data = this->empty; - outb->datas[0].chunk = outb->chunk; - outb->datas[0].chunk->offset = 0; - outb->datas[0].chunk->size = n_samples * this->stride; - outb->datas[0].chunk->stride = this->stride; - outb->datas[0].maxsize = maxsize; - - mix_ops_process(&this->ops, outb->datas[0].data, datas, n_buffers, n_samples); + struct spa_data *d = outb->buf.datas; + + *outb->buffer = outb->buf; + + maxsize = SPA_MIN(maxsize, d[0].maxsize); + + d[0].chunk->offset = 0; + d[0].chunk->size = maxsize; + d[0].chunk->stride = this->stride; + + mix_ops_process(&this->ops, d[0].data, + datas, n_buffers, maxsize / this->stride); } outio->buffer_id = outb->id; @@ -875,6 +874,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -891,6 +891,13 @@ if (this->cpu) this->cpu_flags = spa_cpu_get_flags(this->cpu); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT(
View file
pipewire-0.3.43.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
@@ -47,7 +47,6 @@ #define MAX_BUFFERS 64 #define MAX_PORTS 128 -#define MAX_SAMPLES 8192 #define MAX_ALIGN 64 #define PORT_DEFAULT_VOLUME 1.0 @@ -73,8 +72,6 @@ struct spa_buffer *buffer; struct spa_meta_header *h; struct spa_buffer buf; - struct spa_data datas[1]; - struct spa_chunk chunk[1]; }; struct port { @@ -107,6 +104,8 @@ struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t quantum_limit; + struct mix_ops ops; uint64_t info_all; @@ -126,8 +125,6 @@ unsigned int have_format:1; unsigned int started:1; - - float empty[MAX_SAMPLES + MAX_ALIGN]; }; #define PORT_VALID(p) ((p) != NULL && (p)->valid) @@ -400,7 +397,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * this->stride, + this->quantum_limit * this->stride, 16 * this->stride, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->stride)); @@ -601,12 +598,13 @@ b->flags = 0; b->id = i; b->h = spa_buffer_find_meta_data(buffers[i], SPA_META_Header, sizeof(*b->h)); + b->buf = *buffers[i]; if (d[0].data == NULL) { spa_log_error(this->log, "%p: invalid memory on buffer %d", this, i); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[0].data, 16)) { + if (!SPA_IS_ALIGNED(d[0].data, 32)) { spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i); } if (direction == SPA_DIRECTION_OUTPUT) @@ -668,9 +666,9 @@ struct impl *this = object; struct port *outport; struct spa_io_buffers *outio; - uint32_t n_samples, n_buffers, i, maxsize; - struct buffer **buffers; - struct buffer *outb; + uint32_t n_buffers, i, maxsize; + struct buffer **buffers; + struct buffer *outb; const void **datas; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -695,7 +693,7 @@ datas = alloca(MAX_PORTS * sizeof(void *)); n_buffers = 0; - maxsize = MAX_SAMPLES * sizeof(float); + maxsize = UINT32_MAX; for (i = 0; i < this->last_port; i++) { struct port *inport = GET_IN_PORT(this, i); @@ -732,21 +730,20 @@ return -EPIPE; } - n_samples = maxsize / sizeof(float); - if (n_buffers == 1) { *outb->buffer = *buffers[0]->buffer; - } - else { - outb->buffer->n_datas = 1; - outb->buffer->datas = outb->datas; - outb->datas[0].data = SPA_PTR_ALIGN(this->empty, MAX_ALIGN, void); - outb->datas[0].chunk = outb->chunk; - outb->datas[0].chunk->offset = 0; - outb->datas[0].chunk->size = n_samples * sizeof(float); - outb->datas[0].chunk->stride = sizeof(float); - - mix_ops_process(&this->ops, outb->datas[0].data, datas, n_buffers, n_samples); + } else { + struct spa_data *d = outb->buf.datas; + *outb->buffer = outb->buf; + + maxsize = SPA_MIN(maxsize, d[0].maxsize); + + d[0].chunk->offset = 0; + d[0].chunk->size = maxsize; + d[0].chunk->stride = sizeof(float); + + mix_ops_process(&this->ops, d[0].data, + datas, n_buffers, maxsize / sizeof(float)); } outio->buffer_id = outb->id; @@ -820,6 +817,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -836,6 +834,13 @@ if (this->cpu) this->cpu_flags = spa_cpu_get_flags(this->cpu); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT(
View file
pipewire-0.3.43.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.44.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c
Changed
@@ -75,7 +75,6 @@ props->volume = DEFAULT_VOLUME; } -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 16 #define MAX_PORTS 1 @@ -119,6 +118,8 @@ struct spa_loop *data_loop; struct spa_system *data_system; + uint32_t quantum_limit; + uint64_t info_all; struct spa_node_info info; struct spa_param_info params[2]; @@ -646,7 +647,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * port->bpf, + this->quantum_limit * port->bpf, 16 * port->bpf, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->bpf)); @@ -1014,6 +1015,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -1027,6 +1029,12 @@ this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); this->data_system = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataSystem); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT(
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c
Changed
@@ -1088,7 +1088,7 @@ } d = spa_bt_device_find_by_address(backend->monitor, endpoint->remote_address, endpoint->local_address); - if (!d) { + if (!d || !d->adapter) { spa_log_debug(backend->log, "No device for %s", endpoint->path); return DBUS_HANDLER_RESULT_HANDLED; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -137,6 +137,8 @@ unsigned int msbc_supported_by_hfp:1; unsigned int hfp_ag_switching_codec:1; unsigned int hfp_ag_initial_codec_setup:2; + unsigned int cind_call_active:1; + unsigned int cind_call_notify:1; enum hfp_hf_state hf_state; enum hsp_hs_state hs_state; unsigned int codec; @@ -676,6 +678,22 @@ } } +static void rfcomm_hfp_ag_set_cind(struct rfcomm *rfcomm, bool call_active) +{ + if (rfcomm->profile != SPA_BT_PROFILE_HFP_HF) + return; + + if (call_active == rfcomm->cind_call_active) + return; + + rfcomm->cind_call_active = call_active; + + if (!rfcomm->cind_call_notify) + return; + + rfcomm_send_reply(rfcomm, "+CIEV: 2,%d", rfcomm->cind_call_active); +} + static bool rfcomm_hfp_ag(struct rfcomm *rfcomm, char* buf) { struct impl *backend = rfcomm->backend; @@ -762,12 +780,20 @@ rfcomm_send_reply(rfcomm, "+CIND:(\"service\",(0-1)),(\"call\",(0-1)),(\"callsetup\",(0-3)),(\"callheld\",(0-2))"); rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+CIND?")) { - rfcomm_send_reply(rfcomm, "+CIND: 0,0,0,0"); + rfcomm_send_reply(rfcomm, "+CIND: 0,%d,0,0", rfcomm->cind_call_active); rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+CMER")) { + int mode, keyp, disp, ind; + rfcomm->slc_configured = true; rfcomm_send_reply(rfcomm, "OK"); + rfcomm->cind_call_active = false; + if (sscanf(buf, "AT+CMER= %d , %d , %d , %d", &mode, &keyp, &disp, &ind) == 4) + rfcomm->cind_call_notify = ind ? true : false; + else + rfcomm->cind_call_notify = false; + /* switch codec to mSBC by sending unsolicited +BCS message */ if (rfcomm->codec_negotiation_supported && rfcomm->msbc_supported_by_hfp) { spa_log_debug(backend->log, "RFCOMM initial codec setup"); @@ -785,7 +811,6 @@ rfcomm_emit_volume_changed(rfcomm, -1, SPA_BT_VOLUME_INVALID); } } - } else if (!rfcomm->slc_configured) { spa_log_warn(backend->log, "RFCOMM receive command before SLC completed: %s", buf); rfcomm_send_reply(rfcomm, "ERROR"); @@ -829,6 +854,11 @@ rfcomm_send_reply(rfcomm, "OK"); if (was_switching_codec) spa_bt_device_emit_codec_switched(rfcomm->device, 0); + } else if (spa_strstartswith(buf, "AT+BIA=")) { + /* We only support 'call' indicator, which HFP 4.35.1 defines as + always active (assuming CMER enabled it), so we don't need to + parse anything here. */ + rfcomm_send_reply(rfcomm, "OK"); } else if (sscanf(buf, "AT+VGM=%u", &gain) == 1) { if (gain <= SPA_BT_VOLUME_HS_MAX) { if (!rfcomm->broken_mic_hw_volume) @@ -1172,12 +1202,17 @@ static int sco_acquire_cb(void *data, bool optional) { struct spa_bt_transport *t = data; + struct transport_data *td = t->user_data; struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this); int sock; socklen_t len; spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t); +#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE + rfcomm_hfp_ag_set_cind(td->rfcomm, true); +#endif + if (optional || t->fd > 0) sock = t->fd; else @@ -1217,10 +1252,15 @@ static int sco_release_cb(void *data) { struct spa_bt_transport *t = data; + struct transport_data *td = t->user_data; struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this); spa_log_info(backend->log, "Transport %s released", t->path); +#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE + rfcomm_hfp_ag_set_cind(td->rfcomm, false); +#endif + if (t->sco_io) { spa_bt_sco_io_destroy(t->sco_io); t->sco_io = NULL; @@ -1689,7 +1729,7 @@ dbus_message_iter_get_basic(&it[0], &path); d = spa_bt_device_find(backend->monitor, path); - if (d == NULL) { + if (d == NULL || d->adapter == NULL) { spa_log_warn(backend->log, "unknown device for path %s", path); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -1816,7 +1856,7 @@ dbus_message_iter_get_basic(&it[0], &path); d = spa_bt_device_find(backend->monitor, path); - if (d == NULL) { + if (d == NULL || d->adapter == NULL) { spa_log_warn(backend->log, "unknown device for path %s", path); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/backend-ofono.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-ofono.c
Changed
@@ -364,7 +364,7 @@ } d = spa_bt_device_find_by_address(backend->monitor, remote_address, local_address); - if (!d) { + if (!d || !d->adapter) { spa_log_error(backend->log, "Device doesn’t exist for %s", path); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; }
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -229,7 +229,7 @@ device->battery_pending_call = NULL; } - if (!device->adapter->has_battery_provider || !device->has_battery) + if (!device->adapter || !device->adapter->has_battery_provider || !device->has_battery) return; spa_log_debug(device->monitor->log, "Removing virtual battery: %s", device->battery_path); @@ -694,6 +694,22 @@ return 0; } +static void adapter_update_devices(struct spa_bt_adapter *adapter) +{ + struct spa_bt_monitor *monitor = adapter->monitor; + struct spa_bt_device *device; + + /* + * Update devices when new adapter appears. + * Devices may appear on DBus before or after the adapter does. + */ + + spa_list_for_each(device, &monitor->device_list, link) { + if (device->adapter == NULL && spa_streq(device->adapter_path, adapter->path)) + device->adapter = adapter; + } +} + static void adapter_register_player(struct spa_bt_adapter *adapter) { if (adapter->player_registered || !adapter->monitor->dummy_avrcp_player) @@ -785,11 +801,20 @@ return d; } +static void device_free(struct spa_bt_device *device); + static void adapter_free(struct spa_bt_adapter *adapter) { struct spa_bt_monitor *monitor = adapter->monitor; + struct spa_bt_device *d, *td; + spa_log_debug(monitor->log, "%p", adapter); + /* Devices should be destroyed before their assigned adapter */ + spa_list_for_each_safe(d, td, &monitor->device_list, link) + if (d->adapter == adapter) + device_free(d); + spa_bt_player_destroy(adapter->dummy_player); spa_list_remove(&adapter->link); @@ -1159,7 +1184,7 @@ } #define DEVICE_RECONNECT_TIMEOUT_SEC 2 -#define DEVICE_PROFILE_TIMEOUT_SEC 3 +#define DEVICE_PROFILE_TIMEOUT_SEC 6 static void device_timer_event(struct spa_source *source) { @@ -1238,19 +1263,34 @@ { struct spa_bt_monitor *monitor = device->monitor; uint32_t connected_profiles = device->connected_profiles; + uint32_t direction_masks[2] = { + SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_HEADSET_AUDIO, + SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY, + }; + bool direction_connected = false; + bool all_connected; + size_t i; if (connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT) connected_profiles |= SPA_BT_PROFILE_HEADSET_HEAD_UNIT; if (connected_profiles & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY) connected_profiles |= SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY; + for (i = 0; i < SPA_N_ELEMENTS(direction_masks); ++i) { + uint32_t mask = direction_masks[i] & device->profiles; + if (mask && (connected_profiles & mask) == mask) + direction_connected = true; + } + + all_connected = (device->profiles & connected_profiles) == device->profiles; + spa_log_debug(monitor->log, "device %p: profiles %08x %08x %d", device, device->profiles, connected_profiles, device->added); if (connected_profiles == 0 && spa_list_is_empty(&device->codec_switch_list)) { device_stop_timer(device); device_connected(monitor, device, BT_DEVICE_DISCONNECTED); - } else if (force || (device->profiles & connected_profiles) == device->profiles) { + } else if (force || direction_connected || all_connected) { device_stop_timer(device); device_connected(monitor, device, BT_DEVICE_CONNECTED); } else { @@ -1349,7 +1389,7 @@ device->adapter = adapter_find(monitor, value); if (device->adapter == NULL) { - spa_log_warn(monitor->log, "unknown adapter %s", value); + spa_log_info(monitor->log, "unknown adapter %s", value); } } else if (spa_streq(key, "Icon")) { @@ -1455,6 +1495,15 @@ return 0; } +static bool device_props_ready(struct spa_bt_device *device) +{ + /* + * In some cases, BlueZ device props may be missing part of + * the information required when the interface first appears. + */ + return device->adapter && device->address; +} + bool spa_bt_device_supports_a2dp_codec(struct spa_bt_device *device, const struct a2dp_codec *codec) { struct spa_bt_monitor *monitor = device->monitor; @@ -2091,9 +2140,16 @@ spa_bt_transport_set_state(transport, spa_bt_transport_state_from_string(value)); } else if (spa_streq(key, "Device")) { - transport->device = spa_bt_device_find(monitor, value); - if (transport->device == NULL) - spa_log_warn(monitor->log, "could not find device %s", value); + struct spa_bt_device *device = spa_bt_device_find(monitor, value); + if (transport->device != device) { + if (transport->device != NULL) + spa_list_remove(&transport->device_link); + transport->device = device; + if (device != NULL) + spa_list_append(&device->transport_list, &transport->device_link); + else + spa_log_warn(monitor->log, "could not find device %s", value); + } } } else if (spa_streq(key, "Codec")) { @@ -2874,7 +2930,6 @@ DBusMessageIter it[2]; DBusMessage *r; struct spa_bt_transport *transport; - bool is_new = false; const struct a2dp_codec *codec; int profile; @@ -2897,9 +2952,8 @@ dbus_message_iter_recurse(&it[0], &it[1]); transport = spa_bt_transport_find(monitor, transport_path); - is_new = transport == NULL; - if (is_new) { + if (transport == NULL) { char *tpath = strdup(transport_path); transport = spa_bt_transport_create(monitor, tpath, 0); @@ -2928,14 +2982,10 @@ transport->a2dp_codec = codec; transport_update_props(transport, &it[1], NULL); - if (transport->device == NULL) { + if (transport->device == NULL || transport->device->adapter == NULL) { spa_log_warn(monitor->log, "no device found for transport"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - spa_bt_device_add_profile(transport->device, transport->profile); - - if (is_new) - spa_list_append(&transport->device->transport_list, &transport->device_link); device_update_last_bluez_action_time(transport->device); @@ -2966,6 +3016,8 @@ spa_log_info(monitor->log, "%p: %s validate conf channels:%d", monitor, path, transport->n_channels); + spa_bt_device_add_profile(transport->device, transport->profile); + spa_bt_device_connect_profile(transport->device, transport->profile); /* Sync initial volumes */ @@ -3585,6 +3637,7 @@ adapter_update_props(a, props_iter, NULL); adapter_register_application(a); adapter_register_player(a); + adapter_update_devices(a); } else if (spa_streq(interface_name, BLUEZ_PROFILE_MANAGER_INTERFACE)) { if (monitor->backends[BACKEND_NATIVE]) @@ -3607,6 +3660,9 @@ device_update_props(d, props_iter, NULL); d->reconnect_state = BT_DEVICE_RECONNECT_INIT; + if (!device_props_ready(d))
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -137,6 +137,7 @@ uint32_t profile; unsigned int switching_codec:1; + unsigned int save_profile:1; uint32_t prev_bt_connected_profiles; const struct a2dp_codec **supported_codecs; @@ -757,7 +758,7 @@ static bool validate_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_audio_codec codec); -static int set_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_audio_codec codec) +static int set_profile(struct impl *this, uint32_t profile, enum spa_bluetooth_audio_codec codec, bool save) { if (!validate_profile(this, profile, codec)) { spa_log_warn(this->log, "trying to set invalid profile %d, codec %d, %08x %08x", @@ -766,6 +767,8 @@ return -EINVAL; } + this->save_profile = save; + if (this->profile == profile && (this->profile != DEVICE_PROFILE_A2DP || codec == this->props.codec) && (this->profile != DEVICE_PROFILE_HSP_HFP || codec == this->props.codec)) @@ -1104,6 +1107,8 @@ /* If default profile is set to HSP/HFP, first try those and exit if found. */ if (this->bt_dev->settings != NULL) { const char *str = spa_dict_lookup(this->bt_dev->settings, "bluez5.profile"); + if (spa_streq(str, "off")) + goto off; if (spa_streq(str, "headset-head-unit") && set_initial_hsp_hfp_profile(this)) return; } @@ -1126,6 +1131,7 @@ if (set_initial_hsp_hfp_profile(this)) return; +off: spa_log_debug(this->log, "initial profile off"); this->profile = DEVICE_PROFILE_OFF; @@ -1133,7 +1139,8 @@ } static struct spa_pod *build_profile(struct impl *this, struct spa_pod_builder *b, - uint32_t id, uint32_t index, uint32_t profile_index, enum spa_bluetooth_audio_codec codec) + uint32_t id, uint32_t index, uint32_t profile_index, enum spa_bluetooth_audio_codec codec, + bool current) { struct spa_bt_device *device = this->bt_dev; struct spa_pod_frame f[2]; @@ -1266,6 +1273,10 @@ } spa_pod_builder_pop(b, &f[1]); } + if (current) { + spa_pod_builder_prop(b, SPA_PARAM_PROFILE_save, 0); + spa_pod_builder_bool(b, this->save_profile); + } if (name_and_codec) free(name_and_codec); @@ -1282,7 +1293,7 @@ uint8_t buffer[1024]; spa_pod_builder_init(&b, buffer, sizeof(buffer)); - return (build_profile(this, &b, 0, 0, profile, codec) != NULL); + return (build_profile(this, &b, 0, 0, profile, codec, false) != NULL); } static struct spa_pod *build_route(struct impl *this, struct spa_pod_builder *b, @@ -1597,7 +1608,7 @@ case DEVICE_PROFILE_AG: case DEVICE_PROFILE_A2DP: case DEVICE_PROFILE_HSP_HFP: - param = build_profile(this, &b, id, result.index, profile, codec); + param = build_profile(this, &b, id, result.index, profile, codec, false); if (param == NULL) goto next; break; @@ -1613,7 +1624,7 @@ switch (result.index) { case 0: index = get_index_from_profile(this, this->profile, this->props.codec); - param = build_profile(this, &b, id, index, this->profile, this->props.codec); + param = build_profile(this, &b, id, index, this->profile, this->props.codec, true); if (param == NULL) return 0; break; @@ -1858,13 +1869,15 @@ uint32_t idx, next; uint32_t profile; enum spa_bluetooth_audio_codec codec; + bool save = false; if (param == NULL) return -EINVAL; if ((res = spa_pod_parse_object(param, SPA_TYPE_OBJECT_ParamProfile, NULL, - SPA_PARAM_PROFILE_index, SPA_POD_Int(&idx))) < 0) { + SPA_PARAM_PROFILE_index, SPA_POD_Int(&idx), + SPA_PARAM_PROFILE_save, SPA_POD_OPT_Bool(&save))) < 0) { spa_log_warn(this->log, "can't parse profile"); spa_debug_pod(0, NULL, param); return res; @@ -1874,8 +1887,8 @@ if (profile == SPA_ID_INVALID) return -EINVAL; - spa_log_debug(this->log, "setting profile %d codec:%d", profile, codec); - return set_profile(this, profile, codec); + spa_log_debug(this->log, "setting profile %d codec:%d save:%d", profile, codec, (int)save); + return set_profile(this, profile, codec, save); } case SPA_PARAM_Route: { @@ -1927,6 +1940,8 @@ return res; } + spa_log_debug(this->log, "setting props codec:%d", codec_id); + if (codec_id == SPA_ID_INVALID) return 0; @@ -1934,16 +1949,16 @@ size_t j; for (j = 0; j < this->supported_codec_count; ++j) { if (this->supported_codecs[j]->id == codec_id) { - return set_profile(this, this->profile, codec_id); + return set_profile(this, this->profile, codec_id, true); } } } else if (this->profile == DEVICE_PROFILE_HSP_HFP) { if (codec_id == SPA_BLUETOOTH_AUDIO_CODEC_CVSD && spa_bt_device_supports_hfp_codec(this->bt_dev, HFP_AUDIO_CODEC_CVSD) == 1) { - return set_profile(this, this->profile, codec_id); + return set_profile(this, this->profile, codec_id, true); } else if (codec_id == SPA_BLUETOOTH_AUDIO_CODEC_MSBC && spa_bt_device_supports_hfp_codec(this->bt_dev, HFP_AUDIO_CODEC_MSBC) == 1) { - return set_profile(this, this->profile, codec_id); + return set_profile(this, this->profile, codec_id, true); } } return -EINVAL;
View file
pipewire-0.3.43.tar.gz/spa/plugins/bluez5/quirks.c -> pipewire-0.3.44.tar.gz/spa/plugins/bluez5/quirks.c
Changed
@@ -332,7 +332,7 @@ } /* Adapter */ - if (this->adapter_rules) { + if (this->adapter_rules && adapter) { uint32_t no_features = 0; int nitems = 0; char vendor_id[64], product_id[64], address[64]; @@ -357,7 +357,7 @@ } /* Device */ - if (this->device_rules) { + if (this->device_rules && device) { uint32_t no_features = 0; int nitems = 0; char vendor_id[64], product_id[64], version_id[64], address[64];
View file
pipewire-0.3.43.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.44.tar.gz/spa/plugins/support/loop.c
Changed
@@ -187,7 +187,7 @@ int32_t filled; uint32_t avail, idx, offset, l0; - if (pthread_equal(impl->thread, pthread_self())) + if (impl->thread == 0 || pthread_equal(impl->thread, pthread_self())) return loop_invoke_inthread(impl, func, seq, data, size, block, user_data); filled = spa_ringbuffer_get_write_index(&impl->buffer, &idx);
View file
pipewire-0.3.43.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.44.tar.gz/spa/plugins/support/null-audio-sink.c
Changed
@@ -70,7 +70,6 @@ #define DEFAULT_CHANNELS 2 #define DEFAULT_RATE 44100 -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 16 #define MAX_PORTS 1 @@ -107,6 +106,8 @@ struct spa_loop *data_loop; struct spa_system *data_system; + uint32_t quantum_limit; + struct props props; uint64_t info_all; @@ -538,7 +539,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(1, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(port->blocks), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * port->bpf, + this->quantum_limit * port->bpf, 16 * port->bpf, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(port->bpf)); @@ -856,7 +857,6 @@ spa_log_error(this->log, "a data_system is needed"); return -EINVAL; } - spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT( @@ -904,7 +904,9 @@ for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key; const char *s = info->items[i].value; - if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) { + if (spa_streq(k, "clock.quantum-limit")) { + spa_atou32(s, &this->quantum_limit, 0); + } else if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) { this->props.channels = atoi(s); } else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) { this->props.rate = atoi(s);
View file
pipewire-0.3.43.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.44.tar.gz/spa/plugins/v4l2/v4l2-udev.c
Changed
@@ -311,18 +311,17 @@ } } - str = udev_device_get_property_value(dev, "ID_V4L_PRODUCT"); + str = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE"); if (!(str && *str)) { - str = udev_device_get_property_value(dev, "ID_MODEL_FROM_DATABASE"); + str = udev_device_get_property_value(dev, "ID_MODEL_ENC"); if (!(str && *str)) { - str = udev_device_get_property_value(dev, "ID_MODEL_ENC"); - if (!(str && *str)) { - str = udev_device_get_property_value(dev, "ID_MODEL"); - } else { - char *t = alloca(strlen(str) + 1); - unescape(str, t); - str = t; - } + str = udev_device_get_property_value(dev, "ID_MODEL"); + if (!(str && *str)) + str = udev_device_get_property_value(dev, "ID_V4L_PRODUCT"); + } else { + char *t = alloca(strlen(str) + 1); + unescape(str, t); + str = t; } } if (str && *str)
View file
pipewire-0.3.43.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.44.tar.gz/spa/plugins/volume/volume.c
Changed
@@ -53,7 +53,6 @@ props->mute = DEFAULT_MUTE; } -#define MAX_SAMPLES 8192 #define MAX_BUFFERS 16 struct buffer { @@ -90,6 +89,7 @@ struct spa_node node; struct spa_log *log; + uint32_t quantum_limit; uint64_t info_all; struct spa_node_info info; @@ -386,7 +386,7 @@ SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), SPA_PARAM_BUFFERS_size, SPA_POD_CHOICE_RANGE_Int( - MAX_SAMPLES * this->bpf, + this->quantum_limit * this->bpf, 16 * this->bpf, INT32_MAX), SPA_PARAM_BUFFERS_stride, SPA_POD_Int(this->bpf)); @@ -777,6 +777,7 @@ { struct impl *this; struct port *port; + uint32_t i; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -788,6 +789,13 @@ this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); + for (i = 0; info && i < info->n_items; i++) { + const char *k = info->items[i].key; + const char *s = info->items[i].value; + if (spa_streq(k, "clock.quantum-limit")) + spa_atou32(s, &this->quantum_limit, 0); + } + spa_hook_list_init(&this->hooks); this->node.iface = SPA_INTERFACE_INIT(
View file
pipewire-0.3.43.tar.gz/spa/tests/meson.build -> pipewire-0.3.44.tar.gz/spa/tests/meson.build
Changed
@@ -9,15 +9,16 @@ '-name', '*.h', '-not', '-name', 'type-info.h', '-type', 'f', - '-printf', '%P\n') + '-printf', '%P\n', + check: false) foreach spa_header : spa_headers.stdout().split('\n') if spa_header.endswith('.h') # skip empty lines ext = have_cpp ? 'cpp' : 'c' - c = configuration_data() - c.set('INCLUDE', spa_header) src = configure_file(input: 'spa-include-test-template.c', - output: 'spa-include-test-@0@.@1@'.format(spa_header.underscorify(), ext), - configuration: c) + output: 'spa-include-test-@0@.@1@'.format(spa_header.underscorify(), ext), + configuration: { + 'INCLUDE': spa_header, + }) executable('spa-include-test-@0@'.format(spa_header.underscorify()), src, dependencies: [ spa_dep ], @@ -40,7 +41,7 @@ install_dir : installed_tests_execdir, ), env : [ - 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')), + 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')), ] )
View file
pipewire-0.3.43.tar.gz/spa/tests/stress-ringbuffer.c -> pipewire-0.3.44.tar.gz/spa/tests/stress-ringbuffer.c
Changed
@@ -13,7 +13,8 @@ #ifdef __FreeBSD__ #include <sys/param.h> -#if __FreeBSD_version < 1400043 +#if (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400043) \ + || (__FreeBSD_version < 1300523) static int sched_getcpu(void) { return -1; }; #endif #endif
View file
pipewire-0.3.43.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -9,6 +9,8 @@ #mem.allow-mlock = true #mem.mlock-all = false log.level = 0 + + #default.clock.quantum-limit = 8192 } context.spa-libs = { @@ -32,13 +34,12 @@ # If ifexists is given, the module is ignored when it is not found. # If nofail is given, module initialization failures are ignored. # - # Uses RTKit to boost the data thread priority. - { name = libpipewire-module-rtkit + # Uses realtime scheduling to boost the audio thread priorities + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] } @@ -75,7 +76,7 @@ #node.latency = 1024/48000 #node.autoconnect = true #resample.quality = 4 - #channelmix.normalize = false + #channelmix.normalize = true #channelmix.mix-lfe = true #channelmix.upmix = false #channelmix.lfe-cutoff = 0
View file
pipewire-0.3.43.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/client.conf.in
Changed
@@ -9,6 +9,8 @@ #mem.allow-mlock = true #mem.mlock-all = false log.level = 0 + + #default.clock.quantum-limit = 8192 } context.spa-libs = { @@ -65,7 +67,7 @@ #node.latency = 1024/48000 #node.autoconnect = true #resample.quality = 4 - #channelmix.normalize = false + #channelmix.normalize = true #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/demonic.conf
Changed
@@ -19,13 +19,12 @@ } context.modules = [ - # Uses RTKit to boost the data thread priority. - { name = libpipewire-module-rtkit + # Uses realtime scheduling to boost the audio thread priorities + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf
Changed
@@ -12,12 +12,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-eq6.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-eq6.conf
Changed
@@ -12,12 +12,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf
Changed
@@ -13,12 +13,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf
Changed
@@ -12,12 +12,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf
Changed
@@ -12,12 +12,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.44.tar.gz/src/daemon/filter-chain/source-rnnoise.conf
Changed
@@ -12,12 +12,11 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/jack.conf.in
Changed
@@ -9,6 +9,8 @@ #mem.allow-mlock = true #mem.mlock-all = false log.level = 0 + + #default.clock.quantum-limit = 8192 } context.spa-libs = { @@ -35,10 +37,9 @@ # Boost the data thread priority. { name = libpipewire-module-rt args = { - #nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] }
View file
pipewire-0.3.43.tar.gz/src/daemon/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/meson.build
Changed
@@ -68,6 +68,7 @@ 'client.conf', 'client-rt.conf', 'jack.conf', + 'minimal.conf', 'pipewire-pulse.conf', ]
View file
pipewire-0.3.44.tar.gz/src/daemon/minimal.conf.in
Added
@@ -0,0 +1,297 @@ +# Simple daemon config file for PipeWire version @VERSION@ # +# +# Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes +# or in ~/.config/pipewire for local changes. + +context.properties = { + ## Configure properties in the system. + #library.name.system = support/libspa-support + #context.data-loop.library.name.system = support/libspa-support + #support.dbus = true + #link.max-buffers = 64 + link.max-buffers = 16 # version < 3 clients can't handle more + #mem.warn-mlock = false + #mem.allow-mlock = true + #mem.mlock-all = false + #clock.power-of-two-quantum = true + #log.level = 2 + #cpu.zero.denormals = true + + core.daemon = true # listening for socket connections + core.name = pipewire-0 # core name and socket name + + ## Properties for the DSP configuration. + #default.clock.rate = 48000 + #default.clock.allowed-rates = [ 48000 ] + #default.clock.quantum = 1024 + #default.clock.min-quantum = 32 + #default.clock.max-quantum = 2048 + #default.clock.quantum-limit = 8192 + #default.video.width = 640 + #default.video.height = 480 + #default.video.rate.num = 25 + #default.video.rate.denom = 1 + # + settings.check-quantum = true + settings.check-rate = true + # + # These overrides are only applied when running in a vm. + vm.overrides = { + default.clock.min-quantum = 1024 + } +} + +context.spa-libs = { + #<factory-name regex> = <library-name> + # + # Used to find spa factory names. It maps an spa factory name + # regular expression to a library name that should contain + # that factory. + # + audio.convert.* = audioconvert/libspa-audioconvert + api.alsa.* = alsa/libspa-alsa + support.* = support/libspa-support +} + +context.modules = [ + #{ name = <module-name> + # [ args = { <key> = <value> ... } ] + # [ flags = [ [ ifexists ] [ nofail ] ] + #} + # + # Loads a module with the given parameters. + # If ifexists is given, the module is ignored when it is not found. + # If nofail is given, module initialization failures are ignored. + # + + # Uses realtime scheduling to boost the audio thread priorities. This uses + # RTKit if the user doesn't have permission to use regular realtime + # scheduling. + { name = libpipewire-module-rt + args = { + nice.level = -11 + #rt.prio = 88 + #rt.time.soft = -1 + #rt.time.hard = -1 + } + flags = [ ifexists nofail ] + } + + # The native communication protocol. + { name = libpipewire-module-protocol-native } + + # The profile module. Allows application to access profiler + # and performance data. It provides an interface that is used + # by pw-top and pw-profiler. + { name = libpipewire-module-profiler } + + # Allows applications to create metadata objects. It creates + # a factory for Metadata objects. + { name = libpipewire-module-metadata } + + # Creates a factory for making nodes that run in the + # context of the PipeWire server. + { name = libpipewire-module-spa-node-factory } + + # Allows creating nodes that run in the context of the + # client. Is used by all clients that want to provide + # data to PipeWire. + { name = libpipewire-module-client-node } + + # The access module can perform access checks and block + # new clients. + { name = libpipewire-module-access + args = { + # access.allowed to list an array of paths of allowed + # apps. + #access.allowed = [ + # @session_manager_path@ + #] + + # An array of rejected paths. + #access.rejected = [ ] + + # An array of paths with restricted access. + #access.restricted = [ ] + + # Anything not in the above lists gets assigned the + # access.force permission. + #access.force = flatpak + } + } + + # Makes a factory for wrapping nodes in an adapter with a + # converter and resampler. + { name = libpipewire-module-adapter } + + # Makes a factory for creating links between ports. + { name = libpipewire-module-link-factory } +] + +context.objects = [ + #{ factory = <factory-name> + # [ args = { <key> = <value> ... } ] + # [ flags = [ [ nofail ] ] + #} + # + # Creates an object from a PipeWire factory with the given parameters. + # If nofail is given, errors are ignored (and no object is created). + # + #{ factory = spa-node-factory args = { factory.name = videotestsrc node.name = videotestsrc Spa:Pod:Object:Param:Props:patternType = 1 } } + #{ factory = spa-device-factory args = { factory.name = api.jack.device foo=bar } flags = [ nofail ] } + #{ factory = spa-device-factory args = { factory.name = api.alsa.enum.udev } } + #{ factory = spa-node-factory args = { factory.name = api.alsa.seq.bridge node.name = Internal-MIDI-Bridge } } + #{ factory = adapter args = { factory.name = audiotestsrc node.name = my-test } } + #{ factory = spa-node-factory args = { factory.name = api.vulkan.compute.source node.name = my-compute-source } } + + # Make a default metadata store + { factory = metadata args = { metadata.name = default } } + + # A default dummy driver. This handles nodes marked with the "node.always-driver" + # property when no other driver is currently active. JACK clients need this. + { factory = spa-node-factory + args = { + factory.name = support.node.driver + node.name = Dummy-Driver + node.group = pipewire.dummy + priority.driver = 20000 + } + } + { factory = spa-node-factory + args = { + factory.name = support.node.driver + node.name = Freewheel-Driver + priority.driver = 19000 + node.group = pipewire.freewheel + node.freewheel = true + } + } + + # This creates a single PCM source device for the given + # alsa device path hw:0. You can change source to sink + # to make a sink in the same way. + { factory = adapter + args = { + factory.name = api.alsa.pcm.source + node.name = "system" + node.description = "system" + media.class = "Audio/Source" + api.alsa.path = "hw:0" + #api.alsa.period-size = 0 + #api.alsa.period-num = 0 + #api.alsa.headroom = 0 + #api.alsa.start-delay = 0 + #api.alsa.disable-mmap = false + #api.alsa.disable-batch = false + #api.alsa.use-chmap = false + #api.alsa.multirate = true + #latency.internal.rate = 0 + #latency.internal.ns = 0 + #clock.name = api.alsa.0 + node.suspend-on-idle = true + #audio.format = "S32" + #audio.rate = 48000 + #audio.allowed-rates = [ ] + #audio.channels = 4 + #audio.position = [ FL FR RL RR ] + #resample.quality = 4 + resample.disable = true + #monitor.channel-volumes = false
View file
pipewire-0.3.43.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -9,6 +9,8 @@ #mem.allow-mlock = true #mem.mlock-all = false #log.level = 2 + + #default.clock.quantum-limit = 8192 } context.spa-libs = { @@ -17,12 +19,12 @@ } context.modules = [ - { name = libpipewire-module-rtkit + { name = libpipewire-module-rt args = { - #nice.level = -11 + nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] } @@ -42,7 +44,7 @@ #"tcp:127.0.0.1:8888" # IPv4 on a single address # #{ address = "tcp:4713" # address - # max-clients = 64 # maximume number of clients + # max-clients = 64 # maximum number of clients # listen-backlog = 32 # backlog in the server listen queue # client.access = "restricted" # permissions for clients #} @@ -73,8 +75,55 @@ #node.latency = 1024/48000 #node.autoconnect = true #resample.quality = 4 - #channelmix.normalize = false + #channelmix.normalize = true #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0 } + +# client/stream specific properties +pulse.rules = [ + { + matches = [ + { + # all keys must match the value. ~ starts regex. + #client.name = "Firefox" + #application.process.binary = "teams" + #application.name = "~speech-dispatcher.*" + } + ] + actions = { + update-props = { + #node.latency = 512/48000 + } + # Possible quirks:" + # force-s16-info forces sink and source info as S16 format + # remove-capture-dont-move removes the capture DONT_MOVE flag + #quirks = [ ] + } + } + { + # skype does not want to use devices that don't have an S16 sample format. + matches = [ + { application.process.binary = "teams" } + { application.process.binary = "skypeforlinux" } + ] + actions = { quirks = [ force-s16-info ] } + } + { + # firefox marks the capture streams as don't move and then they + # can't be moved with pavucontrol or other tools. + matches = [ { application.process.binary = "firefox" } ] + actions = { quirks = [ remove-capture-dont-move ] } + } + { + # speech dispatcher asks for too small latency and then underruns. + matches = [ { application.name = "~speech-dispatcher*" } ] + actions = { + update-props = { + pulse.min.req = 1024/48000 # 21ms + pulse.min.quantum = 1024/48000 # 21ms + } + } + } +]
View file
pipewire-0.3.43.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.44.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -25,12 +25,16 @@ #default.clock.allowed-rates = [ 48000 ] #default.clock.quantum = 1024 #default.clock.min-quantum = 32 - #default.clock.max-quantum = 8192 + #default.clock.max-quantum = 2048 + #default.clock.quantum-limit = 8192 #default.video.width = 640 #default.video.height = 480 #default.video.rate.num = 25 #default.video.rate.denom = 1 # + #settings.check-quantum = false + #settings.check-rate = false + # # These overrides are only applied when running in a vm. vm.overrides = { default.clock.min-quantum = 1024 @@ -67,28 +71,19 @@ # If nofail is given, module initialization failures are ignored. # - # Uses RTKit to boost the data thread priority. - { name = libpipewire-module-rtkit + # Uses realtime scheduling to boost the audio thread priorities. This uses + # RTKit if the user doesn't have permission to use regular realtime + # scheduling. + { name = libpipewire-module-rt args = { - #nice.level = -11 + nice.level = -11 #rt.prio = 88 - #rt.time.soft = 2000000 - #rt.time.hard = 2000000 + #rt.time.soft = -1 + #rt.time.hard = -1 } flags = [ ifexists nofail ] } - # Set thread priorities without using RTKit. - #{ name = libpipewire-module-rt - # args = { - # nice.level = -11 - # rt.prio = 88 - # rt.time.soft = 2000000 - # rt.time.hard = 2000000 - # } - # flags = [ ifexists nofail ] - #} - # The native communication protocol. { name = libpipewire-module-protocol-native } @@ -156,6 +151,16 @@ # Provides factories to make session manager objects. { name = libpipewire-module-session-manager } + + # Use libcanberra to play X11 Bell + #{ name = libpipewire-module-x11-bell + # args = { + # #sink.name = "@DEFAULT_SINK@" + # #sample.name = "bell-window-system" + # #x11.display = null + # #x11.xauthority = null + # } + #} ] context.objects = [
View file
pipewire-0.3.43.tar.gz/src/daemon/systemd/system/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/systemd/system/meson.build
Changed
@@ -1,4 +1,7 @@ -systemd_system_services_dir = systemd.get_variable(pkgconfig: 'systemdsystemunitdir', pkgconfig_define : [ 'rootprefix', prefix]) +systemd_system_services_dir = systemd.get_variable('systemdsystemunitdir', pkgconfig_define : [ 'rootprefix', prefix]) +if get_option('systemd-system-unit-dir') != '' + systemd_system_services_dir = get_option('systemd-system-unit-dir') +endif install_data(sources : 'pipewire.socket', install_dir : systemd_system_services_dir)
View file
pipewire-0.3.43.tar.gz/src/daemon/systemd/user/meson.build -> pipewire-0.3.44.tar.gz/src/daemon/systemd/user/meson.build
Changed
@@ -1,4 +1,4 @@ -systemd_user_services_dir = systemd.get_variable(pkgconfig: 'systemduserunitdir', pkgconfig_define : [ 'prefix', prefix]) +systemd_user_services_dir = systemd.get_variable('systemduserunitdir', pkgconfig_define : [ 'prefix', prefix]) if get_option('systemd-user-unit-dir') != '' systemd_user_services_dir = get_option('systemd-user-unit-dir') endif
View file
pipewire-0.3.43.tar.gz/src/modules/meson.build -> pipewire-0.3.44.tar.gz/src/modules/meson.build
Changed
@@ -21,12 +21,12 @@ 'module-protocol-simple.c', 'module-pulse-tunnel.c', 'module-rt.c', - 'module-rtkit.c', 'module-raop-discover.c', 'module-session-manager.c', 'module-zeroconf-discover.c', 'module-roc-source.c', 'module-roc-sink.c', + 'module-x11-bell.c', ] pipewire_module_access = shared_library('pipewire-module-access', [ 'module-access.c' ], @@ -137,21 +137,18 @@ dependencies : [spa_dep, mathlib, dl_lib, pipewire_dep], ) -build_module_rt = build_machine.system() == 'linux' +build_module_rt = dbus_dep.found() if build_module_rt pipewire_module_rt = shared_library('pipewire-module-rt', [ 'module-rt.c' ], include_directories : [configinc], install : true, install_dir : modules_install_dir, install_rpath: modules_install_dir, - dependencies : [dl_lib, pipewire_dep], + dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep], ) -endif -summary({'rt': build_module_rt}, bool_yn: true, section: 'Optional Modules') - -build_module_rtkit = dbus_dep.found() -if build_module_rtkit -pipewire_module_rtkit = shared_library('pipewire-module-rtkit', [ 'module-rtkit.c' ], +# TODO: This serves as a temporary alias to prevent breaking existing setups +# while `module-rtkit` is being migrated to `module-rt` +pipewire_module_rtkit = shared_library('pipewire-module-rtkit', [ 'module-rt.c' ], include_directories : [configinc], install : true, install_dir : modules_install_dir, @@ -159,7 +156,7 @@ dependencies : [dbus_dep, mathlib, dl_lib, pipewire_dep], ) endif -summary({'rtkit': build_module_rtkit}, bool_yn: true, section: 'Optional Modules') +summary({'rt': build_module_rt}, bool_yn: true, section: 'Optional Modules') build_module_portal = dbus_dep.found() if build_module_portal @@ -259,6 +256,7 @@ 'module-protocol-pulse/modules/module-switch-on-connect.c', 'module-protocol-pulse/modules/module-tunnel-sink.c', 'module-protocol-pulse/modules/module-tunnel-source.c', + 'module-protocol-pulse/modules/module-x11-bell.c', 'module-protocol-pulse/modules/module-zeroconf-discover.c', ] @@ -370,9 +368,9 @@ install_dir : installed_tests_execdir, ), env : [ - 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')), - 'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'confdatadir')), - 'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'moduledir')), + 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')), + 'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable('confdatadir')), + 'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable('moduledir')), ] ) @@ -488,3 +486,16 @@ endif summary({'roc-sink': build_module_roc}, bool_yn: true, section: 'Optional Modules') summary({'roc-source': build_module_roc}, bool_yn: true, section: 'Optional Modules') + +build_module_x11_bell = x11_dep.found() and canberra_dep.found() +if build_module_x11_bell +pipewire_module_x11_bell = shared_library('pipewire-module-x11-bell', + [ 'module-x11-bell.c' ], + include_directories : [configinc], + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, canberra_dep], +) +endif +summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules')
View file
pipewire-0.3.43.tar.gz/src/modules/module-adapter/adapter.c -> pipewire-0.3.44.tar.gz/src/modules/module-adapter/adapter.c
Changed
@@ -38,10 +38,15 @@ #include <spa/utils/string.h> #include <spa/utils/type-info.h> #include <spa/param/format.h> +#include <spa/param/audio/format.h> +#include <spa/param/audio/format-utils.h> #include <spa/param/format-utils.h> #include <spa/debug/types.h> +#include <spa/debug/pod.h> +#include <spa/utils/json-pod.h> #include "pipewire/pipewire.h" +#include "pipewire/private.h" #include "modules/spa/spa-node.h" @@ -170,6 +175,29 @@ .port_init = node_port_init, }; +static int handle_node_param(struct pw_impl_node *node, const char *key, const char *value) +{ + const struct spa_type_info *ti; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + struct spa_pod *pod; + int res; + + ti = spa_debug_type_find_short(spa_type_param, key); + if (ti == NULL) + return -ENOENT; + + if ((res = spa_json_to_pod(&b, 0, ti, value, strlen(value))) < 0) + return res; + + if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) + return -ENOSPC; + + if ((res = pw_impl_node_set_param(node, ti->type, 0, pod)) < 0) + return res; + + return 0; +} static int find_format(struct pw_impl_node *node, enum pw_direction direction, uint32_t *media_type, uint32_t *media_subtype) @@ -201,6 +229,113 @@ return 0; } +static int do_auto_port_config(struct node *n, const char *str) +{ + uint32_t state = 0, i; + uint8_t buffer[4096]; + struct spa_pod_builder b; +#define POSITION_PRESERVE 0 +#define POSITION_AUX 1 +#define POSITION_UNKNOWN 2 + int res, position = POSITION_PRESERVE; + struct spa_pod *param; + uint32_t media_type, media_subtype; + bool have_format = false, monitor = false; + struct spa_audio_info format = { 0, }; + enum spa_param_port_config_mode mode = SPA_PARAM_PORT_CONFIG_MODE_none; + struct spa_json it[2]; + char key[1024], val[256]; + + spa_json_init(&it[0], str, strlen(str)); + if (spa_json_enter_object(&it[0], &it[1]) <= 0) + return -EINVAL; + + while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) { + if (spa_json_get_string(&it[1], val, sizeof(val)) <= 0) + break; + + if (spa_streq(key, "mode")) { + mode = spa_debug_type_find_type_short(spa_type_param_port_config_mode, val); + if (mode == SPA_ID_INVALID) + mode = SPA_PARAM_PORT_CONFIG_MODE_none; + } else if (spa_streq(key, "monitor")) { + monitor = spa_atob(val); + } else if (spa_streq(key, "position")) { + if (spa_streq(val, "unknown")) + position = POSITION_UNKNOWN; + else if (spa_streq(val, "aux")) + position = POSITION_AUX; + else + position = POSITION_PRESERVE; + } + } + + while (true) { + struct spa_audio_info info = { 0, }; + struct spa_pod *position = NULL; + uint32_t n_position = 0; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + if ((res = spa_node_port_enum_params_sync(pw_impl_node_get_implementation(n->follower), + n->direction == PW_DIRECTION_INPUT ? + SPA_DIRECTION_INPUT : + SPA_DIRECTION_OUTPUT, 0, + SPA_PARAM_EnumFormat, &state, + NULL, ¶m, &b)) != 1) + break; + + if ((res = spa_format_parse(param, &media_type, &media_subtype)) < 0) + continue; + + if (media_type != SPA_MEDIA_TYPE_audio || + media_subtype != SPA_MEDIA_SUBTYPE_raw) + continue; + + spa_pod_object_fixate((struct spa_pod_object*)param); + + if (spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_AUDIO_format, SPA_POD_Id(&info.info.raw.format), + SPA_FORMAT_AUDIO_rate, SPA_POD_Int(&info.info.raw.rate), + SPA_FORMAT_AUDIO_channels, SPA_POD_Int(&info.info.raw.channels), + SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)) < 0) + continue; + + if (position != NULL) + n_position = spa_pod_copy_array(position, SPA_TYPE_Id, + info.info.raw.position, SPA_AUDIO_MAX_CHANNELS); + if (n_position == 0 || n_position != info.info.raw.channels) + SPA_FLAG_SET(info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED); + + if (format.info.raw.channels >= info.info.raw.channels) + continue; + + format = info; + have_format = true; + } + if (!have_format) + return -ENOENT; + + if (position == POSITION_AUX) { + for (i = 0; i < format.info.raw.channels; i++) + format.info.raw.position[i] = SPA_AUDIO_CHANNEL_START_Aux + i; + } else if (position == POSITION_UNKNOWN) { + for (i = 0; i < format.info.raw.channels; i++) + format.info.raw.position[i] = SPA_AUDIO_CHANNEL_UNKNOWN; + } + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + param = spa_format_audio_raw_build(&b, SPA_PARAM_Format, &format.info.raw); + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamPortConfig, SPA_PARAM_PortConfig, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(n->direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(mode), + SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_Bool(monitor), + SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); + pw_impl_node_set_param(n->node, SPA_PARAM_PortConfig, 0, param); + + return 0; +} struct pw_impl_node *pw_adapter_new(struct pw_context *context, struct pw_impl_node *follower, @@ -214,6 +349,8 @@ enum pw_direction direction; int res; uint32_t media_type, media_subtype; + const struct spa_dict_item *it; + struct pw_properties *copy; info = pw_impl_node_get_info(follower); if (info == NULL) { @@ -272,11 +409,16 @@ goto error; } + copy = pw_properties_new(NULL, NULL); + spa_dict_for_each(it, &props->dict) { + if (!spa_strstartswith(it->key, "node.param.") && + !spa_strstartswith(it->key, "port.param.")) + pw_properties_set(copy, it->key, it->value); + } node = pw_spa_node_load(context, factory_name, PW_SPA_NODE_FLAG_ACTIVATE | PW_SPA_NODE_FLAG_NO_REGISTER, - pw_properties_copy(props), - sizeof(struct node) + user_data_size); + copy, sizeof(struct node) + user_data_size); if (node == NULL) { res = -errno; pw_log_error("can't load spa node: %m"); @@ -298,6 +440,15 @@ pw_impl_node_add_listener(node, &n->node_listener, &node_events, n); + if ((str = pw_properties_get(props, "adapter.auto-port-config")) != NULL) + do_auto_port_config(n, str); + + spa_dict_for_each(it, &props->dict) { + if (spa_strstartswith(it->key, "node.param.")) { + if ((res = handle_node_param(node, &it->key[11], it->value)) < 0) + pw_log_warn("can't set node param: %s", spa_strerror(res)); + }
View file
pipewire-0.3.43.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.44.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -219,6 +219,8 @@ if (mix_id >= len) { size_t need = sizeof(struct mix) * (mix_id + 1 - len); void *ptr = pw_array_add(&p->mix, need); + if (ptr == NULL) + return NULL; memset(ptr, 0, need); } mix = pw_array_get_unchecked(&p->mix, mix_id, struct mix); @@ -1388,8 +1390,15 @@ return -ENOMEM; mix->id = pw_map_insert_new(&impl->io_map, NULL); - if (mix->id == SPA_ID_INVALID) + if (mix->id == SPA_ID_INVALID) { + m->valid = false; return -errno; + } + if (mix->id > MAX_AREAS) { + pw_map_remove(&impl->io_map, mix->id); + m->valid = false; + return -ENOMEM; + } mix->io = SPA_PTROFF(impl->io_areas->map->ptr, mix->id * sizeof(struct spa_io_buffers), void);
View file
pipewire-0.3.43.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.44.tar.gz/src/modules/module-echo-cancel.c
Changed
@@ -109,6 +109,15 @@ * */ +/** + * .--------. .---------. .--------. .----------. .-------. + * | source | --> | capture | --> | | --> | source | --> | app | + * '--------' '---------' | echo | '----------' '-------' + * | cancel | + * .--------. .---------. | | .----------. .--------. + * | app | --> | sink | --> | | --> | playback | --> | sink | + * '--------' '---------' '--------' '----------' '--------' + */ #define NAME "echo-cancel" PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); @@ -117,6 +126,7 @@ /* Hopefully this is enough for any combination of AEC engine and resampler * input requirement for rate matching */ #define MAX_BUFSIZE_MS 100 +#define DELAY_MS 0 static const struct spa_dict_item module_props[] = { { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, @@ -126,6 +136,8 @@ "[ audio.rate=<sample rate> ] " "[ audio.channels=<number of channels> ] " "[ audio.position=<channel map> ] " + "[ buffer.max_size=<max buffer size in ms> ] " + "[ buffer.play_delay=<play delay in ms> ] " "[ aec.method=<aec method> ] " "[ aec.args=<aec arguments> ] " "[ source.props=<properties> ] " @@ -166,6 +178,7 @@ void *play_buffer[SPA_AUDIO_MAX_CHANNELS]; uint32_t play_ringsize; struct spa_ringbuffer play_ring; + struct spa_ringbuffer play_delayed_ring; struct spa_io_rate_match *play_rate_match; void *out_buffer[SPA_AUDIO_MAX_CHANNELS]; @@ -181,6 +194,9 @@ unsigned int do_disconnect:1; unsigned int unloading:1; + + uint32_t max_buffer_size; + uint32_t buffer_delay; }; static void do_unload_module(void *obj, void *data, int res, uint32_t id) @@ -202,13 +218,15 @@ struct pw_buffer *pout; float rec_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)]; float play_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)]; + float play_delayed_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)]; float out_buf[impl->info.channels][impl->aec_blocksize / sizeof(float)]; const float *rec[impl->info.channels]; const float *play[impl->info.channels]; + const float *play_delayed[impl->info.channels]; float *out[impl->info.channels]; struct spa_data *dd; uint32_t i, size; - uint32_t rindex, pindex, oindex, avail; + uint32_t rindex, pindex, oindex, pdindex, avail; int32_t stride = 0; if ((pout = pw_stream_dequeue_buffer(impl->playback)) == NULL) { @@ -222,12 +240,15 @@ spa_ringbuffer_get_read_index(&impl->rec_ring, &rindex); spa_ringbuffer_get_read_index(&impl->play_ring, &pindex); + spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &pdindex); for (i = 0; i < impl->info.channels; i++) { /* captured samples, with echo from sink */ rec[i] = &rec_buf[i][0]; /* echo from sink */ play[i] = &play_buf[i][0]; + /* echo from sink delayed */ + play_delayed[i] = &play_delayed_buf[i][0]; /* filtered samples, without echo from sink */ out[i] = &out_buf[i][0]; @@ -241,6 +262,11 @@ impl->play_ringsize, pindex % impl->play_ringsize, (void *)play[i], size); + stride = 0; + spa_ringbuffer_read_data(&impl->play_delayed_ring, impl->play_buffer[i], + impl->play_ringsize, pdindex % impl->play_ringsize, + (void *)play_delayed[i], size); + /* output to sink, just copy */ dd = &pout->buffer->datas[i]; memcpy(dd->data, play[i], size); @@ -252,11 +278,12 @@ spa_ringbuffer_read_update(&impl->rec_ring, rindex + size); spa_ringbuffer_read_update(&impl->play_ring, pindex + size); + spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + size); pw_stream_queue_buffer(impl->playback, pout); /* Now run the canceller */ - echo_cancel_run(impl->aec_info, impl->aec, rec, play, out, size / sizeof(float)); + echo_cancel_run(impl->aec_info, impl->aec, rec, play_delayed, out, size / sizeof(float)); /* Next, copy over the output to the output ringbuffer */ avail = spa_ringbuffer_get_write_index(&impl->out_ring, &oindex); @@ -544,6 +571,9 @@ spa_ringbuffer_get_read_index(&impl->play_ring, &rindex); spa_ringbuffer_read_update(&impl->play_ring, rindex + drop); + spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &rindex); + spa_ringbuffer_read_update(&impl->play_delayed_ring, rindex + drop); + avail += drop; } @@ -604,6 +634,7 @@ struct spa_pod_builder b; struct pw_properties *props; const char *str; + uint32_t index; props = pw_properties_new( PW_KEY_NODE_NAME, "echo-cancel-capture", @@ -710,9 +741,9 @@ params, n_params)) < 0) return res; - impl->rec_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000; - impl->play_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000; - impl->out_ringsize = sizeof(float) * MAX_BUFSIZE_MS * impl->info.rate / 1000; + impl->rec_ringsize = sizeof(float) * impl->max_buffer_size * impl->info.rate / 1000; + impl->play_ringsize = sizeof(float) * (impl->max_buffer_size + impl->buffer_delay) * impl->info.rate / 1000; + impl->out_ringsize = sizeof(float) * impl->max_buffer_size * impl->info.rate / 1000; for (i = 0; i < impl->info.channels; i++) { impl->rec_buffer[i] = malloc(impl->rec_ringsize); impl->play_buffer[i] = malloc(impl->play_ringsize); @@ -720,8 +751,14 @@ } spa_ringbuffer_init(&impl->rec_ring); spa_ringbuffer_init(&impl->play_ring); + spa_ringbuffer_init(&impl->play_delayed_ring); spa_ringbuffer_init(&impl->out_ring); + spa_ringbuffer_get_write_index(&impl->play_ring, &index); + spa_ringbuffer_write_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay) * impl->info.rate / 1000)); + spa_ringbuffer_get_read_index(&impl->play_ring, &index); + spa_ringbuffer_read_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay) * impl->info.rate / 1000)); + return 0; } @@ -997,6 +1034,9 @@ copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_NODE_LATENCY); + impl->max_buffer_size = pw_properties_get_uint32(props,"buffer.max_size", MAX_BUFSIZE_MS); + impl->buffer_delay = pw_properties_get_uint32(props,"buffer.play_delay", DELAY_MS); + pw_properties_free(props); pw_proxy_add_listener((struct pw_proxy*)impl->core,
View file
pipewire-0.3.43.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.44.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -343,7 +343,7 @@ char *col, *node_name, *port_name, *str; struct port *ports; const struct fc_descriptor *d; - uint32_t i, n_ports; + uint32_t i, n_ports, port_id = SPA_ID_INVALID; str = strdupa(name); col = strchr(str, ':'); @@ -359,6 +359,9 @@ if (node == NULL) return NULL; + if (!spa_atou32(port_name, &port_id, 0)) + port_id = SPA_ID_INVALID; + if (FC_IS_PORT_INPUT(descriptor)) { if (FC_IS_PORT_CONTROL(descriptor)) { ports = node->control_port; @@ -381,7 +384,8 @@ d = node->desc->desc; for (i = 0; i < n_ports; i++) { struct port *port = &ports[i]; - if (spa_streq(d->ports[port->p].name, port_name)) + if (i == port_id || + spa_streq(d->ports[port->p].name, port_name)) return port; } return NULL; @@ -1701,11 +1705,8 @@ if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); - if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) - pw_properties_setf(props, PW_KEY_NODE_NAME, "filter-chain-%u", id); if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) - pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, - pw_properties_get(props, PW_KEY_NODE_NAME)); + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, "filter-chain-%u", id); if ((str = pw_properties_get(props, "capture.props")) != NULL) pw_properties_update_string(impl->capture_props, str, strlen(str)); @@ -1715,7 +1716,6 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); - copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); copy_props(impl, props, PW_KEY_NODE_GROUP); copy_props(impl, props, PW_KEY_NODE_LINK_GROUP); @@ -1726,18 +1726,25 @@ parse_audio_info(impl->capture_props, &impl->capture_info); parse_audio_info(impl->playback_props, &impl->playback_info); + if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME, + "input.filter-chain-%u", id); + if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME, + "output.filter-chain-%u", id); + + if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input", + pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION)); + if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output", + pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION)); + if ((res = load_graph(&impl->graph, props)) < 0) { pw_log_error("can't load graph: %s", spa_strerror(res)); goto error; } - if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL) - pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "filter input %s", - pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME)); - if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL) - pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "filter output %s", - pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME)); - impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); if (impl->core == NULL) { str = pw_properties_get(props, PW_KEY_REMOTE_NAME);
View file
pipewire-0.3.43.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.44.tar.gz/src/modules/module-loopback.c
Changed
@@ -461,11 +461,9 @@ if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); - if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) - pw_properties_setf(props, PW_KEY_NODE_NAME, "loopback-%u", id); if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) - pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, - pw_properties_get(props, PW_KEY_NODE_NAME)); + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "loopback-%u", id); if ((str = pw_properties_get(props, "capture.props")) != NULL) pw_properties_update_string(impl->capture_props, str, strlen(str)); @@ -475,25 +473,29 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); - copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); copy_props(impl, props, PW_KEY_NODE_GROUP); copy_props(impl, props, PW_KEY_NODE_LINK_GROUP); copy_props(impl, props, PW_KEY_NODE_LATENCY); copy_props(impl, props, PW_KEY_NODE_VIRTUAL); + copy_props(impl, props, PW_KEY_MEDIA_NAME); + + if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME, + "input.loopback-%u", id); + if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME, + "output.loopback-%u", id); parse_audio_info(impl->capture_props, &impl->capture_info); parse_audio_info(impl->playback_props, &impl->playback_info); if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL) - pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, - "loopback input %s", - pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME)); - + pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input", + pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION)); if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL) - pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, - "loopback output %s", - pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME)); + pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output", + pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION)); impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); if (impl->core == NULL) {
View file
pipewire-0.3.43.tar.gz/src/modules/module-metadata.c -> pipewire-0.3.44.tar.gz/src/modules/module-metadata.c
Changed
@@ -74,43 +74,70 @@ uint32_t new_id) { struct factory_data *data = _data; + struct pw_context *context = pw_impl_module_get_context(data->module); void *result; - struct pw_resource *metadata_resource; - struct pw_impl_client *client = pw_resource_get_client(resource); + struct pw_resource *metadata_resource = NULL; + struct pw_impl_client *client = resource ? pw_resource_get_client(resource) : NULL; int res; - metadata_resource = pw_resource_new(client, new_id, PW_PERM_ALL, type, version, 0); - if (metadata_resource == NULL) { - res = -errno; - goto error_resource; - } + if (properties == NULL) + properties = pw_properties_new(NULL, NULL); + if (properties == NULL) + return NULL; + + pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d", + pw_impl_factory_get_info(data->this)->id); + pw_properties_setf(properties, PW_KEY_MODULE_ID, "%d", + pw_impl_module_get_info(data->module)->id); + + if (pw_properties_get(properties, PW_KEY_METADATA_NAME) == NULL) + pw_properties_set(properties, PW_KEY_METADATA_NAME, "default"); + + if (client) { + metadata_resource = pw_resource_new(client, new_id, PW_PERM_ALL, type, version, 0); + if (metadata_resource == NULL) { + res = -errno; + goto error_resource; + } - if (properties) { - pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d", - pw_impl_factory_get_info(data->this)->id); pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", pw_impl_client_get_info(client)->id); - } - result = pw_metadata_new(pw_impl_client_get_context(client), metadata_resource, properties); - if (result == NULL) { - res = -errno; - goto error_node; + result = pw_metadata_new(context, metadata_resource, properties); + if (result == NULL) { + properties = NULL; + res = -errno; + goto error_node; + } + } else { + result = pw_context_create_metadata(context, NULL, properties, 0); + if (result == NULL) { + properties = NULL; + res = -errno; + goto error_node; + } + pw_impl_metadata_register(result, NULL); } return result; error_resource: pw_log_error("can't create resource: %s", spa_strerror(res)); - pw_resource_errorf_id(resource, new_id, res, "can't create resource: %s", spa_strerror(res)); + if (resource) + pw_resource_errorf_id(resource, new_id, res, + "can't create resource: %s", spa_strerror(res)); goto error_exit; error_node: pw_log_error("can't create metadata: %s", spa_strerror(res)); - pw_resource_errorf_id(resource, new_id, res, "can't create metadata: %s", spa_strerror(res)); + if (resource) + pw_resource_errorf_id(resource, new_id, res, + "can't create metadata: %s", spa_strerror(res)); goto error_exit_free; error_exit_free: - pw_resource_remove(metadata_resource); + if (metadata_resource) + pw_resource_remove(metadata_resource); error_exit: + pw_properties_free(properties); errno = -res; return NULL; }
View file
pipewire-0.3.43.tar.gz/src/modules/module-metadata/metadata.c -> pipewire-0.3.44.tar.gz/src/modules/module-metadata/metadata.c
Changed
@@ -271,9 +271,6 @@ return NULL; } - if (pw_properties_get(properties, PW_KEY_METADATA_NAME) == NULL) - pw_properties_set(properties, PW_KEY_METADATA_NAME, "default"); - pw_resource_install_marshal(resource, true); impl->global = pw_global_new(context,
View file
pipewire-0.3.43.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.44.tar.gz/src/modules/module-profiler.c
Changed
@@ -379,6 +379,10 @@ struct pw_properties *props; struct impl *impl; struct pw_loop *main_loop = pw_context_get_main_loop(context); + static const char * const keys[] = { + PW_KEY_OBJECT_SERIAL, + NULL + }; PW_LOG_TOPIC_INIT(mod_topic); @@ -409,9 +413,14 @@ free(impl); return -errno; } + pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", impl->global->id); + pw_properties_setf(impl->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64, + pw_global_get_serial(impl->global)); impl->flush_timeout = pw_loop_add_timer(main_loop, flush_timeout, impl); + pw_global_update_keys(impl->global, &impl->properties->dict, keys); + pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-native/connection.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-native/connection.c
Changed
@@ -175,10 +175,37 @@ pw_log_error("connection %p: could not recvmsg on fd:%d: %s", conn, conn->fd, strerror(res)); } +static size_t cmsg_data_length(const struct cmsghdr *cmsg) +{ + const void *begin = CMSG_DATA(cmsg); + const void *end = SPA_PTROFF(cmsg, cmsg->cmsg_len, void); + + spa_assert(begin <= end); + + return SPA_PTRDIFF(end, begin); +} + +static void close_all_fds(struct msghdr *msg, struct cmsghdr *from) +{ + for (; from != NULL; from = CMSG_NXTHDR(msg, from)) { + if (from->cmsg_level != SOL_SOCKET || from->cmsg_type != SCM_RIGHTS) + continue; + + size_t n_fds = cmsg_data_length(from) / sizeof(int); + for (size_t i = 0; i < n_fds; i++) { + const void *p = SPA_PTROFF(CMSG_DATA(from), sizeof(int) * i, void); + int fd; + + memcpy(&fd, p, sizeof(fd)); + close(fd); + } + } +} + static int refill_buffer(struct pw_protocol_native_connection *conn, struct buffer *buf) { ssize_t len; - struct cmsghdr *cmsg; + struct cmsghdr *cmsg = NULL; struct msghdr msg = { 0 }; struct iovec iov[1]; char cmsgbuf[CMSG_SPACE(MAX_FDS_MSG * sizeof(int))]; @@ -198,7 +225,7 @@ while (true) { len = recvmsg(conn->fd, &msg, msg.msg_flags); if (msg.msg_flags & MSG_CTRUNC) - return -EPROTO; + goto cmsgs_truncated; if (len == 0 && avail != 0) return -EPIPE; else if (len < 0) { @@ -218,10 +245,9 @@ if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS) continue; - n_fds = - (cmsg->cmsg_len - ((char *) CMSG_DATA(cmsg) - (char *) cmsg)) / sizeof(int); + n_fds = cmsg_data_length(cmsg) / sizeof(int); if (n_fds + buf->n_fds > MAX_FDS) - return -EPROTO; + goto too_many_fds; memcpy(&buf->fds[buf->n_fds], CMSG_DATA(cmsg), n_fds * sizeof(int)); buf->n_fds += n_fds; } @@ -234,6 +260,14 @@ recv_error: handle_connection_error(conn, errno); return -errno; + +cmsgs_truncated: + close_all_fds(&msg, CMSG_FIRSTHDR(&msg)); + return -EPROTO; + +too_many_fds: + close_all_fds(&msg, cmsg); + return -EPROTO; } static void clear_buffer(struct buffer *buf, bool fds)
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
@@ -295,23 +295,34 @@ return 0; } -/* returns true if an event with the (mask, event, id) triplet should be dropped because it is redundant */ -static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t id) +static bool drop_from_out_queue(struct client *client, struct message *m) { - struct impl *impl = client->impl; - struct message *m, *t, *first; + spa_assert(!spa_list_is_empty(&client->out_messages)); - if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW) + struct message *first = spa_list_first(&client->out_messages, struct message, link); + if (m == first && client->out_index > 0) return false; - first = spa_list_first(&client->out_messages, struct message, link); + message_free(client->impl, m, true, false); + + return true; +} + +/* returns true if an event with the (mask, event, index) triplet should be dropped because it is redundant */ +static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t index) +{ + struct message *m, *t; + + if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW) + return false; + /* NOTE: reverse iteration */ spa_list_for_each_safe_reverse(m, t, &client->out_messages, link) { if (m->extra[0] != COMMAND_SUBSCRIBE_EVENT) continue; if ((m->extra[1] ^ event) & SUBSCRIPTION_EVENT_FACILITY_MASK) continue; - if (m->extra[2] != id) + if (m->extra[2] != index) continue; if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_REMOVE) { @@ -319,25 +330,39 @@ * point in keeping the old events regarding * entry in the queue. */ - /* if the first message has already been partially sent, do not drop it */ - if (m != first || client->out_index == 0) { - message_free(impl, m, true, false); - pw_log_debug("client %p: dropped redundant event due to remove event", client); + bool is_new = (m->extra[1] & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_NEW; + + if (drop_from_out_queue(client, m)) { + pw_log_debug("client %p: dropped redundant event due to remove event for object %u", + client, index); + + /* if the NEW event for the current object could successfully be dropped, + there is no need to deliver the REMOVE event */ + if (is_new) + goto drop; } + + /* stop if the NEW event for the current object is reached */ + if (is_new) + break; } if ((event & SUBSCRIPTION_EVENT_TYPE_MASK) == SUBSCRIPTION_EVENT_CHANGE) { /* This object has changed. If a "new" or "change" event for * this object is still in the queue we can exit. */ - pw_log_debug("client %p: dropped redundant event due to change event", client); - return true; + goto drop; } } return false; + +drop: + pw_log_debug("client %p: dropped redundant event for object %u", client, index); + + return true; } -int client_queue_subscribe_event(struct client *client, uint32_t mask, uint32_t event, uint32_t id) +int client_queue_subscribe_event(struct client *client, uint32_t mask, uint32_t event, uint32_t index) { if (client->disconnect) return -ENOTCONN; @@ -345,21 +370,21 @@ if (!(client->subscribed & mask)) return 0; - pw_log_debug("client %p: SUBSCRIBE event:%08x id:%u", client, event, id); + pw_log_debug("client %p: SUBSCRIBE event:%08x index:%u", client, event, index); - if (client_prune_subscribe_events(client, mask, event, id)) + if (client_prune_subscribe_events(client, mask, event, index)) return 0; struct message *reply = message_alloc(client->impl, -1, 0); reply->extra[0] = COMMAND_SUBSCRIBE_EVENT; reply->extra[1] = event; - reply->extra[2] = id; + reply->extra[2] = index; message_put(reply, TAG_U32, COMMAND_SUBSCRIBE_EVENT, TAG_U32, -1, TAG_U32, event, - TAG_U32, id, + TAG_U32, index, TAG_INVALID); return client_queue_message(client, reply);
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/collect.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/collect.c
Changed
@@ -58,19 +58,41 @@ continue; if (o->id == s->id) return o; + if (o->index == s->index) + return o; if (s->accumulate) s->accumulate(s, o); if (o->props && s->key != NULL && s->value != NULL && (str = pw_properties_get(o->props, s->key)) != NULL && spa_streq(str, s->value)) return o; - if (s->value != NULL && (uint32_t)atoi(s->value) == o->id) + if (s->value != NULL && (uint32_t)atoi(s->value) == o->index) return o; } return s->best; } -bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction) +uint32_t id_to_index(struct pw_manager *m, uint32_t id) +{ + struct pw_manager_object *o; + spa_list_for_each(o, &m->object_list, link) { + if (o->id == id) + return o->index; + } + return SPA_ID_INVALID; +} + +uint32_t index_to_id(struct pw_manager *m, uint32_t index) +{ + struct pw_manager_object *o; + spa_list_for_each(o, &m->object_list, link) { + if (o->index == index) + return o->id; + } + return SPA_ID_INVALID; +} + +bool collect_is_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction) { struct pw_manager_object *o; uint32_t in_node, out_node; @@ -83,14 +105,14 @@ pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0) continue; - if ((direction == PW_DIRECTION_OUTPUT && obj_id == out_node) || - (direction == PW_DIRECTION_INPUT && obj_id == in_node)) + if ((direction == PW_DIRECTION_OUTPUT && id == out_node) || + (direction == PW_DIRECTION_INPUT && id == in_node)) return true; } return false; } -struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction) +struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction) { struct pw_manager_object *o, *p; uint32_t in_node, out_node; @@ -103,12 +125,12 @@ pw_properties_fetch_uint32(o->props, PW_KEY_LINK_INPUT_NODE, &in_node) != 0) continue; - if (direction == PW_DIRECTION_OUTPUT && obj_id == out_node) { + if (direction == PW_DIRECTION_OUTPUT && id == out_node) { struct selector sel = { .id = in_node, .type = pw_manager_object_is_sink, }; if ((p = select_object(m, &sel)) != NULL) return p; } - if (direction == PW_DIRECTION_INPUT && obj_id == in_node) { + if (direction == PW_DIRECTION_INPUT && id == in_node) { struct selector sel = { .id = out_node, .type = pw_manager_object_is_recordable, }; if ((p = select_object(m, &sel)) != NULL) return p; @@ -157,7 +179,7 @@ if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_ParamProfile, NULL, - SPA_PARAM_PROFILE_index, SPA_POD_Int(&pi->id), + SPA_PARAM_PROFILE_index, SPA_POD_Int(&pi->index), SPA_PARAM_PROFILE_name, SPA_POD_String(&pi->name), SPA_PARAM_PROFILE_description, SPA_POD_OPT_String(&pi->description), SPA_PARAM_PROFILE_priority, SPA_POD_OPT_Int(&pi->priority), @@ -167,7 +189,7 @@ } if (pi->description == NULL) pi->description = pi->name; - if (pi->id == card_info->active_profile) + if (pi->index == card_info->active_profile) card_info->active_profile_name = pi->name; if (classes != NULL) { @@ -198,12 +220,12 @@ return n; } -uint32_t find_profile_id(struct pw_manager_object *card, const char *name) +uint32_t find_profile_index(struct pw_manager_object *card, const char *name) { struct pw_manager_param *p; spa_list_for_each(p, &card->param_list, link) { - uint32_t id; + uint32_t index; const char *test_name; if (p->id != SPA_PARAM_EnumProfile) @@ -211,12 +233,12 @@ if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_ParamProfile, NULL, - SPA_PARAM_PROFILE_index, SPA_POD_Int(&id), + SPA_PARAM_PROFILE_index, SPA_POD_Int(&index), SPA_PARAM_PROFILE_name, SPA_POD_String(&test_name)) < 0) continue; if (spa_streq(test_name, name)) - return id; + return index; } return SPA_ID_INVALID; @@ -229,7 +251,7 @@ if (card && !monitor) { spa_list_for_each(p, &card->param_list, link) { - uint32_t id, dev; + uint32_t index, dev; struct spa_pod *props; if (p->id != SPA_PARAM_Route) @@ -237,13 +259,13 @@ if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_ParamRoute, NULL, - SPA_PARAM_ROUTE_index, SPA_POD_Int(&id), + SPA_PARAM_ROUTE_index, SPA_POD_Int(&index), SPA_PARAM_ROUTE_device, SPA_POD_Int(&dev), SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props)) < 0) continue; if (dev != dev_info->device) continue; - dev_info->active_port = id; + dev_info->active_port = index; if (props) { volume_parse_param(props, &dev_info->volume_info, monitor); dev_info->have_volume = true; @@ -316,7 +338,7 @@ if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_ParamRoute, NULL, - SPA_PARAM_ROUTE_index, SPA_POD_Int(&pi->id), + SPA_PARAM_ROUTE_index, SPA_POD_Int(&pi->index), SPA_PARAM_ROUTE_direction, SPA_POD_Id(&pi->direction), SPA_PARAM_ROUTE_name, SPA_POD_String(&pi->name), SPA_PARAM_ROUTE_description, SPA_POD_OPT_String(&pi->description), @@ -341,7 +363,7 @@ continue; if (!array_contains(pi->devices, pi->n_devices, dev_info->device)) continue; - if (pi->id == dev_info->active_port) + if (pi->index == dev_info->active_port) dev_info->active_port_name = pi->name; } @@ -377,12 +399,12 @@ return n; } -uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name) +uint32_t find_port_index(struct pw_manager_object *card, uint32_t direction, const char *port_name) { struct pw_manager_param *p; spa_list_for_each(p, &card->param_list, link) { - uint32_t id, dir; + uint32_t index, dir; const char *name; if (p->id != SPA_PARAM_EnumRoute) @@ -390,14 +412,14 @@ if (spa_pod_parse_object(p->param, SPA_TYPE_OBJECT_ParamRoute, NULL, - SPA_PARAM_ROUTE_index, SPA_POD_Int(&id), + SPA_PARAM_ROUTE_index, SPA_POD_Int(&index), SPA_PARAM_ROUTE_direction, SPA_POD_Id(&dir), SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0) continue; if (dir != direction) continue; if (spa_streq(name, port_name)) - return id; + return index; } return SPA_ID_INVALID;
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/collect.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/collect.h
Changed
@@ -44,6 +44,7 @@ struct selector { bool (*type) (struct pw_manager_object *o); uint32_t id; + uint32_t index; const char *key; const char *value; void (*accumulate) (struct selector *sel, struct pw_manager_object *o); @@ -52,6 +53,8 @@ }; struct pw_manager_object *select_object(struct pw_manager *m, struct selector *s); +uint32_t id_to_index(struct pw_manager *m, uint32_t id); +uint32_t index_to_id(struct pw_manager *m, uint32_t index); void select_best(struct selector *s, struct pw_manager_object *o); /* ========================================================================== */ @@ -103,7 +106,7 @@ /* ========================================================================== */ struct profile_info { - uint32_t id; + uint32_t index; const char *name; const char *description; uint32_t priority; @@ -118,7 +121,7 @@ /* ========================================================================== */ struct port_info { - uint32_t id; + uint32_t index; uint32_t direction; const char *name; const char *description; @@ -154,9 +157,9 @@ /* ========================================================================== */ struct spa_dict *collect_props(struct spa_pod *info, struct spa_dict *dict); -uint32_t find_profile_id(struct pw_manager_object *card, const char *name); -uint32_t find_port_id(struct pw_manager_object *card, uint32_t direction, const char *port_name); -struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction); -bool collect_is_linked(struct pw_manager *m, uint32_t obj_id, enum pw_direction direction); +uint32_t find_profile_index(struct pw_manager_object *card, const char *name); +uint32_t find_port_index(struct pw_manager_object *card, uint32_t direction, const char *port_name); +struct pw_manager_object *find_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction); +bool collect_is_linked(struct pw_manager *m, uint32_t id, enum pw_direction direction); #endif
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/defs.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/defs.h
Changed
@@ -56,10 +56,9 @@ #define SCACHE_ENTRY_SIZE_MAX (1024*1024*16) -#define INDEX_MASK 0xffffu -#define MONITOR_FLAG (1u << 16) -#define EXTENSION_FLAG (1u << 17) -#define MODULE_FLAG (1u << 18) +#define MODULE_INDEX_MASK 0xfffffffu +#define MODULE_EXTENSION_FLAG (1u << 28) +#define MODULE_FLAG (1u << 29) #define DEFAULT_SINK "@DEFAULT_SINK@" #define DEFAULT_SOURCE "@DEFAULT_SOURCE@"
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extension.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extension.c
Changed
@@ -30,17 +30,17 @@ #include "extensions/registry.h" static const struct extension extensions[] = { - { "module-stream-restore", 0 | EXTENSION_FLAG, do_extension_stream_restore, }, - { "module-device-restore", 1 | EXTENSION_FLAG, do_extension_device_restore, }, - { "module-device-manager", 2 | EXTENSION_FLAG, do_extension_device_manager, }, + { "module-stream-restore", 0 | MODULE_EXTENSION_FLAG, do_extension_stream_restore, }, + { "module-device-restore", 1 | MODULE_EXTENSION_FLAG, do_extension_device_restore, }, + { "module-device-manager", 2 | MODULE_EXTENSION_FLAG, do_extension_device_manager, }, }; -const struct extension *extension_find(uint32_t idx, const char *name) +const struct extension *extension_find(uint32_t index, const char *name) { const struct extension *ext; SPA_FOR_EACH_ELEMENT(extensions, ext) { - if (idx == ext->idx || spa_streq(name, ext->name)) + if (index == ext->index || spa_streq(name, ext->name)) return ext; }
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extension.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extension.h
Changed
@@ -38,10 +38,10 @@ struct extension { const char *name; - uint32_t idx; + uint32_t index; int (*process)(struct client *client, uint32_t tag, struct message *m); }; -const struct extension *extension_find(uint32_t idx, const char *name); +const struct extension *extension_find(uint32_t index, const char *name); #endif /* PULSE_SERVER_EXTENSION_H */
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c
Changed
@@ -108,7 +108,7 @@ } message_put(d->reply, TAG_U32, DEVICE_TYPE_SINK, - TAG_U32, o->id, + TAG_U32, o->index, /* sink index */ TAG_U8, n_info, /* n_formats */ TAG_INVALID); for (i = 0; i < n_info; i++) { @@ -157,7 +157,7 @@ } spa_zero(sel); - sel.id = sink_index; + sel.index = sink_index; sel.type = pw_manager_object_is_sink; o = select_object(manager, &sel); @@ -173,7 +173,7 @@ return client_queue_message(client, data.reply); } -static int set_card_codecs(struct pw_manager_object *o, uint32_t id, +static int set_card_codecs(struct pw_manager_object *o, uint32_t port_index, uint32_t device_id, uint32_t n_codecs, uint32_t *codecs) { char buf[1024]; @@ -190,7 +190,7 @@ spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_ParamRoute, SPA_PARAM_Route); spa_pod_builder_add(&b, - SPA_PARAM_ROUTE_index, SPA_POD_Int(id), + SPA_PARAM_ROUTE_index, SPA_POD_Int(port_index), SPA_PARAM_ROUTE_device, SPA_POD_Int(device_id), 0); spa_pod_builder_prop(&b, SPA_PARAM_ROUTE_props, 0); @@ -279,7 +279,7 @@ return -ENOTSUP; spa_zero(sel); - sel.id = sink_index; + sel.index = sink_index; sel.type = pw_manager_object_is_sink; o = select_object(manager, &sel);
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/internal.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/internal.h
Changed
@@ -51,7 +51,7 @@ struct spa_fraction min_quantum; struct sample_spec sample_spec; struct channel_map channel_map; - uint32_t max_quantum; + uint32_t quantum_limit; }; struct stats {
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/manager.c
Changed
@@ -64,7 +64,7 @@ struct object_data { struct spa_list link; - const char *id; + const char *key; size_t size; }; @@ -163,7 +163,7 @@ } -static struct object *find_object(struct manager *m, uint32_t id) +static struct object *find_object_by_id(struct manager *m, uint32_t id) { struct object *o; spa_list_for_each(o, &m->this.object_list, this.link) { @@ -586,6 +586,7 @@ struct manager *m = data; struct object *o; const struct object_info *info; + const char *str; struct pw_proxy *proxy; info = find_info(type, version); @@ -603,10 +604,15 @@ pw_proxy_destroy(proxy); return; } + str = props ? spa_dict_lookup(props, PW_KEY_OBJECT_SERIAL) : NULL; + if (!spa_atou64(str, &o->this.serial, 0)) + o->this.serial = SPA_ID_INVALID; + o->this.id = id; o->this.permissions = permissions; o->this.type = info->type; o->this.version = version; + o->this.index = o->this.serial < (1ULL<<32) ? o->this.serial : SPA_ID_INVALID; o->this.props = props ? pw_properties_new_dict(props) : NULL; o->this.proxy = proxy; o->this.creating = true; @@ -638,7 +644,7 @@ struct manager *m = object; struct object *o; - if ((o = find_object(m, id)) == NULL) + if ((o = find_object_by_id(m, id)) == NULL) return; o->this.removing = true; @@ -757,7 +763,7 @@ char buf[1024]; char *value; - if ((s = find_object(m, subject)) == NULL) + if ((s = find_object_by_id(m, subject)) == NULL) return -ENOENT; if (!SPA_FLAG_IS_SET(s->this.permissions, PW_PERM_M)) return -EACCES; @@ -793,7 +799,7 @@ int res; spa_list_for_each(o, &m->this.object_list, this.link) { - if (o->this.creating) + if (o->this.creating || o->this.removing) continue; if ((res = callback(data, &o->this)) != 0) return res; @@ -820,22 +826,22 @@ free(m); } -static struct object_data *object_find_data(struct object *o, const char *id) +static struct object_data *object_find_data(struct object *o, const char *key) { struct object_data *d; spa_list_for_each(d, &o->data_list, link) { - if (spa_streq(d->id, id)) + if (spa_streq(d->key, key)) return d; } return NULL; } -void *pw_manager_object_add_data(struct pw_manager_object *obj, const char *id, size_t size) +void *pw_manager_object_add_data(struct pw_manager_object *obj, const char *key, size_t size) { struct object *o = SPA_CONTAINER_OF(obj, struct object, this); struct object_data *d; - d = object_find_data(o, id); + d = object_find_data(o, key); if (d != NULL) { if (d->size == size) goto done; @@ -844,7 +850,7 @@ } d = calloc(1, sizeof(struct object_data) + size); - d->id = id; + d->key = key; d->size = size; spa_list_append(&o->data_list, &d->link);
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/manager.h
Changed
@@ -75,10 +75,12 @@ struct pw_manager_object { struct spa_list link; /**< link in manager object_list */ + uint64_t serial; uint32_t id; uint32_t permissions; const char *type; uint32_t version; + uint32_t index; struct pw_properties *props; struct pw_proxy *proxy; char *message_object_path; @@ -111,8 +113,8 @@ int (*callback) (void *data, struct pw_manager_object *object), void *data); -void *pw_manager_object_add_data(struct pw_manager_object *o, const char *id, size_t size); -void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *id); +void *pw_manager_object_add_data(struct pw_manager_object *o, const char *key, size_t size); +void *pw_manager_object_get_data(struct pw_manager_object *obj, const char *key); bool pw_manager_object_is_client(struct pw_manager_object *o); bool pw_manager_object_is_module(struct pw_manager_object *o);
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/message-handler.c
Changed
@@ -122,7 +122,7 @@ { const char *str; - if (o->id == 0) { + if (o->id == PW_ID_CORE) { free(o->message_object_path); o->message_object_path = strdup("/core"); o->message_handler = core_object_message_handler;
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
@@ -42,7 +42,7 @@ #include "log.h" #include "module.h" -static void on_module_unload(void *obj, void *data, int res, uint32_t id) +static void on_module_unload(void *obj, void *data, int res, uint32_t index) { struct module *module = obj; module_unload(NULL, module); @@ -83,7 +83,7 @@ int module_load(struct client *client, struct module *module) { - pw_log_info("load module id:%u name:%s", module->idx, module->name); + pw_log_info("load module index:%u name:%s", module->index, module->name); if (module->methods->load == NULL) return -ENOTSUP; /* subscription event is sent when the module does a @@ -97,8 +97,8 @@ module_emit_destroy(module); - if (module->idx != SPA_ID_INVALID) - pw_map_remove(&impl->modules, module->idx & INDEX_MASK); + if (module->index != SPA_ID_INVALID) + pw_map_remove(&impl->modules, module->index & MODULE_INDEX_MASK); spa_hook_list_clean(&module->listener_list); pw_work_queue_cancel(impl->work_queue, module, SPA_ID_INVALID); @@ -118,7 +118,7 @@ /* Note that client can be NULL (when the module is being unloaded * internally and not by a client request */ - pw_log_info("unload module id:%u name:%s", module->idx, module->name); + pw_log_info("unload module index:%u name:%s", module->index, module->name); if (module->methods->unload) res = module->methods->unload(client, module); @@ -127,7 +127,7 @@ broadcast_subscribe_event(impl, SUBSCRIPTION_MASK_MODULE, SUBSCRIPTION_EVENT_REMOVE | SUBSCRIPTION_EVENT_MODULE, - module->idx); + module->index); module_free(module); @@ -270,6 +270,7 @@ #endif { "module-roc-sink", create_module_roc_sink, }, { "module-roc-source", create_module_roc_source, }, + { "module-x11-bell", create_module_x11_bell, }, }; static const struct module_info *find_module_info(const char *name) @@ -299,13 +300,13 @@ if (module == NULL) return NULL; - module->idx = pw_map_insert_new(&impl->modules, module); - if (module->idx == SPA_ID_INVALID) { + module->index = pw_map_insert_new(&impl->modules, module); + if (module->index == SPA_ID_INVALID) { module_unload(client, module); return NULL; } module->name = strdup(name); module->args = args ? strdup(args) : NULL; - module->idx |= MODULE_FLAG; + module->index |= MODULE_FLAG; return module; }
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.h
Changed
@@ -57,7 +57,7 @@ }; struct module { - uint32_t idx; + uint32_t index; const char *name; const char *args; struct pw_properties *props;
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
@@ -262,11 +262,11 @@ props = pw_properties_new(NULL, NULL); pw_properties_setf(props, PW_KEY_NODE_NAME, - "combine_output.sink-%u.%s", data->module->idx, sink_name); + "combine_output.sink-%u.%s", data->module->index, sink_name); pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, data->sink_name); pw_properties_set(props, PW_KEY_NODE_TARGET, sink_name); - pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->idx); - pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->idx); + pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index); + pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index); pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); pw_properties_set(props, PW_KEY_NODE_PASSIVE, "true"); @@ -351,8 +351,8 @@ pw_properties_set(props, PW_KEY_NODE_NAME, data->sink_name); pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, data->sink_name); pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->idx); - pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->idx); + pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index); + pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index); pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); if ((str = pw_properties_get(module->props, "sink_properties")) != NULL)
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
@@ -73,8 +73,8 @@ if ((label = pw_properties_get(module->props, "label")) == NULL) return -EINVAL; - pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->idx); - pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->idx); + pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index); + pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -84,11 +84,24 @@ fprintf(f, " type = ladspa "); fprintf(f, " plugin = \"%s\" ", plugin); fprintf(f, " label = \"%s\" ", label); + if ((str = pw_properties_get(module->props, "control")) != NULL) { + size_t len; + const char *s, *state = NULL; + int count = 0; + + fprintf(f, " control = {"); + while ((s = pw_split_walk(str, ", ", &len, &state))) { + fprintf(f, " \"%d\" = %.*s", count, (int)len, s); + count++; + } + fprintf(f, " }"); + } + fprintf(f, " } ]"); if ((str = pw_properties_get(module->props, "inputs")) != NULL) fprintf(f, " inputs = [ %s ] ", str); if ((str = pw_properties_get(module->props, "outputs")) != NULL) fprintf(f, " outputs = [ %s ] ", str); - fprintf(f, " } ] }"); + fprintf(f, " }"); fprintf(f, " capture.props = {"); pw_properties_serialize_dict(f, &data->capture_props->dict, 0); fprintf(f, " } playback.props = {"); @@ -190,7 +203,7 @@ module_args_add_props(props, argument); if ((str = pw_properties_get(props, "sink_name")) != NULL) { - pw_properties_set(props, PW_KEY_NODE_NAME, str); + pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "sink_name", NULL); } if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
@@ -73,8 +73,8 @@ if ((label = pw_properties_get(module->props, "label")) == NULL) return -EINVAL; - pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->idx); - pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->idx); + pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index); + pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -84,11 +84,24 @@ fprintf(f, " type = ladspa "); fprintf(f, " plugin = \"%s\" ", plugin); fprintf(f, " label = \"%s\" ", label); + if ((str = pw_properties_get(module->props, "control")) != NULL) { + size_t len; + const char *s, *state = NULL; + int count = 0; + + fprintf(f, " control = {"); + while ((s = pw_split_walk(str, ", ", &len, &state))) { + fprintf(f, " \"%d\" = %.*s", count, (int)len, s); + count++; + } + fprintf(f, " }"); + } + fprintf(f, " } ]"); if ((str = pw_properties_get(module->props, "inputs")) != NULL) fprintf(f, " inputs = [ %s ] ", str); if ((str = pw_properties_get(module->props, "outputs")) != NULL) fprintf(f, " outputs = [ %s ] ", str); - fprintf(f, " } ] }"); + fprintf(f, " }"); fprintf(f, " capture.props = {"); pw_properties_serialize_dict(f, &data->capture_props->dict, 0); fprintf(f, " } playback.props = {"); @@ -190,8 +203,7 @@ module_args_add_props(props, argument); if ((str = pw_properties_get(props, "source_name")) != NULL) { - pw_properties_set(props, PW_KEY_NODE_NAME, str); - pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); + pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "source_name", NULL); } if ((str = pw_properties_get(props, "source_properties")) != NULL) {
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
@@ -70,8 +70,8 @@ char *args; size_t size, i; - pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->idx); - pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->idx); + pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); + pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{");
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
@@ -67,8 +67,8 @@ char *args; size_t size; - pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->idx); - pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->idx); + pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index); + pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -169,7 +169,7 @@ module_args_add_props(props, argument); if ((str = pw_properties_get(props, "sink_name")) != NULL) { - pw_properties_set(props, PW_KEY_NODE_NAME, str); + pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "sink_name", NULL); } if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
@@ -67,8 +67,8 @@ char *args; size_t size; - pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->idx); - pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->idx); + pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index); + pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -169,7 +169,7 @@ module_args_add_props(props, argument); if ((str = pw_properties_get(props, "source_name")) != NULL) { - pw_properties_set(props, PW_KEY_NODE_NAME, str); + pw_properties_set(playback_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "source_name", NULL); } if ((str = pw_properties_get(props, "source_properties")) != NULL) {
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c
Added
@@ -0,0 +1,145 @@ +/* PipeWire + * + * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> + * + * 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 <pipewire/pipewire.h> + +#include "../module.h" + +#define NAME "x11-bell" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct module_x11_bell_data { + struct module *module; + + struct pw_impl_module *mod; + struct spa_hook mod_listener; +}; + +static void module_destroy(void *data) +{ + struct module_x11_bell_data *d = data; + spa_hook_remove(&d->mod_listener); + d->mod = NULL; + module_schedule_unload(d->module); +} + +static const struct pw_impl_module_events module_events = { + PW_VERSION_IMPL_MODULE_EVENTS, + .destroy = module_destroy +}; + +static int module_x11_bell_load(struct client *client, struct module *module) +{ + struct module_x11_bell_data *data = module->user_data; + FILE *f; + char *args; + const char *str; + size_t size; + + f = open_memstream(&args, &size); + fprintf(f, "{"); + if ((str = pw_properties_get(module->props, "sink")) != NULL) + fprintf(f, " sink.name = \"%s\"", str); + if ((str = pw_properties_get(module->props, "sample")) != NULL) + fprintf(f, " sample.name = \"%s\"", str); + if ((str = pw_properties_get(module->props, "display")) != NULL) + fprintf(f, " x11.display = \"%s\"", str); + if ((str = pw_properties_get(module->props, "xauthority")) != NULL) + fprintf(f, " x11.xauthority = \"%s\"", str); + fprintf(f, " }"); + fclose(f); + + data->mod = pw_context_load_module(module->impl->context, + "libpipewire-module-x11-bell", + args, NULL); + free(args); + + if (data->mod == NULL) + return -errno; + + pw_impl_module_add_listener(data->mod, + &data->mod_listener, + &module_events, data); + return 0; +} + +static int module_x11_bell_unload(struct client *client, struct module *module) +{ + struct module_x11_bell_data *d = module->user_data; + + if (d->mod) { + spa_hook_remove(&d->mod_listener); + pw_impl_module_destroy(d->mod); + d->mod = NULL; + } + return 0; +} + +static const struct module_methods module_x11_bell_methods = { + VERSION_MODULE_METHODS, + .load = module_x11_bell_load, + .unload = module_x11_bell_unload, +}; + +static const struct spa_dict_item module_x11_bell_info[] = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "X11 bell interceptor" }, + { PW_KEY_MODULE_USAGE, "sink=<sink to connect to> " + "sample=<the sample to play> " + "display=<X11 display> " + "xauthority=<X11 Authority>" }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +struct module *create_module_x11_bell(struct impl *impl, const char *argument) +{ + struct module *module; + struct pw_properties *props = NULL; + int res; + + PW_LOG_TOPIC_INIT(mod_topic); + + props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_x11_bell_info)); + if (props == NULL) { + res = -EINVAL; + goto out; + } + if (argument) + module_args_add_props(props, argument); + + module = module_new(impl, &module_x11_bell_methods, sizeof(struct module_x11_bell_data)); + if (module == NULL) { + res = -errno; + goto out; + } + module->props = props; + + return module; +out: + pw_properties_free(props); + errno = -res; + return NULL; +}
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/modules/registry.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/registry.h
Changed
@@ -48,5 +48,6 @@ struct module *create_module_zeroconf_publish(struct impl *impl, const char *argument); struct module *create_module_roc_sink(struct impl *impl, const char *argument); struct module *create_module_roc_source(struct impl *impl, const char *argument); +struct module *create_module_x11_bell(struct impl *impl, const char *argument); #endif
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -97,12 +97,12 @@ unsigned int initialized:1; }; -static struct sample *find_sample(struct impl *impl, uint32_t idx, const char *name) +static struct sample *find_sample(struct impl *impl, uint32_t index, const char *name) { union pw_map_item *item; - if (idx != SPA_ID_INVALID) - return pw_map_lookup(&impl->samples, idx); + if (index != SPA_ID_INVALID) + return pw_map_lookup(&impl->samples, index); pw_array_for_each(item, &impl->samples.items) { struct sample *s = item->data; @@ -113,13 +113,13 @@ return NULL; } -void broadcast_subscribe_event(struct impl *impl, uint32_t mask, uint32_t event, uint32_t id) +void broadcast_subscribe_event(struct impl *impl, uint32_t mask, uint32_t event, uint32_t index) { struct server *s; spa_list_for_each(s, &impl->servers, link) { struct client *c; spa_list_for_each(c, &s->clients, link) - client_queue_subscribe_event(c, mask, event, id); + client_queue_subscribe_event(c, mask, event, index); } } @@ -159,23 +159,25 @@ static int reply_set_client_name(struct client *client, uint32_t tag) { + struct pw_manager *manager = client->manager; struct message *reply; struct pw_client *c; - uint32_t id; + uint32_t id, index; c = pw_core_get_client(client->core); if (c == NULL) return -ENOENT; id = pw_proxy_get_bound_id((struct pw_proxy*)c); + index = id_to_index(manager, id); - pw_log_info("[%s] reply tag:%u id:%u", client->name, tag, id); + pw_log_info("[%s] reply tag:%u id:%u index:%u", client->name, tag, id, index); reply = reply_new(client, tag); if (client->version >= 13) { message_put(reply, - TAG_U32, id, /* client index */ + TAG_U32, index, /* client index */ TAG_INVALID); } return client_queue_message(client, reply); @@ -196,13 +198,13 @@ operation_complete(o); } -static struct stream *find_stream(struct client *client, uint32_t id) +static struct stream *find_stream(struct client *client, uint32_t index) { union pw_map_item *item; pw_array_for_each(item, &client->streams.items) { struct stream *s = item->data; if (!pw_map_item_is_free(item) && - s->id == id) + s->index == index) return s; } return NULL; @@ -211,17 +213,15 @@ static int send_object_event(struct client *client, struct pw_manager_object *o, uint32_t facility) { - uint32_t event = 0, mask = 0, res_id = o->id; + uint32_t event = 0, mask = 0, res_index = o->index; if (pw_manager_object_is_sink(o)) { client_queue_subscribe_event(client, SUBSCRIPTION_MASK_SINK, SUBSCRIPTION_EVENT_SINK | facility, - res_id); + res_index); } if (pw_manager_object_is_source_or_monitor(o)) { - if (!pw_manager_object_is_source(o)) - res_id |= MONITOR_FLAG; mask = SUBSCRIPTION_MASK_SOURCE; event = SUBSCRIPTION_EVENT_SOURCE; } @@ -251,12 +251,12 @@ client_queue_subscribe_event(client, mask, event | facility, - res_id); + res_index); return 0; } static struct pw_manager_object *find_device(struct client *client, - uint32_t id, const char *name, bool sink, bool *is_monitor); + uint32_t index, const char *name, bool sink, bool *is_monitor); static int64_t get_node_latency_offset(struct pw_manager_object *o) { @@ -276,6 +276,7 @@ static void send_latency_offset_subscribe_event(struct client *client, struct pw_manager_object *o) { + struct pw_manager *manager = client->manager; struct latency_offset_data *d; struct pw_node_info *info; const char *str; @@ -310,7 +311,7 @@ client_queue_subscribe_event(client, SUBSCRIPTION_MASK_CARD, SUBSCRIPTION_EVENT_CARD | SUBSCRIPTION_EVENT_CHANGE, - card_id); + id_to_index(manager, card_id)); } static void send_default_change_subscribe_event(struct client *client, bool sink, bool source) @@ -370,8 +371,8 @@ struct defs *defs = &s->impl->defs; frame_size = s->frame_size; - minreq = frac_to_bytes_round_up(defs->min_req, &s->ss); - max_latency = defs->max_quantum * frame_size; + minreq = frac_to_bytes_round_up(s->min_req, &s->ss); + max_latency = defs->quantum_limit * frame_size; if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH) attr->maxlength = MAXLENGTH; @@ -379,7 +380,7 @@ attr->maxlength = SPA_MAX(attr->maxlength, frame_size); if (attr->tlength == (uint32_t) -1) - attr->tlength = frac_to_bytes_round_up(defs->default_tlength, &s->ss); + attr->tlength = frac_to_bytes_round_up(s->default_tlength, &s->ss); if (attr->tlength > attr->maxlength) attr->tlength = attr->maxlength; attr->tlength -= attr->tlength % frame_size; @@ -387,7 +388,7 @@ attr->tlength = SPA_MAX(attr->tlength, minreq); if (attr->minreq == (uint32_t) -1) { - uint32_t process = frac_to_bytes_round_up(defs->default_req, &s->ss); + uint32_t process = frac_to_bytes_round_up(s->default_req, &s->ss); /* With low-latency, tlength/4 gives a decent default in all of traditional, * adjust latency and early request modes. */ uint32_t m = attr->tlength / 4; @@ -434,7 +435,6 @@ attr->prebuf = max_prebuf; attr->prebuf -= attr->prebuf % frame_size; - s->missing = attr->tlength; attr->fragsize = 0; pw_log_info("[%s] maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u %u", @@ -447,8 +447,9 @@ static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer) { struct client *client = stream->client; + struct pw_manager *manager = client->manager; struct message *reply; - uint32_t missing, peer_id; + uint32_t missing, peer_index; struct spa_dict_item items[5]; char latency[32]; char attr_maxlength[32]; @@ -458,7 +459,6 @@ const char *peer_name; struct spa_fraction lat; uint64_t lat_usec; - struct defs *defs = &stream->impl->defs; lat.denom = stream->ss.rate; lat.num = fix_playback_buffer_attr(stream, &stream->attr); @@ -467,9 +467,9 @@ if (stream->buffer == NULL) return -errno; - if (lat.num * defs->min_quantum.denom / lat.denom < defs->min_quantum.num) - lat.num = (defs->min_quantum.num * lat.denom + - (defs->min_quantum.denom -1)) / defs->min_quantum.denom; + if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num) + lat.num = (stream->min_quantum.num * lat.denom + + (stream->min_quantum.denom -1)) / stream->min_quantum.denom; lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); @@ -489,22 +489,23 @@ stream->in_prebuf = true;
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/quirks.c
Changed
@@ -30,23 +30,7 @@ #include "log.h" #include "quirks.h" - -#define QUOTE(...) #__VA_ARGS__ - -static const char quirks_rules[] = -"# List of quirks" -"#" -"# All key/value pairs need to match before the quirks are applied." -"#" -"# Possible quirks:" -"# force-s16-info forces sink and source info as S16 format" -"# remove-capture-dont-move removes the capture DONT_MOVE flag" -"#\n" -"[" -" { application.process.binary = teams, quirks = [ force-s16-info ] }," -" { application.process.binary = skypeforlinux, quirks = [ force-s16-info ] }," -" { application.process.binary = firefox, quirks = [ remove-capture-dont-move ] }," -"]"; +#include "internal.h" static uint64_t parse_quirks(const char *str) { @@ -62,72 +46,139 @@ return 0; } -static int match(const char *rules, struct spa_dict *dict, uint64_t *quirks) +static bool find_match(struct spa_json *arr, const struct spa_dict *props) { - struct spa_json rules_json = SPA_JSON_INIT(rules, strlen(rules)); - struct spa_json rules_arr, it[2]; - - if (spa_json_enter_array(&rules_json, &rules_arr) <= 0) - return -EINVAL; + struct spa_json it[1]; - while (spa_json_enter_object(&rules_arr, &it[0]) > 0) { - char key[256]; - int match = true; - uint64_t quirks_cur = 0; + while (spa_json_enter_object(arr, &it[0]) > 0) { + char key[256], val[1024]; + const char *str, *value; + int match = 0, fail = 0; + int len; while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { - char val[4096]; - const char *str, *value; - int len; bool success = false; - if (spa_streq(key, "quirks")) { - if (spa_json_enter_array(&it[0], &it[1]) > 0) { - while (spa_json_get_string(&it[1], val, sizeof(val)) > 0) - quirks_cur |= parse_quirks(val); - } - continue; - } if ((len = spa_json_next(&it[0], &value)) <= 0) break; + str = spa_dict_lookup(props, key); + if (spa_json_is_null(value, len)) { - value = NULL; + success = str == NULL; } else { if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) continue; value = val; + len = strlen(val); } - str = spa_dict_lookup(dict, key); - if (value == NULL) { - success = str == NULL; - } else if (str != NULL) { + if (str != NULL) { if (value[0] == '~') { - regex_t r; - if (regcomp(&r, value+1, REG_EXTENDED | REG_NOSUB) == 0) { - if (regexec(&r, str, 0, NULL, 0) == 0) + regex_t preg; + if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { + if (regexec(&preg, str, 0, NULL, 0) == 0) success = true; - regfree(&r); + regfree(&preg); } - } else if (spa_streq(str, value)) { + } else if (strncmp(str, value, len) == 0 && + strlen(str) == (size_t)len) { success = true; } } + if (success) { + match++; + pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value); + } + else + fail++; + } + if (match > 0 && fail == 0) + return true; + } + return false; +} - if (!success) { - match = false; - break; +static int pw_conf_match_rules(const char *rules, size_t size, const struct spa_dict *props, + int (*matched) (void *data, const char *action, const char *val, int len), + void *data) +{ + const char *val; + struct spa_json it[4], actions; + int count = 0; + + spa_json_init(&it[0], rules, size); + if (spa_json_enter_array(&it[0], &it[1]) < 0) + return 0; + + while (spa_json_enter_object(&it[1], &it[2]) > 0) { + char key[64]; + bool have_match = false, have_actions = false; + + while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) { + if (spa_streq(key, "matches")) { + if (spa_json_enter_array(&it[2], &it[3]) < 0) + break; + + have_match = find_match(&it[3], props); } - } - if (match) { - *quirks = quirks_cur; - return 1; + else if (spa_streq(key, "actions")) { + if (spa_json_enter_object(&it[2], &actions) > 0) + have_actions = true; + } + else if (spa_json_next(&it[2], &val) <= 0) + break; + } + if (!have_match || !have_actions) + continue; + + while (spa_json_get_string(&actions, key, sizeof(key)) > 0) { + int res, len; + pw_log_debug("action %s", key); + + if ((len = spa_json_next(&actions, &val)) <= 0) + break; + + if (spa_json_is_container(val, len)) + len = spa_json_container_len(&actions, val, len); + + if ((res = matched(data, key, val, len)) < 0) + return res; + + count += res; + } + } + return count; +} + +static int client_rule_matched(void *data, const char *action, const char *val, int len) +{ + struct client *client = data; + + if (spa_streq(action, "update-props")) { + pw_properties_update_string(client->props, val, len); + } else if (spa_streq(action, "quirks")) { + struct spa_json quirks = SPA_JSON_INIT(val, len), it[1]; + uint64_t quirks_cur = 0; + char v[128]; + + if (spa_json_enter_array(&quirks, &it[0]) > 0) { + while (spa_json_get_string(&it[0], v, sizeof(v)) > 0) + quirks_cur |= parse_quirks(v); } + client->quirks = quirks_cur; } return 0; } int client_update_quirks(struct client *client) { - return match(quirks_rules, &client->props->dict, &client->quirks); + struct impl *impl = client->impl; + struct pw_context *context = impl->context; + const char *rules; + + if ((rules = pw_context_get_conf_section(context, "pulse.rules")) == NULL) + return 0; +
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -167,7 +167,6 @@ index += diff; filled += diff; stream->write_index += diff; - stream->missing -= diff; if (filled < 0) { /* underrun, reported on reader side */ @@ -188,6 +187,8 @@ spa_ringbuffer_write_update(&stream->ring, index); stream->requested -= SPA_MIN(msg->length, stream->requested); + stream_send_request(stream); + finish: message_free(impl, msg, false, false); return res; @@ -378,7 +379,7 @@ goto error; } - if (server->n_clients >= MAX_CLIENTS) { + if (server->n_clients >= server->max_clients) { close(client_fd); errno = ECONNREFUSED; goto error; @@ -943,7 +944,7 @@ while ((len = spa_json_next(&it[1], &v)) > 0) { char addr_str[FORMATTED_SOCKET_ADDR_STRLEN] = { 0 }; char key[128], client_access[64] = { 0 }; - struct sockaddr_storage addr[2]; + struct sockaddr_storage addrs[2]; int i, max_clients = MAX_CLIENTS, listen_backlog = LISTEN_BACKLOG, n_addr; if (spa_json_is_object(v, len)) { @@ -966,7 +967,7 @@ spa_json_parse_stringn(v, len, addr_str, sizeof(addr_str)); } - n_addr = parse_address(addr_str, addr, 2); + n_addr = parse_address(addr_str, addrs, SPA_N_ELEMENTS(addrs)); if (n_addr < 0) { pw_log_warn("pulse-server %p: failed to parse address '%s': %s", impl, addr_str, spa_strerror(n_addr)); @@ -976,7 +977,9 @@ /* try to create sockets for each address in the list */ for (i = 0; i < n_addr; i++) { + const struct sockaddr_storage *addr = &addrs[i]; struct server * const server = server_new(impl); + if (server == NULL) { UPDATE_ERR(-errno); continue;
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
@@ -44,11 +44,25 @@ #include "reply.h" #include "stream.h" +static int parse_frac(struct pw_properties *props, const char *key, + const struct spa_fraction *def, struct spa_fraction *res) +{ + const char *str; + if (props == NULL || + (str = pw_properties_get(props, key)) == NULL || + sscanf(str, "%u/%u", &res->num, &res->denom) != 2 || + res->denom == 0) { + *res = *def; + } + return 0; +} + struct stream *stream_new(struct client *client, enum stream_type type, uint32_t create_tag, const struct sample_spec *ss, const struct channel_map *map, const struct buffer_attr *attr) { int res; + struct defs *defs = &client->impl->defs; struct stream *stream = calloc(1, sizeof(*stream)); if (stream == NULL) @@ -67,6 +81,13 @@ stream->attr = *attr; spa_ringbuffer_init(&stream->ring); + parse_frac(client->props, "pulse.min.req", &defs->min_req, &stream->min_req); + parse_frac(client->props, "pulse.min.frag", &defs->min_frag, &stream->min_frag); + parse_frac(client->props, "pulse.min.quantum", &defs->min_quantum, &stream->min_quantum); + parse_frac(client->props, "pulse.default.req", &defs->default_req, &stream->default_req); + parse_frac(client->props, "pulse.default.frag", &defs->default_frag, &stream->default_frag); + parse_frac(client->props, "pulse.default.tlength", &defs->default_tlength, &stream->default_tlength); + switch (type) { case STREAM_TYPE_RECORD: stream->direction = PW_DIRECTION_INPUT; @@ -136,9 +157,6 @@ stream->ring.writeindex = stream->ring.readindex; stream->write_index = stream->read_index; - stream->missing = stream->attr.tlength - - SPA_MIN(stream->requested, stream->attr.tlength); - if (stream->attr.prebuf > 0) stream->in_prebuf = true; @@ -153,13 +171,8 @@ } } -static bool stream_prebuf_active(struct stream *stream) +static bool stream_prebuf_active(struct stream *stream, int32_t avail) { - uint32_t index; - int32_t avail; - - avail = spa_ringbuffer_get_write_index(&stream->ring, &index); - if (stream->in_prebuf) { if (avail >= (int32_t) stream->attr.prebuf) stream->in_prebuf = false; @@ -172,30 +185,34 @@ uint32_t stream_pop_missing(struct stream *stream) { - uint32_t missing; + int64_t missing, avail; + + avail = stream->write_index - stream->read_index; + + missing = stream->attr.tlength; + missing -= stream->requested; + missing -= avail; - if (stream->missing <= 0) + if (missing <= 0) return 0; - if (stream->missing < stream->attr.minreq && !stream_prebuf_active(stream)) + if (missing < stream->attr.minreq && !stream_prebuf_active(stream, avail)) return 0; - missing = stream->missing; stream->requested += missing; - stream->missing = 0; return missing; } -int stream_send_underflow(struct stream *stream, int64_t offset, uint32_t underrun_for) +int stream_send_underflow(struct stream *stream, int64_t offset) { struct client *client = stream->client; struct impl *impl = client->impl; struct message *reply; if (ratelimit_test(&impl->rate_limit, stream->timestamp, SPA_LOG_LEVEL_INFO)) { - pw_log_info("[%s]: UNDERFLOW channel:%u offset:%" PRIi64 " underrun:%u", - client->name, stream->channel, offset, underrun_for); + pw_log_info("[%s]: UNDERFLOW channel:%u offset:%" PRIi64, + client->name, stream->channel, offset); } reply = message_alloc(impl, -1, 0); @@ -314,7 +331,6 @@ if (new_tlength <= old_tlength) return 0; - stream->missing += new_tlength - old_tlength; stream->attr.tlength = new_tlength; if (client->version >= 15) {
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
@@ -58,6 +58,7 @@ uint32_t create_tag; uint32_t channel; /* index in map */ uint32_t id; /* id of global */ + uint32_t index; /* index */ struct impl *impl; struct client *client; @@ -83,9 +84,15 @@ int64_t delay; uint32_t last_quantum; - int64_t missing; int64_t requested; + struct spa_fraction min_req; + struct spa_fraction default_req; + struct spa_fraction min_frag; + struct spa_fraction default_frag; + struct spa_fraction default_tlength; + struct spa_fraction min_quantum; + struct sample_spec ss; struct channel_map map; struct buffer_attr attr; @@ -116,7 +123,7 @@ void stream_flush(struct stream *stream); uint32_t stream_pop_missing(struct stream *stream); -int stream_send_underflow(struct stream *stream, int64_t offset, uint32_t underrun_for); +int stream_send_underflow(struct stream *stream, int64_t offset); int stream_send_overflow(struct stream *stream); int stream_send_killed(struct stream *stream); int stream_send_started(struct stream *stream);
View file
pipewire-0.3.43.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.44.tar.gz/src/modules/module-protocol-simple.c
Changed
@@ -111,7 +111,7 @@ struct spa_hook core_proxy_listener; struct spa_source *source; - char name[512]; + char name[128]; struct pw_stream *capture; struct spa_hook capture_listener; @@ -477,7 +477,7 @@ { struct server *server = data; struct impl *impl = server->impl; - struct sockaddr addr; + struct sockaddr_in addr; socklen_t addrlen; int client_fd, val; struct client *client = NULL; @@ -503,7 +503,7 @@ spa_list_append(&server->client_list, &client->link); server->n_clients++; - if (inet_ntop(addr.sa_family, addr.sa_data, client->name, sizeof(client->name)) == NULL) + if (inet_ntop(addr.sin_family, &addr.sin_addr.s_addr, client->name, sizeof(client->name)) == NULL) snprintf(client->name, sizeof(client->name), "client %d", client_fd); client->source = pw_loop_add_io(impl->loop,
View file
pipewire-0.3.43.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.44.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
@@ -203,9 +203,12 @@ if (res == 0) return -EPIPE; if (res < 0) { - if (res == EAGAIN) - return 0; - return -errno; + res = -errno; + if (res == -EINTR) + continue; + if (res != -EAGAIN && res != -EWOULDBLOCK) + return res; + return 0; } if (c == '\n') { client->line_buf[client->line_pos] = '\0'; @@ -435,9 +438,10 @@ true, on_source_io, client); if (client->source == NULL) { + res = -errno; pw_log_error("%p: source create failed: %m", client); close(fd); - return -errno; + return res; } client->connecting = true; free(client->session_id);
View file
pipewire-0.3.43.tar.gz/src/modules/module-roc-sink.c -> pipewire-0.3.44.tar.gz/src/modules/module-roc-sink.c
Changed
@@ -441,8 +441,6 @@ pw_properties_set(capture_props, PW_KEY_NODE_VIRTUAL, "true"); if (pw_properties_get(capture_props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(capture_props, PW_KEY_NODE_NETWORK, "true"); - if (pw_properties_get(capture_props, PW_KEY_NODE_PASSIVE) == NULL) - pw_properties_set(capture_props, PW_KEY_NODE_PASSIVE, "true"); if ((str = pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS)) == NULL) pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
View file
pipewire-0.3.43.tar.gz/src/modules/module-roc-source.c -> pipewire-0.3.44.tar.gz/src/modules/module-roc-source.c
Changed
@@ -486,8 +486,6 @@ pw_properties_set(playback_props, PW_KEY_NODE_VIRTUAL, "true"); if (pw_properties_get(playback_props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(playback_props, PW_KEY_NODE_NETWORK, "true"); - if (pw_properties_get(playback_props, PW_KEY_NODE_PASSIVE) == NULL) - pw_properties_set(playback_props, PW_KEY_NODE_PASSIVE, "true"); if ((str = pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS)) == NULL) pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source");
View file
pipewire-0.3.43.tar.gz/src/modules/module-rt.c -> pipewire-0.3.44.tar.gz/src/modules/module-rt.c
Changed
@@ -1,6 +1,6 @@ /* PipeWire * - * Copyright © 2021 Axis Communications AB + * 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"), @@ -22,76 +22,452 @@ * DEALINGS IN THE SOFTWARE. */ -#include <errno.h> -#include <sched.h> -#include <stdbool.h> #include <stdlib.h> -#include <unistd.h> -#include <sys/types.h> +#include <stdbool.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> #include <sys/stat.h> -#include <sys/syscall.h> -#include <sys/time.h> -#include <sys/resource.h> +#ifdef __FreeBSD__ +#include <sys/thr.h> +#endif +#include <fcntl.h> +#include <unistd.h> #include <pthread.h> +#include <sys/resource.h> -#include <spa/utils/dict.h> +#include "config.h" + +#include <spa/support/dbus.h> #include <spa/utils/result.h> +#include <spa/utils/string.h> #include <pipewire/impl.h> #include <pipewire/thread.h> -#include "config.h" - /** \page page_module_rt PipeWire Module: RT + * + * The `rt` module uses the operating system's scheduler to enable realtime + * scheduling for certain threads to assist with low latency audio processing. + * This requires `RLIMIT_RTPRIO` to be set to a value that's equal to this + * module's `rt.prio` parameter or higher. Most distros will come with some + * package that configures this for certain groups or users. If this is not set + * up and DBus is available, then this module will fall back to using RTKit. */ - #define NAME "rt" PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic -#define DEFAULT_POLICY SCHED_FIFO +#define REALTIME_POLICY SCHED_FIFO +#ifdef SCHED_RESET_ON_FORK +#define PW_SCHED_RESET_ON_FORK SCHED_RESET_ON_FORK +#else +/* FreeBSD compat */ +#define PW_SCHED_RESET_ON_FORK 0 +#endif -#define DEFAULT_NICE_LEVEL -11 -#define DEFAULT_RT_PRIO 88 -#define DEFAULT_RT_TIME_SOFT 2000000 -#define DEFAULT_RT_TIME_HARD 2000000 +#define IS_VALID_NICE_LEVEL(l) ((l)>=-20 && (l)<=19) -#define MODULE_USAGE \ - "[nice.level=<priority: default " SPA_STRINGIFY(DEFAULT_NICE_LEVEL) ">] " \ - "[rt.prio=<priority: default " SPA_STRINGIFY(DEFAULT_RT_PRIO) ">] " \ - "[rt.time.soft=<in usec: default " SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] " \ - "[rt.time.hard=<in usec: default " SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] " +#define DEFAULT_NICE_LEVEL 20 +#define DEFAULT_RT_PRIO 88 +#define DEFAULT_RT_TIME_SOFT -1 +#define DEFAULT_RT_TIME_HARD -1 -#ifndef RLIMIT_RTTIME -#define RLIMIT_RTTIME 15 -#endif +#define MODULE_USAGE "[nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL)"(don't change)>] " \ + "[rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO)">] " \ + "[rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"] " \ + "[rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"] " static const struct spa_dict_item module_props[] = { - { PW_KEY_MODULE_AUTHOR, "Jonas Holmberg <jonashg@axis.com>" }, - { PW_KEY_MODULE_DESCRIPTION, "Set thread priorities" }, + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "Use realtime thread scheduling, falling back to RTKit" }, { PW_KEY_MODULE_USAGE, MODULE_USAGE }, { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; +struct pw_rtkit_bus; + +struct thread { + struct impl *impl; + struct spa_list link; + pthread_t thread; + pid_t pid; + void *(*start)(void*); + void *arg; +}; + struct impl { struct pw_context *context; struct spa_thread_utils thread_utils; + int nice_level; int rt_prio; rlim_t rt_time_soft; rlim_t rt_time_hard; struct spa_hook module_listener; + + bool use_rtkit; + struct pw_rtkit_bus *system_bus; + + /* These are only for the RTKit implementation to fill in the `thread` + * struct. Since there's barely any overhead here we'll do this + * regardless of which backend is used. */ + pthread_mutex_t lock; + pthread_cond_t cond; + struct spa_list threads_list; }; +/*** + Copyright 2009 Lennart Poettering + Copyright 2010 David Henningsson <diwic@ubuntu.com> + + 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 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 <dbus/dbus.h> + +#include "config.h" + +#include <sys/syscall.h> + +#define RTKIT_SERVICE_NAME "org.freedesktop.RealtimeKit1" +#define RTKIT_OBJECT_PATH "/org/freedesktop/RealtimeKit1" + +#ifndef RLIMIT_RTTIME +#define RLIMIT_RTTIME 15 +#endif + +/** \cond */ +struct pw_rtkit_bus { + DBusConnection *bus; +}; +/** \endcond */ + +struct pw_rtkit_bus *pw_rtkit_bus_get_system(void) +{ + struct pw_rtkit_bus *bus; + DBusError error; + + if (getenv("DISABLE_RTKIT")) { + errno = ENOTSUP; + return NULL; + } + + dbus_error_init(&error); + + bus = calloc(1, sizeof(struct pw_rtkit_bus)); + if (bus == NULL) + return NULL; + + bus->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); + if (bus->bus == NULL)
View file
pipewire-0.3.44.tar.gz/src/modules/module-x11-bell.c
Added
@@ -0,0 +1,291 @@ +/* PipeWire + * + * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> + * + * 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 <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "config.h" + +#include <spa/utils/string.h> + +#include <X11/Xlib.h> +#include <X11/Xlib-xcb.h> +#include <X11/XKBlib.h> + +#include <canberra.h> + +#include "pipewire/pipewire.h" +#include "pipewire/impl.h" + +/** \page page_module_x11_bell PipeWire Module: X11 Bell + * + * The `x11-bell` module intercept the X11 bell events and uses libcanberra to + * play a sound. + * + * ## Module Options + * + * - `sink.name = <str>`: node.name of the sink to connect to + * - `sample.name = <str>`: the name of the sample to play, default 'bell-window-system' + * - `x11.display = <str>`: the X11 display to use + * - `x11.xauthority = <str>`: the X11 XAuthority string placed in XAUTHORITY env + * + * ## General options + * + * There are no general options for this module. + * + * ## Example configuration + *\code{.unparsed} + * context.modules = [ + * { name = libpipewire-x11-bell } + * args = { + * #sink.name = @DEFAULT_SINK@ + * sample.name = "bell-window-system" + * #x11.display = ":1" + * #x11.xauthority = "test" + * ] + *\endcode + * + */ + +#define NAME "x11-bell" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct impl { + struct pw_context *context; + struct pw_thread_loop *thread_loop; + struct pw_loop *loop; + struct spa_source *source; + + struct pw_properties *properties; + + struct spa_hook module_listener; + + Display *display; + int xkb_event_base; +}; + +static int play_sample(struct impl *impl, const char *sample) +{ + int res; + ca_context *ca; + + if ((res = ca_context_create(&ca)) < 0) { + pw_log_error("canberra context create error: %s", ca_strerror(res)); + res = -EIO; + goto exit; + } + if ((res = ca_context_open(ca)) < 0) { + pw_log_error("canberra context open error: %s", ca_strerror(res)); + res = -EIO; + goto exit_destroy; + } + if ((res = ca_context_play(ca, 0, + CA_PROP_EVENT_ID, sample, + CA_PROP_MEDIA_NAME, "X11 bell event", + CA_PROP_CANBERRA_CACHE_CONTROL, "permanent", + NULL)) < 0) { + pw_log_warn("can't play sample (%s): %s", sample, ca_strerror(res)); + } + +exit_destroy: + ca_context_destroy(ca); +exit: + return res; +} +static void display_io(void *data, int fd, uint32_t mask) +{ + struct impl *impl = data; + XEvent e; + const char *sample = NULL; + + while (XPending(impl->display)) { + XNextEvent(impl->display, &e); + + if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify) + continue; + + if (impl->properties) + sample = pw_properties_get(impl->properties, "sample.name"); + if (sample == NULL) + sample = "bell-window-system"; + + pw_log_debug("play sample %s", sample); + play_sample(impl, sample); + } +} + +static void x11_close(struct impl *impl) +{ + if (impl->source) { + pw_loop_destroy_source(impl->loop, impl->source); + impl->source = NULL; + } + if (impl->display) { + XCloseDisplay(impl->display); + impl->display = NULL; + } +} + +static int x11_connect(struct impl *impl, const char *name) +{ + int res, major, minor; + unsigned int auto_ctrls, auto_values; + + if (!(impl->display = XOpenDisplay(name))) { + pw_log_warn("XOpenDisplay() failed"); + res = -EIO; + goto error; + } + + impl->source = pw_loop_add_io(impl->loop, + ConnectionNumber(impl->display), + SPA_IO_IN, false, display_io, impl); + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbLibraryVersion(&major, &minor)) { + pw_log_warn("XkbLibraryVersion() failed"); + res = -EIO; + goto error; + } + + major = XkbMajorVersion; + minor = XkbMinorVersion; + + if (!XkbQueryExtension(impl->display, NULL, &impl->xkb_event_base, + NULL, &major, &minor)) { + res = -EIO; + pw_log_warn("XkbQueryExtension() failed"); + goto error; + } + + XkbSelectEvents(impl->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); + auto_ctrls = auto_values = XkbAudibleBellMask; + XkbSetAutoResetControls(impl->display, XkbAudibleBellMask, &auto_ctrls, &auto_values); + XkbChangeEnabledControls(impl->display, XkbUseCoreKbd, XkbAudibleBellMask, 0); + + res = 0; +error: + if (res < 0) + x11_close(impl);
View file
pipewire-0.3.43.tar.gz/src/modules/spa/spa-node.c -> pipewire-0.3.44.tar.gz/src/modules/spa/spa-node.c
Changed
@@ -242,6 +242,13 @@ int res; struct spa_handle *handle; void *iface; + const struct pw_properties *p; + + if (properties) { + p = pw_context_get_properties(context); + pw_properties_set(properties, "clock.quantum-limit", + pw_properties_get(p, "default.clock.quantum-limit")); + } handle = pw_context_load_spa_handle(context, factory_name,
View file
pipewire-0.3.43.tar.gz/src/pipewire/conf.c -> pipewire-0.3.44.tar.gz/src/pipewire/conf.c
Changed
@@ -49,7 +49,7 @@ PW_LOG_TOPIC_EXTERN(log_conf); #define PW_LOG_TOPIC_DEFAULT log_conf -static int make_path(char *path, int size, const char *paths[]) +static int make_path(char *path, size_t size, const char *paths[]) { int i, len; char *p = path; @@ -57,7 +57,7 @@ len = snprintf(p, size, "%s%s", i == 0 ? "" : "/", paths[i]); if (len < 0) return -errno; - if (len >= size) + if ((size_t)len >= size) return -ENOSPC; p += len; size -= len;
View file
pipewire-0.3.43.tar.gz/src/pipewire/context.c -> pipewire-0.3.44.tar.gz/src/pipewire/context.c
Changed
@@ -134,7 +134,8 @@ res = pw_thread_utils_drop_rt(thr); } else { pw_log_info("%p: exit freewheel", context); - res = pw_thread_utils_acquire_rt(thr, 88); + // Use the priority as configured within the realtime module + res = pw_thread_utils_acquire_rt(thr, -1); } if (res < 0) pw_log_info("%p: freewheel error:%s", context, spa_strerror(res)); @@ -893,24 +894,31 @@ return pw_impl_node_set_state(node, state); } -static int collect_nodes(struct pw_context *context, struct pw_impl_node *driver) +static int collect_nodes(struct pw_context *context, struct pw_impl_node *node) { struct spa_list queue; - struct pw_impl_node *n, *t; + struct pw_impl_node *n, *t, *driver; struct pw_impl_port *p; struct pw_impl_link *l; - spa_list_consume(t, &driver->follower_list, follower_link) { - spa_list_remove(&t->follower_link); - spa_list_init(&t->follower_link); - } + pw_log_debug("node %p: '%s'", node, node->name); - pw_log_debug("driver %p: '%s'", driver, driver->name); + if (node->driver) { + driver = node; + spa_list_consume(t, &driver->follower_list, follower_link) { + spa_list_remove(&t->follower_link); + spa_list_init(&t->follower_link); + } + } else { + driver = node->driver_node; + if (driver == NULL) + return -EINVAL; + } - /* start with driver in the queue */ + /* start with node in the queue */ spa_list_init(&queue); - spa_list_append(&queue, &driver->sort_link); - driver->visited = true; + spa_list_append(&queue, &node->sort_link); + node->visited = true; /* now follow all the links from the nodes in the queue * and add the peers to the queue. */ @@ -980,26 +988,32 @@ } static inline void get_quantums(struct pw_context *context, uint32_t *def, - uint32_t *min, uint32_t *max, uint32_t *rate) + uint32_t *min, uint32_t *max, uint32_t *limit, uint32_t *rate) { struct settings *s = &context->settings; - *def = s->clock_force_quantum == 0 ? s->clock_quantum : s->clock_force_quantum; - *min = s->clock_force_quantum == 0 ? s->clock_min_quantum : s->clock_force_quantum; - *max = s->clock_force_quantum == 0 ? s->clock_max_quantum : s->clock_force_quantum; - *rate = s->clock_force_quantum == 0 ? s->clock_rate : s->clock_force_rate; + if (s->clock_force_quantum != 0) { + *def = *min = *max = s->clock_force_quantum; + *rate = 0; + } else { + *def = s->clock_quantum; + *min = s->clock_min_quantum; + *max = s->clock_max_quantum; + *rate = s->clock_rate; + } + *limit = s->clock_quantum_limit; } static inline uint32_t *get_rates(struct pw_context *context, uint32_t *def, uint32_t *n_rates, - bool *force_rate) + bool *force) { struct settings *s = &context->settings; if (s->clock_force_rate != 0) { - *force_rate = true; + *force = true; *n_rates = 1; *def = s->clock_force_rate; return &s->clock_force_rate; } else { - *force_rate = false; + *force = false; *n_rates = s->n_clock_rates; *def = s->clock_rate; return s->clock_rates; @@ -1053,7 +1067,7 @@ { struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this); struct pw_impl_node *n, *s, *target, *fallback; - uint32_t max_quantum, min_quantum, def_quantum, rate_quantum; + uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum; uint32_t *rates, n_rates, def_rate; bool freewheel = false, force_rate; @@ -1067,7 +1081,7 @@ again: impl->recalc = true; - get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum); + get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum); rates = get_rates(context, &def_rate, &n_rates, &force_rate); /* start from all drivers and group all nodes that are linked @@ -1135,8 +1149,10 @@ pw_impl_node_set_driver(n, t); if (t == NULL) ensure_state(n, false); - else + else { t->passive = false; + collect_nodes(context, n); + } } n->visited = false; } @@ -1221,6 +1237,7 @@ if (rate_quantum != 0 && current_rate != rate_quantum) { def_quantum = def_quantum * current_rate / rate_quantum; min_quantum = min_quantum * current_rate / rate_quantum; + max_quantum = max_quantum * current_rate / rate_quantum; } /* calculate desired quantum */ @@ -1234,6 +1251,7 @@ if (latency.denom != 0) quantum = (latency.num * current_rate / latency.denom); quantum = SPA_CLAMP(quantum, min_quantum, max_quantum); + quantum = SPA_MIN(quantum, lim_quantum); if (context->settings.clock_power_of_two_quantum) quantum = flp2(quantum);
View file
pipewire-0.3.43.tar.gz/src/pipewire/filter.c -> pipewire-0.3.44.tar.gz/src/pipewire/filter.c
Changed
@@ -52,7 +52,6 @@ #define MASK_BUFFERS (MAX_BUFFERS-1) #define MAX_PORTS 1024 -static float empty[MAX_SAMPLES]; static bool mlock_warned = false; static uint32_t mappable_dataTypes = (1<<SPA_DATA_MemFd); @@ -1223,6 +1222,17 @@ } if ((str = getenv("PIPEWIRE_LATENCY")) != NULL) pw_properties_set(props, PW_KEY_NODE_LATENCY, str); + if ((str = getenv("PIPEWIRE_RATE")) != NULL) + pw_properties_set(props, PW_KEY_NODE_RATE, str); + if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) { + struct spa_fraction q; + if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) { + pw_properties_setf(props, PW_KEY_NODE_RATE, + "1/%u", q.denom); + pw_properties_setf(props, PW_KEY_NODE_LATENCY, + "%u/%u", q.num, q.denom); + } + } spa_hook_list_init(&impl->hooks); this->properties = props; @@ -1860,7 +1870,7 @@ struct spa_data *d; if ((buf = pw_filter_dequeue_buffer(port_data)) == NULL) - return empty; + return NULL; d = &buf->buffer->datas[0];
View file
pipewire-0.3.43.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-link.c
Changed
@@ -451,7 +451,7 @@ return res; } -static int select_io(struct pw_impl_link *this) +static void select_io(struct pw_impl_link *this) { struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); struct spa_io_buffers *io; @@ -461,13 +461,9 @@ io = this->rt.out_mix.io; if (io == NULL) io = &impl->io; - if (io == NULL) - return -EIO; this->io = io; *this->io = SPA_IO_BUFFERS_INIT; - - return 0; } static int do_allocation(struct pw_impl_link *this) @@ -1133,7 +1129,7 @@ if (check_permission(this->context, this->output, this->input, this->properties) < 0) { pw_impl_link_destroy(this); - } else { + } else if (this->global != NULL) { pw_global_update_permissions(this->global, client, old, new); } } @@ -1229,6 +1225,16 @@ spa_hook_list_init(&this->listener_list); impl->format_filter = format_filter; + this->info.format = NULL; + this->info.props = &this->properties->dict; + + this->rt.out_mix.peer_id = input->global->id; + this->rt.in_mix.peer_id = output->global->id; + + if ((res = pw_impl_port_init_mix(output, &this->rt.out_mix)) < 0) + goto error_output_mix; + if ((res = pw_impl_port_init_mix(input, &this->rt.in_mix)) < 0) + goto error_input_mix; pw_impl_port_add_listener(input, &impl->input_port_listener, &input_port_events, impl); pw_impl_node_add_listener(input_node, &impl->input_node_listener, &input_node_events, impl); @@ -1245,19 +1251,9 @@ spa_list_append(&output->links, &this->output_link); spa_list_append(&input->links, &this->input_link); - this->info.format = NULL; - this->info.props = &this->properties->dict; - impl->io = SPA_IO_BUFFERS_INIT; - this->rt.out_mix.peer_id = input->global->id; - this->rt.in_mix.peer_id = output->global->id; - - pw_impl_port_init_mix(output, &this->rt.out_mix); - pw_impl_port_init_mix(input, &this->rt.in_mix); - - if ((res = select_io(this)) < 0) - goto error_no_io; + select_io(this); if (this->feedback) { impl->inode = output_node; @@ -1317,8 +1313,12 @@ res = -errno; pw_log_debug("work queue failed: %m"); goto error_free; -error_no_io: - pw_log_debug("%p: can't set io %d (%s)", this, res, spa_strerror(res)); +error_output_mix: + pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res)); + goto error_free; +error_input_mix: + pw_log_error("%p: can't get input mix %d (%s)", this, res, spa_strerror(res)); + pw_impl_port_release_mix(output, &this->rt.out_mix); goto error_free; error_free: free(impl);
View file
pipewire-0.3.43.tar.gz/src/pipewire/impl-metadata.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-metadata.c
Changed
@@ -523,14 +523,15 @@ int pw_impl_metadata_register(struct pw_impl_metadata *metadata, struct pw_properties *properties) { + struct pw_context *context = metadata->context; static const char * const keys[] = { + PW_KEY_OBJECT_SERIAL, PW_KEY_MODULE_ID, + PW_KEY_FACTORY_ID, PW_KEY_METADATA_NAME, NULL }; - struct pw_context *context = metadata->context; - if (metadata->registered) goto error_existed;
View file
pipewire-0.3.43.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-module.c
Changed
@@ -171,6 +171,11 @@ const char *state = NULL, *p; size_t len; char path_part[PATH_MAX]; + static const char * const keys[] = { + PW_KEY_OBJECT_SERIAL, + PW_KEY_MODULE_NAME, + NULL + }; module_dir = getenv("PIPEWIRE_MODULE_DIR"); if (module_dir == NULL) { @@ -234,9 +239,7 @@ this->global = pw_global_new(context, PW_TYPE_INTERFACE_Module, PW_VERSION_MODULE, - pw_properties_new( - PW_KEY_MODULE_NAME, name, - NULL), + NULL, global_bind, this); @@ -251,6 +254,8 @@ pw_global_get_serial(this->global)); this->info.props = &this->properties->dict; + pw_global_update_keys(this->global, &this->properties->dict, keys); + pw_impl_module_emit_initialized(this); pw_global_add_listener(this->global, &this->global_listener, &global_events, this);
View file
pipewire-0.3.43.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-node.c
Changed
@@ -59,6 +59,7 @@ struct spa_list pending_list; unsigned int pause_on_idle:1; + unsigned int suspend_on_idle:1; unsigned int cache_params:1; unsigned int pending_play:1; }; @@ -387,6 +388,10 @@ spa_list_for_each(resource, &node->global->resource_list, link) pw_resource_error(resource, res, error); } + if (old == PW_NODE_STATE_RUNNING && + state == PW_NODE_STATE_IDLE && + impl->suspend_on_idle) + pw_impl_node_set_state(node, PW_NODE_STATE_SUSPENDED); } static int suspend_node(struct pw_impl_node *this) @@ -867,8 +872,9 @@ } impl->pause_on_idle = pw_properties_get_bool(node->properties, PW_KEY_NODE_PAUSE_ON_IDLE, true); + impl->suspend_on_idle = pw_properties_get_bool(node->properties, PW_KEY_NODE_SUSPEND_ON_IDLE, false); impl->cache_params = pw_properties_get_bool(node->properties, PW_KEY_NODE_CACHE_PARAMS, true); - node->transport_sync = pw_properties_get_bool(node->properties, "node.transport.sync", false); + node->transport_sync = pw_properties_get_bool(node->properties, PW_KEY_NODE_TRANSPORT_SYNC, false); driver = pw_properties_get_bool(node->properties, PW_KEY_NODE_DRIVER, false); if (node->driver != driver) { @@ -1654,6 +1660,16 @@ if (SPA_UNLIKELY(node->driver && !node->driving)) return 0; + if (!node->driver) { + struct timespec ts; + struct pw_node_activation *a = node->rt.activation; + struct spa_system *data_system = node->context->data_system; + + spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts); + a->status = PW_NODE_ACTIVATION_AWAKE; + a->signal_time = a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts); + } + if (status & SPA_STATUS_HAVE_DATA) { spa_list_for_each(p, &node->rt.output_mix, rt.node_link) spa_node_process(p->mix);
View file
pipewire-0.3.43.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.44.tar.gz/src/pipewire/impl-port.c
Changed
@@ -214,16 +214,16 @@ if (port_id == SPA_ID_INVALID) return -errno; + if ((res = spa_node_add_port(port->mix, port->direction, port_id, NULL)) < 0 && + res != -ENOTSUP) + goto error_remove_map; + mix->port.direction = port->direction; mix->port.port_id = port_id; - - spa_list_append(&port->mix_list, &mix->link); - port->n_mix++; mix->p = port; - spa_node_add_port(port->mix, port->direction, port_id, NULL); - - res = pw_impl_port_call_init_mix(port, mix); + if ((res = pw_impl_port_call_init_mix(port, mix)) < 0) + goto error_remove_port; /* set the same format on the mixer as on the port if any */ { @@ -242,11 +242,20 @@ } } + spa_list_append(&port->mix_list, &mix->link); + port->n_mix++; + pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port, port->n_mix, port->port_id, mix->port.port_id, mix->io, spa_strerror(res)); return res; + +error_remove_port: + spa_node_remove_port(port->mix, port->direction, port_id); +error_remove_map: + pw_map_remove(&port->mix_port_map, port_id); + return res; } SPA_EXPORT @@ -261,7 +270,9 @@ res = pw_impl_port_call_release_mix(port, mix); - spa_node_remove_port(port->mix, port->direction, port_id); + if ((res = spa_node_remove_port(port->mix, port->direction, port_id)) < 0 && + res != -ENOTSUP) + pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res)); pw_log_debug("%p: release mix %d %d.%d", port, port->n_mix, port->port_id, mix->port.port_id); @@ -583,8 +594,10 @@ int res; const char *fallback_lib, *factory_name; struct spa_handle *handle; - struct spa_dict_item items[1]; + struct spa_dict_item items[2]; + char quantum_limit[16]; void *iface; + struct pw_context *context = port->node->context; if ((res = spa_format_parse(param, &media_type, &media_subtype)) < 0) return res; @@ -634,7 +647,11 @@ } items[0] = SPA_DICT_ITEM_INIT(SPA_KEY_LIBRARY_NAME, fallback_lib); - handle = pw_context_load_spa_handle(port->node->context, factory_name, + spa_scnprintf(quantum_limit, sizeof(quantum_limit), "%u", + context->settings.clock_quantum_limit); + items[1] = SPA_DICT_ITEM_INIT("clock.quantum-limit", quantum_limit); + + handle = pw_context_load_spa_handle(context, factory_name, &SPA_DICT_INIT_ARRAY(items)); if (handle == NULL) return -errno; @@ -1070,10 +1087,12 @@ } if (port->direction == PW_DIRECTION_INPUT) { - pw_map_insert_at(&node->input_port_map, port->port_id, NULL); + if ((res = pw_map_insert_at(&node->input_port_map, port->port_id, NULL)) < 0) + pw_log_warn("%p: can't remove input port: %s", port, spa_strerror(res)); node->info.n_input_ports--; } else { - pw_map_insert_at(&node->output_port_map, port->port_id, NULL); + if ((res = pw_map_insert_at(&node->output_port_map, port->port_id, NULL)) < 0) + pw_log_warn("%p: can't remove output port: %s", port, spa_strerror(res)); node->info.n_output_ports--; }
View file
pipewire-0.3.43.tar.gz/src/pipewire/keys.h -> pipewire-0.3.44.tar.gz/src/pipewire/keys.h
Changed
@@ -171,7 +171,9 @@ #define PW_KEY_NODE_WANT_DRIVER "node.want-driver" /**< the node wants to be grouped with a driver * node in order to schedule the graph. */ #define PW_KEY_NODE_PAUSE_ON_IDLE "node.pause-on-idle" /**< pause the node when idle */ +#define PW_KEY_NODE_SUSPEND_ON_IDLE "node.suspend-on-idle" /**< suspend the node when idle */ #define PW_KEY_NODE_CACHE_PARAMS "node.cache-params" /**< cache the node params */ +#define PW_KEY_NODE_TRANSPORT_SYNC "node.transport.sync" /**< the node handles transport sync */ #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 */ @@ -326,6 +328,8 @@ #define PW_KEY_PRIORITY_MASTER "priority.master" /**< deprecated */ #endif /* PW_ENABLE_DEPRECATED */ +#define PW_KEY_TARGET_OBJECT "target.object" /**< a target object to link to */ + /** \} */
View file
pipewire-0.3.43.tar.gz/src/pipewire/private.h -> pipewire-0.3.44.tar.gz/src/pipewire/private.h
Changed
@@ -51,7 +51,7 @@ #define MAX_RATES 16u #define CLOCK_MIN_QUANTUM 4u -#define CLOCK_MAX_QUANTUM 8192u +#define CLOCK_MAX_QUANTUM 65536u struct settings { uint32_t log_level; @@ -61,12 +61,15 @@ uint32_t clock_quantum; /* default quantum */ uint32_t clock_min_quantum; /* min quantum */ uint32_t clock_max_quantum; /* max quantum */ + uint32_t clock_quantum_limit; /* quantum limit */ struct spa_rectangle video_size; struct spa_fraction video_rate; uint32_t link_max_buffers; unsigned int mem_warn_mlock:1; unsigned int mem_allow_mlock:1; unsigned int clock_power_of_two_quantum:1; + unsigned int check_quantum:1; + unsigned int check_rate:1; #define CLOCK_RATE_UPDATE_MODE_HARD 0 #define CLOCK_RATE_UPDATE_MODE_SOFT 1 int clock_rate_update_mode;
View file
pipewire-0.3.43.tar.gz/src/pipewire/settings.c -> pipewire-0.3.44.tar.gz/src/pipewire/settings.c
Changed
@@ -43,7 +43,8 @@ #define DEFAULT_CLOCK_RATE 48000u #define DEFAULT_CLOCK_QUANTUM 1024u #define DEFAULT_CLOCK_MIN_QUANTUM 32u -#define DEFAULT_CLOCK_MAX_QUANTUM 8192u +#define DEFAULT_CLOCK_MAX_QUANTUM 2048u +#define DEFAULT_CLOCK_QUANTUM_LIMIT 8192u #define DEFAULT_CLOCK_POWER_OF_TWO_QUANTUM true #define DEFAULT_VIDEO_WIDTH 640 #define DEFAULT_VIDEO_HEIGHT 480 @@ -52,6 +53,8 @@ #define DEFAULT_LINK_MAX_BUFFERS 64u #define DEFAULT_MEM_WARN_MLOCK false #define DEFAULT_MEM_ALLOW_MLOCK true +#define DEFAULT_CHECK_QUANTUM false +#define DEFAULT_CHECK_RATE false struct impl { struct pw_context *context; @@ -184,12 +187,23 @@ recalc = true; } else if (spa_streq(key, "clock.force-rate")) { v = value ? atoi(value) : 0; - s->clock_force_rate = v; - recalc = true; + if (v != 0 && s->check_rate && + !uint32_array_contains(s->clock_rates, s->n_clock_rates, v)) { + pw_log_info("invalid %s: %d not in allowed rates", key, v); + } else { + s->clock_force_rate = v; + recalc = true; + } } else if (spa_streq(key, "clock.force-quantum")) { v = value ? atoi(value) : 0; - s->clock_force_quantum = SPA_MIN(v, 8192u); - recalc = true; + if (v != 0 && s->check_quantum && + (v < s->clock_min_quantum || v > s->clock_max_quantum)) { + pw_log_info("invalid %s: %d not in (%d-%d)", key, v, + s->clock_min_quantum, s->clock_max_quantum); + } else { + s->clock_force_quantum = v; + recalc = true; + } } if (recalc) pw_context_recalc_graph(context, "settings changed"); @@ -213,6 +227,7 @@ d->clock_quantum = get_default_int(p, "default.clock.quantum", DEFAULT_CLOCK_QUANTUM); d->clock_min_quantum = get_default_int(p, "default.clock.min-quantum", DEFAULT_CLOCK_MIN_QUANTUM); d->clock_max_quantum = get_default_int(p, "default.clock.max-quantum", DEFAULT_CLOCK_MAX_QUANTUM); + d->clock_quantum_limit = get_default_int(p, "default.clock.quantum-limit", DEFAULT_CLOCK_QUANTUM_LIMIT); d->video_size.width = get_default_int(p, "default.video.width", DEFAULT_VIDEO_WIDTH); d->video_size.height = get_default_int(p, "default.video.height", DEFAULT_VIDEO_HEIGHT); d->video_rate.num = get_default_int(p, "default.video.rate.num", DEFAULT_VIDEO_RATE_NUM); @@ -225,8 +240,13 @@ d->mem_warn_mlock = get_default_bool(p, "mem.warn-mlock", DEFAULT_MEM_WARN_MLOCK); d->mem_allow_mlock = get_default_bool(p, "mem.allow-mlock", DEFAULT_MEM_ALLOW_MLOCK); - d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum, + d->check_quantum = get_default_bool(p, "settings.check-quantum", DEFAULT_CHECK_QUANTUM); + d->check_rate = get_default_bool(p, "settings.check-rate", DEFAULT_CHECK_RATE); + + d->clock_quantum_limit = SPA_CLAMP(d->clock_quantum_limit, CLOCK_MIN_QUANTUM, CLOCK_MAX_QUANTUM); + d->clock_max_quantum = SPA_CLAMP(d->clock_max_quantum, + CLOCK_MIN_QUANTUM, d->clock_quantum_limit); d->clock_min_quantum = SPA_CLAMP(d->clock_min_quantum, CLOCK_MIN_QUANTUM, d->clock_max_quantum); d->clock_quantum = SPA_CLAMP(d->clock_quantum,
View file
pipewire-0.3.43.tar.gz/src/pipewire/stream.c -> pipewire-0.3.44.tar.gz/src/pipewire/stream.c
Changed
@@ -1358,6 +1358,17 @@ } if ((str = getenv("PIPEWIRE_LATENCY")) != NULL) pw_properties_set(props, PW_KEY_NODE_LATENCY, str); + if ((str = getenv("PIPEWIRE_RATE")) != NULL) + pw_properties_set(props, PW_KEY_NODE_RATE, str); + if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) { + struct spa_fraction q; + if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) { + pw_properties_setf(props, PW_KEY_NODE_RATE, + "1/%u", q.denom); + pw_properties_setf(props, PW_KEY_NODE_LATENCY, + "%u/%u", q.num, q.denom); + } + } spa_hook_list_init(&impl->hooks); this->properties = props;
View file
pipewire-0.3.43.tar.gz/src/tests/meson.build -> pipewire-0.3.44.tar.gz/src/tests/meson.build
Changed
@@ -13,9 +13,9 @@ install : installed_tests_enabled, install_dir : installed_tests_execdir), env : [ - 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable(internal: 'plugindir')), - 'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'confdatadir')), - 'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable(internal: 'moduledir')), + 'SPA_PLUGIN_DIR=@0@'.format(spa_dep.get_variable('plugindir')), + 'PIPEWIRE_CONFIG_DIR=@0@'.format(pipewire_dep.get_variable('confdatadir')), + 'PIPEWIRE_MODULE_DIR=@0@'.format(pipewire_dep.get_variable('moduledir')), ]) if installed_tests_enabled
View file
pipewire-0.3.43.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.44.tar.gz/src/tools/pw-cat.c
Changed
@@ -1906,9 +1906,10 @@ spa_list_for_each(target, &data.targets, link) { if (target->type != TARGET_TYPE_SINK) continue; - printf("%s\t%"PRIu32": sink description=\"%s\" prio=%d\n", - target == target_default ? "*" : "", - target->id, target->desc, target->prio); + printf("%s\t%"PRIu32": %s description=\"%s\" prio=%d\n", + target == target_default ? "*" : "", + target->id, data.mode == mode_record ? "monitor" : "sink", + target->desc, target->prio); } spa_list_for_each(target, &data.targets, link) { if (target->type != TARGET_TYPE_STREAM)
View file
pipewire-0.3.43.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.44.tar.gz/src/tools/pw-cli.c
Changed
@@ -32,6 +32,7 @@ #include <alloca.h> #endif #include <getopt.h> +#include <fnmatch.h> #include <readline/readline.h> #include <readline/history.h> @@ -41,7 +42,7 @@ #include <spa/utils/string.h> #include <spa/debug/pod.h> #include <spa/utils/keys.h> -#include <spa/utils/json.h> +#include <spa/utils/json-pod.h> #include <spa/pod/builder.h> #include <pipewire/impl.h> @@ -53,6 +54,18 @@ static char prompt[64]; struct remote_data; +struct proxy_data; + +typedef void (*info_func_t) (struct proxy_data *pd); + +struct class { + const char *type; + uint32_t version; + const void *events; + pw_destroy_t destroy; + info_func_t info; + const char *name_key; +}; struct data { struct pw_main_loop *loop; @@ -73,6 +86,7 @@ uint32_t permissions; uint32_t version; char *type; + const struct class *class; struct pw_proxy *proxy; bool info_pending; struct pw_properties *properties; @@ -96,19 +110,15 @@ struct pw_map globals; }; -struct proxy_data; - -typedef void (*info_func_t) (struct proxy_data *pd); struct proxy_data { struct remote_data *rd; struct global *global; struct pw_proxy *proxy; - void *info; - info_func_t info_func; - pw_destroy_t destroy; - struct spa_hook proxy_listener; - struct spa_hook object_listener; + void *info; + const struct class *class; + struct spa_hook proxy_listener; + struct spa_hook object_listener; }; struct command { @@ -303,6 +313,29 @@ } } +static bool global_matches(struct global *g, const char *pattern) +{ + const char *str; + + if (g->properties == NULL) + return false; + + if (strstr(g->type, pattern) != NULL) + return true; + if ((str = pw_properties_get(g->properties, PW_KEY_OBJECT_PATH)) != NULL && + fnmatch(pattern, str, FNM_EXTMATCH) == 0) + return true; + if ((str = pw_properties_get(g->properties, PW_KEY_OBJECT_SERIAL)) != NULL && + spa_streq(pattern, str)) + return true; + if (g->class != NULL && g->class->name_key != NULL && + (str = pw_properties_get(g->properties, g->class->name_key)) != NULL && + fnmatch(pattern, str, FNM_EXTMATCH) == 0) + return true; + + return false; +} + static int print_global(void *obj, void *data) { struct global *global = obj; @@ -311,7 +344,7 @@ if (global == NULL) return 0; - if (filter && !strstr(global->type, filter)) + if (filter && !global_matches(global, filter)) return 0; fprintf(stdout, "\tid %d, type %s/%d\n", global->id, @@ -403,6 +436,24 @@ .global_remove = registry_event_global_remove, }; +static struct global *find_global(struct remote_data *rd, const char *pattern) +{ + uint32_t id; + union pw_map_item *item; + + if (spa_atou32(pattern, &id, 0)) + return pw_map_lookup(&rd->globals, id); + + pw_array_for_each(item, &rd->globals.items) { + struct global *g = item->data; + if (pw_map_item_is_free(item) || g == NULL) + continue; + if (global_matches(g, pattern)) + return g; + } + return NULL; +} + static void on_core_error(void *_data, uint32_t id, int seq, int res, const char *message) { struct remote_data *rd = _data; @@ -1106,14 +1157,14 @@ spa_hook_remove(&pd->proxy_listener); spa_hook_remove(&pd->object_listener); - if (pd->info == NULL) - return; - if (pd->global) pd->global->proxy = NULL; - if (pd->destroy) - pd->destroy(pd->info); + if (pd->info == NULL) + return; + + if (pd->class->destroy) + pd->class->destroy(pd->info); pd->info = NULL; } @@ -1130,88 +1181,150 @@ return true; } +static const struct class core_class = { + .type = PW_TYPE_INTERFACE_Core, + .version = PW_VERSION_CORE, + .events = &core_events, + .destroy = (pw_destroy_t) pw_core_info_free, + .info = info_core, + .name_key = PW_KEY_CORE_NAME, +}; +static const struct class module_class = { + .type = PW_TYPE_INTERFACE_Module, + .version = PW_VERSION_MODULE, + .events = &module_events, + .destroy = (pw_destroy_t) pw_module_info_free, + .info = info_module, + .name_key = PW_KEY_MODULE_NAME, +}; + +static const struct class factory_class = { + .type = PW_TYPE_INTERFACE_Factory, + .version = PW_VERSION_FACTORY, + .events = &factory_events, + .destroy = (pw_destroy_t) pw_factory_info_free, + .info = info_factory, + .name_key = PW_KEY_FACTORY_NAME, +}; + +static const struct class client_class = { + .type = PW_TYPE_INTERFACE_Client, + .version = PW_VERSION_CLIENT, + .events = &client_events, + .destroy = (pw_destroy_t) pw_client_info_free, + .info = info_client, + .name_key = PW_KEY_APP_NAME, +}; +static const struct class device_class = { + .type = PW_TYPE_INTERFACE_Device, + .version = PW_VERSION_DEVICE, + .events = &device_events, + .destroy = (pw_destroy_t) pw_device_info_free, + .info = info_device, + .name_key = PW_KEY_DEVICE_NAME, +}; +static const struct class node_class = { + .type = PW_TYPE_INTERFACE_Node,
View file
pipewire-0.3.43.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.44.tar.gz/src/tools/pw-dump.c
Changed
@@ -30,6 +30,7 @@ #include <getopt.h> #include <limits.h> #include <math.h> +#include <fnmatch.h> #include <spa/utils/result.h> #include <spa/utils/string.h> @@ -37,6 +38,7 @@ #include <spa/debug/types.h> #include <spa/utils/json.h> #include <spa/utils/ansi.h> +#include <spa/utils/string.h> #include <pipewire/pipewire.h> #include <pipewire/extensions/metadata.h> @@ -65,7 +67,7 @@ struct spa_list object_list; - uint32_t id; + const char *pattern; FILE *out; int level; @@ -93,6 +95,7 @@ const void *events; void (*destroy) (struct object *object); void (*dump) (struct object *object); + const char *name_key; }; struct object { @@ -552,6 +555,7 @@ .type = PW_TYPE_INTERFACE_Core, .version = PW_VERSION_CORE, .dump = core_dump, + .name_key = PW_KEY_CORE_NAME, }; /* client */ @@ -608,6 +612,7 @@ .events = &client_events, .destroy = client_destroy, .dump = client_dump, + .name_key = PW_KEY_APP_NAME, }; /* module */ @@ -667,6 +672,7 @@ .events = &module_events, .destroy = module_destroy, .dump = module_dump, + .name_key = PW_KEY_MODULE_NAME, }; /* factory */ @@ -726,6 +732,7 @@ .events = &factory_events, .destroy = factory_destroy, .dump = factory_dump, + .name_key = PW_KEY_FACTORY_NAME, }; /* device */ @@ -810,6 +817,7 @@ .events = &device_events, .destroy = device_destroy, .dump = device_dump, + .name_key = PW_KEY_DEVICE_NAME, }; /* node */ @@ -906,6 +914,7 @@ .events = &node_events, .destroy = node_destroy, .dump = node_dump, + .name_key = PW_KEY_NODE_NAME, }; /* port */ @@ -991,6 +1000,7 @@ .events = &port_events, .destroy = port_destroy, .dump = port_dump, + .name_key = PW_KEY_PORT_NAME, }; /* link */ @@ -1206,6 +1216,7 @@ .events = &metadata_events, .destroy = metadata_destroy, .dump = metadata_dump, + .name_key = PW_KEY_METADATA_NAME, }; static const struct class *classes[] = @@ -1331,6 +1342,32 @@ .global_remove = registry_event_global_remove, }; +static bool object_matches(struct object *o, const char *pattern) +{ + uint32_t id; + const char *str; + + if (spa_atou32(pattern, &id, 0) && o->id == id) + return true; + + if (o->props == NULL) + return false; + + if (strstr(o->type, pattern) != NULL) + return true; + if ((str = pw_properties_get(o->props, PW_KEY_OBJECT_PATH)) != NULL && + fnmatch(pattern, str, FNM_EXTMATCH) == 0) + return true; + if ((str = pw_properties_get(o->props, PW_KEY_OBJECT_SERIAL)) != NULL && + spa_streq(pattern, str)) + return true; + if (o->class != NULL && o->class->name_key != NULL && + (str = pw_properties_get(o->props, o->class->name_key)) != NULL && + fnmatch(pattern, str, FNM_EXTMATCH) == 0) + return true; + return false; +} + static void dump_objects(struct data *d) { static const struct flags_info fl[] = { @@ -1345,7 +1382,7 @@ d->state = STATE_FIRST; spa_list_for_each(o, &d->object_list, link) { - if (d->id != SPA_ID_INVALID && d->id != o->id) + if (d->pattern != NULL && !object_matches(o, d->pattern)) continue; if (o->changed == 0) continue; @@ -1493,10 +1530,8 @@ } } - data.id = SPA_ID_INVALID; - if (optind < argc) { - spa_atou32(argv[optind++], &data.id, 0); - } + if (optind < argc) + data.pattern = argv[optind++]; data.loop = pw_main_loop_new(NULL); if (data.loop == NULL) {
View file
pipewire-0.3.43.tar.gz/src/tools/pw-metadata.c -> pipewire-0.3.44.tar.gz/src/tools/pw-metadata.c
Changed
@@ -96,7 +96,8 @@ if (!spa_streq(type, PW_TYPE_INTERFACE_Metadata)) return; - if ((str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL && + if (props != NULL && + (str = spa_dict_lookup(props, PW_KEY_METADATA_NAME)) != NULL && !spa_streq(str, d->opt_name)) return;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.