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 23
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Mon Mar 13 12:30:13 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.66 + +------------------------------------------------------------------- Thu Jan 26 20:45:06 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.65
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.65 +Version: 0.3.66 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/libcamera-client.c
Deleted
@@ -1,247 +0,0 @@ -/* Spa libcamera client - * - * Copyright (C) 2020, Collabora Ltd. - * Author: Raghavendra Rao Sidlagatta <raghavendra.rao@collabora.com> - * - * libcamera-client.c - * - * 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 <errno.h> -#include <stddef.h> -#include <stdio.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <fcntl.h> - -#include <spa/support/log.h> -#include <spa/support/loop.h> -#include <spa/support/plugin.h> -#include <spa/utils/type.h> -#include <spa/utils/keys.h> -#include <spa/utils/names.h> -#include <spa/utils/string.h> -#include <spa/monitor/device.h> -#include <spa/monitor/utils.h> - -#include "libcamera.h" - -struct impl { - struct spa_handle handle; - struct spa_device device; - - struct spa_log *log; - struct spa_loop *main_loop; - - struct spa_hook_list hooks; - - uint64_t info_all; - struct spa_device_info info; - - struct spa_source source; -}; - -static int emit_object_info(struct impl *this, uint32_t id) -{ - struct spa_device_object_info info; - struct spa_dict_item items20; - uint32_t n_items = 0; - - info = SPA_DEVICE_OBJECT_INFO_INIT(); - - info.type = SPA_TYPE_INTERFACE_Device; - info.factory_name = SPA_NAME_API_LIBCAMERA_DEVICE; - info.change_mask = (SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS | - SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS); - info.flags = 0; - - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_ENUM_API,"libcamera-client"); - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "libcamera"); - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Video/Device"); - - info.props = &SPA_DICT_INIT(items, n_items); - spa_device_emit_object_info(&this->hooks, id, &info); - - return 1; -} - -static const struct spa_dict_item device_info_items = { - { SPA_KEY_DEVICE_API, "libcamera" }, - { SPA_KEY_DEVICE_NICK, "libcamera-client" }, - { SPA_KEY_API_UDEV_MATCH, "libcamera" }, -}; - - -static void emit_device_info(struct impl *this, bool full) -{ - uint64_t old = full ? this->info.change_mask : 0; - if (full) - this->info.change_mask = this->info_all; - if (this->info.change_mask) { - this->info.props = &SPA_DICT_INIT_ARRAY(device_info_items); - spa_device_emit_info(&this->hooks, &this->info); - this->info.change_mask = old; - } -} - -static void impl_hook_removed(struct spa_hook *hook) -{ - return; -} - -static int -impl_device_add_listener(void *object, struct spa_hook *listener, - const struct spa_device_events *events, void *data) -{ - struct impl *this = object; - struct spa_hook_list save; - - spa_return_val_if_fail(this != NULL, -EINVAL); - spa_return_val_if_fail(events != NULL, -EINVAL); - - spa_hook_list_isolate(&this->hooks, &save, listener, events, data); - - emit_device_info(this, true); - - emit_object_info(this, 0); - - spa_hook_list_join(&this->hooks, &save); - - listener->removed = impl_hook_removed; - listener->priv = this; - - return 0; -} - -static const struct spa_device_methods impl_device = { - SPA_VERSION_DEVICE_METHODS, - .add_listener = impl_device_add_listener, -}; - -static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface) -{ - struct impl *this; - - spa_return_val_if_fail(handle != NULL, -EINVAL); - spa_return_val_if_fail(interface != NULL, -EINVAL); - - this = (struct impl *) handle; - - if (spa_streq(type, SPA_TYPE_INTERFACE_Device)) - *interface = &this->device; - else - return -ENOENT; - - return 0; -} - -static int impl_clear(struct spa_handle *handle) -{ - struct impl *this = (struct impl *) handle; - - if(this->dev.camera) { - deleteLibCamera(this->dev.camera); - this->dev.camera = NULL; - } - return 0; -} - -static size_t -impl_get_size(const struct spa_handle_factory *factory, - const struct spa_dict *params) -{ - return sizeof(struct impl); -} - -static int -impl_init(const struct spa_handle_factory *factory, - struct spa_handle *handle, - const struct spa_dict *info, - const struct spa_support *support, - uint32_t n_support) -{ - struct impl *this; - - spa_return_val_if_fail(factory != NULL, -EINVAL); - spa_return_val_if_fail(handle != NULL, -EINVAL); - - handle->get_interface = impl_get_interface; - handle->clear = impl_clear; - - this = (struct impl *) handle; - - this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - libcamera_log_topic_init(this->log); - - this->main_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Loop); - - if (this->main_loop == NULL) { - spa_log_error(this->log, "a main-loop is needed"); - return -EINVAL; - }
View file
pipewire-0.3.65.tar.gz/.gitignore -> pipewire-0.3.66.tar.gz/.gitignore
Changed
@@ -15,6 +15,11 @@ subprojects/wireplumber subprojects/media-session subprojects/packagecache +subprojects/googletest* +subprojects/gtest.wrap +subprojects/libyaml.wrap +subprojects/libyaml +subprojects/libcamera # Created by https://www.gitignore.io/api/vim
View file
pipewire-0.3.65.tar.gz/.gitlab-ci.yml -> pipewire-0.3.66.tar.gz/.gitlab-ci.yml
Changed
@@ -25,7 +25,7 @@ .fedora: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2022-11-07.0' + FDO_DISTRIBUTION_TAG: '2023-01-18.0' FDO_DISTRIBUTION_VERSION: '35' FDO_DISTRIBUTION_PACKAGES: >- alsa-lib-devel @@ -46,6 +46,7 @@ jack-audio-connection-kit-devel libcanberra-devel libldac-devel + libmysofa-devel libsndfile-devel libusb-devel lilv-devel
View file
pipewire-0.3.65.tar.gz/NEWS -> pipewire-0.3.66.tar.gz/NEWS
Changed
@@ -1,3 +1,81 @@ +# PipeWire 0.3.66 (2023-02-16) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a regression in the pulseaudio module-combine-stream because the new + module-combine-stream was not installed. + - PipeWire can now generate a limits.d config file with our recommended + settings for priorities and memlock. + + +## PipeWire + - Avoid rate switches when the graph is idle. + - The rate selection algorithm was improved. This ensures minimal performance + and quality loss when resampling. + - The default min.quantum was set to 32 again after it got erronously changed + to (the too low) 16 in version 0.3.45. + - Fix compilation issues with rust bindings because of macros in defines. + Work around it for now. (#2952) + - Invalid file mappings are now refused (#2617 #2914 #3007) + - Modules, exec and objects can now be loaded depending on conditions. One + example is the X11-bell module that can now be disabled with a custom + property override. + - Filter now also supports _trigger_process() to drive the graph. + - TID is now added to the journald log. + - PipeWire generates and installs */etc/security/limits.d/25-pw-rlimits.conf* + that by default contains project's recommended settings. Creation of the + pipewire group is left to the distro or user ( `groupadd -r pipewire` ). + See the rlimits-* Meson options for controlling this behavior. + - Additionally there is now by default disabled Meson option that will + install */etc/security/limits.d/20-pw-defaults.conf* with the current Linux + default memlock value. Distros with only kernels >=5.16 or always using + systemd v251 or newer do not need this. But all other builds should set the + `-Dpam-defaults-install=true` Meson option to ensure that the memlock value + is always large enough. Thanks to Rickie Schroeder for pointing out that + the default Linux memlock value has been somewhat recently increased. + +## modules + - Install module-combine-stream. + - RTP source now has support for custom channel names. + - RTP source will now stop when inactive. + - There is now + - Filter-chain has a new mysofa based spacializer plugin. + - The RTP modules can now use direct clock timestamps to send and receive + packets. This makes it possible to synchronize sender and receiver with + a PTP clock, for example. + - Filter-chain now has an invert plugin to invert the polarity of a + signal. (#3008) + +## SPA + - There is now an option to set the channels used for probing Pro Audio + devices. This could unlock more samplerates for some devices when they are + probed with fewer channels. (#2990) + - Support was added for other clocks than the MONOTONIC clock in the + driver nodes. This can be used to synchronize the graph to a PTP clock, + for example. + - The ALSA source has some more headroom when rate matching to avoid + stuttering when following another driver. + - libcamera controls are now mapped to standard PipeWire property values. + - The channelmixer has seen some improvements. MONO and undefined channel + layouts are now upmixed and downmixed more correctly. (#3010) + +## Bluetooth + - Many BAP support fixes. + +## GStreamer + - The gstreamer elements now support buffer video metadata so that strides + are correctly handled. + - pipewiresrc will now error out correctly in more cases. (#2935) + +## JACK + - The frame to/from time functions are improved to also work with negative + time and frame offsets. + +Older versions: + + # PipeWire 0.3.65 (2023-01-26) This is a bugfix release that is API and ABI compatible with previous @@ -109,9 +187,6 @@ this. - pipewiresrc will now always be a live source unless told otherwise. -Older versions: - - # PipeWire 0.3.64 (2023-01-12) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.65.tar.gz/meson.build -> pipewire-0.3.66.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.65', + version : '0.3.66', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.59.0', default_options : 'warning_level=3', @@ -285,6 +285,9 @@ sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile')) summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain') cdata.set('HAVE_SNDFILE', sndfile_dep.found()) +libmysofa_dep = dependency('libmysofa', required : get_option('libmysofa')) +summary({'libmysofa': libmysofa_dep.found()}, bool_yn: true, section: 'filter-chain') +cdata.set('HAVE_LIBMYSOFA', libmysofa_dep.found()) pulseaudio_dep = dependency('libpulse', required : get_option('libpulse')) summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons') avahi_dep = dependency('avahi-client', required : get_option('avahi'))
View file
pipewire-0.3.65.tar.gz/meson_options.txt -> pipewire-0.3.66.tar.gz/meson_options.txt
Changed
@@ -213,6 +213,10 @@ description: 'Enable code that depends on libsndfile', type: 'feature', value: 'auto') +option('libmysofa', + description: 'Enable code that depends on libmysofa', + type: 'feature', + value: 'auto') option('libpulse', description: 'Enable code that depends on libpulse', type: 'feature', @@ -281,3 +285,36 @@ description: 'Enable ALSA Compress-Offload support', type: 'feature', value: 'disabled') +option('pam-defaults-install', + description: 'Install limits.d file modifying defaults for all PAM users. Only for old kernels/systemd!', + type: 'boolean', + value: 'false') +option('pam-memlock-default', + description : 'The default memlock value for any PAM user in kilobytes. Multiples of 64 recommended.', + type : 'integer', + min: 640, + value: 8192) +option('rlimits-install', + description: 'Install PAM limits.d file. Voids all following rlimits-* options, if false', + type: 'boolean', + value: 'true') +option('rlimits-match', + description : 'PAM match rule for the generated limits.d file. @<name> denotes matching a group.', + type : 'string', + value: '@pipewire') +option('rlimits-rtprio', + description : 'RR and FIFO scheduler priority permitted for realtime threads of the matching user(s)', + type : 'integer', + min: 11, + max: 99, + value: 95) +option('rlimits-memlock', + description : 'kB of memory each process of the user matched by the rule can lock. Can be unlimited .', + type : 'string', + value: '4194304') +option('rlimits-nice', + description : 'Not niceness permitted for non-realtime threads of the matching user(s)', + type : 'integer', + min: -20, + max: -1, + value: -19)
View file
pipewire-0.3.65.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.66.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -5784,15 +5784,18 @@ { struct client *c = (struct client *) client; struct spa_io_position *pos; - double df; spa_return_val_if_fail(c != NULL, -EINVAL); - if (SPA_UNLIKELY((pos = c->rt.position) == NULL)) + if (SPA_UNLIKELY((pos = c->rt.position) == NULL) || c->buffer_frames == 0) return 0; - df = (frames - pos->clock.position) * (double)SPA_NSEC_PER_SEC / c->sample_rate; - return (pos->clock.nsec + (int64_t)rint(df)) / SPA_NSEC_PER_USEC; + uint32_t nf = (uint32_t)pos->clock.position; + uint64_t w = pos->clock.nsec/SPA_NSEC_PER_USEC; + uint64_t nw = pos->clock.next_nsec/SPA_NSEC_PER_USEC; + int32_t df = frames - nf; + int64_t dp = nw - w; + return w + (int64_t)rint((double) df * (double) dp / c->buffer_frames); } SPA_EXPORT @@ -5800,15 +5803,18 @@ { struct client *c = (struct client *) client; struct spa_io_position *pos; - double du; spa_return_val_if_fail(c != NULL, -EINVAL); if (SPA_UNLIKELY((pos = c->rt.position) == NULL)) return 0; - du = (usecs - pos->clock.nsec/SPA_NSEC_PER_USEC) * (double)c->sample_rate / SPA_USEC_PER_SEC; - return pos->clock.position + (int32_t)rint(du); + uint32_t nf = (uint32_t)pos->clock.position; + uint64_t w = pos->clock.nsec/SPA_NSEC_PER_USEC; + uint64_t nw = pos->clock.next_nsec/SPA_NSEC_PER_USEC; + int64_t du = usecs - w; + int64_t dp = nw - w; + return nf + (int32_t)rint((double)du / (double)dp * c->buffer_frames); } SPA_EXPORT
View file
pipewire-0.3.65.tar.gz/po/oc.po -> pipewire-0.3.66.tar.gz/po/oc.po
Changed
@@ -1,4 +1,4 @@ -# French translation of pipewire. +# Occitan translation of pipewire. # Copyright (C) 2006-2008 Lennart Poettering # This file is distributed under the same license as the pipewire package. # Robert-André Mauchin <zebob.m@pengzone.org>, 2008. @@ -8,24 +8,25 @@ # Thomas Canniot <mrtom@fedoraproject.org>, 2009, 2012. # Cédric Valmary (Tot en Òc) <cvalmary@yahoo.fr>, 2015. # Cédric Valmary (totenoc.eu) <cvalmary@yahoo.fr>, 2016. +# Quentin PAGÈS, 2023. msgid "" msgstr "" "Project-Id-Version: pipewire trunk\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/" "issues/new\n" -"POT-Creation-Date: 2021-04-18 16:54+0800\n" -"PO-Revision-Date: 2016-10-12 22:20+0200\n" -"Last-Translator: Cédric Valmary (totenoc.eu) <cvalmary@yahoo.fr>\n" +"POT-Creation-Date: 2022-06-30 12:50+0200\n" +"PO-Revision-Date: 2023-02-11 00:11+0100\n" +"Last-Translator: Quentin PAGÈS\n" "Language-Team: Tot En Òc\n" "Language: oc\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n" -"X-Generator: Virtaal 0.7.1\n" +"X-Generator: Poedit 3.2.2\n" "X-Launchpad-Export-Date: 2016-10-12 20:12+0000\n" -#: src/daemon/pipewire.c:43 +#: src/daemon/pipewire.c:46 #, c-format msgid "" "%s options\n" @@ -33,40 +34,56 @@ " --version Show version\n" " -c, --config Load config (Default %s)\n" msgstr "" +"%s opcions\n" +" -h, --help Afichar aquesta ajuda\n" +" --version Afichar la version\n" +" -c, --config Cargar la conf. (Defaut %s)\n" -#: src/daemon/pipewire.desktop.in:4 -msgid "PipeWire Media System" -msgstr "" - -#: src/daemon/pipewire.desktop.in:5 -msgid "Start the PipeWire Media System" -msgstr "" +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180 +#, c-format +msgid "Tunnel to %s/%s" +msgstr "Tunèl cap a %s/%s" -#: src/examples/media-session/alsa-monitor.c:526 -#: spa/plugins/alsa/acp/compat.c:187 -msgid "Built-in Audio" -msgstr "Àudio integrat" +#: src/modules/module-fallback-sink.c:51 +msgid "Dummy Output" +msgstr "Sortida factícia" -#: src/examples/media-session/alsa-monitor.c:530 -#: spa/plugins/alsa/acp/compat.c:192 -msgid "Modem" -msgstr "Modèm" +#: src/modules/module-pulse-tunnel.c:662 +#, c-format +msgid "Tunnel for %s@%s" +msgstr "Tunèl per %s@%s" -#: src/examples/media-session/alsa-monitor.c:539 +#: src/modules/module-zeroconf-discover.c:332 msgid "Unknown device" -msgstr "" +msgstr "Periferic desconegut" + +#: src/modules/module-zeroconf-discover.c:344 +#, c-format +msgid "%s on %s@%s" +msgstr "%s sus %s@%s" -#: src/tools/pw-cat.c:991 +#: src/modules/module-zeroconf-discover.c:348 +#, c-format +msgid "%s on %s" +msgstr "%s sus %s" + +#: src/tools/pw-cat.c:784 #, c-format msgid "" -"%s options <file>\n" +"%s options <file>|-\n" " -h, --help Show this help\n" " --version Show version\n" " -v, --verbose Enable verbose operations\n" "\n" msgstr "" +"%s opcions <file>|-\n" +" -h, --help Afichar aquesta ajuda\n" +" --version Afichar la version\n" +" -v, --verbose Activar las operacions verbosas\n" +"\n" -#: src/tools/pw-cat.c:998 +#: src/tools/pw-cat.c:791 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -80,11 +97,11 @@ " or direct samples (256)\n" " the rate is the one of the source " "file\n" -" --list-targets List available targets for --target\n" +" -P --properties Set node properties\n" "\n" msgstr "" -#: src/tools/pw-cat.c:1016 +#: src/tools/pw-cat.c:809 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -104,15 +121,21 @@ "\n" msgstr "" -#: src/tools/pw-cat.c:1033 +#: src/tools/pw-cat.c:826 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" " -m, --midi Midi mode\n" +" -d, --dsd DSD mode\n" "\n" msgstr "" +" -p, --playback Mòde lectura\n" +" -r, --record Mòde enregistrament\n" +" -m, --midi Mòde Midi\n" +" -d, --dsd Mòde DSD\n" +"\n" -#: src/tools/pw-cli.c:2932 +#: src/tools/pw-cli.c:2250 #, c-format msgid "" "%s options command\n" @@ -122,360 +145,353 @@ " -r, --remote Remote daemon name\n" "\n" msgstr "" +"%s opcions comanda\n" +" -h, --help Afichar aquesta ajuda\n" +" --version Afichar la version\n" +" -d, --daemon Aviar coma demòni (Per defaut " +"false)\n" +" -r, --remote Remote daemon name\n" +"\n" -#: spa/plugins/alsa/acp/acp.c:290 +#: spa/plugins/alsa/acp/acp.c:321 msgid "Pro Audio" msgstr "" -#: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704 -#: spa/plugins/bluez5/bluez5-device.c:1000 +#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1236 msgid "Off" msgstr "Atudat" -#: spa/plugins/alsa/acp/channelmap.h:466 -msgid "(invalid)" -msgstr "(invalid)" - -#: spa/plugins/alsa/acp/alsa-mixer.c:2709 +#: spa/plugins/alsa/acp/alsa-mixer.c:2652 msgid "Input" msgstr "Entrada" -#: spa/plugins/alsa/acp/alsa-mixer.c:2710 +#: spa/plugins/alsa/acp/alsa-mixer.c:2653 msgid "Docking Station Input" msgstr "Entrada de l'estacion d'acuèlh" -#: spa/plugins/alsa/acp/alsa-mixer.c:2711 +#: spa/plugins/alsa/acp/alsa-mixer.c:2654 msgid "Docking Station Microphone" msgstr "Microfòn de l'estacion d'acuèlh" -#: spa/plugins/alsa/acp/alsa-mixer.c:2712 +#: spa/plugins/alsa/acp/alsa-mixer.c:2655 msgid "Docking Station Line In" msgstr "Entrada linha de l'estacion d'acuèlh"
View file
pipewire-0.3.65.tar.gz/po/uk.po -> pipewire-0.3.66.tar.gz/po/uk.po
Changed
@@ -1,14 +1,14 @@ # Copyright (C) 2009 Free Software Foundation, Inc. # This file is distributed under the same license as the pipewire package. # -# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021, 2022. +# Yuri Chornoivan <yurchor@ukr.net>, 2009-2021, 2022, 2023. msgid "" msgstr "" "Project-Id-Version: pipewire\n" -"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issue" -"s\n" -"POT-Creation-Date: 2022-05-20 15:26+0000\n" -"PO-Revision-Date: 2022-06-18 13:07+0300\n" +"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issu" +"es\n" +"POT-Creation-Date: 2023-02-06 15:27+0000\n" +"PO-Revision-Date: 2023-02-11 17:42+0200\n" "Last-Translator: Yuri Chornoivan <yurchor@ukr.net>\n" "Language-Team: Ukrainian <trans-uk@lists.fedoraproject.org>\n" "Language: uk\n" @@ -41,8 +41,8 @@ msgid "Start the PipeWire Media System" msgstr "Запустити мультимедійну систему PipeWire" -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:183 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:183 +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:179 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:179 #, c-format msgid "Tunnel to %s/%s" msgstr "Тунель до %s/%s" @@ -51,33 +51,27 @@ msgid "Dummy Output" msgstr "Фіктивний вихід" -#: src/modules/module-pulse-tunnel.c:639 +#: src/modules/module-pulse-tunnel.c:695 #, c-format msgid "Tunnel for %s@%s" msgstr "Тунель для %s@%s" -#: src/modules/module-zeroconf-discover.c:332 +#: src/modules/module-zeroconf-discover.c:335 msgid "Unknown device" msgstr "Невідомий пристрій" -#: src/modules/module-zeroconf-discover.c:344 +#: src/modules/module-zeroconf-discover.c:347 #, c-format msgid "%s on %s@%s" msgstr "%s на %s@%s" -#: src/modules/module-zeroconf-discover.c:348 +#: src/modules/module-zeroconf-discover.c:351 #, c-format msgid "%s on %s" msgstr "%s на %s" -#: src/tools/pw-cat.c:872 +#: src/tools/pw-cat.c:940 #, c-format -#| msgid "" -#| "%s options <file>\n" -#| " -h, --help Show this help\n" -#| " --version Show version\n" -#| " -v, --verbose Enable verbose operations\n" -#| "\n" msgid "" "%s options <file>|-\n" " -h, --help Show this help\n" @@ -92,7 +86,7 @@ "інформації\n" "\n" -#: src/tools/pw-cat.c:879 +#: src/tools/pw-cat.c:947 #, c-format #| msgid "" #| " -R, --remote Remote daemon name\n" @@ -106,13 +100,15 @@ #| " or direct samples (256)\n" #| " the rate is the one of the " #| "source file\n" +#| " -P --properties Set node properties\n" #| "\n" msgid "" " -R, --remote Remote daemon name\n" " --media-type Set media type (default %s)\n" " --media-category Set media category (default %s)\n" " --media-role Set media role (default %s)\n" -" --target Set node target (default %s)\n" +" --target Set node target serial or name " +"(default %s)\n" " 0 means don't link\n" " --latency Set node latency (default %s)\n" " Xunit (unit = s, ms, us, ns)\n" @@ -129,7 +125,8 @@ "(типово, %s)\n" " --media-role встановити роль мультимедіа (типово, " "%s)\n" -" --target встановити ціль вузла (типово, %s)\n" +" --target встановити назву або серійний номер" +" цілі вузла (типово, %s)\n" " 0 — не пов'язувати\n" " --latency встановити затримку вузла (типово, " "%s)\n" @@ -140,7 +137,7 @@ " -P --properties встановити властивості вузла\n" "\n" -#: src/tools/pw-cat.c:897 +#: src/tools/pw-cat.c:965 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -176,28 +173,44 @@ "(типово, %d)\n" "\n" -#: src/tools/pw-cat.c:914 +#: src/tools/pw-cat.c:982 +#| msgid "" +#| " -p, --playback Playback mode\n" +#| " -r, --record Recording mode\n" +#| " -m, --midi Midi mode\n" +#| " -d, --dsd DSD mode\n" +#| "\n" msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" " -m, --midi Midi mode\n" " -d, --dsd DSD mode\n" +" -o, --encoded\t\t\t Encoded mode\n" "\n" msgstr "" " -p, --playback режим відтворення\n" " -r, --record режим запису\n" " -m, --midi режим MIDI\n" " -d, --dsd режим DSD\n" +" -o, --encoded\t\t\t закодований режим\n" "\n" -#: src/tools/pw-cli.c:3139 +#: src/tools/pw-cli.c:2236 #, c-format +#| msgid "" +#| "%s options command\n" +#| " -h, --help Show this help\n" +#| " --version Show version\n" +#| " -d, --daemon Start as daemon (Default false)\n" +#| " -r, --remote Remote daemon name\n" +#| "\n" msgid "" "%s options command\n" " -h, --help Show this help\n" " --version Show version\n" " -d, --daemon Start as daemon (Default false)\n" " -r, --remote Remote daemon name\n" +" -m, --monitor Monitor activity\n" "\n" msgstr "" "%s параметри команда\n" @@ -206,14 +219,15 @@ " -d, --daemon запустити як фонову службу (типово, " "false)\n" " -r, --remote назва віддаленої фонової служби\n" +" -m, --monitor спостерігати за діями\n" "\n" -#: spa/plugins/alsa/acp/acp.c:321 +#: spa/plugins/alsa/acp/acp.c:323 msgid "Pro Audio" msgstr "Професійний звук" -#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1161 +#: spa/plugins/alsa/acp/acp.c:447 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1303 msgid "Off" msgstr "Вимкнено" @@ -240,7 +254,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1330 +#: spa/plugins/bluez5/bluez5-device.c:1536 msgid "Microphone" msgstr "Мікрофон" @@ -306,7 +320,7 @@ msgstr "Без підсилення" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1335 +#: spa/plugins/bluez5/bluez5-device.c:1542 msgid "Speaker" msgstr "Динамік" @@ -421,7 +435,7 @@
View file
pipewire-0.3.65.tar.gz/spa/include/spa/param/port-config.h -> pipewire-0.3.66.tar.gz/spa/include/spa/param/port-config.h
Changed
@@ -48,7 +48,7 @@ /** properties for SPA_TYPE_OBJECT_ParamPortConfig */ enum spa_param_port_config { SPA_PARAM_PORT_CONFIG_START, - SPA_PARAM_PORT_CONFIG_direction, /**< direction, input/output (Id enum spa_direction) */ + SPA_PARAM_PORT_CONFIG_direction, /**< (Id enum spa_direction) direction */ SPA_PARAM_PORT_CONFIG_mode, /**< (Id enum spa_param_port_config_mode) mode */ SPA_PARAM_PORT_CONFIG_monitor, /**< (Bool) enable monitor output ports on input ports */ SPA_PARAM_PORT_CONFIG_control, /**< (Bool) enable control ports */
View file
pipewire-0.3.65.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.66.tar.gz/spa/include/spa/utils/defs.h
Changed
@@ -142,7 +142,7 @@ for ((ptr) = arr; (void*)(ptr) < SPA_PTROFF(arr, sizeof(arr), void); (ptr)++) #define SPA_FOR_EACH_ELEMENT_VAR(arr, var) \ - for (__typeof__((arr)0)* (var) = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++) + for (__typeof__((arr)0)* var = arr; (void*)(var) < SPA_PTROFF(arr, sizeof(arr), void); (var)++) #define SPA_ABS(a) \ ({ \
View file
pipewire-0.3.65.tar.gz/spa/meson.build -> pipewire-0.3.66.tar.gz/spa/meson.build
Changed
@@ -41,14 +41,23 @@ # plugin-specific dependencies alsa_dep = dependency('alsa', required: get_option('alsa')) summary({'ALSA': alsa_dep.found()}, bool_yn: true, section: 'Backend') + bluez_dep = dependency('bluez', version : '>= 4.101', required: get_option('bluez5')) gio_dep = dependency('gio-2.0', required : get_option('bluez5')) gio_unix_dep = dependency('gio-unix-2.0', required : get_option('bluez5')) - bluez_deps_found = bluez_dep.found() and gio_dep.found() and gio_unix_dep.found() + bluez_glib2_dep = dependency('glib-2.0', required : get_option('bluez5')) + sbc_dep = dependency('sbc', required: get_option('bluez5')) + summary({'SBC': sbc_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') + bluez5_deps = mathlib, dbus_dep, sbc_dep, bluez_dep, bluez_glib2_dep, gio_dep, gio_unix_dep + bluez_deps_found = get_option('bluez5').allowed() + foreach dep: bluez5_deps + if get_option('bluez5').enabled() and not dep.found() + error('bluez5 enabled, but dependency not found: ' + dep.name()) + endif + bluez_deps_found = bluez_deps_found and dep.found() + endforeach summary({'Bluetooth audio': bluez_deps_found}, bool_yn: true, section: 'Backend') if bluez_deps_found - sbc_dep = dependency('sbc', required: get_option('bluez5')) - summary({'SBC': sbc_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') ldac_dep = dependency('ldacBT-enc', required : get_option('bluez5-codec-ldac')) summary({'LDAC': ldac_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') ldac_abr_dep = dependency('ldacBT-abr', required : get_option('bluez5-codec-ldac'))
View file
pipewire-0.3.65.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -315,7 +315,7 @@ ss.format = PA_SAMPLE_S32LE; ss.rate = impl->rate; - ss.channels = 64; + ss.channels = impl->pro_channels; ap = pa_xnew0(pa_alsa_profile, 1); ap->profile_set = ps; @@ -1564,6 +1564,7 @@ impl->auto_port = true; impl->ignore_dB = false; impl->rate = DEFAULT_RATE; + impl->pro_channels = 64; if (props) { if ((s = acp_dict_lookup(props, "api.alsa.use-ucm")) != NULL) @@ -1582,6 +1583,8 @@ impl->auto_port = spa_atob(s); if ((s = acp_dict_lookup(props, "api.acp.probe-rate")) != NULL) impl->rate = atoi(s); + if ((s = acp_dict_lookup(props, "api.acp.pro-channels")) != NULL) + impl->pro_channels = atoi(s); } impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE;
View file
pipewire-0.3.65.tar.gz/spa/plugins/alsa/acp/card.h -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/acp/card.h
Changed
@@ -48,6 +48,7 @@ bool auto_port; bool ignore_dB; uint32_t rate; + uint32_t pro_channels; pa_alsa_ucm_config ucm; pa_alsa_profile_set *profile_set;
View file
pipewire-0.3.65.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.66.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -1879,6 +1879,8 @@ } else { *delay = avail; *target = SPA_MAX(*target, state->read_size); + if (state->matching) + *target += 32; } *target = SPA_CLAMP(*target, state->min_delay, state->buffer_frames); return 0;
View file
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
@@ -142,18 +142,67 @@ #define MATRIX_DOLBY 1 #define MATRIX_DPLII 2 -#define _CH(ch) ((SPA_AUDIO_CHANNEL_ ## ch)-3) +#define _SH 2 +#define _CH(ch) ((SPA_AUDIO_CHANNEL_ ## ch)-_SH) #define _MASK(ch) (1ULL << _CH(ch)) #define FRONT (_MASK(FC)) #define STEREO (_MASK(FL)|_MASK(FR)) #define REAR (_MASK(RL)|_MASK(RR)) #define SIDE (_MASK(SL)|_MASK(SR)) +static uint32_t mask_to_ch(struct channelmix *mix, uint64_t mask) +{ + uint32_t ch = 0; + while (mask > 1) { + ch++; + mask >>= 1; + } + return ch; +} + +static void distribute_mix(struct channelmix *mix, + float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + uint64_t mask) +{ + uint32_t i, ch = mask_to_ch(mix, mask); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + matrixich= 1.0f; +} +static void average_mix(struct channelmix *mix, + float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + uint64_t mask) +{ + uint32_t i, ch = mask_to_ch(mix, mask); + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + matrixchi= 1.0f; +} +static void pair_mix(float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS) +{ + uint32_t i; + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + matrixii= 1.0f; +} +static bool match_mix(struct channelmix *mix, + float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + uint64_t src_mask, uint64_t dst_mask) +{ + bool matched = false; + uint32_t i; + for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + if ((src_mask & dst_mask & (1ULL << i))) { + spa_log_info(mix->log, "matched channel %u (%f)", i, 1.0f); + matrixii = 1.0f; + matched = true; + } + } + return matched; +} + static int make_matrix(struct channelmix *mix) { float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS = {{ 0.0f }}; - uint64_t src_mask = mix->src_mask; - uint64_t dst_mask = mix->dst_mask; + uint64_t src_mask = mix->src_mask, src_paired; + uint64_t dst_mask = mix->dst_mask, dst_paired; uint32_t src_chan = mix->src_chan; uint32_t dst_chan = mix->dst_chan; uint64_t unassigned, keep; @@ -162,89 +211,110 @@ float slev = SQRT1_2; float llev = 0.5f; float maxsum = 0.0f; - bool filter_fc = false, filter_lfe = false; + bool filter_fc = false, filter_lfe = false, matched = false, normalize; #define _MATRIX(s,d) matrix_CH(s)_CH(d) + normalize = SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_NORMALIZE); + 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. */ - if ((src_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0) { - if (src_chan == 1) - src_mask = 0; - else - src_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC); - } - if ((dst_mask & (1Ull << SPA_AUDIO_CHANNEL_MONO)) != 0) - dst_mask |= (1ULL << SPA_AUDIO_CHANNEL_FC); + /* shift so that bit 0 is MONO */ + src_mask >>= _SH; + dst_mask >>= _SH; - /* shift so that bit 0 is FL */ - src_mask >>= 3; - dst_mask >>= 3; + if (src_chan > 1 && (src_mask & _MASK(MONO))) + src_mask = 0; + if (dst_chan > 1 && (dst_mask & _MASK(MONO))) + dst_mask = 0; - /* unknown channels or just 1 channel */ + src_paired = src_mask; + dst_paired = dst_mask; + + /* unknown channels */ if (src_mask == 0 || dst_mask == 0) { if (src_chan == 1) { - /* one FC/MONO src goes everywhere */ - spa_log_debug(mix->log, "distribute FC/MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) - matrixi0= 1.0f; + /* one src channel goes everywhere */ + spa_log_info(mix->log, "distribute UNK (%f) %"PRIu64, 1.0f, src_mask); + distribute_mix(mix, matrix, src_mask); } else if (dst_chan == 1) { - /* one FC/MONO dst get average of everything */ - spa_log_debug(mix->log, "average FC/MONO (%f)", 1.0f / src_chan); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) - matrix0i= 1.0f / src_chan; + /* one dst channel get average of everything */ + spa_log_info(mix->log, "average UNK (%f) %"PRIu64, 1.0f / src_chan, dst_mask); + average_mix(mix, matrix, dst_mask); + normalize = true; } else { /* just pair channels */ - spa_log_debug(mix->log, "pairing channels (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) - matrixii= 1.0f; + spa_log_info(mix->log, "pairing UNK channels (%f)", 1.0f); + if (src_mask == 0) + src_paired = dst_mask; + else if (dst_mask == 0) + dst_paired = src_mask; + pair_mix(matrix); } - if (dst_mask & FRONT) - filter_fc = true; - if (dst_mask & _MASK(LFE)) - filter_lfe = true; - src_mask = dst_mask = ~0LU; goto done; } else { spa_log_debug(mix->log, "matching channels"); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { - if ((src_mask & dst_mask & (1ULL << i))) { - spa_log_debug(mix->log, "matched channel %u (%f)", i, 1.0f); - matrixii= 1.0f; - } - } + matched = match_mix(mix, matrix, src_mask, dst_mask); } unassigned = src_mask & ~dst_mask; keep = dst_mask & ~src_mask; if (!SPA_FLAG_IS_SET(mix->options, CHANNELMIX_OPTION_UPMIX)) { + /* upmix completely disabled */ keep = 0; } else { + /* some upmixing (FC and LFE) enabled. */ if (mix->upmix == CHANNELMIX_UPMIX_NONE) keep = 0; - keep |= FRONT; + if (mix->fc_cutoff > 0.0f) + keep |= FRONT; + else + keep &= ~FRONT; if (mix->lfe_cutoff > 0.0f) keep |= _MASK(LFE); else keep &= ~_MASK(LFE); } + /* if we have no channel matched, try to upmix or keep the stereo + * pair or else we might end up with silence. */ + if (dst_mask & STEREO && !matched) + keep |= STEREO; + + spa_log_info(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep); + + if (unassigned & _MASK(MONO)) { + if ((dst_mask & STEREO) == STEREO) { + spa_log_info(mix->log, "assign MONO to STEREO (%f)", 1.0f); + _MATRIX(FL,MONO) += 1.0f; + _MATRIX(FR,MONO) += 1.0f; + keep &= ~STEREO; + } else if ((dst_mask & FRONT) == FRONT) { + spa_log_info(mix->log, "assign MONO to FRONT (%f)", 1.0f); + _MATRIX(FC,MONO) += 1.0f; + normalize = true; + } else { + spa_log_warn(mix->log, "can't assign MONO"); + } + }
View file
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/test-audioconvert.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/test-audioconvert.c
Changed
@@ -38,6 +38,7 @@ #include <spa/node/node.h> #include <spa/node/io.h> #include <spa/debug/mem.h> +#include <spa/debug/log.h> #include <spa/support/log-impl.h> SPA_LOG_IMPL(logger); @@ -682,8 +683,10 @@ res = memcmp(b->datasj.data, out_data->datak, out_data->size); if (res != 0) { fprintf(stderr, "error port %d plane %d\n", i, j); - spa_debug_mem(0, b->datasj.data, out_data->size); - spa_debug_mem(0, out_data->datak, out_data->size); + spa_debug_log_mem(&logger.log, SPA_LOG_LEVEL_WARN, + 0, b->datasj.data, out_data->size); + spa_debug_log_mem(&logger.log, SPA_LOG_LEVEL_WARN, + 2, out_data->datak, out_data->size); } spa_assert_se(res == 0);
View file
pipewire-0.3.65.tar.gz/spa/plugins/audioconvert/test-channelmix.c -> pipewire-0.3.66.tar.gz/spa/plugins/audioconvert/test-channelmix.c
Changed
@@ -72,6 +72,8 @@ mix.src_mask = src_mask; mix.dst_mask = dst_mask; mix.log = &logger.log; + mix.fc_cutoff = 120.0f; + mix.lfe_cutoff = 12000.0f; spa_assert_se(channelmix_init(&mix) == 0); channelmix_set_volume(&mix, 1.0f, false, 0, NULL); @@ -83,11 +85,17 @@ test_mix(1, _M(MONO), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 1.0)); test_mix(1, _M(MONO), 3, _M(FL)|_M(FR)|_M(LFE), 0, + MATRIX(1.0, 1.0, 0.0)); + test_mix(1, _M(MONO), 3, _M(FL)|_M(FR)|_M(LFE), CHANNELMIX_OPTION_UPMIX, MATRIX(1.0, 1.0, 1.0)); test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 0, + MATRIX(1.0, 1.0, 0.0, 0.0)); + test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), CHANNELMIX_OPTION_UPMIX, MATRIX(1.0, 1.0, 1.0, 1.0)); test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 0, - MATRIX(1.0, 1.0, 1.0, 1.0)); + MATRIX(1.0, 1.0, 0.0, 0.0)); + test_mix(1, _M(MONO), 4, _M(FL)|_M(FR)|_M(RL)|_M(RR), CHANNELMIX_OPTION_UPMIX, + MATRIX(1.0, 1.0, 0.0, 0.0)); test_mix(1, _M(MONO), 12, 0, 0, MATRIX(1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0)); @@ -119,16 +127,49 @@ test_mix(1, _M(FC), 1, _M(FC), 0, MATRIX(1.0)); test_mix(2, _M(FL)|_M(FR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107)); + MATRIX(0.5, 0.5)); test_mix(12, 0, 1, _M(MONO), 0, MATRIX(0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.083333, 0.0833333)); } +static void test_2_N(void) +{ + test_mix(2, _M(FL)|_M(FR), 1, _M(MONO), 0, MATRIX(0.5, 0.5)); + test_mix(2, _M(FL)|_M(FR), 1, 0, 0, MATRIX(0.5, 0.5)); + test_mix(2, _M(FL)|_M(FR), 2, 0, 0, MATRIX(1.0, 0.0, 0.0, 1.0)); + test_mix(2, _M(FL)|_M(FR), 2, _M(MONO), 0, MATRIX(1.0, 0.0, 0.0, 1.0)); + test_mix(2, _M(FL)|_M(FR), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.0, 1.0)); + test_mix(2, _M(FL)|_M(FR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 0, + MATRIX(1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0, + 0.0, 0.0)); + test_mix(2, _M(FL)|_M(FR), 4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), CHANNELMIX_OPTION_UPMIX, + MATRIX(1.0, 0.0, + 0.0, 1.0, + 0.707107, 0.707107, + 0.5, 0.5)); + test_mix(2, _M(FL)|_M(FR), 6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 0, + MATRIX(1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0, + 0.0, 0.0, + 0.0, 0.0, + 0.0, 0.0)); + test_mix(2, _M(FL)|_M(FR), 6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), CHANNELMIX_OPTION_UPMIX, + MATRIX(1.0, 0.0, + 0.0, 1.0, + 0.707107, 0.707107, + 0.5, 0.5, + 0.0, 0.0, + 0.0, 0.0)); +} + static void test_3p1_N(void) { test_mix(4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 1.0, 0.0)); + MATRIX(0.333333, 0.333333, 0.333333, 0.0)); test_mix(4, _M(FL)|_M(FR)|_M(LFE)|_M(FC), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.707107, 0.0 )); @@ -151,9 +192,9 @@ static void test_4_N(void) { test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 0.5, 0.5)); + MATRIX(0.25, 0.25, 0.25, 0.25)); test_mix(4, _M(FL)|_M(FR)|_M(SL)|_M(SR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 0.5, 0.5)); + MATRIX(0.25, 0.25, 0.25, 0.25)); test_mix(4, _M(FL)|_M(FR)|_M(RL)|_M(RR), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.0, 0.707107)); @@ -178,13 +219,13 @@ MATRIX(1.0, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.0, 0.707107, 0.707107, 0.707107, 0.0, 0.0, - 0.0, 0.0, 0.0, 0.0)); + 0.5, 0.5, 0.0, 0.0)); } static void test_5p1_N(void) { test_mix(6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5)); + MATRIX(0.20, 0.20, 0.20, 0.0, 0.20, 0.20)); test_mix(6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.707107, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.707107, 0.0, 0.0, 0.707107)); @@ -223,7 +264,7 @@ static void test_6p1_N(void) { test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(RC)|_M(SL)|_M(SR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5, 0.5)); + MATRIX(0.166667, 0.166667, 0.166667, 0.0, 0.166667, 0.166667, 0.166667)); test_mix(7, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RC), 6, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR), 0, MATRIX(1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, @@ -263,7 +304,7 @@ static void test_7p1_N(void) { test_mix(8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 1, _M(MONO), 0, - MATRIX(0.707107, 0.707107, 1.0, 0.0, 0.5, 0.5, 0.5, 0.5)); + MATRIX(0.142857, 0.142857, 0.142857, 0.0, 0.142857, 0.142857, 0.142857, 0.142857)); test_mix(8, _M(FL)|_M(FR)|_M(LFE)|_M(FC)|_M(SL)|_M(SR)|_M(RL)|_M(RR), 2, _M(FL)|_M(FR), 0, MATRIX(1.0, 0.0, 0.707107, 0.0, 0.707107, 0.0, 0.707107, 0.0, 0.0, 1.0, 0.707107, 0.0, 0.0, 0.707107, 0.0, 0.707107)); @@ -362,6 +403,7 @@ test_1_N_MONO(); test_1_N_FC(); test_N_1(); + test_2_N(); test_3p1_N(); test_4_N(); test_5p1_N();
View file
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -134,8 +134,6 @@ /* A reference audio info for A2DP codec configuration. */ struct media_codec_audio_info default_audio_info; - - bool le_audio_supported; }; /* Stream endpoints owned by BlueZ for each device */ @@ -1008,6 +1006,52 @@ return 0; } +static int adapter_media_update_props(struct spa_bt_adapter *adapter, + DBusMessageIter *props_iter, + DBusMessageIter *invalidated_iter) +{ + /* Handle org.bluez.Media1 interface properties of .Adapter1 objects */ + struct spa_bt_monitor *monitor = adapter->monitor; + + while (dbus_message_iter_get_arg_type(props_iter) != DBUS_TYPE_INVALID) { + DBusMessageIter it2; + const char *key; + + dbus_message_iter_recurse(props_iter, &it0); + dbus_message_iter_get_basic(&it0, &key); + dbus_message_iter_next(&it0); + dbus_message_iter_recurse(&it0, &it1); + + if (spa_streq(key, "SupportedUUIDs")) { + DBusMessageIter iter; + + if (!check_iter_signature(&it1, "as")) + goto next; + + dbus_message_iter_recurse(&it1, &iter); + + while (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_INVALID) { + const char *uuid; + + dbus_message_iter_get_basic(&iter, &uuid); + + if (spa_streq(uuid, SPA_BT_UUID_BAP_SINK)) { + adapter->le_audio_supported = true; + spa_log_info(monitor->log, "Adapter %s: LE Audio supported", + adapter->path); + } + dbus_message_iter_next(&iter); + } + } + else + spa_log_debug(monitor->log, "media: unhandled key %s", key); + +next: + dbus_message_iter_next(props_iter); + } + return 0; +} + static void adapter_update_devices(struct spa_bt_adapter *adapter) { struct spa_bt_monitor *monitor = adapter->monitor; @@ -1875,6 +1919,8 @@ { struct spa_bt_monitor *monitor = device->monitor; struct spa_bt_remote_endpoint *ep; + enum spa_bt_profile codec_profile; + struct spa_bt_transport *t; const struct { enum spa_bluetooth_audio_codec codec; uint32_t mask; } quirks = { { SPA_BLUETOOTH_AUDIO_CODEC_SBC_XQ, SPA_BT_FEATURE_SBC_XQ }, { SPA_BLUETOOTH_AUDIO_CODEC_FASTSTREAM, SPA_BT_FEATURE_FASTSTREAM }, @@ -1887,10 +1933,13 @@ if (!is_media_codec_enabled(device->monitor, codec)) return false; - if (!device->adapter->application_registered) { + if (!device->adapter->a2dp_application_registered && !codec->bap) { /* Codec switching not supported: only plain SBC allowed */ - return (codec->codec_id == A2DP_CODEC_SBC && spa_streq(codec->name, "sbc")); + return (codec->codec_id == A2DP_CODEC_SBC && spa_streq(codec->name, "sbc") && + device->adapter->legacy_endpoints_registered); } + if (!device->adapter->bap_application_registered && codec->bap) + return false; /* Check codec quirks */ for (i = 0; i < SPA_N_ELEMENTS(quirks); ++i) { @@ -1906,16 +1955,15 @@ return false; } + if (codec->bap) + codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; + else + codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE; + spa_list_for_each(ep, &device->remote_endpoint_list, device_link) { const enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid); - enum spa_bt_profile expected; - if (codec->bap) - expected = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; - else - expected = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE; - - if (profile != expected) + if (profile != codec_profile) continue; if (media_codec_check_caps(codec, ep->codec, ep->capabilities, ep->capabilities_len, @@ -1923,6 +1971,21 @@ return true; } + /* Codecs on configured transports are always supported. + * + * Remote BAP endpoints correspond to capabilities of the remote + * BAP Server, not to remote BAP Client, and need not be the same. + * BAP Clients may not have any remote endpoints. In this case we + * can only know that the currently configured codec is supported. + */ + spa_list_for_each(t, &device->transport_list, device_link) { + if (t->profile != codec_profile) + continue; + + if (codec == t->media_codec) + return true; + } + return false; } @@ -3355,7 +3418,8 @@ const struct media_codec *preferred_codec = NULL; size_t i, j, num_codecs, num_eps; - if (!device->adapter->application_registered) { + if (!device->adapter->a2dp_application_registered && + !device->adapter->bap_application_registered) { /* Codec switching not supported */ return -ENOTSUP; } @@ -3690,9 +3754,10 @@ return res; } -static void bluez_register_endpoint_reply(DBusPendingCall *pending, void *user_data) +static void bluez_register_endpoint_legacy_reply(DBusPendingCall *pending, void *user_data) { - struct spa_bt_monitor *monitor = user_data; + struct spa_bt_adapter *adapter = user_data; + struct spa_bt_monitor *monitor = adapter->monitor; DBusMessage *r; r = dbus_pending_call_steal_reply(pending); @@ -3711,6 +3776,8 @@ goto finish; } + adapter->legacy_endpoints_registered = true; + finish: dbus_message_unref(r); } @@ -3739,10 +3806,12 @@ dbus_message_iter_close_container(dict, &dict_entry_it); } -static int bluez_register_endpoint(struct spa_bt_monitor *monitor, - const char *path, enum spa_bt_media_direction direction, +static int bluez_register_endpoint_legacy(struct spa_bt_adapter *adapter, + enum spa_bt_media_direction direction, const char *uuid, const struct media_codec *codec) { + struct spa_bt_monitor *monitor = adapter->monitor; + const char *path = adapter->path; char *object_path = NULL; DBusMessage *m; DBusMessageIter object_it, dict_it; @@ -3783,7 +3852,7 @@ dbus_message_iter_close_container(&object_it, &dict_it); dbus_connection_send_with_reply(monitor->conn, m, &call, -1); - dbus_pending_call_set_notify(call, bluez_register_endpoint_reply, monitor, NULL); + dbus_pending_call_set_notify(call, bluez_register_endpoint_legacy_reply, adapter, NULL); dbus_message_unref(m); free(object_path); @@ -3795,14 +3864,15 @@ return ret; } -static int adapter_register_endpoints(struct spa_bt_adapter *a) +static int adapter_register_endpoints_legacy(struct spa_bt_adapter *a) { struct spa_bt_monitor *monitor = a->monitor; const struct media_codec * const * const media_codecs = monitor->media_codecs; int i; int err = 0; + bool registered = false;
View file
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -204,6 +204,33 @@ return media_codec; } +static bool is_bap_client(struct impl *this) +{ + struct spa_bt_device *device = this->bt_dev; + struct spa_bt_transport *t; + + spa_list_for_each(t, &device->transport_list, device_link) { + if (t->bap_initiator) + return true; + } + + return false; +} + +static bool can_bap_codec_switch(struct impl *this) +{ + if (!is_bap_client(this)) + return false; + + /* XXX: codec switching for source/duplex is not currently + * XXX: implemented properly. TODO: fix this + */ + if (this->bt_dev->connected_profiles & SPA_BT_PROFILE_BAP_SOURCE) + return false; + + return true; +} + static unsigned int get_hfp_codec(enum spa_bluetooth_audio_codec id) { switch (id) { @@ -873,9 +900,15 @@ * A2DP/BAP: ensure there's a transport with the selected codec (0 means any). * Don't try to switch codecs when the device is in the A2DP source role, since * devices do not appear to like that. + * + * For BAP, only BAP client can configure the codec. + * + * XXX: codec switching also currently does not work in the duplex or + * XXX: source-only case, as it will only switch the sink, and we only + * XXX: list the sink codecs here. TODO: fix this */ - if ((profile == DEVICE_PROFILE_A2DP || profile == DEVICE_PROFILE_BAP) - && !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) { + if ((profile == DEVICE_PROFILE_A2DP || (profile == DEVICE_PROFILE_BAP && can_bap_codec_switch(this))) + && !(this->bt_dev->connected_profiles & SPA_BT_PROFILE_A2DP_SOURCE)) { int ret; const struct media_codec *codecs64; @@ -1332,11 +1365,6 @@ if (profile == 0) return NULL; - if (!codec) { - errno = EINVAL; - return NULL; - } - if (profile & (SPA_BT_PROFILE_BAP_SINK)) n_sink++; if (profile & (SPA_BT_PROFILE_BAP_SOURCE)) @@ -1344,28 +1372,51 @@ name = spa_bt_profile_name(profile); - media_codec = get_supported_media_codec(this, codec, &idx); - if (media_codec == NULL) { - errno = EINVAL; + /* If we can't codec switch, emit codecless profile */ + if (current && !can_bap_codec_switch(this)) { + codec = 0; + index = get_index_from_profile(this, profile_index, codec); + } else if ((codec != 0) != can_bap_codec_switch(this)) { + errno = -EINVAL; return NULL; } - name_and_codec = spa_aprintf("%s-%s", name, media_codec->name); - name = name_and_codec; - switch (profile) { - case SPA_BT_PROFILE_BAP_SINK: - desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"), - media_codec->description); - break; - case SPA_BT_PROFILE_BAP_SOURCE: - desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"), - media_codec->description); - break; - default: - desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"), - media_codec->description); + + if (codec) { + media_codec = get_supported_media_codec(this, codec, &idx); + if (media_codec == NULL) { + errno = EINVAL; + return NULL; + } + name_and_codec = spa_aprintf("%s-%s", name, media_codec->name); + name = name_and_codec; + switch (profile) { + case SPA_BT_PROFILE_BAP_SINK: + desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"), + media_codec->description); + break; + case SPA_BT_PROFILE_BAP_SOURCE: + desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"), + media_codec->description); + break; + default: + desc_and_codec = spa_aprintf(_("High Fidelity Duplex (BAP Source/Sink, codec %s)"), + media_codec->description); + } + desc = desc_and_codec; + priority = 128 + this->supported_codec_count - idx; /* order as in codec list */ + } else { + switch (profile) { + case SPA_BT_PROFILE_BAP_SINK: + desc = _("High Fidelity Playback (BAP Sink)"); + break; + case SPA_BT_PROFILE_BAP_SOURCE: + desc = _("High Fidelity Input (BAP Source)"); + break; + default: + desc = _("High Fidelity Duplex (BAP Source/Sink)"); + } + priority = 128; } - desc = desc_and_codec; - priority = 128 + this->supported_codec_count - idx; /* order as in codec list */ break; } case DEVICE_PROFILE_HSP_HFP:
View file
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/defs.h
Changed
@@ -161,12 +161,13 @@ #define HFP_AUDIO_CODEC_CVSD 0x01 #define HFP_AUDIO_CODEC_MSBC 0x02 -#define MEDIA_OBJECT_MANAGER_PATH "/MediaEndpoint" -#define A2DP_SINK_ENDPOINT MEDIA_OBJECT_MANAGER_PATH "/A2DPSink" -#define A2DP_SOURCE_ENDPOINT MEDIA_OBJECT_MANAGER_PATH "/A2DPSource" +#define A2DP_OBJECT_MANAGER_PATH "/MediaEndpoint" +#define A2DP_SINK_ENDPOINT A2DP_OBJECT_MANAGER_PATH "/A2DPSink" +#define A2DP_SOURCE_ENDPOINT A2DP_OBJECT_MANAGER_PATH "/A2DPSource" -#define BAP_SINK_ENDPOINT MEDIA_OBJECT_MANAGER_PATH "/BAPSink" -#define BAP_SOURCE_ENDPOINT MEDIA_OBJECT_MANAGER_PATH "/BAPSource" +#define BAP_OBJECT_MANAGER_PATH "/MediaEndpointLE" +#define BAP_SINK_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPSink" +#define BAP_SOURCE_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPSource" #define SPA_BT_UNKNOWN_DELAY 0 @@ -358,11 +359,15 @@ int powered; unsigned int has_msbc:1; unsigned int msbc_probed:1; - unsigned int endpoints_registered:1; - unsigned int application_registered:1; + unsigned int legacy_endpoints_registered:1; + unsigned int a2dp_application_registered:1; + unsigned int bap_application_registered:1; unsigned int player_registered:1; unsigned int has_battery_provider:1; unsigned int battery_provider_unavailable:1; + unsigned int le_audio_supported:1; + unsigned int has_adapter1_interface:1; + unsigned int has_media1_interface:1; }; enum spa_bt_form_factor {
View file
pipewire-0.3.65.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/bluez5/meson.build
Changed
@@ -1,12 +1,5 @@ gnome = import('gnome') -bluez5_deps = mathlib, dbus_dep, glib2_dep, sbc_dep, bluez_dep, gio_dep, gio_unix_dep -foreach dep: bluez5_deps - if not dep.found() - subdir_done() - endif -endforeach - cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', get_option('bluez5-backend-hsp-native').allowed() or get_option('bluez5-backend-hfp-native').allowed())
View file
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.66.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp
Changed
@@ -35,6 +35,7 @@ #include <limits.h> #include <linux/media.h> +#include <libcamera/control_ids.h> int spa_libcamera_open(struct impl *impl) { @@ -458,6 +459,38 @@ } +static struct { + uint32_t id; + uint32_t spa_id; +} control_map = { + { libcamera::controls::BRIGHTNESS, SPA_PROP_brightness }, + { libcamera::controls::CONTRAST, SPA_PROP_contrast }, + { libcamera::controls::SATURATION, SPA_PROP_saturation }, + { libcamera::controls::EXPOSURE_TIME, SPA_PROP_exposure }, + { libcamera::controls::ANALOGUE_GAIN, SPA_PROP_gain }, + { libcamera::controls::SHARPNESS, SPA_PROP_sharpness }, +}; + +static uint32_t control_to_prop_id(struct impl *impl, uint32_t control_id) +{ + SPA_FOR_EACH_ELEMENT_VAR(control_map, c) { + if (c->id == control_id) + return c->spa_id; + } + return SPA_PROP_START_CUSTOM + control_id; +} + +static uint32_t prop_id_to_control(struct impl *impl, uint32_t prop_id) +{ + SPA_FOR_EACH_ELEMENT_VAR(control_map, c) { + if (c->spa_id == prop_id) + return c->id; + } + if (prop_id >= SPA_PROP_START_CUSTOM) + return prop_id - SPA_PROP_START_CUSTOM; + return SPA_ID_INVALID; +} + static int spa_libcamera_enum_controls(struct impl *impl, struct port *port, int seq, uint32_t start, uint32_t num, @@ -469,7 +502,7 @@ struct spa_pod_frame f2; struct spa_result_node_params result; struct spa_pod *ctrl; - uint32_t count = 0, skip; + uint32_t count = 0, skip, id; int res; const ControlId *ctrl_id; ControlInfo ctrl_info; @@ -492,10 +525,12 @@ ctrl_id = it->first; ctrl_info = it->second; + id = control_to_prop_id(impl, ctrl_id->id()); + spa_pod_builder_init(&b, buffer, sizeof(buffer)); spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); spa_pod_builder_add(&b, - SPA_PROP_INFO_id, SPA_POD_Id(ctrl_id->id()), + SPA_PROP_INFO_id, SPA_POD_Id(id), SPA_PROP_INFO_description, SPA_POD_String(ctrl_id->name().c_str()), 0); @@ -601,8 +636,13 @@ const ControlId *ctrl_id; int res; struct val d; + uint32_t control_id; + + control_id = prop_id_to_control(impl, prop->key); + if (control_id == SPA_ID_INVALID) + return -ENOENT; - auto v = info.idmap().find(prop->key); + auto v = info.idmap().find(control_id); if (v == info.idmap().end()) return -ENOENT;
View file
pipewire-0.3.65.tar.gz/spa/plugins/libcamera/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/libcamera/meson.build
Changed
@@ -5,13 +5,8 @@ 'libcamera-source.cpp' -libdrm_dep = dependency('libdrm', version : '>= 2.4.98', - required : get_option('libcamera')) -summary({'libdrm': libdrm_dep.found()}, bool_yn: true, section: 'Backend') -if libdrm_dep.found() - libcameralib = shared_library('spa-libcamera', - libcamera_sources, - dependencies : spa_dep, libudev_dep, libcamera_dep, pthread_lib, libdrm_dep , - install : true, - install_dir : spa_plugindir / 'libcamera') -endif +libcameralib = shared_library('spa-libcamera', + libcamera_sources, + dependencies : spa_dep, libudev_dep, libcamera_dep, pthread_lib , + install : true, + install_dir : spa_plugindir / 'libcamera')
View file
pipewire-0.3.65.tar.gz/spa/plugins/support/journal.c -> pipewire-0.3.66.tar.gz/spa/plugins/support/journal.c
Changed
@@ -22,6 +22,8 @@ * DEALINGS IN THE SOFTWARE. */ +#include "config.h" + #include <stddef.h> #include <unistd.h> #include <string.h> @@ -114,6 +116,9 @@ sd_journal_send_with_location(file_buffer, line_buffer, func, "MESSAGE=%s", message_buffer, "PRIORITY=%i", priority, +#ifdef HAVE_GETTID + "TID=%jd", (intmax_t) gettid(), +#endif NULL); }
View file
pipewire-0.3.65.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.66.tar.gz/spa/plugins/support/meson.build
Changed
@@ -18,7 +18,7 @@ spa_support_lib = shared_library('spa-support', spa_support_sources, c_args : simd_cargs , - dependencies : spa_dep, pthread_lib, epoll_shim_dep , + dependencies : spa_dep, pthread_lib, epoll_shim_dep, mathlib , install : true, install_dir : spa_plugindir / 'support') spa_support_dep = declare_dependency(link_with: spa_support_lib) @@ -61,6 +61,7 @@ spa_journal_lib = shared_library('spa-journal', spa_journal_sources, + include_directories : configinc , dependencies : spa_dep, systemd_dep , install : true, install_dir : spa_plugindir / 'support')
View file
pipewire-0.3.65.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.66.tar.gz/spa/plugins/support/node-driver.c
Changed
@@ -27,6 +27,7 @@ #include <unistd.h> #include <string.h> #include <stdio.h> +#include <fcntl.h> #include <spa/support/plugin.h> #include <spa/support/log.h> @@ -34,6 +35,7 @@ #include <spa/utils/names.h> #include <spa/utils/result.h> #include <spa/utils/string.h> +#include <spa/utils/dll.h> #include <spa/node/node.h> #include <spa/node/keys.h> #include <spa/node/io.h> @@ -43,11 +45,20 @@ #define NAME "driver" #define DEFAULT_FREEWHEEL false -#define DEFAULT_CLOCK_NAME "clock.system.monotonic" +#define DEFAULT_CLOCK_PREFIX "clock.system" +#define DEFAULT_CLOCK_ID CLOCK_MONOTONIC + +#define CLOCKFD 3 +#define FD_TO_CLOCKID(fd) ((~(clockid_t) (fd) << 3) | CLOCKFD) +#define CLOCKID_TO_FD(clk) ((unsigned int) ~((clk) >> 3)) + +#define BW_PERIOD (3 * SPA_NSEC_PER_SEC) +#define MAX_ERROR_MS 1 struct props { bool freewheel; char clock_name64; + clockid_t clock_id; }; struct impl { @@ -72,19 +83,62 @@ struct spa_source timer_source; struct itimerspec timerspec; + int clock_fd; bool started; bool following; + bool tracking; + clockid_t timer_clockid; uint64_t next_time; + uint64_t last_time; + uint64_t base_time; + struct spa_dll dll; + double max_error; }; static void reset_props(struct props *props) { props->freewheel = DEFAULT_FREEWHEEL; - spa_scnprintf(props->clock_name, sizeof(props->clock_name), - "%s", DEFAULT_CLOCK_NAME); + spa_zero(props->clock_name); + props->clock_id = CLOCK_MONOTONIC; } +static const struct clock_info { + const char *name; + clockid_t id; +} clock_info = { + { "realtime", CLOCK_REALTIME }, + { "tai", CLOCK_TAI }, + { "monotonic", CLOCK_MONOTONIC }, + { "monotonic-raw", CLOCK_MONOTONIC_RAW }, + { "boottime", CLOCK_BOOTTIME }, +}; + +static bool clock_for_timerfd(clockid_t id) +{ + return id == CLOCK_REALTIME || + id == CLOCK_MONOTONIC || + id == CLOCK_BOOTTIME; +} + +static clockid_t clock_name_to_id(const char *name) +{ + SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) { + if (spa_streq(i->name, name)) + return i->id; + } + return -1; +} +static const char *clock_id_to_name(clockid_t id) +{ + SPA_FOR_EACH_ELEMENT_VAR(clock_info, i) { + if (i->id == id) + return i->name; + } + return "custom"; +} + + static void set_timeout(struct impl *this, uint64_t next_time) { spa_log_trace(this->log, "set timeout %"PRIu64, next_time); @@ -94,14 +148,22 @@ this->timer_source.fd, SPA_FD_TIMER_ABSTIME, &this->timerspec, NULL); } +static inline uint64_t gettime_nsec(struct impl *this, clockid_t clock_id) +{ + struct timespec now = { 0 }; + uint64_t nsec; + if (spa_system_clock_gettime(this->data_system, clock_id, &now) < 0) + return 0; + nsec = SPA_TIMESPEC_TO_NSEC(&now); + spa_log_trace(this->log, "%p now:%"PRIu64, this, nsec); + return nsec; +} + static int set_timers(struct impl *this) { - struct timespec now; - int res; + this->next_time = gettime_nsec(this, this->timer_clockid); - if ((res = spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &now)) < 0) - return res; - this->next_time = SPA_TIMESPEC_TO_NSEC(&now); + spa_log_debug(this->log, "%p now:%"PRIu64, this, this->next_time); if (this->following) { set_timeout(this, 0); @@ -176,15 +238,23 @@ return 0; } +static inline uint64_t scale_u64(uint64_t val, uint32_t num, uint32_t denom) +{ +#if 0 + return ((__uint128_t)val * num) / denom; +#else + return (double)val / denom * num; +#endif +} + static void on_timeout(struct spa_source *source) { struct impl *this = source->data; - uint64_t expirations, nsec, duration; + uint64_t expirations, nsec, duration, current_time, current_position, position; uint32_t rate; + double corr = 1.0, err = 0.0; int res; - spa_log_trace(this->log, "timeout"); - if ((res = spa_system_timerfd_read(this->data_system, this->timer_source.fd, &expirations)) < 0) { if (res != EAGAIN) @@ -192,9 +262,6 @@ this, spa_strerror(res)); return; } - - nsec = this->next_time; - if (SPA_LIKELY(this->position)) { duration = this->position->clock.duration; rate = this->position->clock.rate.denom; @@ -202,15 +269,61 @@ duration = 1024; rate = 48000; } + nsec = this->next_time; + + if (this->tracking) + /* we are actually following another clock */ + current_time = gettime_nsec(this, this->props.clock_id); + else + current_time = nsec; + + current_position = scale_u64(current_time, rate, SPA_NSEC_PER_SEC); + + if (SPA_LIKELY(this->clock)) + position = this->clock->position; + else + position = current_position; + + if (this->last_time == 0) { + spa_dll_set_bw(&this->dll, SPA_DLL_BW_MIN, duration, rate); + this->max_error = rate * MAX_ERROR_MS / 1000; + position = current_position; + } - this->next_time = nsec + duration * SPA_NSEC_PER_SEC / rate; + /* check the elapsed time of the other clock against + * the graph clock elapsed time, feed this error into the + * dll and adjust the timeout of our MONOTONIC clock. */ + err = (double)position - (double)current_position; + if (err > this->max_error) + err = this->max_error;
View file
pipewire-0.3.65.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -31,8 +31,9 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Loads a module with the given parameters.
View file
pipewire-0.3.65.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/client.conf.in
Changed
@@ -31,8 +31,9 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Loads a module with the given parameters.
View file
pipewire-0.3.65.tar.gz/src/daemon/filter-chain.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/filter-chain.conf.in
Changed
@@ -30,8 +30,9 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Loads a module with the given parameters.
View file
pipewire-0.3.66.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf
Added
@@ -0,0 +1,157 @@ +# Headphone surround sink +# +# Copy this file into a conf.d/ directory such as +# ~/.config/pipewire/filter-chain.conf.d/ +# +context.modules = + { name = libpipewire-module-filter-chain + args = { + node.description = "Spatial Sink" + media.name = "Spatial Sink" + filter.graph = { + nodes = + { + type = sofa + label = spatializer + name = spFL + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 30.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spFR + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 330.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spFC + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 0.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spRL + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 150.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spRR + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 210.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spSL + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 90.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spSR + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 270.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + { + type = sofa + label = spatializer + name = spLFE + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 0.0 + "Elevation" = -60.0 + "Radius" = 3.0 + } + } + + { type = builtin label = mixer name = mixL } + { type = builtin label = mixer name = mixR } + + links = + # output + { output = "spFL:Out L" input="mixL:In 1" } + { output = "spFL:Out R" input="mixR:In 1" } + { output = "spFR:Out L" input="mixL:In 2" } + { output = "spFR:Out R" input="mixR:In 2" } + { output = "spFC:Out L" input="mixL:In 3" } + { output = "spFC:Out R" input="mixR:In 3" } + { output = "spRL:Out L" input="mixL:In 4" } + { output = "spRL:Out R" input="mixR:In 4" } + { output = "spRR:Out L" input="mixL:In 5" } + { output = "spRR:Out R" input="mixR:In 5" } + { output = "spSL:Out L" input="mixL:In 6" } + { output = "spSL:Out R" input="mixR:In 6" } + { output = "spSR:Out L" input="mixL:In 7" } + { output = "spSR:Out R" input="mixR:In 7" } + { output = "spLFE:Out L" input="mixL:In 8" } + { output = "spLFE:Out R" input="mixR:In 8" } + + inputs = "spFL:In" "spFR:In" "spFC:In" "spLFE:In" "spRL:In" "spRR:In", "spSL:In", "spSR:In" + outputs = "mixL:Out" "mixR:Out" + } + capture.props = { + node.name = "effect_input.spatializer" + media.class = Audio/Sink + audio.channels = 8 + audio.position = FL FR FC LFE RL RR SL SR + } + playback.props = { + node.name = "effect_output.spatializer" + node.passive = true + audio.channels = 2 + audio.position = FL FR + } + } + } +
View file
pipewire-0.3.66.tar.gz/src/daemon/filter-chain/spatializer-single.conf
Added
@@ -0,0 +1,45 @@ +# A virtual sound source sink +# Useful for testing spatial effects by moving it around with controls +# +# Copy this file into a conf.d/ directory such as +# ~/.config/pipewire/filter-chain.conf.d/ +# +context.modules = + { name = libpipewire-module-filter-chain + args = { + node.description = "3D Sink" + media.name = "3D Sink" + filter.graph = { + nodes = + { + type = sofa + label = spatializer + name = sp + config = { + filename = "~/.config/hrtf-sofa/hrtf b_nh724.sofa" + } + control = { + "Azimuth" = 220.0 + "Elevation" = 0.0 + "Radius" = 3.0 + } + } + + inputs = "sp:In" + outputs = "sp:Out L" "sp:Out R" + } + capture.props = { + node.name = "effect_input.3d" + media.class = Audio/Sink + audio.channels = 1 + audio.position = FC + } + playback.props = { + node.name = "effect_output.3d" + node.passive = true + audio.channels = 2 + audio.position = FL FR + } + } + } +
View file
pipewire-0.3.65.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/jack.conf.in
Changed
@@ -30,8 +30,9 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Loads a module with the given parameters.
View file
pipewire-0.3.65.tar.gz/src/daemon/meson.build -> pipewire-0.3.66.tar.gz/src/daemon/meson.build
Changed
@@ -72,6 +72,7 @@ 'minimal.conf', 'pipewire-pulse.conf', 'pipewire-avb.conf', + 'pipewire-aes67.conf', foreach c : conf_files @@ -109,6 +110,14 @@ dependencies : spa_dep, pipewire_dep, , ) +executable('pipewire-aes67', + pipewire_daemon_sources, + install: true, + c_args : pipewire_c_args, + include_directories : configinc , + dependencies : spa_dep, pipewire_dep, , +) + ln = find_program('ln') custom_target('pipewire-uninstalled',
View file
pipewire-0.3.65.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/minimal.conf.in
Changed
@@ -60,8 +60,9 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Loads a module with the given parameters. @@ -135,8 +136,9 @@ context.objects = #{ factory = <factory-name> - # args = { <key> = <value> ... } - # flags = nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Creates an object from a PipeWire factory with the given parameters. @@ -339,7 +341,10 @@ context.exec = - #{ path = <program-name> args = "<arguments>" } + #{ path = <program-name> + # ( args = "<arguments>" ) + # ( condition = { <key> = <value> ... } ... ) + #} # # Execute the given program with arguments. #
View file
pipewire-0.3.66.tar.gz/src/daemon/pipewire-aes67.conf.in
Added
@@ -0,0 +1,52 @@ +# AES67 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. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/pipewire-aes67.conf.d/ for system-wide changes or in +# ~/.config/pipewire/pipewire-aes67.conf.d/ for local changes. +# + +context.properties = { + ## Configure properties in the system. + #mem.warn-mlock = false + #mem.allow-mlock = true + #mem.mlock-all = false + #log.level = 2 + + #default.clock.quantum-limit = 8192 +} + +#context.spa-libs = { +# audio.convert.* = audioconvert/libspa-audioconvert +# support.* = support/libspa-support +#} + +context.modules = + { name = libpipewire-module-rt + args = { + nice.level = -11 + #rt.prio = 88 + #rt.time.soft = -1 + #rt.time.hard = -1 + } + flags = ifexists nofail + } + { name = libpipewire-module-protocol-native } + { name = libpipewire-module-client-node } + { name = libpipewire-module-adapter } + { name = libpipewire-module-rtp-source + args = { + sap.ip = 239.255.255.255 + sap.port = 9875 + sess.latency.msec = 10 + local.ifname = eth0 + stream.props = { + media.class = "Audio/Source" + node.virtual = false + device.api = aes67 + } + } + } +
View file
pipewire-0.3.65.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -57,11 +57,11 @@ # Extra commands can be executed here. # load-module : loads a module with args and flags # args = "<module-name> <module-args>" -# flags = "no-fail" +# ( flags = nofail ) pulse.cmd = { cmd = "load-module" args = "module-always-sink" flags = } #{ cmd = "load-module" args = "module-switch-on-connect" } - #{ cmd = "load-module" args = "module-gsettings" flags = "nofail" } + #{ cmd = "load-module" args = "module-gsettings" flags = nofail } stream.properties = {
View file
pipewire-0.3.65.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.66.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -29,7 +29,7 @@ #default.clock.rate = 48000 #default.clock.allowed-rates = 48000 #default.clock.quantum = 1024 - default.clock.min-quantum = 16 + #default.clock.min-quantum = 32 #default.clock.max-quantum = 2048 #default.clock.quantum-limit = 8192 #default.video.width = 640 @@ -44,6 +44,9 @@ vm.overrides = { default.clock.min-quantum = 1024 } + + # keys checked below to disable module loading + module.x11.bell = true } context.spa-libs = { @@ -68,13 +71,16 @@ context.modules = #{ name = <module-name> - # args = { <key> = <value> ... } - # flags = ifexists nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( ifexists ) ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # 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. + # If condition is given, the module is loaded only when the context + # properties all match the match rules. # # Uses realtime scheduling to boost the audio thread priorities. This uses @@ -167,17 +173,21 @@ #x11.xauthority = null } flags = ifexists nofail + condition = { module.x11.bell = true } } context.objects = #{ factory = <factory-name> - # args = { <key> = <value> ... } - # flags = nofail + # ( args = { <key> = <value> ... } ) + # ( flags = ( nofail ) ) + # ( condition = { <key> = <value> ... } ... ) #} # # Creates an object from a PipeWire factory with the given parameters. # If nofail is given, errors are ignored (and no object is created). + # If condition is given, the object is created only when the context properties + # all match the match rules. # #{ 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 } @@ -194,6 +204,8 @@ node.name = Dummy-Driver node.group = pipewire.dummy priority.driver = 20000 + #clock.id = monotonic # realtime | tai | monotonic-raw | boottime + #clock.name = "clock.system.monotonic" } } { factory = spa-node-factory @@ -205,6 +217,20 @@ node.freewheel = true } } + # An example clock reading from /dev/ptp0. Another option is to sync the + # ptp clock to CLOCK_TAI and then set clock.id = tai. + #{ factory = spa-node-factory + # args = { + # factory.name = support.node.driver + # node.name = PTP0-Driver + # node.group = pipewire.ptp0 + # priority.driver = 30000 + # clock.name = "clock.system.ptp0" + # #clock.id = tai + # clock.device = "/dev/ptp0" + # } + #} + # This creates a new Source node. It will have input ports # that you can link, to provide audio for this source. #{ factory = adapter @@ -240,9 +266,14 @@ context.exec = - #{ path = <program-name> args = "<arguments>" } + #{ path = <program-name> + # ( args = "<arguments>" ) + # ( condition = { <key> = <value> ... } ... ) + #} # # Execute the given program with arguments. + # If condition is given, the program is executed only when the context + # properties all match the match rules. # # You can optionally start the session manager here, # but it is better to start it as a systemd service.
View file
pipewire-0.3.65.tar.gz/src/gst/gstpipewirepool.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewirepool.c
Changed
@@ -109,6 +109,16 @@ gst_buffer_insert_memory (buf, i, gmem); } + if (pool->add_metavideo) { + gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, + GST_VIDEO_INFO_FORMAT (&pool->video_info), + GST_VIDEO_INFO_WIDTH (&pool->video_info), + GST_VIDEO_INFO_HEIGHT (&pool->video_info), + GST_VIDEO_INFO_N_PLANES (&pool->video_info), + pool->video_info.offset, + pool->video_info.stride); + } + data->pool = gst_object_ref (pool); data->owner = NULL; data->header = spa_buffer_find_meta_data (b->buffer, SPA_META_Header, sizeof(*data->header)); @@ -208,6 +218,41 @@ } } +static const gchar ** +get_options (GstBufferPool * pool) +{ + static const gchar *options = { GST_BUFFER_POOL_OPTION_VIDEO_META, NULL }; + return options; +} + +static gboolean +set_config (GstBufferPool * pool, GstStructure * config) +{ + GstPipeWirePool *p = GST_PIPEWIRE_POOL (pool); + GstCaps *caps; + guint size, min_buffers, max_buffers; + gboolean has_video; + + if (!gst_buffer_pool_config_get_params (config, &caps, &size, &min_buffers, &max_buffers)) { + GST_WARNING_OBJECT (pool, "invalid config"); + return FALSE; + } + + if (caps == NULL) { + GST_WARNING_OBJECT (pool, "no caps in config"); + return FALSE; + } + + has_video = gst_video_info_from_caps (&p->video_info, caps); + + p->add_metavideo = has_video && gst_buffer_pool_config_has_option (config, + GST_BUFFER_POOL_OPTION_VIDEO_META); + + gst_buffer_pool_config_set_params (config, caps, p->video_info.size, min_buffers, max_buffers); + + return GST_BUFFER_POOL_CLASS (gst_pipewire_pool_parent_class)->set_config (pool, config); +} + static void flush_start (GstBufferPool * pool) { @@ -252,6 +297,8 @@ gobject_class->finalize = gst_pipewire_pool_finalize; + bufferpool_class->get_options = get_options; + bufferpool_class->set_config = set_config; bufferpool_class->start = do_start; bufferpool_class->flush_start = flush_start; bufferpool_class->acquire_buffer = acquire_buffer;
View file
pipewire-0.3.65.tar.gz/src/gst/gstpipewirepool.h -> pipewire-0.3.66.tar.gz/src/gst/gstpipewirepool.h
Changed
@@ -27,6 +27,8 @@ #include <gst/gst.h> +#include <gst/video/video.h> + #include <pipewire/pipewire.h> G_BEGIN_DECLS @@ -66,6 +68,9 @@ struct pw_stream *stream; struct pw_type *t; + gboolean add_metavideo; + GstVideoInfo video_info; + GstAllocator *fd_allocator; GstAllocator *dmabuf_allocator;
View file
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresink.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresink.c
Changed
@@ -142,6 +142,7 @@ GstPipeWireSink *pwsink = GST_PIPEWIRE_SINK (bsink); gst_query_add_allocation_pool (query, GST_BUFFER_POOL_CAST (pwsink->pool), 0, 0, 0); + gst_query_add_allocation_meta (query, GST_VIDEO_META_API_TYPE, NULL); return TRUE; } @@ -504,6 +505,22 @@ d->chunk->stride = 0; } + GstVideoMeta *meta = gst_buffer_get_video_meta (buffer); + if (meta) { + if (meta->n_planes == b->n_datas) { + gsize video_size = 0; + for (i = 0; i < meta->n_planes; i++) { + struct spa_data *d = &b->datasi; + d->chunk->offset += meta->offseti - video_size; + d->chunk->stride = meta->stridei; + + video_size += d->chunk->size; + } + } else { + GST_ERROR ("plane num not matching, meta:%u buffer:%u", meta->n_planes, b->n_datas); + } + } + if ((res = pw_stream_queue_buffer (pwsink->stream, data->b)) < 0) { g_warning ("can't send buffer %s", spa_strerror(res)); }
View file
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresrc.c
Changed
@@ -615,6 +615,27 @@ } } + if (pwsrc->is_video) { + gsize video_size = 0; + GstVideoInfo *info = &pwsrc->video_info; + GstVideoMeta *meta = gst_buffer_add_video_meta_full (buf, GST_VIDEO_FRAME_FLAG_NONE, + GST_VIDEO_INFO_FORMAT (info), + GST_VIDEO_INFO_WIDTH (info), + GST_VIDEO_INFO_HEIGHT (info), + GST_VIDEO_INFO_N_PLANES (info), + info->offset, + info->stride); + + meta->n_planes = MIN(meta->n_planes, b->buffer->n_datas); + for (i = 0; i < meta->n_planes; i++) { + struct spa_data *d = &b->buffer->datasi; + meta->offseti = video_size; + meta->stridei = d->chunk->stride; + + video_size += d->chunk->size; + } + } + for (i = 0; i < b->buffer->n_datas; i++) { struct spa_data *d = &b->buffer->datasi; GstMemory *pmem = gst_buffer_peek_memory (data->buf, i); @@ -658,6 +679,7 @@ case PW_STREAM_STATE_STREAMING: break; case PW_STREAM_STATE_ERROR: + pw_stream_set_error (pwsrc->stream, -EPIPE, "%s", error); GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, ("stream error: %s", error), (NULL)); break; @@ -958,6 +980,10 @@ gst_caps_unref(pwsrc->caps); pwsrc->caps = gst_caps_from_format (param); + pwsrc->is_video = pwsrc->caps != NULL + ? gst_video_info_from_caps (&pwsrc->video_info, pwsrc->caps) + : FALSE; + pwsrc->negotiated = pwsrc->caps != NULL; if (pwsrc->negotiated) {
View file
pipewire-0.3.65.tar.gz/src/gst/gstpipewiresrc.h -> pipewire-0.3.66.tar.gz/src/gst/gstpipewiresrc.h
Changed
@@ -28,6 +28,8 @@ #include <gst/gst.h> #include <gst/base/gstpushsrc.h> +#include <gst/video/video.h> + #include <pipewire/pipewire.h> #include <gst/gstpipewirepool.h> #include <gst/gstpipewirecore.h> @@ -71,6 +73,9 @@ GstCaps *caps; + gboolean is_video; + GstVideoInfo video_info; + gboolean negotiated; gboolean flushing; gboolean started;
View file
pipewire-0.3.65.tar.gz/src/modules/meson.build -> pipewire-0.3.66.tar.gz/src/modules/meson.build
Changed
@@ -1,3 +1,4 @@ +subdir('module-rt') subdir('spa') # The list of "main" source files for modules, the ones that have the @@ -108,10 +109,11 @@ 'module-filter-chain/biquad.c', 'module-filter-chain/ladspa_plugin.c', 'module-filter-chain/builtin_plugin.c', + 'module-filter-chain/sofa_plugin.c', 'module-filter-chain/convolver.c' filter_chain_dependencies = - mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep + mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep, libmysofa_dep if lilv_lib.found() @@ -139,7 +141,7 @@ pipewire_module_combine_stream = shared_library('pipewire-module-combine-stream', 'module-combine-stream.c' , include_directories : configinc, - install : false, + install : true, install_dir : modules_install_dir, install_rpath: modules_install_dir, dependencies : spa_dep, dl_lib, pipewire_dep, @@ -174,27 +176,25 @@ build_module_rtkit = dbus_dep.found() and (get_option('legacy-rtkit') == true) if build_module_rtkit -# 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, - install_rpath: modules_install_dir, - dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep, -) + pipewire_module_rtkit = shared_library('pipewire-module-rtkit', 'module-rt.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep, + ) endif summary({'rt': '@0@ RTKit'.format(build_module_rtkit ? 'with' : 'without')}, section: 'Optional Modules') build_module_portal = dbus_dep.found() if build_module_portal -pipewire_module_portal = shared_library('pipewire-module-portal', 'module-portal.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep, -) + pipewire_module_portal = shared_library('pipewire-module-portal', 'module-portal.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : dbus_dep, mathlib, dl_lib, pipewire_dep, + ) endif summary({'portal': build_module_portal}, bool_yn: true, section: 'Optional Modules') @@ -332,16 +332,16 @@ ) build_module_pulse_tunnel = pulseaudio_dep.found() -if build_module_pulse_tunnel - pipewire_module_pulse_tunnel = shared_library('pipewire-module-pulse-tunnel', - 'module-pulse-tunnel.c', - 'module-protocol-pulse/format.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, pipewire_dep, pulseaudio_dep, -) + if build_module_pulse_tunnel + pipewire_module_pulse_tunnel = shared_library('pipewire-module-pulse-tunnel', + 'module-pulse-tunnel.c', + 'module-protocol-pulse/format.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, pipewire_dep, pulseaudio_dep, + ) endif summary({'pulse-tunnel': build_module_pulse_tunnel}, bool_yn: true, section: 'Optional Modules') @@ -474,44 +474,44 @@ build_module_zeroconf_discover = avahi_dep.found() if build_module_zeroconf_discover -pipewire_module_zeroconf_discover = shared_library('pipewire-module-zeroconf-discover', - 'module-zeroconf-discover.c', - 'module-protocol-pulse/format.c', - 'module-zeroconf-discover/avahi-poll.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep, -) + pipewire_module_zeroconf_discover = shared_library('pipewire-module-zeroconf-discover', + 'module-zeroconf-discover.c', + 'module-protocol-pulse/format.c', + 'module-zeroconf-discover/avahi-poll.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep, + ) endif summary({'zeroconf-discover': build_module_zeroconf_discover}, bool_yn: true, section: 'Optional Modules') build_module_raop_discover = avahi_dep.found() if build_module_raop_discover -pipewire_module_raop_discover = shared_library('pipewire-module-raop-discover', - 'module-raop-discover.c', - 'module-zeroconf-discover/avahi-poll.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep, -) + pipewire_module_raop_discover = shared_library('pipewire-module-raop-discover', + 'module-raop-discover.c', + 'module-zeroconf-discover/avahi-poll.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, avahi_dep, + ) endif summary({'raop-discover (needs Avahi)': build_module_raop_discover}, bool_yn: true, section: 'Optional Modules') build_module_raop = openssl_lib.found() if build_module_raop -pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink', - 'module-raop-sink.c', - 'module-raop/rtsp-client.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, openssl_lib, -) + pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink', + 'module-raop-sink.c', + 'module-raop/rtsp-client.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, openssl_lib, + ) endif summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules') @@ -538,37 +538,37 @@ build_module_roc = roc_dep.found() if build_module_roc -pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink', - 'module-roc-sink.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep, -) + pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink', + 'module-roc-sink.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep, + ) -pipewire_module_roc_source = shared_library('pipewire-module-roc-source', - 'module-roc-source.c' , - include_directories : configinc, - install : true, - install_dir : modules_install_dir, - install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, roc_dep, -) + pipewire_module_roc_source = shared_library('pipewire-module-roc-source', + 'module-roc-source.c' ,
View file
pipewire-0.3.65.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.66.tar.gz/src/modules/module-combine-stream.c
Changed
@@ -847,6 +847,7 @@ } static const struct pw_proxy_events core_proxy_events = { + PW_VERSION_PROXY_EVENTS, .removed = core_removed, };
View file
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -273,6 +273,12 @@ * - `max-delay` the maximum delay in seconds. The "Delay (s)" parameter will * be clamped to this value. * + * ### Invert + * + * The invert plugin can be used to invert the phase of the signal. + * + * It has an input port "In" and an output port "Out". + * * ## General options * * Options with well-known behavior. Most options can be added to the global @@ -445,7 +451,7 @@ struct plugin { struct spa_list link; int ref; - char type64; + char type256; char pathPATH_MAX; struct fc_plugin *plugin; @@ -506,6 +512,7 @@ unsigned int n_deps; unsigned int visited:1; unsigned int disabled:1; + unsigned int control_changed:1; }; struct link { @@ -878,7 +885,8 @@ old = port->control_data; port->control_data = value ? *value : desc->default_controlport->idx; pw_log_info("control %d ('%s') from %f to %f", port->idx, name, old, port->control_data); - return old == port->control_data ? 0 : 1; + node->control_changed = old != port->control_data; + return node->control_changed ? 1 : 0; } static int parse_params(struct graph *graph, const struct spa_pod *pod) @@ -938,6 +946,24 @@ d->activate(*hndl->hndl); } } + +static void node_control_changed(struct node *node) +{ + const struct fc_descriptor *d = node->desc->desc; + uint32_t i; + + if (!node->control_changed) + return; + + for (i = 0; i < node->n_hndl; i++) { + if (node->hndli == NULL) + continue; + if (d->control_changed) + d->control_changed(node->hndli); + } + node->control_changed = false; +} + static void param_props_changed(struct impl *impl, const struct spa_pod *param) { struct spa_pod_object *obj = (struct spa_pod_object *) param; @@ -953,6 +979,10 @@ uint8_t buffer1024; struct spa_pod_dynamic_builder b; const struct spa_pod *params1; + struct node *node; + + spa_list_for_each(node, &graph->node_list, link) + node_control_changed(node); spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); params0 = get_props_param(graph, &b.b); @@ -1205,6 +1235,9 @@ if (spa_streq(type, "builtin")) { pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL); } + else if (spa_streq(type, "sofa")) { + pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL); + } else if (spa_streq(type, "ladspa")) { pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL); } @@ -1696,6 +1729,7 @@ free(node->output_port); free(node->control_port); free(node->notify_port); + free(node->config); free(node); } @@ -1767,6 +1801,8 @@ } if (d->activate) d->activate(node->hndli); + if (node->control_changed && d->control_changed) + d->control_changed(node->hndli); } } return 0; @@ -1902,6 +1938,8 @@ pw_log_error("input port %s not found", v); goto error; } else { + bool disabled = false; + desc = port->node->desc; d = desc->desc; if (i == 0 && port->external != SPA_ID_INVALID) { @@ -1936,12 +1974,14 @@ gp->hndl = &peer->node->hndli; gp->port = peer->p; gp->next = true; + disabled = true; } if (gp != NULL) gp->next = false; } - port->node->disabled = true; - } else { + port->node->disabled = disabled; + } + if (!disabled) { pw_log_info("input port %s%d:%s", port->node->name, i, d->portsport->p.name); port->external = graph->n_input;
View file
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
@@ -978,6 +978,38 @@ .cleanup = delay_cleanup, }; +static void invert_run(void * Instance, unsigned long SampleCount) +{ + struct builtin *impl = Instance; + float *in = impl->port1, *out = impl->port0; + unsigned long n; + for (n = 0; n < SampleCount; n++) + outn = -inn; +} + +static struct fc_port invert_ports = { + { .index = 0, + .name = "Out", + .flags = FC_PORT_OUTPUT | FC_PORT_AUDIO, + }, + { .index = 1, + .name = "In", + .flags = FC_PORT_INPUT | FC_PORT_AUDIO, + }, +}; + +static const struct fc_descriptor invert_desc = { + .name = "invert", + + .n_ports = 2, + .ports = invert_ports, + + .instantiate = builtin_instantiate, + .connect_port = builtin_connect_port, + .run = invert_run, + .cleanup = builtin_cleanup, +}; + static const struct fc_descriptor * builtin_descriptor(unsigned long Index) { switch(Index) { @@ -1005,6 +1037,8 @@ return &convolve_desc; case 11: return &delay_desc; + case 12: + return &invert_desc; } return NULL; }
View file
pipewire-0.3.65.tar.gz/src/modules/module-filter-chain/plugin.h -> pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/plugin.h
Changed
@@ -83,6 +83,7 @@ void (*cleanup) (void *instance); void (*connect_port) (void *instance, unsigned long port, float *data); + void (*control_changed) (void *instance); void (*activate) (void *instance); void (*deactivate) (void *instance); @@ -108,5 +109,7 @@ struct dsp_ops *dsp, const char *path, const char *config); struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support, struct dsp_ops *dsp, const char *path, const char *config); +struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support, + struct dsp_ops *dsp, const char *path, const char *config); #endif /* PLUGIN_H */
View file
pipewire-0.3.66.tar.gz/src/modules/module-filter-chain/sofa_plugin.c
Added
@@ -0,0 +1,375 @@ +#include "config.h" + +#include <spa/utils/json.h> +#include <spa/support/loop.h> + +#include <pipewire/log.h> +#include "plugin.h" +#include "convolver.h" +#include "dsp-ops.h" +#include "pffft.h" + +#ifdef HAVE_LIBMYSOFA +#include <mysofa.h> + +#define MAX_SAMPLES 8192u +#endif + +static struct dsp_ops *dsp_ops; +static struct spa_loop *data_loop; +static struct spa_loop *main_loop; + +struct spatializer_impl { + unsigned long rate; + float *port6; + int n_samples, blocksize, tailsize; + float *tmp2; + +#ifdef HAVE_LIBMYSOFA + struct MYSOFA_EASY *sofa; +#endif + unsigned int interpolate:1; + struct convolver *l_conv3; + struct convolver *r_conv3; +}; + +static void * spatializer_instantiate(const struct fc_descriptor * Descriptor, + unsigned long SampleRate, int index, const char *config) +{ +#ifdef HAVE_LIBMYSOFA + struct spatializer_impl *impl; + struct spa_json it2; + const char *val; + char key256; + char filenamePATH_MAX = ""; + + errno = EINVAL; + if (config == NULL) + return NULL; + + spa_json_init(&it0, config, strlen(config)); + if (spa_json_enter_object(&it0, &it1) <= 0) + return NULL; + + impl = calloc(1, sizeof(*impl)); + if (impl == NULL) { + errno = ENOMEM; + return NULL; + } + + while (spa_json_get_string(&it1, key, sizeof(key)) > 0) { + if (spa_streq(key, "blocksize")) { + if (spa_json_get_int(&it1, &impl->blocksize) <= 0) { + pw_log_error("spatializer:blocksize requires a number"); + errno = EINVAL; + goto error; + } + } + else if (spa_streq(key, "tailsize")) { + if (spa_json_get_int(&it1, &impl->tailsize) <= 0) { + pw_log_error("spatializer:tailsize requires a number"); + errno = EINVAL; + goto error; + } + } + else if (spa_streq(key, "filename")) { + if (spa_json_get_string(&it1, filename, sizeof(filename)) <= 0) { + pw_log_error("spatializer:filename requires a string"); + errno = EINVAL; + goto error; + } + } + else if (spa_json_next(&it1, &val) < 0) + break; + } + if (!filename0) { + pw_log_error("spatializer:filename was not given"); + errno = EINVAL; + goto error; + } + + int ret = MYSOFA_OK; + + impl->sofa = mysofa_open_cached(filename, SampleRate, &impl->n_samples, &ret); + + if (ret != MYSOFA_OK) { + pw_log_error("Unable to load HRTF from %s: %d", filename, ret); + errno = ENOENT; + goto error; + } + + if (impl->blocksize <= 0) + impl->blocksize = SPA_CLAMP(impl->n_samples, 64, 256); + if (impl->tailsize <= 0) + impl->tailsize = SPA_CLAMP(4096, impl->blocksize, 32768); + + pw_log_info("using n_samples:%u %d:%d blocksize sofa:%s", impl->n_samples, + impl->blocksize, impl->tailsize, filename); + + impl->tmp0 = calloc(MAX_SAMPLES, sizeof(float)); + impl->tmp1 = calloc(MAX_SAMPLES, sizeof(float)); + impl->rate = SampleRate; + return impl; +error: + if (impl->sofa) + mysofa_close_cached(impl->sofa); + free(impl); + return NULL; +#else + pw_log_error("libmysofa is required for spatializer, but disabled at compile time"); + errno = EINVAL; + return NULL; +#endif +} + +#ifdef HAVE_LIBMYSOFA +static int +do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data, + size_t size, void *user_data) +{ + struct spatializer_impl *impl = user_data; + + if (impl->l_conv0 == NULL) { + SPA_SWAP(impl->l_conv0, impl->l_conv2); + SPA_SWAP(impl->r_conv0, impl->r_conv2); + } else { + SPA_SWAP(impl->l_conv1, impl->l_conv2); + SPA_SWAP(impl->r_conv1, impl->r_conv2); + } + impl->interpolate = impl->l_conv0 && impl->l_conv1; + + return 0; +} + +static void spatializer_reload(void * Instance) +{ + struct spatializer_impl *impl = Instance; + float *left_ir = calloc(impl->n_samples, sizeof(float)); + float *right_ir = calloc(impl->n_samples, sizeof(float)); + float left_delay; + float right_delay; + float coords3; + + for (uint8_t i = 0; i < 3; i++) + coordsi = impl->port3 + i0; + + mysofa_s2c(coords); + mysofa_getfilter_float( + impl->sofa, + coords0, + coords1, + coords2, + left_ir, + right_ir, + &left_delay, + &right_delay + ); + + // TODO: make use of delay + if ((left_delay || right_delay) && (!isnan(left_delay) || !isnan(right_delay))) { + pw_log_warn("delay dropped l: %f, r: %f", left_delay, right_delay); + } + + if (impl->l_conv2) + convolver_free(impl->l_conv2); + if (impl->r_conv2) + convolver_free(impl->r_conv2); + + impl->l_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, + left_ir, impl->n_samples); + impl->r_conv2 = convolver_new(dsp_ops, impl->blocksize, impl->tailsize, + right_ir, impl->n_samples); + + free(left_ir); + free(right_ir); + + if (impl->l_conv2 == NULL || impl->r_conv2 == NULL) { + pw_log_error("reloading left or right convolver failed"); + return; + } + spa_loop_invoke(data_loop, do_switch, 1, NULL, 0, true, impl); +} + +struct free_data { + void *item2; +}; + +static int +do_free(struct spa_loop *loop, bool async, uint32_t seq, const void *data, + size_t size, void *user_data)
View file
pipewire-0.3.65.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.66.tar.gz/src/modules/module-loopback.c
Changed
@@ -111,6 +111,32 @@ * *\endcode * + * ## Example configuration of a virtual source + * + * This Virtual source routes the front-left channel of a multi-channel input to a mono channel. + * This is useful for splitting up multi-channel inputs from USB audio interfaces that are not yet fully supported by alsa. + * + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-loopback + * args = { + * node.description = "Scarlett Focusrite Line 1" + * capture.props = { + * audio.position = FL + * stream.dont-remix = true + * node.target = "alsa_input.usb-Focusrite_Scarlett_Solo_USB_Y7ZD17C24495BC-00.analog-stereo" + * node.passive = true + * } + * playback.props = { + * node.name = "SF_mono_in_1" + * media.class = "Audio/Source" + * audio.position = MONO + * } + * } + * } + * + *\endcode + * * ## See also * * `pw-loopback` : a tool that loads the loopback module with given parameters.
View file
pipewire-0.3.65.tar.gz/src/modules/module-protocol-pulse/cmd.c -> pipewire-0.3.66.tar.gz/src/modules/module-protocol-pulse/cmd.c
Changed
@@ -76,7 +76,10 @@ /* * pulse.cmd = - * { cmd = <command> args = "<arguments>" } + * { cmd = <command> + * ( args = "<arguments>" ) + * ( flags = ( nofail ) ) + * } * ... * */
View file
pipewire-0.3.66.tar.gz/src/modules/module-rt
Added
+(directory)
View file
pipewire-0.3.66.tar.gz/src/modules/module-rt/20-pw-defaults.conf.in
Added
@@ -0,0 +1,20 @@ +# This file was installed by PipeWire project for buffer locking to always work + +# Required to memlock audio buffers for all client types +# +# This will match all PAM users i.e. those going through the login procedure but +# it should not get applied to system daemons, since they are run bypassing PAM. +# +# While at first glance this might appear very relevant, in fact abusing this +# can at most allow for either more rapid OOM or enhance malicious system memory +# thrashing while evading systemd-oomd limits that are based on the requirement +# that swap utilization must be high before issues arise. As such it's perfectly +# reasonable to just set a limit where each client can lock a few megabytes with +# nearly no impact on regular systems. Meanwhile malicious attackers can OOM +# just as they could. And instead tooling for OOM and resource abuse should be +# improved, if such denial of service attacks are a serious consideration at all. +# +# Starting with Linux 5.16 or systemd v253 the default is 8192 which is plenty +# good enough and this file should not be installed on such systems. +# +* - memlock @PAM_MEMLOCK@
View file
pipewire-0.3.66.tar.gz/src/modules/module-rt/25-pw-rlimits.conf.in
Added
@@ -0,0 +1,8 @@ +# This file was installed by PipeWire project for its libpipewire-module-rt.so + +# It's believed to be acceptable to have match rules that will never be true +# i.e. a group that does not exist. +# +@MATCH@ - rtprio @RTPRIO@ +@MATCH@ - nice @NICE@ +@MATCH@ - memlock @MEMLOCK@
View file
pipewire-0.3.66.tar.gz/src/modules/module-rt/meson.build
Added
@@ -0,0 +1,23 @@ +rlimits_install = get_option('rlimits-install') +rlimits_data = configuration_data() +rlimits_data.set('MATCH', get_option('rlimits-match')) +rlimits_data.set('RTPRIO', get_option('rlimits-rtprio')) +rlimits_data.set('NICE', get_option('rlimits-nice')) +rlimits_data.set('MEMLOCK', get_option('rlimits-memlock')) +configure_file(input: '25-pw-rlimits.conf.in', + output: '25-pw-rlimits.conf', + install: rlimits_install, + install_dir: get_option('sysconfdir') / 'security' / 'limits.d', + configuration: rlimits_data) +summary({'RLIMITs': '@0@ limits.d file affecting matching PAM users'.format(rlimits_install ? 'with' : 'without')}) + +# The pam-defaults-install related code can be removed once all Linux <5.16 kernels are EOL (projected Dec, 2026) +pam_defaults_install = get_option('pam-defaults-install') +pam_defaults_data = configuration_data() +pam_defaults_data.set('PAM_MEMLOCK', get_option('pam-memlock-default')) +configure_file(input: '20-pw-defaults.conf.in', + output: '20-pw-defaults.conf', + install: pam_defaults_install, + install_dir: get_option('sysconfdir') / 'security' / 'limits.d', + configuration: pam_defaults_data) +summary({'PAM defaults': '@0@ limits.d file affecting all PAM users (not needed with modern systemd or kernel)'.format(pam_defaults_install ? 'with' : 'without')})
View file
pipewire-0.3.65.tar.gz/src/modules/module-rtp-sink.c -> pipewire-0.3.66.tar.gz/src/modules/module-rtp-sink.c
Changed
@@ -70,6 +70,8 @@ * - `sess.min-ptime = <int>`: minimum packet time in milliseconds, default 2 * - `sess.max-ptime = <int>`: maximum packet time in milliseconds, default 20 * - `sess.name = <str>`: a session name + * - `sess.ts-offset = <int>`: an offset to apply to the timestamp, default -1 = random offset + * - `sess.ts-refclk = <string>`: the name of a reference clock * - `stream.props = {}`: properties to be passed to the stream * * ## General options @@ -149,6 +151,7 @@ #define DEFAULT_MIN_PTIME 2 #define DEFAULT_MAX_PTIME 20 +#define DEFAULT_TS_OFFSET -1 #define USAGE "sap.ip=<SAP IP address to send announce, default:"DEFAULT_SAP_IP"> " \ "sap.port=<SAP port to send on, default:"SPA_STRINGIFY(DEFAULT_SAP_PORT)"> " \ @@ -212,6 +215,8 @@ struct pw_stream *stream; struct spa_hook stream_listener; + struct spa_io_position *io_position; + unsigned int do_disconnect:1; char *ifname; @@ -220,9 +225,9 @@ int mtu; bool ttl; bool mcast_loop; - uint32_t min_ptime; - uint32_t max_ptime; - uint32_t pbytes; + float min_ptime; + float max_ptime; + uint32_t psamples; struct sockaddr_storage src_addr; socklen_t src_len; @@ -240,17 +245,20 @@ struct spa_audio_info_raw info; const struct format_info *format_info; - uint32_t frame_size; + uint32_t stride; int payload; uint16_t seq; - uint32_t timestamp; uint32_t ssrc; + uint32_t ts_offset; + char ts_refclk64; struct spa_ringbuffer ring; uint8_t bufferBUFFER_SIZE; int rtp_fd; int sap_fd; + + unsigned sync:1; }; @@ -274,20 +282,21 @@ static void flush_packets(struct impl *impl) { int32_t avail; - uint32_t index; + uint32_t stride, timestamp; struct iovec iov3; struct msghdr msg; ssize_t n; struct rtp_header header; int32_t tosend; - avail = spa_ringbuffer_get_read_index(&impl->ring, &index); - - tosend = impl->pbytes; + avail = spa_ringbuffer_get_read_index(&impl->ring, ×tamp); + tosend = impl->psamples; if (avail < tosend) return; + stride = impl->stride; + spa_zero(header); header.v = 2; header.pt = impl->payload; @@ -306,13 +315,14 @@ while (avail >= tosend) { header.sequence_number = htons(impl->seq); - header.timestamp = htonl(impl->timestamp); + header.timestamp = htonl(impl->ts_offset + timestamp); set_iovec(&impl->ring, impl->buffer, BUFFER_SIZE, - index & BUFFER_MASK, - &iov1, tosend); + (timestamp * stride) & BUFFER_MASK, + &iov1, tosend * stride); + pw_log_trace("sending %d timestamp:%d", tosend, timestamp); n = sendmsg(impl->rtp_fd, &msg, MSG_NOSIGNAL); if (n < 0) { switch (errno) { @@ -321,18 +331,18 @@ pw_log_debug("remote end not listening"); break; default: - pw_log_warn("sendmsg() failed: %m"); + pw_log_warn("sendmsg() failed, seq:%u dropped: %m", + impl->seq); break; } } impl->seq++; - impl->timestamp += tosend / impl->frame_size; - index += tosend; + timestamp += tosend; avail -= tosend; } - spa_ringbuffer_read_update(&impl->ring, index); + spa_ringbuffer_read_update(&impl->ring, timestamp); } static void stream_process(void *data) @@ -340,8 +350,8 @@ struct impl *impl = data; struct pw_buffer *buf; struct spa_data *d; - uint32_t index; - int32_t filled, wanted; + uint32_t offs, size, timestamp, expected_timestamp, stride; + int32_t filled, wanted; if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) { pw_log_debug("Out of stream buffers: %m"); @@ -349,27 +359,56 @@ } d = buf->buffer->datas; - wanted = d0.chunk->size; + offs = SPA_MIN(d0.chunk->offset, d0.maxsize); + size = SPA_MIN(d0.chunk->size, d0.maxsize - offs); + stride = impl->stride; + wanted = size / stride; + + filled = spa_ringbuffer_get_write_index(&impl->ring, &expected_timestamp); + if (SPA_LIKELY(impl->io_position)) + timestamp = impl->io_position->clock.position; + else + timestamp = expected_timestamp; + + if (impl->sync) { + if (expected_timestamp != timestamp) { + pw_log_warn("expected %u != timestamp %u", expected_timestamp, timestamp); + impl->sync = false; + } else if (filled + wanted > (int32_t)(BUFFER_SIZE / stride)) { + pw_log_warn("overrun %u + %u > %u", filled, wanted, BUFFER_SIZE / stride); + impl->sync = false; + } + } + if (!impl->sync) { + pw_log_info("sync to timestamp %u", timestamp); + impl->ring.readindex = impl->ring.writeindex = timestamp; + memset(impl->buffer, 0, BUFFER_SIZE); + impl->sync = true; + } - filled = spa_ringbuffer_get_write_index(&impl->ring, &index); + spa_ringbuffer_write_data(&impl->ring, + impl->buffer, + BUFFER_SIZE, + (timestamp * stride) & BUFFER_MASK, + SPA_PTROFF(d0.data, offs, void), wanted * stride); + timestamp += wanted; + spa_ringbuffer_write_update(&impl->ring, timestamp); - if (filled + wanted > (int32_t)BUFFER_SIZE) { - pw_log_warn("overrun %u + %u > %u", filled, wanted, BUFFER_SIZE); - } else { - spa_ringbuffer_write_data(&impl->ring, - impl->buffer, - BUFFER_SIZE, - index & BUFFER_MASK, - d0.data, wanted); - - index += wanted; - spa_ringbuffer_write_update(&impl->ring, index); - } pw_stream_queue_buffer(impl->stream, buf); flush_packets(impl); } +static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{
View file
pipewire-0.3.65.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.66.tar.gz/src/modules/module-rtp-source.c
Changed
@@ -25,6 +25,7 @@ #include "config.h" #include <limits.h> +#include <string.h> #include <unistd.h> #include <sys/stat.h> #include <sys/socket.h> @@ -84,6 +85,7 @@ * #sap.port = 9875 * #local.ifname = eth0 * sess.latency.msec = 100 + * #node.always-process = false # true to receive even when not running * stream.props = { * #media.class = "Audio/Source" * #node.name = "rtp-source" @@ -97,11 +99,14 @@ * #rtp.payload = "127" * #rtp.fmt = "L16/48000/2" * #rtp.session = "PipeWire RTP Stream on fedora" + * #rtp.ts-offset = 0 + * #rtp.ts-refclk = "private" * } * * actions = { * create-stream = { * #sess.latency.msec = 100 + * #sess.ts-direct = false * #target.object = "" * } * } @@ -169,6 +174,7 @@ char *ifname; char *sap_ip; + bool always_process; int sap_port; int sess_latency_msec; uint32_t cleanup_interval; @@ -202,6 +208,7 @@ char origin128; char session256; + char channelmap512; struct sockaddr_storage sa; socklen_t salen; @@ -212,6 +219,9 @@ const struct format_info *format_info; struct spa_audio_info_raw info; uint32_t stride; + + uint32_t ts_offset; + char refclk64; }; struct session { @@ -237,12 +247,13 @@ uint8_t bufferBUFFER_SIZE; struct spa_io_rate_match *rate_match; + struct spa_io_position *position; struct spa_dll dll; uint32_t target_buffer; - uint32_t last_packet_size; float max_error; - unsigned buffering:1; unsigned first:1; + unsigned receiving:1; + unsigned direct_timestamp:1; }; static void stream_destroy(void *d) @@ -257,8 +268,8 @@ struct session *sess = data; struct pw_buffer *buf; struct spa_data *d; - uint32_t index, target_buffer; - int32_t avail, wanted; + uint32_t wanted, timestamp, target_buffer, stride, maxsize; + int32_t avail; if ((buf = pw_stream_dequeue_buffer(sess->stream)) == NULL) { pw_log_debug("Out of stream buffers: %m"); @@ -266,38 +277,53 @@ } d = buf->buffer->datas; - wanted = buf->requested ? - SPA_MIN(buf->requested * sess->info.stride, d0.maxsize) - : d0.maxsize; + stride = sess->info.stride; - avail = spa_ringbuffer_get_read_index(&sess->ring, &index); + maxsize = d0.maxsize / stride; + wanted = buf->requested ? SPA_MIN(buf->requested, maxsize) : maxsize; - target_buffer = sess->target_buffer + sess->last_packet_size / 2; + if (sess->position && sess->direct_timestamp) { + /* in direct mode, read directly from the timestamp index, + * because sender and receiver are in sync, this would keep + * target_buffer of bytes available. */ + spa_ringbuffer_read_update(&sess->ring, + sess->position->clock.position); + } + avail = spa_ringbuffer_get_read_index(&sess->ring, ×tamp); - if (avail < wanted || sess->buffering) { - memset(d0.data, 0, wanted); - if (!sess->buffering && sess->have_sync) { - pw_log_debug("underrun %u/%u < %u, buffering...", - avail, target_buffer, wanted); - sess->buffering = true; + target_buffer = sess->target_buffer; + + if (avail < (int32_t)wanted) { + enum spa_log_level level; + memset(d0.data, 0, wanted * stride); + if (sess->have_sync) { + sess->have_sync = false; + level = SPA_LOG_LEVEL_WARN; + } else { + level = SPA_LOG_LEVEL_DEBUG; } + pw_log(level, "underrun %d/%u < %u", + avail, target_buffer, wanted); } else { float error, corr; - if (avail > (int32_t)SPA_MIN(target_buffer * 8, BUFFER_SIZE)) { + if (avail > (int32_t)SPA_MIN(target_buffer * 8, BUFFER_SIZE / stride)) { pw_log_warn("overrun %u > %u", avail, target_buffer * 8); - index += avail - target_buffer; + timestamp += avail - target_buffer; avail = target_buffer; - } else { - if (sess->first) { - if ((uint32_t)avail > target_buffer) { - uint32_t skip = avail - target_buffer; - pw_log_debug("first: avail:%d skip:%u target:%u", + } else if (sess->first) { + if ((uint32_t)avail > target_buffer) { + uint32_t skip = avail - target_buffer; + pw_log_debug("first: avail:%d skip:%u target:%u", avail, skip, target_buffer); - index += skip; - avail = target_buffer; - } - sess->first = false; + timestamp += skip; + avail = target_buffer; } + sess->first = false; + } + if (!sess->direct_timestamp) { + /* when not using direct timestamp and clocks are not + * in sync, try to adjust our playback rate to keep the + * requested target_buffer bytes in the ringbuffer */ error = (float)target_buffer - (float)avail; error = SPA_CLAMP(error, -sess->max_error, sess->max_error); @@ -307,46 +333,28 @@ target_buffer, error, corr); if (sess->rate_match) { - SPA_FLAG_SET(sess->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE); + SPA_FLAG_SET(sess->rate_match->flags, + SPA_IO_RATE_MATCH_FLAG_ACTIVE); sess->rate_match->rate = 1.0f / corr; } } spa_ringbuffer_read_data(&sess->ring, sess->buffer, BUFFER_SIZE, - index & BUFFER_MASK, - d0.data, wanted); + (timestamp * stride) & BUFFER_MASK, + d0.data, wanted * stride); - index += wanted; - spa_ringbuffer_read_update(&sess->ring, index); + timestamp += wanted; + spa_ringbuffer_read_update(&sess->ring, timestamp); } - d0.chunk->size = wanted; - d0.chunk->stride = sess->info.stride; + d0.chunk->size = wanted * stride; + d0.chunk->stride = stride; d0.chunk->offset = 0; - buf->size = wanted / sess->info.stride; + buf->size = wanted; pw_stream_queue_buffer(sess->stream, buf); } -static void on_stream_state_changed(void *d, enum pw_stream_state old, - enum pw_stream_state state, const char *error) -{ - struct session *sess = d; - struct impl *impl = sess->impl; -
View file
pipewire-0.3.65.tar.gz/src/pipewire/conf.c -> pipewire-0.3.66.tar.gz/src/pipewire/conf.c
Changed
@@ -605,10 +605,70 @@ } /* + * { + * # all keys must match the value. ~ in value starts regex. + * <key> = <value> + * ... + * } + */ +static bool find_match(struct spa_json *arr, const struct spa_dict *props) +{ + struct spa_json it1; + + while (spa_json_enter_object(arr, &it0) > 0) { + char key256, val1024; + const char *str, *value; + int match = 0, fail = 0; + int len; + + while (spa_json_get_string(&it0, key, sizeof(key)) > 0) { + bool success = false; + + if ((len = spa_json_next(&it0, &value)) <= 0) + break; + + str = spa_dict_lookup(props, key); + + if (spa_json_is_null(value, len)) { + success = str == NULL; + } else { + if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) + continue; + value = val; + len = strlen(val); + } + if (str != NULL) { + if (value0 == '~') { + regex_t preg; + if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { + if (regexec(&preg, str, 0, NULL, 0) == 0) + success = true; + regfree(&preg); + } + } 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; +} + +/* * context.modules = * { name = <module-name> - * args = { <key> = <value> ... } - * flags = ifexists nofail + * ( args = { <key> = <value> ... } ) + * ( flags = ( ifexists ) ( nofail ) + * ( condition = { key = value, .. } .. ) * } * */ @@ -617,7 +677,7 @@ { struct data *d = user_data; struct pw_context *context = d->context; - struct spa_json it3; + struct spa_json it4; char key512, *s; int res = 0; @@ -631,6 +691,7 @@ while (spa_json_enter_object(&it1, &it2) > 0) { char *name = NULL, *args = NULL, *flags = NULL; + bool have_match = true; while (spa_json_get_string(&it2, key, sizeof(key)) > 0) { const char *val; @@ -653,8 +714,16 @@ len = spa_json_container_len(&it2, val, len); flags = (char*)val; spa_json_parse_stringn(val, len, flags, len+1); + } else if (spa_streq(key, "condition")) { + if (!spa_json_is_array(val, len)) + break; + spa_json_enter(&it2, &it3); + have_match = find_match(&it3, &context->properties->dict); } } + if (!have_match) + continue; + if (name != NULL) res = load_module(context, name, args, flags); @@ -698,8 +767,9 @@ /* * context.objects = * { factory = <factory-name> - * args = { <key> = <value> ... } - * flags = nofail + * ( args = { <key> = <value> ... } ) + * ( flags = ( nofail ) ) + * ( condition = { key = value, .. } .. ) * } * */ @@ -708,7 +778,7 @@ { struct data *d = user_data; struct pw_context *context = d->context; - struct spa_json it3; + struct spa_json it4; char key512, *s; int res = 0; @@ -722,6 +792,7 @@ while (spa_json_enter_object(&it1, &it2) > 0) { char *factory = NULL, *args = NULL, *flags = NULL; + bool have_match = true; while (spa_json_get_string(&it2, key, sizeof(key)) > 0) { const char *val; @@ -745,8 +816,16 @@ flags = (char*)val; spa_json_parse_stringn(val, len, flags, len+1); + } else if (spa_streq(key, "condition")) { + if (!spa_json_is_array(val, len)) + break; + spa_json_enter(&it2, &it3); + have_match = find_match(&it3, &context->properties->dict); } } + if (!have_match) + continue; + if (factory != NULL) res = create_object(context, factory, args, flags); @@ -807,8 +886,9 @@ /* * context.exec = - * { path = <program-name> - * args = "<arguments>" + * { path = <program-name> + * ( args = "<arguments>" ) + * ( condition = { key = value, .. } .. ) * } * */ @@ -817,7 +897,7 @@ { struct data *d = user_data; struct pw_context *context = d->context; - struct spa_json it3; + struct spa_json it4; char key512, *s; int res = 0; @@ -831,6 +911,7 @@ while (spa_json_enter_object(&it1, &it2) > 0) { char *path = NULL, *args = NULL; + bool have_match = true; while (spa_json_get_string(&it2, key, sizeof(key)) > 0) { const char *val; @@ -845,8 +926,16 @@ } else if (spa_streq(key, "args")) { args = (char*)val; spa_json_parse_stringn(val, len, args, len+1); + } else if (spa_streq(key, "condition")) { + if (!spa_json_is_array(val, len)) + break; + spa_json_enter(&it2, &it3); + have_match = find_match(&it3, &context->properties->dict); } } + if (!have_match) + continue; + if (path != NULL) res = do_exec(context, path, args); @@ -1014,65 +1103,6 @@
View file
pipewire-0.3.65.tar.gz/src/pipewire/context.c -> pipewire-0.3.66.tar.gz/src/pipewire/context.c
Changed
@@ -970,15 +970,114 @@ return fa < fb ? -1 : (fa > fb ? 1 : 0); } -static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t best) +static inline uint32_t calc_gcd(uint32_t a, uint32_t b) { - uint32_t i; + while (b != 0) { + uint32_t temp = a; + a = b; + b = temp % b; + } + return a; +} + +struct rate_info { + uint32_t rate; + uint32_t gcd; + uint32_t diff; +}; + +static inline void update_highest_rate(struct rate_info *best, struct rate_info *current) +{ + /* find highest rate */ + if (best->rate == 0 || best->rate < current->rate) + *best = *current; +} + +static inline void update_nearest_gcd(struct rate_info *best, struct rate_info *current) +{ + /* find nearest GCD */ + if (best->rate == 0 || + (best->gcd < current->gcd) || + (best->gcd == current->gcd && best->diff > current->diff)) + *best = *current; +} +static inline void update_nearest_rate(struct rate_info *best, struct rate_info *current) +{ + /* find nearest rate */ + if (best->rate == 0 || best->diff > current->diff) + *best = *current; +} + +static uint32_t find_best_rate(const uint32_t *rates, uint32_t n_rates, uint32_t rate, uint32_t def) +{ + uint32_t i, limit; + struct rate_info best; + struct rate_info infon_rates; + + for (i = 0; i < n_rates; i++) { + infoi.rate = ratesi; + infoi.gcd = calc_gcd(rate, ratesi); + infoi.diff = SPA_ABS((int32_t)rate - (int32_t)ratesi); + } + + /* first find higher nearest GCD. This tries to find next bigest rate that + * requires the least amount of resample filter banks. Usually these are + * rates that are multiples of eachother or multiples of a common rate. + * + * 44100 and 32000 56000 88200 96000 -> 88200 + * 48000 and 32000 56000 88200 96000 -> 96000 + * 88200 and 44100 48000 96000 192000 -> 96000 + * 32000 and 44100 192000 -> 44100 + * 8000 and 44100 48000 -> 48000 + * 8000 and 44100 192000 -> 44100 + * 11025 and 44100 48000 -> 44100 + * 44100 and 48000 176400 -> 48000 + */ + spa_zero(best); + /* Don't try to do excessive upsampling by limiting the max rate + * for desired < default to default*2. For other rates allow + * a x3 upsample rate max */ + limit = rate < def ? def*2 : rate*3; + for (i = 0; i < n_rates; i++) { + if (infoi.rate >= rate && infoi.rate <= limit) + update_nearest_gcd(&best, &infoi); + } + if (best.rate != 0) + return best.rate; + + /* we would need excessive upsampling, pick a nearest higher rate */ + spa_zero(best); + for (i = 0; i < n_rates; i++) { + if (infoi.rate >= rate) + update_nearest_rate(&best, &infoi); + } + if (best.rate != 0) + return best.rate; + + /* There is nothing above the rate, we need to downsample. Try to downsample + * but only to something that is from a common rate family. Also don't + * try to downsample to something that will sound worse (< 44100). + * + * 88200 and 22050 44100 48000 -> 44100 + * 88200 and 22050 48000 -> 48000 + */ + spa_zero(best); for (i = 0; i < n_rates; i++) { - if (SPA_ABS((int32_t)rate - (int32_t)ratesi) < - SPA_ABS((int32_t)rate - (int32_t)best)) - best = ratesi; + if (infoi.rate >= 44100) + update_nearest_gcd(&best, &infoi); } - return best; + if (best.rate != 0) + return best.rate; + + /* There is nothing to downsample above our threshold. Downsample to whatever + * is the highest rate then. */ + spa_zero(best); + for (i = 0; i < n_rates; i++) + update_highest_rate(&best, &infoi); + if (best.rate != 0) + return best.rate; + + return def; } /* here we evaluate the complete state of the graph. @@ -1201,10 +1300,12 @@ running = true; current_rate = n->current_rate.denom; - if (lock_rate || n->reconfigure || + if (lock_rate || n->reconfigure || !running || (!force_rate && (n->info.state > PW_NODE_STATE_IDLE))) /* when someone wants us to lock the rate of this driver or + * when we are in the process of reconfiguring the driver or + * when we are not running any followers or * when the driver is busy and we don't need to force a rate, * keep the current rate */ target_rate = current_rate;
View file
pipewire-0.3.65.tar.gz/src/pipewire/filter.c -> pipewire-0.3.66.tar.gz/src/pipewire/filter.c
Changed
@@ -95,15 +95,15 @@ struct pw_properties *props; - uint32_t change_mask_all; + uint64_t change_mask_all; struct spa_port_info info; struct spa_list param_list; -#define IDX_EnumFormat 0 -#define IDX_Meta 1 -#define IDX_IO 2 -#define IDX_Format 3 -#define IDX_Buffers 4 -#define IDX_Latency 5 +#define PORT_EnumFormat 0 +#define PORT_Meta 1 +#define PORT_IO 2 +#define PORT_Format 3 +#define PORT_Buffers 4 +#define PORT_Latency 5 #define N_PORT_PARAMS 6 struct spa_param_info paramsN_PORT_PARAMS; @@ -133,6 +133,7 @@ struct spa_node impl_node; struct spa_hook_list hooks; struct spa_callbacks callbacks; + struct spa_io_clock *clock; struct spa_io_position *position; struct { @@ -142,12 +143,12 @@ struct spa_list port_list; struct pw_map ports2; - uint32_t change_mask_all; + uint64_t change_mask_all; struct spa_node_info info; struct spa_list param_list; -#define IDX_PropInfo 0 -#define IDX_Props 1 -#define IDX_ProcessLatency 2 +#define NODE_PropInfo 0 +#define NODE_Props 1 +#define NODE_ProcessLatency 2 #define N_NODE_PARAMS 3 struct spa_param_info paramsN_NODE_PARAMS; @@ -168,17 +169,18 @@ unsigned int allow_mlock:1; unsigned int warn_mlock:1; unsigned int process_rt:1; + unsigned int driving:1; }; static int get_param_index(uint32_t id) { switch (id) { case SPA_PARAM_PropInfo: - return IDX_PropInfo; + return NODE_PropInfo; case SPA_PARAM_Props: - return IDX_Props; + return NODE_Props; case SPA_PARAM_ProcessLatency: - return IDX_ProcessLatency; + return NODE_ProcessLatency; default: return -1; } @@ -188,17 +190,17 @@ { switch (id) { case SPA_PARAM_EnumFormat: - return IDX_EnumFormat; + return PORT_EnumFormat; case SPA_PARAM_Meta: - return IDX_Meta; + return PORT_Meta; case SPA_PARAM_IO: - return IDX_IO; + return PORT_IO; case SPA_PARAM_Format: - return IDX_Format; + return PORT_Format; case SPA_PARAM_Buffers: - return IDX_Buffers; + return PORT_Buffers; case SPA_PARAM_Latency: - return IDX_Latency; + return PORT_Latency; default: return -1; } @@ -475,6 +477,12 @@ pw_log_debug("%p: io %d %p/%zd", impl, id, data, size); switch(id) { + case SPA_IO_Clock: + if (data && size >= sizeof(struct spa_io_clock)) + impl->clock = data; + else + impl->clock = NULL; + break; case SPA_IO_Position: if (data && size >= sizeof(struct spa_io_position)) impl->position = data; @@ -484,6 +492,7 @@ do_set_position, 1, NULL, 0, true, impl); break; } + impl->driving = impl->clock && impl->position && impl->position->clock.id == impl->clock->id; pw_filter_emit_io_changed(&impl->this, NULL, id, data, size); return 0; @@ -1530,9 +1539,9 @@ impl->info.max_output_ports = UINT32_MAX; impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0; impl->info.props = &filter->properties->dict; - impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); - impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); - impl->paramsIDX_ProcessLatency = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0); + impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); + impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); + impl->paramsNODE_ProcessLatency = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0); impl->info.params = impl->params; impl->info.n_params = N_NODE_PARAMS; impl->info.change_mask = impl->change_mask_all; @@ -1712,12 +1721,12 @@ p->info.flags |= SPA_PORT_FLAG_CAN_ALLOC_BUFFERS; p->info.props = &p->props->dict; p->change_mask_all |= SPA_PORT_CHANGE_MASK_PARAMS; - p->paramsIDX_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0); - p->paramsIDX_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0); - p->paramsIDX_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0); - p->paramsIDX_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); - p->paramsIDX_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); - p->paramsIDX_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE); + p->paramsPORT_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0); + p->paramsPORT_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0); + p->paramsPORT_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0); + p->paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + p->paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + p->paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE); p->info.params = p->params; p->info.n_params = N_PORT_PARAMS; @@ -1749,22 +1758,23 @@ return NULL; } -SPA_EXPORT -int pw_filter_remove_port(void *port_data) +static inline void free_port(struct filter *impl, struct port *port) { - struct port *port = SPA_CONTAINER_OF(port_data, struct port, user_data); - struct filter *impl = port->filter; - - spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL); - spa_list_remove(&port->link); + spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL); pw_map_remove(&impl->portsport->direction, port->id); - clear_buffers(port); clear_params(impl, port, SPA_ID_INVALID); pw_properties_free(port->props); free(port); +} +SPA_EXPORT +int pw_filter_remove_port(void *port_data) +{ + struct port *port = SPA_CONTAINER_OF(port_data, struct port, user_data); + struct filter *impl = port->filter; + free_port(impl, port); return 0; } @@ -1844,25 +1854,6 @@ return 0; } -static int -do_process(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct filter *impl = user_data; - int res = impl_node_process(impl); - return spa_node_call_ready(&impl->callbacks, res); -} - -static inline int call_trigger(struct filter *impl) -{ - int res = 0; - if (SPA_FLAG_IS_SET(impl->flags, PW_FILTER_FLAG_DRIVER)) { - res = pw_loop_invoke(impl->context->data_loop, - do_process, 1, NULL, 0, false, impl); - } - return res;
View file
pipewire-0.3.65.tar.gz/src/pipewire/filter.h -> pipewire-0.3.66.tar.gz/src/pipewire/filter.h
Changed
@@ -239,6 +239,16 @@ * be called when all data is played or recorded */ int pw_filter_flush(struct pw_filter *filter, bool drain); +/** Check if the filter is driving. The filter needs to have the + * PW_FILTER_FLAG_DRIVER set. When the filter is driving, + * pw_filter_trigger_process() needs to be called when data is + * available (output) or needed (input). Since 0.3.66 */ +bool pw_filter_is_driving(struct pw_filter *filter); + +/** Trigger a push/pull on the filter. One iteration of the graph will + * be scheduled and process() will be called. Since 0.3.66 */ +int pw_filter_trigger_process(struct pw_filter *filter); + /** * \} */
View file
pipewire-0.3.65.tar.gz/src/pipewire/impl-core.c -> pipewire-0.3.66.tar.gz/src/pipewire/impl-core.c
Changed
@@ -351,7 +351,7 @@ if (obj == NULL) goto error_create_failed; - return 0; + return obj; error_no_factory: res = -ENOENT;
View file
pipewire-0.3.65.tar.gz/src/pipewire/keys.h -> pipewire-0.3.66.tar.gz/src/pipewire/keys.h
Changed
@@ -342,8 +342,13 @@ * and object name or object.serial */ #ifndef PW_REMOVE_DEPRECATED -#define PW_KEY_PRIORITY_MASTER PW_DEPRECATED("priority.master") /**< deprecated, use priority.driver */ -#define PW_KEY_NODE_TARGET PW_DEPRECATED("node.target") /**< deprecated since 0.3.64, use target.object. */ +# ifdef PW_ENABLE_DEPRECATED +# define PW_KEY_PRIORITY_MASTER "priority.master" /**< deprecated, use priority.driver */ +# define PW_KEY_NODE_TARGET "node.target" /**< deprecated since 0.3.64, use target.object. */ +# else +# define PW_KEY_PRIORITY_MASTER PW_DEPRECATED("priority.master") +# define PW_KEY_NODE_TARGET PW_DEPRECATED("node.target") +# endif /* PW_ENABLE_DEPRECATED */ #endif /* PW_REMOVE_DEPRECATED */ /** \}
View file
pipewire-0.3.65.tar.gz/src/pipewire/log.c -> pipewire-0.3.66.tar.gz/src/pipewire/log.c
Changed
@@ -29,6 +29,7 @@ #include <spa/pod/pod.h> #include <spa/debug/types.h> +#include <spa/debug/format.h> #include <spa/pod/iter.h> #include <spa/utils/list.h> @@ -241,13 +242,14 @@ { struct spa_debug_log_ctx ctx = SPA_LOGF_DEBUG_INIT(global_log, level, topic, file, line, func ); - if (flags & PW_LOG_OBJECT_POD) { + if (object == NULL) { + pw_log_logt(level, topic, file, line, func, "NULL"); + } else { const struct spa_pod *pod = object; - if (pod == NULL) { - pw_log_logt(level, topic, file, line, func, "NULL"); - } else { + if (flags & PW_LOG_OBJECT_POD) spa_debugc_pod(&ctx.ctx, 0, SPA_TYPE_ROOT, pod); - } + else if (flags & PW_LOG_OBJECT_FORMAT) + spa_debugc_format(&ctx.ctx, 0, NULL, pod); } }
View file
pipewire-0.3.65.tar.gz/src/pipewire/mem.c -> pipewire-0.3.66.tar.gz/src/pipewire/mem.c
Changed
@@ -33,6 +33,7 @@ #include <unistd.h> #include <stdlib.h> #include <sys/syscall.h> +#include <sys/stat.h> #include <spa/utils/list.h> #include <spa/buffer/buffer.h> @@ -363,6 +364,23 @@ struct mapping *m; struct memmap *mm; struct pw_map_range range; + struct stat sb; + + if (fstat(b->this.fd, &sb) != 0) + return NULL; + + const bool valid = (int64_t) offset + size <= (int64_t) sb.st_size; + pw_log(valid ? SPA_LOG_LEVEL_DEBUG : SPA_LOG_LEVEL_ERROR, + "%p: block %p%u mapping %" PRIu32 "+%" PRIu32 " of file=%d/%" PRIu64 ":%" PRIu64 " with size=%" PRId64, + block->pool, block, block->id, + offset, size, + block->fd, (uint64_t) sb.st_dev, (uint64_t) sb.st_ino, + (int64_t) sb.st_size); + + if (!valid) { + errno = -EINVAL; + return NULL; + } pw_map_range_init(&range, offset, size, p->pagesize);
View file
pipewire-0.3.65.tar.gz/src/pipewire/private.h -> pipewire-0.3.66.tar.gz/src/pipewire/private.h
Changed
@@ -1276,6 +1276,7 @@ void pw_impl_client_unref(struct pw_impl_client *client); #define PW_LOG_OBJECT_POD (1<<0) +#define PW_LOG_OBJECT_FORMAT (1<<1) void pw_log_log_object(enum spa_log_level level, const struct spa_log_topic *topic, const char *file, int line, const char *func, uint32_t flags, const void *object); @@ -1288,7 +1289,7 @@ }) #define pw_log_pod(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_POD,pod) -#define pw_log_format(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_POD,pod) +#define pw_log_format(lev,pod) pw_log_object(lev,PW_LOG_TOPIC_DEFAULT,PW_LOG_OBJECT_FORMAT,pod) bool pw_log_is_default(void);
View file
pipewire-0.3.65.tar.gz/src/pipewire/stream.c -> pipewire-0.3.66.tar.gz/src/pipewire/stream.c
Changed
@@ -123,7 +123,7 @@ struct spa_io_position *position; } rt; - uint32_t port_change_mask_all; + uint64_t port_change_mask_all; struct spa_port_info port_info; struct pw_properties *port_props; #define PORT_EnumFormat 0 @@ -137,7 +137,7 @@ struct spa_list param_list; - uint32_t change_mask_all; + uint64_t change_mask_all; struct spa_node_info info; #define NODE_PropInfo 0 #define NODE_Props 1
View file
pipewire-0.3.65.tar.gz/src/pipewire/thread-loop.c -> pipewire-0.3.66.tar.gz/src/pipewire/thread-loop.c
Changed
@@ -435,7 +435,7 @@ * */ SPA_EXPORT -int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime) +int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, const struct timespec *abstime) { int ret; loop->n_waiting++;
View file
pipewire-0.3.65.tar.gz/src/pipewire/thread-loop.h -> pipewire-0.3.66.tar.gz/src/pipewire/thread-loop.h
Changed
@@ -153,7 +153,7 @@ /** Release the lock and wait up to \a abstime until some thread calls * \ref pw_thread_loop_signal. Use \ref pw_thread_loop_get_time to make a timeout. * Since: 0.3.7 */ -int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, struct timespec *abstime); +int pw_thread_loop_timed_wait_full(struct pw_thread_loop *loop, const struct timespec *abstime); /** Signal all threads waiting with \ref pw_thread_loop_wait */ void pw_thread_loop_signal(struct pw_thread_loop *loop, bool wait_for_accept);
View file
pipewire-0.3.65.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.66.tar.gz/src/tools/pw-cat.c
Changed
@@ -255,14 +255,13 @@ static int encoded_playback_fill(struct data *d, void *dest, unsigned int n_frames) { int ret, size = 0; - uint8_t buffer16384 = { 0 }; + uint8_t buffer16384; - ret = fread(buffer, 1, 16384, d->encoded_file); + ret = fread(buffer, 1, SPA_MIN(n_frames, sizeof(buffer)), d->encoded_file); if (ret > 0) { memcpy(dest, buffer, ret); size = ret; } - return (int)size; } @@ -786,31 +785,6 @@ n_frames = d->maxsize / data->stride; n_frames = SPA_MIN(n_frames, (int)b->requested); -#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION - n_fill_frames = data->fill(data, p, n_frames); - - if (n_fill_frames > 0 || n_frames == 0) { - d->chunk->offset = 0; - if (data->data_type == TYPE_ENCODED) { - d->chunk->stride = 0; - // encoded_playback_fill returns number of bytes - // read and not number of frames like other - // functions for raw audio. - d->chunk->size = n_fill_frames; - b->size = n_fill_frames; - } else { - d->chunk->stride = data->stride; - d->chunk->size = n_fill_frames * data->stride; - b->size = n_frames; - } - have_data = true; - } else if (n_fill_frames < 0) { - fprintf(stderr, "fill error %d\n", n_fill_frames); - } else { - if (data->verbose) - printf("drain start\n"); - } -#else n_fill_frames = data->fill(data, p, n_frames); if (n_fill_frames > 0 || n_frames == 0) { @@ -825,7 +799,6 @@ if (data->verbose) printf("drain start\n"); } -#endif } else { offset = SPA_MIN(d->chunk->offset, d->maxsize); size = SPA_MIN(d->chunk->size, d->maxsize - offset);
View file
pipewire-0.3.66.tar.gz/subprojects/libcamera.wrap
Added
@@ -0,0 +1,3 @@ +wrap-git +url = https://git.libcamera.org/libcamera/libcamera.git +revision = head
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
.