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 61
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed Jan 7 20:28:17 UTC 2026 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.5.84 + +------------------------------------------------------------------- Sat Nov 15 13:00:32 UTC 2025 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.5.83
View file
pipewire-aptx.spec
Changed
@@ -8,7 +8,7 @@ %define minimum_version 1.5.0 Name: pipewire-aptx -Version: 1.5.83 +Version: 1.5.84 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
_service:download_files:pipewire-1.5.83.tar.bz2/NEWS -> _service:download_files:pipewire-1.5.84.tar.bz2/NEWS
Changed
@@ -1,16 +1,61 @@ -# PipeWire 1.5.83 (2025-11-06) +# PipeWire 1.5.84 (2025-11-27) -This is the third 1.6 release candidate that is API and ABI +This is the fourth 1.6 release candidate that is API and ABI compatible with previous 1.4.x, 1.2.x and 1.0.x releases. Changes since the last pre-release: ## Highlights - - Include the NEWS and updated version number. + - Capabilities wer added to improve negotiation over links. + - The audio resampler now has a configurable window function to better + tune the resampler quality. A kaiser and blackman window was added + and the default parameters were tuned. + - Various small fixes and improvements. + +## PipeWire + - Capabilities and PeerCapabilities were added to exchange key/value + pairs between consumer and producer right after a link is made. This + can be used to detect how the negotiation of formats and buffers + should be done. + +## Modules + - Avoid segfaults in RTP source. (#4970) + - The AVB module has seen some improvements. + +## Pulse-server + - @NONE@ can now be used to clear the default sink/source. + +## SPA + - Support longer convolver filenames and also support inline + IRs. + - The audio resampler window function is now selectable and + configurable. A kaiser window and blackman window was added + and the default qualities were tweaked to improve quality. + - The filter-graph convolver latency is now set by default to + something more sensible. (0 by default and N/2 for hilbert). + (#4980) + +## Bluetooth + - Better xrun and error handling for iso streams. + - The +CNUM reply was fixed. + - The CIEC call status was fixed. (#1744) + - Add BAP context metadata to improve compatibility. + - Improve compatiblity with Creative Zen Hybrid Pro by releasing + transports simultaneously. Older versions: +# PipeWire 1.5.83 (2025-11-06) + +This is the third 1.6 release candidate that is API and ABI +compatible with previous 1.4.x, 1.2.x and 1.0.x releases. + +Changes since the last pre-release: + +## Highlights + - Include the NEWS and updated version number. + # PipeWire 1.5.82 (2025-11-06) This is the second 1.6 release candidate that is API and ABI
View file
_service:download_files:pipewire-1.5.83.tar.bz2/doc/dox/config/pipewire-client.conf.5.md -> _service:download_files:pipewire-1.5.84.tar.bz2/doc/dox/config/pipewire-client.conf.5.md
Changed
@@ -59,6 +59,14 @@ #node.autoconnect = true #resample.disable = false #resample.quality = 4 + #resample.window = exp # blackman kaiser + #resample.cutoff = 0.0 + #resample.n-taps = 0 + #resample.param.exp.A = 0.0 + #resample.param.blackman.alpha = 0.0 + #resample.param.kaiser.alpha = 0.0 + #resample.param.kaiser.stopband-attenuation = 0.0 + #resample.param.kaiser.transition-bandwidth = 0.0 #monitor.channel-volumes = false #channelmix.disable = false #channelmix.min-volume = 0.0
View file
_service:download_files:pipewire-1.5.83.tar.bz2/doc/dox/config/pipewire-props.7.md -> _service:download_files:pipewire-1.5.84.tar.bz2/doc/dox/config/pipewire-props.7.md
Changed
@@ -558,6 +558,41 @@ Disable the resampler entirely. The node will only be able to negotiate with the graph when the samplerates are compatible. +@PAR@ node-prop resample.window = exp +The resampler window function to use. By default an exponential window function is used +that gives a good balance between complexitiy and quality. + +You can also specify a blackman or kaiser window, both with different tradeoffs. + +@PAR@ node-prop resample.cutoff = 0.0 +The resampler cutoff frequency. A value of 0.0 will use a predefined value based on +the resampler quality. + +@PAR@ node-prop resample.n-taps = 0 +The resampler number of taps. A value of 0 will use a predefined value based on +the resampler quality or other window function parameters. + +@PAR@ node-prop resample.param.exp.A = 0.0 +The A parameter for the exponential window function. A value of 0.0 will use a predefined +value based on the quality when the exp window is in use. + +@PAR@ node-prop resample.param.blackman.alpha = 0.0 +The alpha value of the blackman function. A value of 0.0 will use a predefined +value based on the quality when the blackman window is in use. + +@PAR@ node-prop resample.param.kaiser.stopband-attenuation = 0.0 +The kaiser window stopband attenuation parameter. A default value of 0.0 will use a +predefined value based on the quality. + +@PAR@ node-prop resample.param.kaiser.transition-bandwidth = 0.0 +The kaiser window transition bandwidth parameter. A default value of 0.0 will use a +predefined value based on the quality. + +@PAR@ node-prop resample.param.kaiser.alpha = 0.0 +The kaiser window alpha parameter. A default value of 0.0 will calculate an alpha value +based on the stopband-attenuation and transition-bandwidth parameters. + + ## Channel Mixer Parameters Source, sinks, capture and playback streams can apply channel mixing on the incoming signal.
View file
_service:download_files:pipewire-1.5.83.tar.bz2/doc/dox/internals/protocol.dox -> _service:download_files:pipewire-1.5.84.tar.bz2/doc/dox/internals/protocol.dox
Changed
@@ -1130,6 +1130,8 @@ |<----------------------------------------| | ClientNode::PortSetMixInfo | mixer inputs for each linked port |<----------------------------------------| + | ClientNode::PortSetParam | PeerCapability of the ports + |<----------------------------------------| | ClientNode::PortSetParam | Latency of the ports |<----------------------------------------| | ClientNode::SetActivation | activation of port peers
View file
_service:download_files:pipewire-1.5.83.tar.bz2/meson.build -> _service:download_files:pipewire-1.5.84.tar.bz2/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '1.5.83', + version : '1.5.84', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3',
View file
_service:download_files:pipewire-1.5.83.tar.bz2/po/sl.po -> _service:download_files:pipewire-1.5.84.tar.bz2/po/sl.po
Changed
@@ -9,16 +9,16 @@ "Project-Id-Version: PipeWire master\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" "issues\n" -"POT-Creation-Date: 2025-09-11 03:34+0000\n" -"PO-Revision-Date: 2025-09-11 11:47+0200\n" +"POT-Creation-Date: 2025-11-04 03:33+0000\n" +"PO-Revision-Date: 2025-11-08 15:23+0100\n" "Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n" "Language-Team: Slovenian <gnome-si@googlegroups.com>\n" "Language: sl\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && " -"n%100<=4 ? 2 : 3);\n" +"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && n" +"%100<=4 ? 2 : 3);\n" "X-Generator: Poedit 2.2.1\n" #: src/daemon/pipewire.c:29 @@ -57,7 +57,7 @@ msgid "Dummy Output" msgstr "Lažni izhod" -#: src/modules/module-pulse-tunnel.c:760 +#: src/modules/module-pulse-tunnel.c:761 #, c-format msgid "Tunnel for %s@%s" msgstr "Prehod za %s@%s" @@ -76,7 +76,7 @@ msgid "%s on %s" msgstr "%s na %s" -#: src/tools/pw-cat.c:1084 +#: src/tools/pw-cat.c:1096 #, c-format msgid "" "%s options <file>|-\n" @@ -92,7 +92,7 @@ "\n" "</file>\n" -#: src/tools/pw-cat.c:1091 +#: src/tools/pw-cat.c:1103 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -129,7 +129,7 @@ " -P --properties Nastavi lastnosti vozlišča\n" "\n" -#: src/tools/pw-cat.c:1109 +#: src/tools/pw-cat.c:1121 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -167,12 +167,12 @@ " -q --quality Kakovost prevzorčenja (0 - 15) " "(privzeto %d)\n" " -a, --raw neobdelan način (RAW)\n" -" -M, --force-midi Vsili zapis midi, eden izmed " -"\"midi\" ali \"ump\" (privzeto ump)\n" +" -M, --force-midi Vsili zapis midi, eden izmed \"midi" +"\" ali \"ump\" (privzeto ump)\n" " -n, --sample-count ŠTEVEC Ustavi po ŠTEVEC vzorcih\n" "\n" -#: src/tools/pw-cat.c:1129 +#: src/tools/pw-cat.c:1141 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -212,203 +212,203 @@ " -m, --monitor Spremljaj dejavnosti\n" "\n" -#: spa/plugins/alsa/acp/acp.c:351 +#: spa/plugins/alsa/acp/acp.c:361 msgid "Pro Audio" msgstr "Profesionalni zvok" -#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635 -#: spa/plugins/bluez5/bluez5-device.c:1974 +#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699 +#: spa/plugins/bluez5/bluez5-device.c:1976 msgid "Off" msgstr "Izklopljeno" -#: spa/plugins/alsa/acp/acp.c:610 +#: spa/plugins/alsa/acp/acp.c:620 #, c-format msgid "%s ALSA UCM error" msgstr "%s napaka ALSA UCM" -#: spa/plugins/alsa/acp/alsa-mixer.c:2652 +#: spa/plugins/alsa/acp/alsa-mixer.c:2721 msgid "Input" msgstr "Vhod" -#: spa/plugins/alsa/acp/alsa-mixer.c:2653 +#: spa/plugins/alsa/acp/alsa-mixer.c:2722 msgid "Docking Station Input" msgstr "Vhod priklopne postaje" -#: spa/plugins/alsa/acp/alsa-mixer.c:2654 +#: spa/plugins/alsa/acp/alsa-mixer.c:2723 msgid "Docking Station Microphone" msgstr "Mikrofon priklopne postaje" -#: spa/plugins/alsa/acp/alsa-mixer.c:2655 +#: spa/plugins/alsa/acp/alsa-mixer.c:2724 msgid "Docking Station Line In" msgstr "Linijski vhod priklopne postaje" -#: spa/plugins/alsa/acp/alsa-mixer.c:2656 -#: spa/plugins/alsa/acp/alsa-mixer.c:2747 +#: spa/plugins/alsa/acp/alsa-mixer.c:2725 +#: spa/plugins/alsa/acp/alsa-mixer.c:2816 msgid "Line In" msgstr "Linijski vhod" -#: spa/plugins/alsa/acp/alsa-mixer.c:2657 -#: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:2372 +#: spa/plugins/alsa/acp/alsa-mixer.c:2726 +#: spa/plugins/alsa/acp/alsa-mixer.c:2810 +#: spa/plugins/bluez5/bluez5-device.c:2374 msgid "Microphone" msgstr "Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2658 -#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +#: spa/plugins/alsa/acp/alsa-mixer.c:2727 +#: spa/plugins/alsa/acp/alsa-mixer.c:2811 msgid "Front Microphone" msgstr "Sprednji mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2659 -#: spa/plugins/alsa/acp/alsa-mixer.c:2743 +#: spa/plugins/alsa/acp/alsa-mixer.c:2728 +#: spa/plugins/alsa/acp/alsa-mixer.c:2812 msgid "Rear Microphone" msgstr "Zadnji mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2660 +#: spa/plugins/alsa/acp/alsa-mixer.c:2729 msgid "External Microphone" msgstr "Zunanji mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2661 -#: spa/plugins/alsa/acp/alsa-mixer.c:2745 +#: spa/plugins/alsa/acp/alsa-mixer.c:2730 +#: spa/plugins/alsa/acp/alsa-mixer.c:2814 msgid "Internal Microphone" msgstr "Notranji mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2662 -#: spa/plugins/alsa/acp/alsa-mixer.c:2748 +#: spa/plugins/alsa/acp/alsa-mixer.c:2731 +#: spa/plugins/alsa/acp/alsa-mixer.c:2817 msgid "Radio" msgstr "Radio" -#: spa/plugins/alsa/acp/alsa-mixer.c:2663 -#: spa/plugins/alsa/acp/alsa-mixer.c:2749 +#: spa/plugins/alsa/acp/alsa-mixer.c:2732 +#: spa/plugins/alsa/acp/alsa-mixer.c:2818 msgid "Video" msgstr "Video" -#: spa/plugins/alsa/acp/alsa-mixer.c:2664 +#: spa/plugins/alsa/acp/alsa-mixer.c:2733 msgid "Automatic Gain Control" msgstr "Samodejni nadzor ojačanja" -#: spa/plugins/alsa/acp/alsa-mixer.c:2665 +#: spa/plugins/alsa/acp/alsa-mixer.c:2734 msgid "No Automatic Gain Control" msgstr "Brez samodejnega nadzora ojačanja" -#: spa/plugins/alsa/acp/alsa-mixer.c:2666 +#: spa/plugins/alsa/acp/alsa-mixer.c:2735 msgid "Boost" msgstr "Ojačitev" -#: spa/plugins/alsa/acp/alsa-mixer.c:2667 +#: spa/plugins/alsa/acp/alsa-mixer.c:2736 msgid "No Boost" msgstr "Brez ojačitve" -#: spa/plugins/alsa/acp/alsa-mixer.c:2668 +#: spa/plugins/alsa/acp/alsa-mixer.c:2737 msgid "Amplifier" msgstr "Ojačevalnik" -#: spa/plugins/alsa/acp/alsa-mixer.c:2669 +#: spa/plugins/alsa/acp/alsa-mixer.c:2738 msgid "No Amplifier" msgstr "Brez ojačevalnika"
View file
_service:download_files:pipewire-1.5.83.tar.bz2/po/zh_CN.po -> _service:download_files:pipewire-1.5.84.tar.bz2/po/zh_CN.po
Changed
@@ -13,8 +13,8 @@ "Project-Id-Version: pipewire.master-tx\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" "issues\n" -"POT-Creation-Date: 2025-11-04 15:35+0000\n" -"PO-Revision-Date: 2025-11-05 07:47+0800\n" +"POT-Creation-Date: 2025-11-25 15:35+0000\n" +"PO-Revision-Date: 2025-11-26 10:19+0800\n" "Last-Translator: lumingzh <lumingzh@qq.com>\n" "Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n" "Language: zh_CN\n" @@ -79,7 +79,7 @@ msgid "%s on %s" msgstr "%2$s 上的 %1$s" -#: src/tools/pw-cat.c:1096 +#: src/tools/pw-cat.c:1088 #, c-format msgid "" "%s options <file>|-\n" @@ -94,7 +94,7 @@ " -v, --verbose 输出详细操作\n" "\n" -#: src/tools/pw-cat.c:1103 +#: src/tools/pw-cat.c:1095 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -126,7 +126,7 @@ " -P --properties 设置节点属性\n" "\n" -#: src/tools/pw-cat.c:1121 +#: src/tools/pw-cat.c:1113 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -134,8 +134,8 @@ " --channels Number of channels (req. for rec) " "(default %u)\n" " --channel-map Channel map\n" -" one of: \"stereo\", " -"\"surround-51\",... or\n" +" one of: \"Stereo\", \"5.1\",... " +"or\n" " comma separated list of channel " "names: eg. \"FL,FR\"\n" " --format Sample format %s (req. for rec) " @@ -152,9 +152,9 @@ " --rate 采样率 (录制模式需要) (默认 %u)\n" " --channels 通道数 (录制模式需要) (默认 %u)\n" " --channel-map 通道映射\n" -" \"stereo\", \"surround-51\",... " -"中的其一或\n" -" 以\",\"分隔的通道名列表: 如 " +" \"stereo\", \"5.1\",... 中的其一" +"或\n" +" 以英文逗号分隔的通道名列表: 如 " "\"FL,FR\"\n" " --format 采样格式 %s (录制模式需要) (默认 " "%s)\n" @@ -166,7 +166,7 @@ " -n, --sample-count COUNT 计数采样后停止\n" "\n" -#: src/tools/pw-cat.c:1141 +#: src/tools/pw-cat.c:1133 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n"
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/dsd-utils.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/audio/dsd-utils.h
Changed
@@ -33,6 +33,8 @@ { struct spa_pod *position = NULL; int res; + uint32_t max_position = SPA_N_ELEMENTS(info->position); + info->flags = 0; res = spa_pod_parse_object(format, SPA_TYPE_OBJECT_Format, NULL, @@ -41,10 +43,13 @@ SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate), SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); + if (info->channels > max_position) + return -ECHRNG; if (position == NULL || - !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position))) + spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) { SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); - + spa_memzero(info->position, max_position * sizeof(info->position0)); + } return res; }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/raw-utils.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/audio/raw-utils.h
Changed
@@ -48,8 +48,10 @@ if (info->channels > max_position) return -ECHRNG; if (position == NULL || - spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) + spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) { SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); + spa_memzero(info->position, max_position * sizeof(info->position0)); + } return res; }
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/dict-types.h
Added
@@ -0,0 +1,38 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_DICT_TYPES_H +#define SPA_PARAM_DICT_TYPES_H + +#include <spa/utils/enum-types.h> +#include <spa/param/param-types.h> +#include <spa/param/dict.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +#define SPA_TYPE_INFO_PARAM_Dict SPA_TYPE_INFO_PARAM_BASE "Dict" +#define SPA_TYPE_INFO_PARAM_DICT_BASE SPA_TYPE_INFO_PARAM_Dict ":" + +static const struct spa_type_info spa_type_param_dict = { + { SPA_PARAM_DICT_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_DICT_BASE, spa_type_param, }, + { SPA_PARAM_DICT_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_DICT_BASE "info", NULL, }, + { 0, 0, NULL, NULL }, +}; + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_DICT_TYPES_H */
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/dict-utils.h
Added
@@ -0,0 +1,125 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_DICT_UTILS_H +#define SPA_PARAM_DICT_UTILS_H + +#include <float.h> + +#include <spa/utils/dict.h> +#include <spa/pod/builder.h> +#include <spa/pod/iter.h> +#include <spa/pod/parser.h> +#include <spa/pod/compare.h> +#include <spa/param/dict.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +#ifndef SPA_API_DICT_UTILS + #ifdef SPA_API_IMPL + #define SPA_API_DICT_UTILS SPA_API_IMPL + #else + #define SPA_API_DICT_UTILS static inline + #endif +#endif + +SPA_API_DICT_UTILS int +spa_param_dict_compare(const struct spa_pod *a, const struct spa_pod *b) +{ + return spa_pod_memcmp(a, b); +} + +SPA_API_DICT_UTILS struct spa_pod * +spa_param_dict_build_dict(struct spa_pod_builder *builder, uint32_t id, struct spa_dict *dict) +{ + struct spa_pod_frame f2; + uint32_t i, n_items; + + spa_pod_builder_push_object(builder, &f0, SPA_TYPE_OBJECT_ParamDict, id); + + n_items = dict ? dict->n_items : 0; + + spa_pod_builder_prop(builder, SPA_PARAM_DICT_info, SPA_POD_PROP_FLAG_HINT_DICT); + spa_pod_builder_push_struct(builder, &f1); + spa_pod_builder_int(builder, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string(builder, dict->itemsi.key); + spa_pod_builder_string(builder, dict->itemsi.value); + } + spa_pod_builder_pop(builder, &f1); + + return (struct spa_pod*)spa_pod_builder_pop(builder, &f0); +} + +SPA_API_DICT_UTILS struct spa_pod * +spa_param_dict_build_info(struct spa_pod_builder *builder, uint32_t id, struct spa_param_dict_info *info) +{ + struct spa_pod_frame f; + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_ParamDict, id); + spa_pod_builder_add(builder, SPA_PARAM_DICT_info, SPA_POD_PROP_FLAG_HINT_DICT); + spa_pod_builder_primitive(builder, info->info); + return (struct spa_pod*)spa_pod_builder_pop(builder, &f); +} + +SPA_API_DICT_UTILS int +spa_param_dict_parse(const struct spa_pod *dict, struct spa_param_dict_info *info, size_t size) +{ + memset(info, 0, size); + return spa_pod_parse_object(dict, + SPA_TYPE_OBJECT_ParamDict, NULL, + SPA_PARAM_DICT_info, SPA_POD_PodStruct(&info->info)); +} + +SPA_API_DICT_UTILS int +spa_param_dict_info_parse(const struct spa_param_dict_info *info, size_t size, + struct spa_dict *dict, struct spa_dict_item *items) +{ + struct spa_pod_parser prs; + uint32_t n, n_items; + const char *key, *value; + struct spa_pod_frame f1; + + spa_pod_parser_pod(&prs, info->info); + if (spa_pod_parser_push_struct(&prs, &f0) < 0 || + spa_pod_parser_get_int(&prs, (int32_t*)&n_items) < 0) + return -EINVAL; + + if (items == NULL) { + dict->n_items = n_items; + return 0; + } + n_items = SPA_MIN(dict->n_items, n_items); + + for (n = 0; n < n_items; n++) { + if (spa_pod_parser_get(&prs, + SPA_POD_String(&key), + SPA_POD_String(&value), + NULL) < 0) + break; + if (key == NULL || value == NULL) + return -EINVAL; + itemsn.key = key; + itemsn.value = value; + } + dict->items = items; + spa_pod_parser_pop(&prs, &f0); + return 0; +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_DICT_UTILS_H */
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/dict.h
Added
@@ -0,0 +1,42 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2025 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_DICT_H +#define SPA_PARAM_DICT_H + +#include <spa/param/param.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +/** properties for SPA_TYPE_OBJECT_ParamDict */ +enum spa_param_dict { + SPA_PARAM_DICT_START, + SPA_PARAM_DICT_info, /**< Struct( + * Int: n_items + * (String: key + * String: value)* + * ) */ +}; + +/** helper structure for managing info objects */ +struct spa_param_dict_info { + const struct spa_pod *info; +}; + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_DICT_H */
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/param-types.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/param-types.h
Changed
@@ -41,7 +41,9 @@ { SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL }, { SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL }, { SPA_PARAM_Tag, SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_INFO_PARAM_ID_BASE "Tag", NULL }, - { SPA_PARAM_PeerFormats, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_ID_BASE "PeerFormats", NULL }, + { SPA_PARAM_PeerEnumFormat, SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_INFO_PARAM_ID_BASE "PeerEnumFormat", NULL }, + { SPA_PARAM_Capability, SPA_TYPE_OBJECT_ParamDict, SPA_TYPE_INFO_PARAM_ID_BASE "Capability", NULL }, + { SPA_PARAM_PeerCapability, SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_INFO_PARAM_ID_BASE "PeerCapability", NULL }, { 0, 0, NULL, NULL }, };
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/param.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/param.h
Changed
@@ -40,7 +40,11 @@ SPA_PARAM_Latency, /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */ SPA_PARAM_ProcessLatency, /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */ SPA_PARAM_Tag, /**< tag reporting, a SPA_TYPE_OBJECT_ParamTag. Since 0.3.79 */ - SPA_PARAM_PeerFormats, /**< peer formats, a SPA_TYPE_Struct of SPA_TYPE_OBJECT_Format. Since 1.5.0 */ + SPA_PARAM_PeerEnumFormat, /**< peer formats, a SPA_TYPE_OBJECT_PeerParam with + * SPA_TYPE_OBJECT_Format. Since 1.5.0 */ + SPA_PARAM_Capability, /**< capability info, a SPA_TYPE_OBJECT_ParamDict, Since 1.5.84 */ + SPA_PARAM_PeerCapability, /**< peer capabilities, a SPA_TYPE_OBJECT_PeerParam with + * SPA_TYPE_OBJECT_ParamDict, since 1.5.84 */ }; /** information about a parameter */
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/peer-types.h
Added
@@ -0,0 +1,38 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_PEER_TYPES_H +#define SPA_PARAM_PEER_TYPES_H + +#include <spa/utils/enum-types.h> +#include <spa/param/param-types.h> +#include <spa/param/peer.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +#define SPA_TYPE_INFO_PeerParam SPA_TYPE_INFO_OBJECT_BASE "PeerParam" +#define SPA_TYPE_INFO_PEER_PARAM_BASE SPA_TYPE_INFO_PeerParam ":" + +static const struct spa_type_info spa_type_peer_param = { + { SPA_PEER_PARAM_START, SPA_TYPE_Id, SPA_TYPE_INFO_PEER_PARAM_BASE, spa_type_param, }, + { SPA_ID_INVALID, SPA_TYPE_Id, SPA_TYPE_INFO_PEER_PARAM_BASE, NULL, }, + { 0, 0, NULL, NULL }, +}; + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_PEER_TYPES_H */
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/peer-utils.h
Added
@@ -0,0 +1,92 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_PEER_PARAM_UTILS_H +#define SPA_PARAM_PEER_PARAM_UTILS_H + +#include <float.h> + +#include <spa/utils/dict.h> +#include <spa/pod/builder.h> +#include <spa/pod/iter.h> +#include <spa/pod/parser.h> +#include <spa/pod/compare.h> +#include <spa/param/peer.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +#ifndef SPA_API_PEER_PARAM_UTILS + #ifdef SPA_API_IMPL + #define SPA_API_PEER_PARAM_UTILS SPA_API_IMPL + #else + #define SPA_API_PEER_PARAM_UTILS static inline + #endif +#endif + +SPA_API_PEER_PARAM_UTILS int +spa_peer_param_parse(const struct spa_pod *param, struct spa_peer_param_info *info, + size_t size, void **state) +{ + int res; + const struct spa_pod_object *obj = (const struct spa_pod_object*)param; + const struct spa_pod_prop *first, *start, *cur; + + if ((res = spa_pod_parse_object(param, + SPA_TYPE_OBJECT_PeerParam, NULL)) < 0) + return res; + + first = spa_pod_prop_first(&obj->body); + start = *state ? spa_pod_prop_next((struct spa_pod_prop*)*state) : first; + + res = 0; + for (cur = start; spa_pod_prop_is_inside(&obj->body, obj->pod.size, cur); + cur = spa_pod_prop_next(cur)) { + info->peer_id = cur->key; + info->param = &cur->value; + *state = (void*)cur; + return 1; + } + return 0; +} + + +SPA_API_PEER_PARAM_UTILS void +spa_peer_param_build_start(struct spa_pod_builder *builder, struct spa_pod_frame *f, uint32_t id) +{ + spa_pod_builder_push_object(builder, f, SPA_TYPE_OBJECT_PeerParam, id); +} + +SPA_API_PEER_PARAM_UTILS void +spa_peer_param_build_add_param(struct spa_pod_builder *builder, uint32_t peer_id, + const struct spa_pod *param) +{ + spa_pod_builder_prop(builder, peer_id, 0); + if (param) + spa_pod_builder_primitive(builder, param); + else + spa_pod_builder_none(builder); +} + +SPA_API_PEER_PARAM_UTILS struct spa_pod * +spa_peer_param_build_end(struct spa_pod_builder *builder, struct spa_pod_frame *f) +{ + return (struct spa_pod*)spa_pod_builder_pop(builder, f); +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_PEER_PARAM_UTILS_H */
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/peer.h
Added
@@ -0,0 +1,37 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2025 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_PARAM_PEER_PARAM_H +#define SPA_PARAM_PEER_PARAM_H + +#include <spa/param/param.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +/** properties for SPA_TYPE_OBJECT_PeerParam */ +enum spa_peer_param { + SPA_PEER_PARAM_START, /**< id of peer as key, SPA_TYPE_Pod as value */ + SPA_PEER_PARAM_END = 0xfffffffe, +}; + +struct spa_peer_param_info { + uint32_t peer_id; + const struct spa_pod *param; +}; +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_PARAM_PEER_PARAM_H */
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/tag-utils.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/tag-utils.h
Changed
@@ -11,6 +11,7 @@ #include <spa/pod/builder.h> #include <spa/pod/iter.h> #include <spa/pod/parser.h> +#include <spa/pod/compare.h> #include <spa/param/tag.h> #ifdef __cplusplus @@ -33,8 +34,7 @@ SPA_API_TAG_UTILS int spa_tag_compare(const struct spa_pod *a, const struct spa_pod *b) { - return ((a == b) || (a && b && SPA_POD_SIZE(a) == SPA_POD_SIZE(b) && - memcmp(a, b, SPA_POD_SIZE(b)) == 0)) ? 0 : 1; + return spa_pod_memcmp(a, b); } SPA_API_TAG_UTILS int
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/type-info.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/param/type-info.h
Changed
@@ -15,5 +15,7 @@ #include <spa/param/profile-types.h> #include <spa/param/route-types.h> #include <spa/param/tag-types.h> +#include <spa/param/dict-types.h> +#include <spa/param/peer-types.h> #endif /* SPA_PARAM_TYPE_INFO_H */
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/compare.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/pod/compare.h
Changed
@@ -80,6 +80,13 @@ return 0; } +SPA_API_POD_COMPARE int spa_pod_memcmp(const struct spa_pod *a, + const struct spa_pod *b) +{ + return ((a == b) || (a && b && SPA_POD_SIZE(a) == SPA_POD_SIZE(b) && + memcmp(a, b, SPA_POD_SIZE(b)) == 0)) ? 0 : 1; +} + SPA_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1, const struct spa_pod *pod2) { @@ -149,12 +156,8 @@ break; } case SPA_TYPE_Array: - { - if (pod1->size != pod2->size) - return -EINVAL; - res = memcmp(SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), pod2->size); + res = spa_pod_memcmp(pod1, pod2); break; - } default: if (pod1->size != pod2->size) return -EINVAL;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/dynamic.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/pod/dynamic.h
Changed
@@ -70,8 +70,10 @@ SPA_API_POD_DYNAMIC void spa_pod_dynamic_builder_clean(struct spa_pod_dynamic_builder *builder) { - if (builder->data != builder->b.data) + if (builder->data != builder->b.data) { free(builder->b.data); + builder->b.data = NULL; + } } SPA_DEFINE_AUTO_CLEANUP(spa_pod_dynamic_builder, struct spa_pod_dynamic_builder, {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/filter.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/pod/filter.h
Changed
@@ -339,9 +339,7 @@ default: if (pf != NULL) { - if (pp->size != pf->size) - return -EINVAL; - if (memcmp(pp, pf, pp->size) != 0) + if (spa_pod_memcmp(pp, pf) != 0) return -EINVAL; do_advance = true; }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/type-info.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/utils/type-info.h
Changed
@@ -5,6 +5,7 @@ #ifndef SPA_TYPE_INFO_H #define SPA_TYPE_INFO_H + #include <spa/utils/defs.h> #include <spa/utils/type.h> #include <spa/utils/enum-types.h> @@ -78,6 +79,8 @@ { SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency }, { SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency }, { SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Tag, spa_type_param_tag }, + { SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_Object, SPA_TYPE_INFO_PeerParam, spa_type_peer_param }, + { SPA_TYPE_OBJECT_ParamDict, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Dict, spa_type_param_dict }, { 0, 0, NULL, NULL } };
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/type.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/include/spa/utils/type.h
Changed
@@ -88,6 +88,8 @@ SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_OBJECT_ParamTag, + SPA_TYPE_OBJECT_PeerParam, + SPA_TYPE_OBJECT_ParamDict, _SPA_TYPE_OBJECT_LAST, /**< not part of ABI */ /* vendor extensions */
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/audioconvert.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -100,6 +100,7 @@ unsigned int mix_disabled:1; unsigned int resample_disabled:1; unsigned int resample_quality; + struct resample_config resample_config; double rate; char wav_path512; unsigned int lock_volumes:1; @@ -122,6 +123,7 @@ props->mix_disabled = false; props->resample_disabled = false; props->resample_quality = RESAMPLE_DEFAULT_QUALITY; + spa_zero(props->resample_config); props->rate = 1.0; spa_zero(props->wav_path); props->lock_volumes = false; @@ -1019,7 +1021,7 @@ if (this->io_position && this->io_clock && this->io_position->clock.target_rate.denom != this->io_clock->target_rate.denom && !this->props.resample_disabled) { - spa_log_warn(this->log, "driver %d changed rate:%u -> %u", this->io_position->clock.id, + spa_log_debug(this->log, "driver %d changed rate:%u -> %u", this->io_position->clock.id, this->io_clock->target_rate.denom, this->io_position->clock.target_rate.denom); @@ -1478,6 +1480,16 @@ this->props.resample_quality = atoi(s); else if (spa_streq(k, "resample.disable")) this->props.resample_disabled = spa_atob(s); + else if (spa_streq(k, "resample.window")) + this->props.resample_config.window = resample_window_from_label(s); + else if (spa_streq(k, "resample.cutoff")) + spa_atod(s, &this->props.resample_config.cutoff); + else if (spa_streq(k, "resample.n-taps")) + spa_atou32(s, &this->props.resample_config.n_taps, 0); + else if (spa_strstartswith(k, "resample.param.")) { + uint32_t idx = resample_param_from_label(k+strlen("resample.param.")); + spa_atod(s, &this->props.resample_config.paramsidx); + } else if (spa_streq(k, "dither.noise")) spa_atou32(s, &this->dir1.conv.noise_bits, 0); else if (spa_streq(k, "dither.method")) @@ -2289,6 +2301,7 @@ this->resample.o_rate = out->format.info.raw.rate; this->resample.log = this->log; this->resample.quality = this->props.resample_quality; + this->resample.config = this->props.resample_config; this->resample.cpu_flags = this->cpu_flags; this->rate_adjust = this->props.rate != 1.0;
View file
_service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/audioconvert/dbesi0.c
Added
@@ -0,0 +1,147 @@ +/* Copyright(C) 1996 Takuya OOURA + +You may use, copy, modify this code for any purpose and +without fee. + +Package home: http://www.kurims.kyoto-u.ac.jp/~ooura/bessel.html +*/ + +/* Bessel I_0(x) function in double precision */ + +#include <math.h> + +static double +dbesi0 (double x) +{ + int k; + double w, t, y; + static double a65 = { + 8.5246820682016865877e-11, 2.5966600546497407288e-9, + 7.9689994568640180274e-8, 1.9906710409667748239e-6, + 4.0312469446528002532e-5, 6.4499871606224265421e-4, + 0.0079012345761930579108, 0.071111111109207045212, + 0.444444444444724909, 1.7777777777777532045, + 4.0000000000000011182, 3.99999999999999998, + 1.0000000000000000001, + 1.1520919130377195927e-10, 2.2287613013610985225e-9, + 8.1903951930694585113e-8, 1.9821560631611544984e-6, + 4.0335461940910133184e-5, 6.4495330974432203401e-4, + 0.0079013012611467520626, 0.071111038160875566622, + 0.44444450319062699316, 1.7777777439146450067, + 4.0000000132337935071, 3.9999999968569015366, + 1.0000000003426703174, + 1.5476870780515238488e-10, 1.2685004214732975355e-9, + 9.2776861851114223267e-8, 1.9063070109379044378e-6, + 4.0698004389917945832e-5, 6.4370447244298070713e-4, + 0.0079044749458444976958, 0.071105052411749363882, + 0.44445280640924755082, 1.7777694934432109713, + 4.0000055808824003386, 3.9999977081165740932, + 1.0000004333949319118, + 2.0675200625006793075e-10, -6.1689554705125681442e-10, + 1.2436765915401571654e-7, 1.5830429403520613423e-6, + 4.2947227560776583326e-5, 6.3249861665073441312e-4, + 0.0079454472840953930811, 0.070994327785661860575, + 0.44467219586283000332, 1.7774588182255374745, + 4.0003038986252717972, 3.9998233869142057195, + 1.0000472932961288324, + 2.7475684794982708655e-10, -3.8991472076521332023e-9, + 1.9730170483976049388e-7, 5.9651531561967674521e-7, + 5.1992971474748995357e-5, 5.7327338675433770752e-4, + 0.0082293143836530412024, 0.069990934858728039037, + 0.44726764292723985087, 1.7726685170014087784, + 4.0062907863712704432, 3.9952750700487845355, + 1.0016354346654179322 + }; + static double b70 = { + 6.7852367144945531383e-8, 4.6266061382821826854e-7, + 6.9703135812354071774e-6, 7.6637663462953234134e-5, + 7.9113515222612691636e-4, 0.0073401204731103808981, + 0.060677114958668837046, 0.43994941411651569622, + 2.7420017097661750609, 14.289661921740860534, + 59.820609640320710779, 188.78998681199150629, + 399.8731367825601118, 427.56411572180478514, + 1.8042097874891098754e-7, 1.2277164312044637357e-6, + 1.8484393221474274861e-5, 2.0293995900091309208e-4, + 0.0020918539850246207459, 0.019375315654033949297, + 0.15985869016767185908, 1.1565260527420641724, + 7.1896341224206072113, 37.354773811947484532, + 155.80993164266268457, 489.5211371158540918, + 1030.9147225169564806, 1093.5883545113746958, + 4.8017305613187493564e-7, 3.261317843912380074e-6, + 4.9073137508166159639e-5, 5.3806506676487583755e-4, + 0.0055387918291051866561, 0.051223717488786549025, + 0.42190298621367914765, 3.0463625987357355872, + 18.895299447327733204, 97.915189029455461554, + 407.13940115493494659, 1274.3088990480582632, + 2670.9883037012547506, 2815.7166284662544712, + 1.2789926338424623394e-6, 8.6718263067604918916e-6, + 1.3041508821299929489e-4, 0.001428224737372747892, + 0.014684070635768789378, 0.13561403190404185755, + 1.1152592585977393953, 8.0387088559465389038, + 49.761318895895479206, 257.2684232313529138, + 1066.8543146269566231, 3328.3874581009636362, + 6948.8586598121634874, 7288.4893398212481055, + 3.409350368197032893e-6, 2.3079025203103376076e-5, + 3.4691373283901830239e-4, 0.003794994977222908545, + 0.038974209677945602145, 0.3594948380414878371, + 2.9522878893539528226, 21.246564609514287056, + 131.28727387146173141, 677.38107093296675421, + 2802.3724744545046518, 8718.5731420798254081, + 18141.348781638832286, 18948.925349296308859 + }; + static double c45 = { + 2.5568678676452702768e-15, 3.0393953792305924324e-14, + 6.3343751991094840009e-13, 1.5041298011833009649e-11, + 4.4569436918556541414e-10, 1.746393051427167951e-8, + 1.0059224011079852317e-6, 1.0729838945088577089e-4, + 0.05150322693642527738, + 5.2527963991711562216e-15, 7.202118481421005641e-15, + 7.2561421229904797156e-13, 1.482312146673104251e-11, + 4.4602670450376245434e-10, 1.7463600061788679671e-8, + 1.005922609132234756e-6, 1.0729838937545111487e-4, + 0.051503226936437300716, + 1.3365917359358069908e-14, -1.2932643065888544835e-13, + 1.7450199447905602915e-12, 1.0419051209056979788e-11, + 4.58047881980598326e-10, 1.7442405450073548966e-8, + 1.0059461453281292278e-6, 1.0729837434500161228e-4, + 0.051503226940658446941, + 5.3771611477352308649e-14, -1.1396193006413731702e-12, + 1.2858641335221653409e-11, -5.9802086004570057703e-11, + 7.3666894305929510222e-10, 1.6731837150730356448e-8, + 1.0070831435812128922e-6, 1.0729733111203704813e-4, + 0.051503227360726294675, + 3.7819492084858931093e-14, -4.8600496888588034879e-13, + 1.6898350504817224909e-12, 4.5884624327524255865e-11, + 1.2521615963377513729e-10, 1.8959658437754727957e-8, + 1.0020716710561353622e-6, 1.073037119856927559e-4, + 0.05150322383300230775 + }; + + w = fabs (x); + if (w < 8.5) { + t = w * w * 0.0625; + k = 13 * ((int) t); + y = (((((((((((ak * t + ak + 1) * t + + ak + 2) * t + ak + 3) * t + + ak + 4) * t + ak + 5) * t + ak + + 6) * t + ak + 7) * t + ak + 8) * t + ak + + 9) * t + ak + 10) * t + ak + 11) * t + ak + 12; + } else if (w < 12.5) { + k = (int) w; + t = w - k; + k = 14 * (k - 8); + y = ((((((((((((bk * t + bk + 1) * t + bk + 2) * t + bk + 3) * t + + bk + 4) * t + bk + 5) * t + bk + + 6) * t + bk + 7) * t + bk + 8) * t + + bk + 9) * t + bk + 10) * t + bk + 11) * t + bk + + 12) * t + bk + 13; + } else { + t = 60 / w; + k = 9 * ((int) t); + y = ((((((((ck * t + ck + 1) * t + + ck + 2) * t + ck + 3) * t + ck + 4) * t + + ck + 5) * t + ck + 6) * t + ck + 7) * t + + ck + 8) * sqrt (t) * exp (w); + } + return y; +}
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/resample-native.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/audioconvert/resample-native.c
Changed
@@ -13,72 +13,186 @@ SPA_LOG_TOPIC_DEFINE(resample_log_topic, "spa.resample"); +#define INHERIT_PARAM(c,q,p) if ((c)->paramsp == 0.0) (c)->paramsp = (q)->paramsp; + struct quality { uint32_t n_taps; - double cutoff; + double cutoff_up; /* when upsampling */ + double cutoff_down; /* for downsampling */ + double paramsRESAMPLE_MAX_PARAMS; }; -static const struct quality window_qualities = { - { 8, 0.53, }, - { 16, 0.67, }, - { 24, 0.75, }, - { 32, 0.80, }, - { 48, 0.85, }, /* default */ - { 64, 0.88, }, - { 80, 0.895, }, - { 96, 0.910, }, - { 128, 0.936, }, - { 144, 0.945, }, - { 160, 0.950, }, - { 192, 0.960, }, - { 256, 0.970, }, - { 896, 0.990, }, - { 1024, 0.995, }, + +struct window_info { + uint32_t window; + void (*func) (struct resample *r, double *w, double t, uint32_t n_taps); + uint32_t n_qualities; + const struct quality *qualities; + void (*config) (struct resample *r); +}; +struct window_info window_info; + +static const struct quality blackman_qualities = { + { 8, 0.58, 0.58, { 0.16, }}, + { 16, 0.70, 0.70, { 0.20, }}, + { 24, 0.77, 0.77, { 0.16, }}, + { 32, 0.82, 0.82, { 0.16, }}, + { 48, 0.87, 0.87, { 0.16, }}, /* default */ + { 64, 0.895, 0.895, { 0.16, }}, + { 80, 0.910, 0.910, { 0.16, }}, + { 96, 0.925, 0.925, { 0.16, }}, + { 128, 0.942, 0.942, { 0.16, }}, + { 144, 0.950, 0.950, { 0.16, }}, + { 160, 0.958, 0.958, { 0.16, }}, + { 192, 0.966, 0.966, { 0.16, }}, + { 256, 0.975, 0.975, { 0.16, }}, + { 896, 0.988, 0.988, { 0.16, }}, + { 1024, 0.990, 0.990, { 0.16, }}, }; -static inline double sinc(double x) +static inline void blackman_window(struct resample *r, double *w, double t, uint32_t n_taps) { - if (x < 1e-6) return 1.0; - x *= M_PI; - return sin(x) / x; + double x, alpha = r->config.paramsRESAMPLE_PARAM_BLACKMAN_ALPHA; + uint32_t i, n_taps12 = n_taps/2; + for (i = 0; i < n_taps12; i++, t += 1.0) { + x = 2.0 * M_PI * t / n_taps; + wi = (1.0 - alpha) / 2.0 + (1.0 / 2.0) * cos(x) + + (alpha / 2.0) * cos(2.0 * x); + } +} +static inline void blackman_config(struct resample *r) +{ + const struct quality *q = &window_infor->config.window.qualitiesr->quality; + INHERIT_PARAM(&r->config, q, RESAMPLE_PARAM_BLACKMAN_ALPHA); } -static inline double window_blackman(double x, double n_taps) +static const struct quality exp_qualities = { + { 8, 0.58, 0.58, { 16.97789, }}, + { 16, 0.70, 0.70, { 16.97789, }}, + { 24, 0.77, 0.77, { 16.97789, }}, + { 32, 0.82, 0.82, { 16.97789, }}, + { 48, 0.87, 0.87, { 16.97789, }}, /* default */ + { 64, 0.895, 0.895, { 16.97789, }}, + { 80, 0.910, 0.910, { 16.97789, }}, + { 96, 0.925, 0.925, { 16.97789, }}, + { 128, 0.942, 0.942, { 16.97789, }}, + { 144, 0.950, 0.950, { 16.97789, }}, + { 160, 0.958, 0.958, { 16.97789, }}, + { 192, 0.966, 0.966, { 16.97789, }}, + { 256, 0.975, 0.975, { 16.97789, }}, + { 896, 0.988, 0.988, { 16.97789, }}, + { 1024, 0.990, 0.990, { 16.97789, }}, +}; + +static inline void exp_window(struct resample *r, double *w, double t, uint32_t n_taps) { - double alpha = 0.232, r; - x = 2.0 * M_PI * x / n_taps; - r = (1.0 - alpha) / 2.0 + (1.0 / 2.0) * cos(x) + - (alpha / 2.0) * cos(2.0 * x); - return r; + double x, A = r->config.paramsRESAMPLE_PARAM_EXP_A; + uint32_t i, n_taps12 = n_taps/2; + + for (i = 0; i < n_taps12; i++, t += 1.0) { + x = 2.0 * t / n_taps; + /* doi:10.1109/RME.2008.4595727 with tweak */ + wi = (exp(A * sqrt(fmax(0.0, 1.0 - x*x))) - 1) / (exp(A) - 1); + } } +static inline void exp_config(struct resample *r) +{ + const struct quality *q = &window_infor->config.window.qualitiesr->quality; + INHERIT_PARAM(&r->config, q, RESAMPLE_PARAM_EXP_A); +} + +#include "dbesi0.c" + +static const struct quality kaiser_qualities = { + { 8, 0.620000, 0.620000, { 3.553376, 110.000000, 0.888064 }}, + { 16, 0.780000, 0.780000, { 3.553376, 110.000000, 0.444032 }}, + { 24, 0.820000, 0.820000, { 3.904154, 120.000000, 0.325043 }}, + { 32, 0.865000, 0.865000, { 4.254931, 130.000000, 0.265548 }}, + { 48, 0.895000, 0.895000, { 4.254931, 130.000000, 0.177032 }}, + { 64, 0.915000, 0.915000, { 4.254931, 130.000000, 0.132774 }}, + { 80, 0.928000, 0.928000, { 4.254931, 130.000000, 0.106219 }}, + { 96, 0.942000, 0.942000, { 4.254931, 130.000000, 0.088516 }}, + { 128, 0.952000, 0.952000, { 4.254931, 130.000000, 0.066387 }}, + { 160, 0.960000, 0.960000, { 4.254931, 130.000000, 0.053110 }}, + { 192, 0.968000, 0.968000, { 4.254931, 130.000000, 0.044258 }}, + { 256, 0.976000, 0.976000, { 4.605709, 140.000000, 0.035914 }}, + { 512, 0.985000, 0.985000, { 4.781097, 145.000000, 0.018637 }}, + { 768, 0.990000, 0.990000, { 4.956486, 150.000000, 0.012878 }}, + { 1024, 0.993000, 0.993000, { 5.131875, 155.000000, 0.009999 }}, +}; -static inline double window_cosh(double x, double n_taps) +static inline void kaiser_window(struct resample *r, double *w, double t, uint32_t n_taps) { - double r; - double A = 16.97789; - double x2; - x = 2.0 * x / n_taps; - x2 = x * x; - if (x2 >= 1.0) - return 0.0; - /* doi:10.1109/RME.2008.4595727 with tweak */ - r = (exp(A * sqrt(1 - x2)) - 1) / (exp(A) - 1); - return r; + double x, beta = r->config.paramsRESAMPLE_PARAM_KAISER_ALPHA * M_PI; + double den = dbesi0(beta); + uint32_t i, n_taps12 = n_taps/2; + for (i = 0; i < n_taps12; i++, t += 1.0) { + x = 2.0 * t / n_taps; + wi = dbesi0(beta * sqrt(fmax(0.0, 1.0 - x*x))) / den; + } } -#define window (1 ? window_cosh : window_blackman) +static inline void kaiser_config(struct resample *r) +{ + double A, B, dw, tr_bw, alpha; + uint32_t n; + const struct quality *q = &window_infor->config.window.qualitiesr->quality; + + if ((A = r->config.paramsRESAMPLE_PARAM_KAISER_SB_ATT) == 0.0) + A = q->paramsRESAMPLE_PARAM_KAISER_SB_ATT; + if ((tr_bw = r->config.paramsRESAMPLE_PARAM_KAISER_TR_BW) == 0.0) + tr_bw = q->paramsRESAMPLE_PARAM_KAISER_TR_BW; + + if ((alpha = r->config.paramsRESAMPLE_PARAM_KAISER_ALPHA) == 0.0) { + /* calculate Beta and alpha */ + if (A > 50) + B = 0.1102 * (A - 8.7); + else if (A >= 21) + B = 0.5842 * pow (A - 21, 0.4) + 0.07886 * (A - 21); + else + B = 0.0; + + r->config.paramsRESAMPLE_PARAM_KAISER_ALPHA = B / M_PI; + } + if (r->config.n_taps == 0) { + /* calculate transition width in radians */ + dw = 2 * M_PI * (tr_bw); + /* order of the filter */ + n = (uint32_t)((A - 8.0) / (2.285 * dw)); + r->config.n_taps = n + 1; + } +} + +struct window_info window_info = { + RESAMPLE_WINDOW_EXP = { RESAMPLE_WINDOW_EXP, exp_window, + SPA_N_ELEMENTS(exp_qualities), exp_qualities, exp_config }, + RESAMPLE_WINDOW_BLACKMAN = { RESAMPLE_WINDOW_BLACKMAN, blackman_window, + SPA_N_ELEMENTS(blackman_qualities), blackman_qualities, blackman_config }, + RESAMPLE_WINDOW_KAISER = { RESAMPLE_WINDOW_KAISER, kaiser_window, + SPA_N_ELEMENTS(kaiser_qualities), kaiser_qualities, kaiser_config },
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/resample.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/audioconvert/resample.h
Changed
@@ -9,6 +9,26 @@ #include <spa/support/log.h> #define RESAMPLE_DEFAULT_QUALITY 4 +#define RESAMPLE_WINDOW_DEFAULT RESAMPLE_WINDOW_EXP +#define RESAMPLE_MAX_PARAMS 16 + +struct resample_config { +#define RESAMPLE_WINDOW_EXP 0 +#define RESAMPLE_WINDOW_BLACKMAN 1 +#define RESAMPLE_WINDOW_KAISER 2 + uint32_t window; + + double cutoff; + uint32_t n_taps; + +#define RESAMPLE_PARAM_EXP_A 0 +#define RESAMPLE_PARAM_BLACKMAN_ALPHA 0 +#define RESAMPLE_PARAM_KAISER_ALPHA 0 +#define RESAMPLE_PARAM_KAISER_SB_ATT 1 /* stopband attenuation */ +#define RESAMPLE_PARAM_KAISER_TR_BW 2 /* transition bandwidth */ +#define RESAMPLE_PARAM_INVALID (RESAMPLE_MAX_PARAMS-1) + double paramsRESAMPLE_MAX_PARAMS; +}; struct resample { struct spa_log *log; @@ -23,6 +43,8 @@ double rate; int quality; + struct resample_config config; /* set to all 0 for defaults */ + void (*free) (struct resample *r); void (*update_rate) (struct resample *r, double rate); uint32_t (*in_len) (struct resample *r, uint32_t out_len); @@ -49,6 +71,56 @@ #define resample_phase(r) (r)->phase(r) int resample_native_init(struct resample *r); +int resample_native_init_config(struct resample *r, struct resample_config *conf); int resample_peaks_init(struct resample *r); +static const struct resample_window_info { + uint32_t window; + const char *label; + const char *description; + uint32_t n_params; +} resample_window_info = { + RESAMPLE_WINDOW_EXP = { RESAMPLE_WINDOW_EXP, + "exp", "Exponential window", 1 }, + RESAMPLE_WINDOW_BLACKMAN = { RESAMPLE_WINDOW_BLACKMAN, + "blackman", "Blackman window", 1 }, + RESAMPLE_WINDOW_KAISER = { RESAMPLE_WINDOW_KAISER, + "kaiser", "Kaiser window", 3 }, +}; + +static inline uint32_t resample_window_from_label(const char *label) +{ + SPA_FOR_EACH_ELEMENT_VAR(resample_window_info, i) { + if (spa_streq(i->label, label)) + return i->window; + } + return RESAMPLE_WINDOW_EXP; +} + +static inline const char *resample_window_name(uint32_t idx) +{ + return resample_window_infoSPA_CLAMP(idx, 0u, SPA_N_ELEMENTS(resample_window_info)-1).label; +} + +static const struct resample_param_info { + uint32_t window; + uint32_t idx; + const char *label; +} resample_param_info = { + { RESAMPLE_WINDOW_EXP, RESAMPLE_PARAM_EXP_A, "exp.A" }, + { RESAMPLE_WINDOW_BLACKMAN, RESAMPLE_PARAM_BLACKMAN_ALPHA, "blackman.alpha" }, + { RESAMPLE_WINDOW_KAISER, RESAMPLE_PARAM_KAISER_ALPHA, "kaiser.alpha" }, + { RESAMPLE_WINDOW_KAISER, RESAMPLE_PARAM_KAISER_SB_ATT, "kaiser.stopband-attenuation" }, + { RESAMPLE_WINDOW_KAISER, RESAMPLE_PARAM_KAISER_TR_BW, "kaiser.transition-bandwidth" }, +}; + +static inline uint32_t resample_param_from_label(const char *label) +{ + SPA_FOR_EACH_ELEMENT_VAR(resample_param_info, i) { + if (spa_streq(i->label, label)) + return i->idx; + } + return RESAMPLE_PARAM_INVALID; +} + #endif /* RESAMPLE_H */
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/spa-resample.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/audioconvert/spa-resample.c
Changed
@@ -29,7 +29,9 @@ bool verbose; int rate; int format; + uint32_t window; int quality; + struct resample_config config; int cpu_flags; const char *iname; @@ -43,15 +45,19 @@ #define STR_FMTS "(s8|s16|s32|f32|f64)" -#define OPTIONS "hvr:f:q:c:" +#define OPTIONS "hvc:r:f:w:q:u:t:p:" static const struct option long_options = { { "help", no_argument, NULL, 'h'}, { "verbose", no_argument, NULL, 'v'}, + { "cpuflags", required_argument, NULL, 'c' }, { "rate", required_argument, NULL, 'r' }, { "format", required_argument, NULL, 'f' }, + { "window", required_argument, NULL, 'w' }, { "quality", required_argument, NULL, 'q' }, - { "cpuflags", required_argument, NULL, 'c' }, + { "cutoff", required_argument, NULL, 'u' }, + { "taps", required_argument, NULL, 't' }, + { "param", required_argument, NULL, 'p' }, { NULL, 0, NULL, 0 } }; @@ -59,6 +65,7 @@ static void show_usage(const char *name, bool is_error) { FILE *fp; + uint32_t i; fp = is_error ? stderr : stdout; @@ -66,14 +73,31 @@ fprintf(fp, " -h, --help Show this help\n" " -v --verbose Be verbose\n" + " -c --cpuflags CPU flags (default 0)\n" "\n"); fprintf(fp, " -r --rate Output sample rate (default as input)\n" - " -f --format Output sample format %s (default as input)\n" + " -f --format Output sample format %s (default as input)\n\n" + " -w --window Window function (default %s)\n", + STR_FMTS, resample_window_name(RESAMPLE_WINDOW_DEFAULT)); + for (i = 0; i < SPA_N_ELEMENTS(resample_window_info); i++) { + fprintf(fp, + " %s: %s\n", + resample_window_infoi.label, + resample_window_infoi.description); + } + fprintf(fp, " -q --quality Resampler quality (default %u)\n" - " -c --cpuflags CPU flags (default 0)\n" - "\n", - STR_FMTS, DEFAULT_QUALITY); + " -u --cutoff Cutoff frequency 0.0..1.0 (default from quality)\n" + " -t --taps Resampler taps (default from quality)\n" + " -p --param Resampler param <name>=<value> (default from quality)\n", + DEFAULT_QUALITY); + for (i = 0; i < SPA_N_ELEMENTS(resample_param_info); i++) { + fprintf(fp, + " %s\n", + resample_param_infoi.label); + } + fprintf(fp, "\n"); } static inline const char * @@ -207,10 +231,23 @@ r.i_rate = d->iinfo.samplerate; r.o_rate = d->oinfo.samplerate; r.quality = d->quality < 0 ? DEFAULT_QUALITY : d->quality; + r.config = d->config; if ((res = resample_native_init(&r)) < 0) { fprintf(stderr, "can't init converter: %s\n", spa_strerror(res)); return res; } + if (d->verbose) { + fprintf(stdout, "window:%s cutoff:%f n_taps:%u\n", + resample_window_name(r.config.window), + r.config.cutoff, r.config.n_taps); + for (i = 0; i < SPA_N_ELEMENTS(resample_param_info); i++) { + if (resample_param_infoi.window != r.config.window) + continue; + fprintf(stdout, " param:%s %f\n", + resample_param_infoi.label, + r.config.paramsresample_param_infoi.idx); + } + } for (j = 0; j < channels; j++) srcj = &inMAX_SAMPLES * j; @@ -320,6 +357,27 @@ case 'c': data.cpu_flags = strtol(optarg, NULL, 0); break; + case 'u': + data.config.cutoff = strtod(optarg, NULL); + fprintf(stderr, "%f\n", data.config.cutoff); + break; + case 'w': + data.config.window = resample_window_from_label(optarg); + break; + case 'p': + { + char *eq; + if ((eq = strchr(optarg, '=')) != NULL) { + uint32_t idx; + *eq = 0; + idx = resample_param_from_label(optarg); + data.config.paramsidx = atof(eq+1); + } + break; + } + case 't': + data.config.n_taps = atoi(optarg); + break; default: fprintf(stderr, "error: unknown option '%c'\n", c); goto error_usage;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-aac.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-aac.c
Changed
@@ -139,7 +139,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_aac_t conf; int i;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-aptx.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-aptx.c
Changed
@@ -110,7 +110,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_aptx_t conf; int i; @@ -146,7 +147,8 @@ static int codec_select_config_ll(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_aptx_ll_ext_t conf = { 0 }; size_t actual_conf_size; @@ -166,7 +168,7 @@ if (codec->duplex_codec && !conf.base.bidirect_link) return -ENOTSUP; - if ((res = codec_select_config(codec, flags, caps, caps_size, info, settings, config)) < 0) + if ((res = codec_select_config(codec, flags, caps, caps_size, info, settings, config, NULL)) < 0) return res; memcpy(&conf.base.aptx, config, sizeof(conf.base.aptx));
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-faststream.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-faststream.c
Changed
@@ -61,7 +61,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_faststream_t conf; int i;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-lc3plus.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-lc3plus.c
Changed
@@ -83,7 +83,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_lc3plus_hr_t conf; @@ -137,8 +138,8 @@ int a, b; /* Order selected configurations by preference */ - res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1); - res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2); + res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1, NULL); + res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2, NULL); #define PREFER_EXPR(expr) \ do { \
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-ldac.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-ldac.c
Changed
@@ -115,7 +115,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_ldac_t conf; int i;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus-g.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus-g.c
Changed
@@ -74,7 +74,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_opus_g_t conf; int frequency, duration, channels; @@ -126,8 +127,8 @@ int a, b; /* Order selected configurations by preference */ - res1 = codec->select_config(codec, flags, caps1, caps1_size, info, global_settings, (uint8_t *)&conf1); - res2 = codec->select_config(codec, flags, caps2, caps2_size, info, global_settings, (uint8_t *)&conf2); + res1 = codec->select_config(codec, flags, caps1, caps1_size, info, global_settings, (uint8_t *)&conf1, NULL); + res2 = codec->select_config(codec, flags, caps2, caps2_size, info, global_settings, (uint8_t *)&conf2, NULL); #define PREFER_EXPR(expr) \ do { \
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus.c
Changed
@@ -590,7 +590,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { struct props props; a2dp_opus_05_t conf; @@ -699,8 +700,8 @@ int a, b; /* Order selected configurations by preference */ - res1 = codec->select_config(codec, flags, caps1, caps1_size, info, global_settings, (uint8_t *)&conf1); - res2 = codec->select_config(codec, flags, caps2, caps2_size, info, global_settings, (uint8_t *)&conf2); + res1 = codec->select_config(codec, flags, caps1, caps1_size, info, global_settings, (uint8_t *)&conf1, NULL); + res2 = codec->select_config(codec, flags, caps2, caps2_size, info, global_settings, (uint8_t *)&conf2, NULL); #define PREFER_EXPR(expr) \ do { \
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-sbc.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/a2dp-codec-sbc.c
Changed
@@ -135,7 +135,8 @@ static int codec_select_config(const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE) + const struct spa_dict *settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data) { a2dp_sbc_t conf; int bitpool, i; @@ -221,8 +222,8 @@ bool xq = (spa_streq(codec->name, "sbc_xq")); /* Order selected configurations by preference */ - res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1); - res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2); + res1 = codec->select_config(codec, 0, caps1, caps1_size, info, NULL, (uint8_t *)&conf1, NULL); + res2 = codec->select_config(codec, 0, caps2, caps2_size, info , NULL, (uint8_t *)&conf2, NULL); #define PREFER_EXPR(expr) \ do { \
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/backend-native.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/backend-native.c
Changed
@@ -852,7 +852,7 @@ if (cfg) libusb_free_config_descriptor(cfg); if (devices) - libusb_free_device_list(devices, 0); + libusb_free_device_list(devices, true); if (ctx) libusb_exit(ctx); return ok; @@ -1010,6 +1010,7 @@ switch (indicator) { case SPA_BT_HFP_HF_INDICATOR_ENHANCED_SAFETY: + rfcomm_send_error(rfcomm, CMEE_AG_FAILURE); break; case SPA_BT_HFP_HF_INDICATOR_BATTERY_LEVEL: // Battery level is reported in range 0-100 @@ -1018,12 +1019,15 @@ if (value <= 100) { // TODO: report without Battery Provider (using props) spa_bt_device_report_battery_level(rfcomm->device, value); + rfcomm_send_reply(rfcomm, "OK"); } else { spa_log_warn(backend->log, "battery HF indicator %u outside of range 0, 100: %u", indicator, value); + rfcomm_send_error(rfcomm, CMEE_AG_FAILURE); } break; default: spa_log_warn(backend->log, "unknown HF indicator:%u value:%u", indicator, value); + rfcomm_send_error(rfcomm, CMEE_AG_FAILURE); break; } } @@ -1307,7 +1311,7 @@ type = INTERNATIONAL_NUMBER; else type = NATIONAL_NUMBER; - rfcomm_send_reply(rfcomm, "+CNUM: ,\"%s\",%u", backend->modem.own_number, type); + rfcomm_send_reply(rfcomm, "+CNUM: ,\"%s\",%u,,4", backend->modem.own_number, type); } rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+COPS=")) { @@ -1350,6 +1354,7 @@ rfcomm_send_reply(rfcomm, "+BIND: (2)"); rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+BIND?")) { + rfcomm_send_reply(rfcomm, "+BIND: 1,0"); rfcomm_send_reply(rfcomm, "+BIND: 2,1"); rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+BIND=")) { @@ -1359,7 +1364,6 @@ rfcomm_send_reply(rfcomm, "OK"); } else if (sscanf(buf, "AT+BIEV=%u,%u", &indicator, &indicator_value) == 2) { process_hfp_hf_indicator(rfcomm, indicator, indicator_value); - rfcomm_send_reply(rfcomm, "OK"); } else if (sscanf(buf, "AT+XAPL=%04x-%04x-%*^,,%u", &xapl_vendor, &xapl_product, &xapl_features) == 3) { if (xapl_features & SPA_BT_HFP_HF_XAPL_FEATURE_BATTERY_REPORTING) { /* claim, that we support battery status reports */ @@ -2759,7 +2763,8 @@ goto fail; #ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE - rfcomm_hfp_ag_set_cind(td->rfcomm, true); + if (!mm_is_available(backend->modemmanager)) + rfcomm_hfp_ag_set_cind(td->rfcomm, true); #endif t->fd = sock; @@ -2813,7 +2818,8 @@ spa_bt_transport_set_state(t, SPA_BT_TRANSPORT_STATE_IDLE); #ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE - rfcomm_hfp_ag_set_cind(td->rfcomm, false); + if (!mm_is_available(backend->modemmanager)) + rfcomm_hfp_ag_set_cind(td->rfcomm, false); #endif sco_destroy_cb(t);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bap-codec-caps.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/bap-codec-caps.h
Changed
@@ -82,6 +82,22 @@ #define LC3_MAX_CHANNELS 28 +/* Metadata types */ +#define BAP_META_TYPE_PREFERRED_CONTEXT 0x01 +#define BAP_META_TYPE_STREAMING_CONTEXT 0x02 +#define BAP_META_TYPE_PROGRAM_INFO 0x03 +#define BAP_META_TYPE_LANGUAGE 0x04 +#define BAP_META_TYPE_CCID_LIST 0x05 +#define BAP_META_TYPE_PARENTAL_RATING 0x06 +#define BAP_META_TYPE_PROGRAM_INFO_URI 0x07 +#define BAP_META_TYPE_AUDIO_ACTIVE_STATE 0x08 +#define BAP_META_TYPE_BCAST_IMMEDIATE 0x09 +#define BAP_META_TYPE_ASSISTED_LISTENING 0x0a +#define BAP_META_TYPE_BCAST_NAME 0x0b +#define BAP_META_TYPE_EXTENDED 0xfe +#define BAP_META_TYPE_VENDOR 0xff + + #define BAP_CHANNEL_MONO 0x00000000 /* mono */ #define BAP_CHANNEL_FL 0x00000001 /* front left */ #define BAP_CHANNEL_FR 0x00000002 /* front right */ @@ -137,12 +153,6 @@ #define BT_ISO_QOS_TARGET_LATENCY_BALANCED 0x02 #define BT_ISO_QOS_TARGET_LATENCY_RELIABILITY 0x03 -struct __attribute__((packed)) ltv { - uint8_t len; - uint8_t type; - uint8_t value; -}; - struct bap_endpoint_qos { uint8_t framing; uint8_t phy;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bap-codec-lc3.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/bap-codec-lc3.c
Changed
@@ -16,6 +16,7 @@ #include <spa/param/audio/format-utils.h> #include <spa/utils/string.h> #include <spa/utils/json.h> +#include <spa/utils/cleanup.h> #include <spa/debug/log.h> #include <lc3.h> @@ -45,9 +46,11 @@ struct settings { uint32_t locations; uint32_t channel_allocation; + uint16_t supported_context; + uint16_t available_context; bool sink; bool duplex; - const char *qos_name; + char *qos_name; int retransmission; int latency; int64_t delay; @@ -55,8 +58,10 @@ }; struct pac_data { - const uint8_t *data; + const void *data; size_t size; + const void *metadata; + size_t metadata_size; int index; const struct settings *settings; }; @@ -81,9 +86,16 @@ uint8_t n_blks; bool sink; bool duplex; + uint16_t preferred_context; unsigned int priority; } bap_lc3_t; +struct config_data { + bap_lc3_t conf; + int pac_index; + struct settings settings; +}; + #define BAP_QOS(name_, rate_, duration_, framing_, framelen_, rtn_, latency_, delay_, priority_) \ ((struct bap_qos){ .name = (name_), .rate = (rate_), .frame_duration = (duration_), .framing = (framing_), \ .framelen = (framelen_), .retransmission = (rtn_), .latency = (latency_), \ @@ -191,32 +203,6 @@ return 0; } -static int write_ltv(uint8_t *dest, uint8_t type, void* value, size_t len) -{ - struct ltv *ltv = (struct ltv *)dest; - - ltv->len = len + 1; - ltv->type = type; - memcpy(ltv->value, value, len); - - return len + 2; -} - -static int write_ltv_uint8(uint8_t *dest, uint8_t type, uint8_t value) -{ - return write_ltv(dest, type, &value, sizeof(value)); -} - -static int write_ltv_uint16(uint8_t *dest, uint8_t type, uint16_t value) -{ - return write_ltv(dest, type, &value, sizeof(value)); -} - -static int write_ltv_uint32(uint8_t *dest, uint8_t type, uint32_t value) -{ - return write_ltv(dest, type, &value, sizeof(value)); -} - static uint16_t parse_rates(const char *str) { struct spa_json it; @@ -319,7 +305,6 @@ static int codec_fill_caps(const struct media_codec *codec, uint32_t flags, const struct spa_dict *settings, uint8_t capsA2DP_MAX_CAPS_SIZE) { - uint8_t *data = caps; const char *str; uint16_t framelen2; uint16_t rate_mask = LC3_FREQ_48KHZ | LC3_FREQ_44KHZ | LC3_FREQ_32KHZ | \ @@ -330,6 +315,7 @@ uint16_t framelen_max = LC3_MAX_FRAME_BYTES; uint8_t max_frames = 2; uint32_t value; + struct ltv_writer writer = LTV_WRITER(caps, A2DP_MAX_CAPS_SIZE); if (settings && (str = spa_dict_lookup(settings, "bluez5.bap-server-capabilities.rates"))) rate_mask = parse_rates(str); @@ -355,17 +341,17 @@ framelen0 = htobs(framelen_min); framelen1 = htobs(framelen_max); - data += write_ltv_uint16(data, LC3_TYPE_FREQ, htobs(rate_mask)); - data += write_ltv_uint8(data, LC3_TYPE_DUR, duration_mask); - data += write_ltv_uint8(data, LC3_TYPE_CHAN, channel_counts); - data += write_ltv(data, LC3_TYPE_FRAMELEN, framelen, sizeof(framelen)); + ltv_writer_uint16(&writer, LC3_TYPE_FREQ, rate_mask); + ltv_writer_uint8(&writer, LC3_TYPE_DUR, duration_mask); + ltv_writer_uint8(&writer, LC3_TYPE_CHAN, channel_counts); + ltv_writer_data(&writer, LC3_TYPE_FRAMELEN, framelen, sizeof(framelen)); /* XXX: we support only one frame block -> max 2 frames per SDU */ if (max_frames > 2) max_frames = 2; - data += write_ltv_uint8(data, LC3_TYPE_BLKS, max_frames); + ltv_writer_uint8(&writer, LC3_TYPE_BLKS, max_frames); - return data - caps; + return ltv_writer_end(&writer); } static void debugc_ltv(struct spa_debug_context *debug_ctx, int pac, struct ltv *ltv) @@ -391,7 +377,7 @@ } } -static int parse_bluez_pacs(const uint8_t *data, size_t data_size, struct pac_data pacsMAX_PACS, +static int parse_bluez_pacs_data(const uint8_t *data, size_t data_size, struct pac_data pacsMAX_PACS, struct spa_debug_context *debug_ctx) { /* @@ -400,7 +386,7 @@ */ int pac = 0; - pacspac = (struct pac_data){ data, 0 }; + pacspac = (struct pac_data){ .data = data }; while (data_size > 0) { struct ltv *ltv = (struct ltv *)data; @@ -411,7 +397,7 @@ break; ++pac; - pacspac = (struct pac_data){ data + 1, 0, pac }; + pacspac = (struct pac_data){ .data = data + 1, .index = pac }; } else if (ltv->len >= data_size) { return -EINVAL; } else { @@ -425,6 +411,28 @@ return pac + 1; } +static int parse_bluez_pacs(const uint8_t *data, size_t data_size, + const uint8_t *metadata, size_t metadata_size, struct pac_data pacsMAX_PACS, + struct spa_debug_context *debug_ctx) +{ + struct pac_data metaMAX_PACS; + int pac_count, meta_count; + + pac_count = parse_bluez_pacs_data(data, data_size, pacs, debug_ctx); + if (pac_count < 0) + return pac_count; + + meta_count = parse_bluez_pacs_data(metadata, metadata_size, meta, debug_ctx); + if (meta_count == pac_count) { + for (int i = 0; i < pac_count; ++i) { + pacsi.metadata = metai.data; + pacsi.metadata_size = metai.size; + } + } + + return pac_count; +} + static uint8_t get_channel_count(uint32_t channels) { uint8_t num; @@ -549,7 +557,7 @@ static bool select_config(bap_lc3_t *conf, const struct pac_data *pac, struct spa_debug_context *debug_ctx) { - const uint8_t *data = pac->data; + const void *data = pac->data; size_t data_size = pac->size; uint16_t framelen_min = 0, framelen_max = 0; int max_frames = -1; @@ -557,9 +565,11 @@ uint8_t max_channels = 0; uint8_t duration_mask = 0; uint16_t rate_mask = 0; + uint16_t preferred_context = 0; struct bap_qos bap_qos; unsigned int i; bool found = false; + const struct ltv *ltv; if (!data_size) return false;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bluez5-dbus.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -152,8 +152,10 @@ char *uuid; unsigned int codec; struct spa_bt_device *device; - uint8_t capabilitiesA2DP_MAX_CAPS_SIZE; - int capabilities_len; + uint8_t *capabilities; + size_t capabilities_len; + uint8_t *metadata; + size_t metadata_len; bool delay_reporting; bool acceptor; @@ -693,7 +695,7 @@ * by codec switching. */ res = codec->select_config(codec, sink ? MEDIA_CODEC_FLAG_SINK : 0, cap, size, &monitor->default_audio_info, - &monitor->global_settings, config); + &monitor->global_settings, config, NULL); else res = -ENOTSUP; @@ -878,8 +880,9 @@ } static int parse_endpoint_props(struct spa_bt_monitor *monitor, DBusMessageIter *iter, - uint8_t capsA2DP_MAX_CAPS_SIZE, int *caps_size, const char **endpoint_path, - struct bap_endpoint_qos *qos) + uint8_t **caps, size_t *caps_size, + uint8_t **meta, size_t *meta_size, + const char **endpoint_path, struct bap_endpoint_qos *qos) { DBusMessageIter dict_iter = *iter; const char *key = NULL; @@ -900,12 +903,25 @@ type = dbus_message_iter_get_arg_type(&it1); - if (spa_streq(key, "Capabilities")) { - uint8_t *buf; + if (spa_streq(key, "Capabilities") || spa_streq(key, "Metadata")) { + uint8_t **dest; + size_t *size; + uint8_t *data, *buf; + int n; + + if (spa_streq(key, "Capabilities")) { + dest = caps; + size = caps_size; + } else { + dest = meta; + size = meta_size; + } - if (!caps) + if (!dest) goto next; + spa_assert(dest && size); + if (type != DBUS_TYPE_ARRAY) goto bad_property; @@ -914,15 +930,19 @@ if (type != DBUS_TYPE_BYTE) goto bad_property; - dbus_message_iter_get_fixed_array(&it2, &buf, caps_size); - if (*caps_size > A2DP_MAX_CAPS_SIZE) { - spa_log_error(monitor->log, "%s size:%d too large", key, (int)*caps_size); - return -EINVAL; - } - memcpy(caps, buf, *caps_size); + dbus_message_iter_get_fixed_array(&it2, &data, &n); - spa_log_info(monitor->log, "%p: %s size:%d", monitor, key, *caps_size); - spa_debug_log_mem(monitor->log, SPA_LOG_LEVEL_DEBUG, ' ', caps, (size_t)*caps_size); + buf = malloc(n); + if (!buf) + return -ENOMEM; + + free(*dest); + *dest = buf; + *size = n; + memcpy(buf, data, n); + + spa_log_info(monitor->log, "%p: %s size:%zu", monitor, key, *size); + spa_debug_log_mem(monitor->log, SPA_LOG_LEVEL_DEBUG, ' ', *dest, *size); } else if (spa_streq(key, "Endpoint")) { if (!endpoint_path) goto next; @@ -1012,8 +1032,12 @@ const char *endpoint_path = NULL; uint8_t configA2DP_MAX_CAPS_SIZE; + void *config_data = NULL; char locations64 = {0}; char channel_allocation64 = {0}; + char supported_context64 = {0}; + char available_context64 = {0}; + char metadata_len64 = {0}; int conf_size; DBusMessageIter dict; @@ -1028,6 +1052,9 @@ path = dbus_message_get_path(m); + if ((r = dbus_message_new_method_return(m)) == NULL) + return DBUS_HANDLER_RESULT_NEED_MEMORY; + /* TODO: for codecs with shared endpoint, this currently always picks the default * one. However, currently we don't have BAP codecs with shared endpoint, so * this does not matter, but in case they are needed later we should pick the @@ -1043,7 +1070,7 @@ /* Find endpoint */ iter = props; - if (parse_endpoint_props(monitor, &iter, NULL, NULL, &endpoint_path, NULL) < 0) + if (parse_endpoint_props(monitor, &iter, NULL, NULL, NULL, NULL, &endpoint_path, NULL) < 0) goto error_invalid; ep = remote_endpoint_find(monitor, endpoint_path); @@ -1059,7 +1086,8 @@ /* Parse endpoint properties */ iter = props; - if (parse_endpoint_props(monitor, &iter, ep->capabilities, &ep->capabilities_len, NULL, &ep->qos) < 0) + if (parse_endpoint_props(monitor, &iter, &ep->capabilities, &ep->capabilities_len, + &ep->metadata, &ep->metadata_len, NULL, &ep->qos) < 0) goto error_invalid; if (ep->qos.locations) @@ -1067,6 +1095,10 @@ if (ep->qos.channel_allocation) spa_scnprintf(channel_allocation, sizeof(channel_allocation), "%"PRIu32, ep->qos.channel_allocation); + spa_scnprintf(supported_context, sizeof(supported_context), "%"PRIu16, ep->qos.supported_context); + spa_scnprintf(available_context, sizeof(available_context), "%"PRIu16, ep->qos.context); + spa_scnprintf(metadata_len, sizeof(metadata_len), "%zu", ep->metadata_len); + if (!ep->device->preferred_profiles) ep->device->preferred_profiles = ep->device->profiles; @@ -1075,16 +1107,20 @@ i = 0; setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.locations", locations); setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.channel-allocation", channel_allocation); + setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.supported-context", supported_context); + setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.available-context", available_context); setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.sink", sink ? "true" : "false"); setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.duplex", duplex ? "true" : "false"); setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.debug", "true"); + setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.metadata", (void *)ep->metadata); + setting_itemsi++ = SPA_DICT_ITEM_INIT("bluez5.bap.metadata-len", metadata_len); if (ep->device->settings) for (j = 0; j < ep->device->settings->n_items && i < SPA_N_ELEMENTS(setting_items); ++i, ++j) setting_itemsi = ep->device->settings->itemsj; settings = SPA_DICT_INIT(setting_items, i); conf_size = codec->select_config(codec, 0, ep->capabilities, ep->capabilities_len, - &monitor->default_audio_info, &settings, config); + &monitor->default_audio_info, &settings, config, &config_data); if (conf_size < 0) { spa_log_error(monitor->log, "can't select config: %d (%s)", conf_size, spa_strerror(conf_size)); @@ -1093,8 +1129,6 @@ spa_log_info(monitor->log, "%p: selected conf %d", monitor, conf_size); spa_debug_log_mem(monitor->log, SPA_LOG_LEVEL_DEBUG, ' ', (uint8_t *)config, (size_t)conf_size); - if ((r = dbus_message_new_method_return(m)) == NULL) - return DBUS_HANDLER_RESULT_NEED_MEMORY; dbus_message_iter_init_append(r, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, @@ -1113,7 +1147,7 @@ spa_zero(qos); - res = codec->get_qos(codec, config, conf_size, &ep->qos, &qos, &settings); + res = codec->get_qos(codec, &ep->qos, config_data, &qos); if (res < 0) { spa_log_error(monitor->log, "can't select QOS config: %d (%s)", res, spa_strerror(res)); @@ -1161,8 +1195,30 @@ dbus_message_iter_close_container(&dict, &entry); } + if (codec->get_metadata) { + uint8_t meta4096 = {}; + size_t meta_size; + + meta_size = res = codec->get_metadata(codec, config_data, meta, sizeof(meta)); + if (res < 0) { + spa_log_error(monitor->log, "can't select metadata config: %d (%s)", + res, spa_strerror(res)); + goto error_invalid; + } + + if (meta_size) {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/iso-io.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/iso-io.c
Changed
@@ -309,6 +309,7 @@ if (stream->this.size == 0) { spa_log_debug(group->log, "%p: ISO group:%u miss fd:%d", group, group->id, stream->fd); + stream->this.resync = true; if (stream_silence(stream) < 0) { fail = true; continue; @@ -625,6 +626,17 @@ struct stream *stream = SPA_CONTAINER_OF(this, struct stream, this); struct group *group = stream->group; + if (!stream->sink) { + struct stream *s; + + spa_list_for_each(s, &group->streams, link) { + if (s->sink && s->fd == stream->fd) { + stream = s; + break; + } + } + } + return spa_bt_latency_recv_errqueue(&stream->tx_latency, stream->fd, group->log); }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/media-codecs.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/media-codecs.c
Changed
@@ -8,6 +8,8 @@ * */ +#include <bluetooth/bluetooth.h> + #include <spa/utils/string.h> #include <spa/utils/cleanup.h> @@ -90,7 +92,7 @@ if (caps == NULL) return false; - res = codec->select_config(codec, 0, caps, caps_size, info, global_settings, config); + res = codec->select_config(codec, 0, caps, caps_size, info, global_settings, config, NULL); if (res < 0) return false; @@ -100,6 +102,52 @@ return ((size_t)res == caps_size); } +void ltv_writer_data(struct ltv_writer *w, uint8_t type, void* value, size_t len) +{ + struct ltv *ltv; + size_t sz = (size_t)w->size + sizeof(struct ltv) + len; + + if (!w->buf || sz > w->max_size || (uint16_t)sz != sz) { + w->buf = NULL; + return; + } + + ltv = SPA_PTROFF(w->buf, w->size, struct ltv); + ltv->len = len + 1; + ltv->type = type; + memcpy(ltv->value, value, len); + + w->size = sz; +} + +void ltv_writer_uint8(struct ltv_writer *w, uint8_t type, uint8_t v) +{ + ltv_writer_data(w, type, &v, sizeof(v)); +} + +void ltv_writer_uint16(struct ltv_writer *w, uint8_t type, uint16_t value) +{ + uint16_t v = htobs(value); + + ltv_writer_data(w, type, &v, sizeof(v)); +} + +void ltv_writer_uint32(struct ltv_writer *w, uint8_t type, uint32_t value) +{ + uint32_t v = htobl(value); + + ltv_writer_data(w, type, &v, sizeof(v)); +} + +int ltv_writer_end(struct ltv_writer *w) +{ + if (!w->buf) + return -ENOSPC; + + w->buf = NULL; + return w->size; +} + #ifdef CODEC_PLUGIN struct impl {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/media-codecs.h -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/media-codecs.h
Changed
@@ -15,6 +15,7 @@ #include <spa/pod/pod.h> #include <spa/pod/builder.h> #include <spa/support/log.h> +#include <spa/debug/log.h> #include "a2dp-codec-caps.h" #include "bap-codec-caps.h" @@ -26,7 +27,7 @@ #define SPA_TYPE_INTERFACE_Bluez5CodecMedia SPA_TYPE_INFO_INTERFACE_BASE "Bluez5:Codec:Media:Private" -#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 15 +#define SPA_VERSION_BLUEZ5_CODEC_MEDIA 16 struct spa_bluez5_codec_a2dp { struct spa_interface iface; @@ -93,7 +94,7 @@ * called again to parse the remaining data. */ int (*get_bis_config)(const struct media_codec *codec, uint8_t *caps, - uint8_t *caps_size, struct spa_dict *settings, + uint8_t *caps_size, struct spa_dict *settings, struct bap_codec_qos *qos); /** If fill_caps is NULL, no endpoint is registered (for sharing with another codec). */ @@ -103,7 +104,8 @@ int (*select_config) (const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, const struct media_codec_audio_info *info, - const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE); + const struct spa_dict *global_settings, uint8_t configA2DP_MAX_CAPS_SIZE, + void **config_data); int (*enum_config) (const struct media_codec *codec, uint32_t flags, const void *caps, size_t caps_size, uint32_t id, uint32_t idx, struct spa_pod_builder *builder, struct spa_pod **param); @@ -111,9 +113,12 @@ const void *caps, size_t caps_size, struct spa_audio_info *info); int (*get_qos)(const struct media_codec *codec, - const void *config, size_t config_size, const struct bap_endpoint_qos *endpoint_qos, - struct bap_codec_qos *qos, const struct spa_dict *settings); + const void *config_data, + struct bap_codec_qos *qos); + int (*get_metadata)(const struct media_codec *codec, const void *config_data, + uint8_t *meta, size_t meta_max_size); + void (*free_config_data)(const struct media_codec *codec, void *config_data); /** qsort comparison sorting caps in order of preference for the codec. * Used in codec switching to select best remote endpoints. @@ -264,4 +269,44 @@ const void *caps, size_t caps_size, const struct media_codec_audio_info *info, const struct spa_dict *global_settings); +struct __attribute__((packed)) ltv { + uint8_t len; + uint8_t type; + uint8_t value; +}; + +struct ltv_writer { + void *buf; + uint16_t size; + size_t max_size; +}; + +#define LTV_WRITER(ptr, max) ((struct ltv_writer) { .buf = (ptr), .max_size = (max) }) + +void ltv_writer_data(struct ltv_writer *w, uint8_t type, void* value, size_t len); +void ltv_writer_uint8(struct ltv_writer *w, uint8_t type, uint8_t v); +void ltv_writer_uint16(struct ltv_writer *w, uint8_t type, uint16_t value); +void ltv_writer_uint32(struct ltv_writer *w, uint8_t type, uint32_t value); +int ltv_writer_end(struct ltv_writer *w); + +static inline const struct ltv *ltv_next(const void **data, size_t *size) +{ + const struct ltv *ltv; + + if (*size == 0) { + *data = NULL; + return NULL; + } + if (*size < sizeof(struct ltv)) + return NULL; + + ltv = *data; + if (ltv->len >= *size) + return NULL; + + *data = SPA_PTROFF(*data, ltv->len + 1, void); + *size -= ltv->len + 1; + return ltv; +} + #endif
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/media-source.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/media-source.c
Changed
@@ -613,6 +613,10 @@ { int res; + if (this->transport && this->transport->iso_io) + if (spa_bt_iso_io_recv_errqueue(this->transport->iso_io) == 0) + return; + /* iso-io/media-sink use these for TX latency. * Someone else should be reading them, so drop * only after yielding.
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/modemmanager.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/modemmanager.c
Changed
@@ -10,6 +10,10 @@ #include "modemmanager.h" +SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.bluez5.modemmanager"); +#undef SPA_LOG_TOPIC_DEFAULT +#define SPA_LOG_TOPIC_DEFAULT &log_topic + #define DBUS_INTERFACE_OBJECTMANAGER "org.freedesktop.DBus.ObjectManager" struct modem { @@ -412,6 +416,26 @@ } } +static bool mm_get_managed_objects(struct impl *this) +{ + spa_autoptr(DBusMessage) m = dbus_message_new_method_call(MM_DBUS_SERVICE, + "/org/freedesktop/ModemManager1", + DBUS_INTERFACE_OBJECTMANAGER, + "GetManagedObjects"); + if (m == NULL) + return false; + + dbus_message_set_auto_start(m, false); + + this->pending = send_with_reply(this->conn, m, mm_get_managed_objects_reply, this); + if (!this->pending) { + spa_log_error(this->log, "dbus call failure"); + return false; + } + + return true; +} + static void call_free(struct call *call) { spa_list_remove(&call->link); @@ -488,8 +512,12 @@ mm_clean_modem(this); } - if (new_owner && *new_owner) + if (new_owner && *new_owner) { spa_log_debug(this->log, "ModemManager daemon appeared (%s)", new_owner); + + if (!mm_get_managed_objects(this)) + goto finish; + } } } else if (dbus_message_is_signal(m, DBUS_INTERFACE_OBJECTMANAGER, DBUS_SIGNAL_INTERFACES_ADDED)) { DBusMessageIter arg_i; @@ -1080,20 +1108,8 @@ if (add_filters(this) < 0) return NULL; - spa_autoptr(DBusMessage) m = dbus_message_new_method_call(MM_DBUS_SERVICE, - "/org/freedesktop/ModemManager1", - DBUS_INTERFACE_OBJECTMANAGER, - "GetManagedObjects"); - if (m == NULL) - return NULL; - - dbus_message_set_auto_start(m, false); - - this->pending = send_with_reply(this->conn, m, mm_get_managed_objects_reply, this); - if (!this->pending) { - spa_log_error(this->log, "dbus call failure"); + if (!mm_get_managed_objects(this)) return NULL; - } return spa_steal_ptr(this); }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/player.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/player.c
Changed
@@ -247,11 +247,12 @@ struct spa_bt_player *spa_bt_player_new(void *dbus_connection, struct spa_log *log) { - struct impl *impl; - const DBusObjectPathVTable vtable = { + static const DBusObjectPathVTable vtable = { .message_function = player_handler, }; + struct impl *impl; + spa_log_topic_init(log, &log_topic); impl = calloc(1, sizeof(struct impl));
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/telephony.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/bluez5/telephony.c
Changed
@@ -1148,20 +1148,23 @@ { struct agimpl *agimpl = SPA_CONTAINER_OF(ag, struct agimpl, this); struct impl *impl = SPA_CONTAINER_OF(agimpl->this.telephony, struct impl, this); - char *path; - const DBusObjectPathVTable vtable = { + static const DBusObjectPathVTable vtable = { .message_function = ag_handler, }; - path = spa_aprintf (PW_TELEPHONY_OBJECT_PATH "/ag%d", agimpl->this.id); + if (agimpl->path) + return -EBUSY; + + spa_autofree char *path = spa_aprintf(PW_TELEPHONY_OBJECT_PATH "/ag%d", agimpl->this.id); /* register object */ if (!dbus_connection_register_object_path(impl->conn, path, &vtable, agimpl)) { spa_log_error(impl->log, "failed to register %s", path); return -EIO; } - agimpl->path = strdup(path); + + agimpl->path = spa_steal_ptr(path); /* notify on ObjectManager of the Manager object */ { @@ -1174,7 +1177,7 @@ dbus_iter_append_ag_interfaces(&iter, ag); if (!dbus_connection_send(impl->conn, msg, NULL)) { - spa_log_error(impl->log, "failed to send InterfacesAdded for %s", path); + spa_log_error(impl->log, "failed to send InterfacesAdded for %s", agimpl->path); telephony_ag_unregister(ag); return -EIO; } @@ -1188,18 +1191,18 @@ msg = dbus_message_new_signal(impl->path, OFONO_MANAGER_IFACE, "ModemAdded"); dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &agimpl->path); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sv}", &props_dict); dbus_message_iter_close_container(&iter, &props_dict); if (!dbus_connection_send(impl->conn, msg, NULL)) { - spa_log_error(impl->log, "failed to send ModemAdded for %s", path); + spa_log_error(impl->log, "failed to send ModemAdded for %s", agimpl->path); telephony_ag_unregister(ag); return -EIO; } } - spa_log_debug(impl->log, "registered AudioGateway: %s", path); + spa_log_debug(impl->log, "registered AudioGateway: %s", agimpl->path); return 0; } @@ -1646,20 +1649,23 @@ struct callimpl *callimpl = SPA_CONTAINER_OF(call, struct callimpl, this); struct agimpl *agimpl = SPA_CONTAINER_OF(callimpl->this.ag, struct agimpl, this); struct impl *impl = SPA_CONTAINER_OF(agimpl->this.telephony, struct impl, this); - char *path; - const DBusObjectPathVTable vtable = { + static const DBusObjectPathVTable vtable = { .message_function = call_handler, }; - path = spa_aprintf ("%s/call%d", agimpl->path, callimpl->this.id); + if (callimpl->path) + return -EBUSY; + + spa_autofree char *path = spa_aprintf("%s/call%d", agimpl->path, callimpl->this.id); /* register object */ if (!dbus_connection_register_object_path(impl->conn, path, &vtable, callimpl)) { spa_log_error(impl->log, "failed to register %s", path); return -EIO; } - callimpl->path = strdup(path); + + callimpl->path = spa_steal_ptr(path); /* notify on ObjectManager of the AudioGateway object */ { @@ -1671,7 +1677,7 @@ DBUS_INTERFACE_OBJECT_MANAGER, "InterfacesAdded"); dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &callimpl->path); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{sa{sv}}", &dict); dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &interface); @@ -1680,7 +1686,7 @@ dbus_message_iter_close_container(&iter, &dict); if (!dbus_connection_send(impl->conn, msg, NULL)) { - spa_log_error(impl->log, "failed to send InterfacesAdded for %s", path); + spa_log_error(impl->log, "failed to send InterfacesAdded for %s", callimpl->path); telephony_call_unregister(call); return -EIO; } @@ -1695,11 +1701,11 @@ OFONO_VOICE_CALL_MANAGER_IFACE, "CallAdded"); dbus_message_iter_init_append(msg, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &path); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &callimpl->path); dbus_iter_append_call_properties(&iter, call, true); if (!dbus_connection_send(impl->conn, msg, NULL)) { - spa_log_error(impl->log, "failed to send CallAdded for %s", path); + spa_log_error(impl->log, "failed to send CallAdded for %s", callimpl->path); telephony_call_unregister(call); return -EIO; } @@ -1707,7 +1713,7 @@ telephony_call_commit_properties(call); - spa_log_debug(impl->log, "registered Call: %s", path); + spa_log_debug(impl->log, "registered Call: %s", callimpl->path); return 0; }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/filter-graph/plugin_builtin.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/filter-graph/plugin_builtin.c
Changed
@@ -704,16 +704,93 @@ struct convolver *conv; }; +struct finfo { +#define TYPE_INVALID 0 +#define TYPE_SNDFILE 1 +#define TYPE_HILBERT 2 +#define TYPE_DIRAC 3 +#define TYPE_IR 4 + uint32_t type; + + const char *filename; #ifdef HAVE_SNDFILE -static float *read_samples_from_sf(SNDFILE *f, const SF_INFO *info, float gain, int delay, - int offset, int length, int channel, long unsigned *rate, int *n_samples) { - float *samples; - int i, n; + SF_INFO info; + SNDFILE *fs; +#endif + int channels; + int def_frames; + int max_frames; + float latency; /* latency relative to number of samples */ + uint32_t rate; + const char *error; +}; + +static int finfo_open(const char *filename, struct finfo *info, int rate) +{ + info->filename = filename; + if (spa_strstartswith(filename, "/hilbert")) { + info->channels = 1; + info->rate = rate; + info->def_frames = 64; + info->max_frames = INT_MAX; + info->type = TYPE_HILBERT; + info->latency = 0.5f; + } + else if (spa_strstartswith(filename, "/dirac")) { + info->channels = 1; + info->def_frames = 1; + info->max_frames = 1; + info->rate = rate; + info->type = TYPE_DIRAC; + info->latency = 0.0f; + } + else if (spa_strstartswith(filename, "/ir:")) { + struct spa_json it1; + float v; + int rate; + info->channels = 1; + info->type = TYPE_IR; + info->def_frames = 0; + if (spa_json_begin_array_relax(&it0, filename+4, strlen(filename+4)) <= 0) + return -EINVAL; + if (spa_json_get_int(&it0, &rate) <= 0) + return -EINVAL; + info->rate = rate; + while (spa_json_get_float(&it0, &v) > 0) + info->def_frames++; + info->max_frames = info->def_frames; + info->latency = 0.0f; + } else { +#ifdef HAVE_SNDFILE + info->fs = sf_open(filename, SFM_READ, &info->info); + if (info->fs == NULL) { + info->error = sf_strerror(NULL); + return -ENOENT; + } + info->channels = info->info.channels; + info->def_frames = info->info.frames; + info->max_frames = info->def_frames; + info->rate = info->info.samplerate; + info->type = TYPE_SNDFILE; + info->latency = 0.0f; +#else + info->error = "compiled without sndfile support, can't load samples"; + return -ENOTSUP; +#endif + } + return 0; +} + +static float *finfo_read_samples(struct plugin *pl, struct finfo *info, float gain, int delay, + int offset, int length, int channel, long unsigned *rate, int *n_samples, int *latency) +{ + float *samples, v; + int i, n, h; if (length <= 0) - length = info->frames; + length = info->def_frames; else - length = SPA_MIN(length, info->frames); + length = SPA_MIN(length, info->max_frames); length -= SPA_MIN(offset, length); @@ -725,127 +802,106 @@ if (samples == NULL) return NULL; - if (offset > 0) - sf_seek(f, offset, SEEK_SET); - sf_readf_float(f, samples + (delay * info->channels), length); - channel = channel % info->channels; - for (i = 0; i < n; i++) - samplesi = samplesinfo->channels * i + channel * gain; - + switch (info->type) { + case TYPE_SNDFILE: +#ifdef HAVE_SNDFILE + if (offset > 0) + sf_seek(info->fs, offset, SEEK_SET); + sf_readf_float(info->fs, samples + (delay * info->channels), length); + for (i = 0; i < n; i++) + samplesi = samplesinfo->channels * i + channel * gain; +#endif + break; + case TYPE_HILBERT: + gain *= 2 / (float)M_PI; + h = length / 2; + for (i = 1; i < h; i += 2) { + v = (gain / i) * (0.43f + 0.57f * cosf(i * (float)M_PI / h)); + samplesdelay + h + i = -v; + samplesdelay + h - i = v; + } + spa_log_info(pl->log, "created hilbert function length %d", length); + break; + case TYPE_DIRAC: + samplesdelay = gain; + spa_log_info(pl->log, "created dirac function"); + break; + case TYPE_IR: + { + struct spa_json it1; + float v; + if (spa_json_begin_array_relax(&it0, info->filename+4, strlen(info->filename+4)) <= 0) + return NULL; + if (spa_json_get_int(&it0, &h) <= 0) + return NULL; + info->rate = h; + i = 0; + while (spa_json_get_float(&it0, &v) > 0) { + samplesdelay + i = v * gain; + i++; + } + break; + } + } *n_samples = n; - *rate = info->samplerate; + *rate = info->rate; + *latency = (int) (n * info->latency); return samples; } -#endif -static float *read_closest(struct plugin *pl, char **filenames, float gain, float delay_sec, int offset, - int length, int channel, long unsigned *rate, int *n_samples) + +static void finfo_close(struct finfo *info) { #ifdef HAVE_SNDFILE - SF_INFO infosMAX_RATES; - SNDFILE *fsMAX_RATES; - - spa_zero(infos); - spa_zero(fs); + if (info->type == TYPE_SNDFILE && info->fs != NULL) + sf_close(info->fs); +#endif +} - int diff = INT_MAX; - uint32_t best = 0, i; +static float *read_closest(struct plugin *pl, char **filenames, float gain, float delay_sec, int offset, + int length, int channel, long unsigned *rate, int *n_samples, int *latency) +{ + struct finfo finfoMAX_RATES; + int res, diff = INT_MAX; + uint32_t best = SPA_ID_INVALID, i; float *samples = NULL; + spa_zero(finfo); + for (i = 0; i < MAX_RATES && filenamesi && filenamesi0; i++) { - fsi = sf_open(filenamesi, SFM_READ, &infosi); - if (fsi == NULL) + res = finfo_open(filenamesi, &finfoi, *rate); + if (res < 0) continue; - if (labs((long)infosi.samplerate - (long)*rate) < diff) { + if (labs((long)finfoi.rate - (long)*rate) < diff) { best = i;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/libcamera/libcamera-source.cpp -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/libcamera/libcamera-source.cpp
Changed
@@ -71,7 +71,6 @@ struct spa_fraction rate = {}; StreamConfiguration streamConfig; - spa_data_type memtype = SPA_DATA_Invalid; uint32_t buffers_blocks = 1; struct buffer buffersMAX_BUFFERS; @@ -449,8 +448,7 @@ uint32_t type, uint32_t subtype, uint32_t format) { for (const auto& f : format_info) { - if (f.media_type == type && f.media_subtype == subtype - && (f.format == SPA_VIDEO_FORMAT_UNKNOWN || f.format == format)) + if (f.media_type == type && f.media_subtype == subtype && f.format == format) return &f; } @@ -667,7 +665,6 @@ const struct format_info *info = nullptr; uint32_t video_format; struct spa_rectangle *size = nullptr; - struct spa_fraction *framerate = nullptr; CameraConfiguration::Status validation; int res; @@ -675,18 +672,15 @@ case SPA_MEDIA_SUBTYPE_raw: video_format = format->info.raw.format; size = &format->info.raw.size; - framerate = &format->info.raw.framerate; break; case SPA_MEDIA_SUBTYPE_mjpg: case SPA_MEDIA_SUBTYPE_jpeg: video_format = SPA_VIDEO_FORMAT_ENCODED; size = &format->info.mjpg.size; - framerate = &format->info.mjpg.framerate; break; case SPA_MEDIA_SUBTYPE_h264: video_format = SPA_VIDEO_FORMAT_ENCODED; size = &format->info.h264.size; - framerate = &format->info.h264.framerate; break; default: video_format = SPA_VIDEO_FORMAT_ENCODED; @@ -695,7 +689,7 @@ info = find_format_info_by_media_type(format->media_type, format->media_subtype, video_format); - if (info == nullptr || size == nullptr || framerate == nullptr) { + if (info == nullptr || size == nullptr) { spa_log_error(impl->log, "unknown media type %d %d %d", format->media_type, format->media_subtype, video_format); return -EINVAL; @@ -1210,21 +1204,17 @@ const std::vector<std::unique_ptr<FrameBuffer>> &bufs = impl->allocator.buffers(stream); - if (n_buffers > 0) { - if (bufs.size() != n_buffers) - return -EINVAL; + if (n_buffers > 0 && bufs.size() != n_buffers) + return -EINVAL; - spa_data *d = buffers0->datas; + const auto choose_memtype = (uint32_t t) { + if (t != SPA_ID_INVALID && t & (1u << SPA_DATA_DmaBuf)) + return SPA_DATA_DmaBuf; + if (t & (1u << SPA_DATA_MemFd)) + return SPA_DATA_MemFd; - if (d0.type != SPA_ID_INVALID && d0.type & (1u << SPA_DATA_DmaBuf)) { - port->memtype = SPA_DATA_DmaBuf; - } else if (d0.type & (1u << SPA_DATA_MemFd)) { - port->memtype = SPA_DATA_MemFd; - } else { - spa_log_error(impl->log, "can't use buffers of type %d", d0.type); - return -EINVAL; - } - } + return SPA_DATA_Invalid; + }; for (uint32_t i = 0; i < n_buffers; i++) { struct buffer *b; @@ -1254,9 +1244,17 @@ spa_data *d = buffersi->datas; for(uint32_t j = 0; j < buffersi->n_datas; ++j) { - dj.type = port->memtype; + const auto memtype = choose_memtype(dj.type); + if (memtype == SPA_DATA_Invalid) { + spa_log_error(impl->log, "can't use buffers of type %" PRIu32, dj.type); + return -EINVAL; + } + + dj.type = memtype; dj.flags = SPA_DATA_FLAG_READABLE; + dj.fd = -1; dj.mapoffset = 0; + dj.data = nullptr; dj.chunk->stride = port->streamConfig.stride; dj.chunk->flags = 0; /* Update parameters according to the plane information */ @@ -1286,15 +1284,16 @@ dj.chunk->size = port->streamConfig.frameSize; } - if (port->memtype == SPA_DATA_DmaBuf || - port->memtype == SPA_DATA_MemFd) { + switch (memtype) { + case SPA_DATA_DmaBuf: + case SPA_DATA_MemFd: dj.flags |= SPA_DATA_FLAG_MAPPABLE; dj.fd = planesj.fd.get(); spa_log_debug(impl->log, "Got fd = %" PRId64 " for buffer: #%d", dj.fd, i); - dj.data = nullptr; - } else { - spa_log_error(impl->log, "invalid buffer type"); - return -EIO; + break; + default: + spa_assert_not_reached(); + break; } } } @@ -1420,20 +1419,17 @@ spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(port->current_format->info.raw.format), SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&port->current_format->info.raw.size), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.raw.framerate), 0); break; case SPA_MEDIA_SUBTYPE_mjpg: case SPA_MEDIA_SUBTYPE_jpeg: spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&port->current_format->info.mjpg.size), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.mjpg.framerate), 0); break; case SPA_MEDIA_SUBTYPE_h264: spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_size, SPA_POD_Rectangle(&port->current_format->info.h264.size), - SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&port->current_format->info.h264.framerate), 0); break; default:
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/support/loop.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/support/loop.c
Changed
@@ -9,7 +9,6 @@ #include <stdlib.h> #include <stdio.h> #include <pthread.h> -#include <threads.h> #include <stdatomic.h> #include <spa/support/loop.h>
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/videoconvert/videoadapter.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/videoconvert/videoadapter.c
Changed
@@ -25,6 +25,7 @@ #include <spa/param/video/format-utils.h> #include <spa/param/latency-utils.h> #include <spa/param/tag-utils.h> +#include <spa/param/peer-utils.h> #include <spa/debug/format.h> #include <spa/debug/pod.h> #include <spa/debug/log.h> @@ -900,7 +901,6 @@ switch (id) { case SPA_IO_Position: this->io_position = data; - this->recheck_format = true; break; default: break; @@ -920,7 +920,7 @@ uint8_t buffer4096; spa_auto(spa_pod_dynamic_builder) b = { 0 }; uint32_t state = 0; - struct spa_pod *param; + struct spa_pod *param, *p, *str; struct spa_pod_frame f; int res; @@ -934,7 +934,6 @@ spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); spa_pod_builder_push_struct(&b.b, &f); - while (true) { res = node_port_enum_params_sync(impl, impl->follower, impl->direction, 0, @@ -951,10 +950,24 @@ spa_pod_simplify(&b.b, ¶m, param); spa_debug_log_pod(impl->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, param); + str = spa_pod_copy(param); + spa_pod_dynamic_builder_clean(&b); + + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_peer_param_build_start(&b.b, &f, SPA_PARAM_PeerEnumFormat); + SPA_POD_STRUCT_FOREACH(str, p) { + spa_debug_log_pod(impl->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, p); + spa_peer_param_build_add_param(&b.b, 1, p); + } + param = spa_peer_param_build_end(&b.b, &f); + + spa_debug_log_pod(impl->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, param); + res = spa_node_port_set_param(impl->target, SPA_DIRECTION_REVERSE(impl->direction), 0, - SPA_PARAM_PeerFormats, 0, param); + SPA_PARAM_PeerEnumFormat, 0, param); + free(str); impl->recheck_format = false; spa_log_debug(impl->log, "done updating peer formats: %d", res);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/videoconvert/videoconvert-ffmpeg.c -> _service:download_files:pipewire-1.5.84.tar.bz2/spa/plugins/videoconvert/videoconvert-ffmpeg.c
Changed
@@ -31,6 +31,7 @@ #include <spa/param/param.h> #include <spa/param/latency-utils.h> #include <spa/param/tag-utils.h> +#include <spa/param/peer-utils.h> #include <spa/pod/filter.h> #include <spa/pod/dynamic.h> #include <spa/debug/types.h> @@ -77,15 +78,16 @@ uint64_t info_all; struct spa_port_info info; -#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 IDX_Tag 6 -#define IDX_PeerFormats 7 -#define N_PORT_PARAMS 8 +#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 IDX_Tag 6 +#define IDX_PeerEnumFormat 7 +#define IDX_PeerCapability 8 +#define N_PORT_PARAMS 9 struct spa_param_info paramsN_PORT_PARAMS; struct spa_pod *peer_format_pod; @@ -485,7 +487,8 @@ port->paramsIDX_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); port->paramsIDX_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE); port->paramsIDX_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE); - port->paramsIDX_PeerFormats = SPA_PARAM_INFO(SPA_PARAM_PeerFormats, SPA_PARAM_INFO_WRITE); + port->paramsIDX_PeerEnumFormat = SPA_PARAM_INFO(SPA_PARAM_PeerEnumFormat, SPA_PARAM_INFO_WRITE); + port->paramsIDX_PeerCapability = SPA_PARAM_INFO(SPA_PARAM_PeerCapability, SPA_PARAM_INFO_WRITE); port->info.params = port->params; port->info.n_params = N_PORT_PARAMS; @@ -1599,7 +1602,7 @@ return 0; } -static int port_param_peer_formats(struct impl *this, struct port *port, uint32_t index, +static int port_param_peer_enum_format(struct impl *this, struct port *port, uint32_t index, const struct spa_pod **param, struct spa_pod_builder *b) { if (index >= port->n_peer_formats) @@ -1664,8 +1667,8 @@ case SPA_PARAM_Tag: res = port_param_tag(this, port, id, result.index, ¶m, &b); break; - case SPA_PARAM_PeerFormats: - res = port_param_peer_formats(this, port, result.index, ¶m, &b); + case SPA_PARAM_PeerEnumFormat: + res = port_param_peer_enum_format(this, port, result.index, ¶m, &b); break; default: return -ENOENT; @@ -1980,7 +1983,7 @@ } -static int port_set_peer_formats(void *object, +static int port_set_peer_enum_format(void *object, enum spa_direction direction, uint32_t port_id, uint32_t flags, @@ -1990,14 +1993,15 @@ struct port *port, *oport; int res = 0; uint32_t i; - const struct spa_pod *format; enum spa_direction other = SPA_DIRECTION_REVERSE(direction); static uint32_t subtypes = { SPA_MEDIA_SUBTYPE_raw, SPA_MEDIA_SUBTYPE_mjpg, SPA_MEDIA_SUBTYPE_h264 }; + struct spa_peer_param_info info; + void *state = NULL; - spa_return_val_if_fail(spa_pod_is_struct(formats), -EINVAL); + spa_return_val_if_fail(spa_pod_is_object(formats), -EINVAL); port = GET_PORT(this, direction, port_id); oport = GET_PORT(this, other, port_id); @@ -2013,9 +2017,10 @@ port->peer_format_pod = spa_pod_copy(formats); for (i = 0; i < SPA_N_ELEMENTS(subtypes); i++) { - SPA_POD_STRUCT_FOREACH(port->peer_format_pod, format) { + state = NULL; + while (spa_peer_param_parse(formats, &info, sizeof(info), &state) > 0) { uint32_t media_type, media_subtype; - if (!spa_format_parse(format, &media_type, &media_subtype) || + if (!spa_format_parse(info.param, &media_type, &media_subtype) || media_type != SPA_MEDIA_TYPE_video || media_subtype != subtypesi) continue; @@ -2024,13 +2029,14 @@ } port->peer_formats = calloc(count, sizeof(struct spa_pod *)); for (i = 0; i < SPA_N_ELEMENTS(subtypes); i++) { - SPA_POD_STRUCT_FOREACH(port->peer_format_pod, format) { + state = NULL; + while (spa_peer_param_parse(port->peer_format_pod, &info, sizeof(info), &state) > 0) { uint32_t media_type, media_subtype; - if (!spa_format_parse(format, &media_type, &media_subtype) || + if (!spa_format_parse(info.param, &media_type, &media_subtype) || media_type != SPA_MEDIA_TYPE_video || media_subtype != subtypesi) continue; - port->peer_formatsport->n_peer_formats++ = format; + port->peer_formatsport->n_peer_formats++ = info.param; } } } @@ -2038,7 +2044,7 @@ oport->paramsIDX_EnumFormat.user++; port->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; port->paramsIDX_EnumFormat.user++; - port->paramsIDX_PeerFormats.user++; + port->paramsIDX_PeerEnumFormat.user++; return res; } @@ -2068,8 +2074,9 @@ case SPA_PARAM_Format: res = port_set_format(this, direction, port_id, flags, param); break; - case SPA_PARAM_PeerFormats: - res = port_set_peer_formats(this, direction, port_id, flags, param); + case SPA_PARAM_PeerEnumFormat: + res = port_set_peer_enum_format(this, direction, port_id, flags, param); + break; break; default: return -ENOENT;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/daemon/systemd/user/pipewire-pulse.service.in -> _service:download_files:pipewire-1.5.84.tar.bz2/src/daemon/systemd/user/pipewire-pulse.service.in
Changed
@@ -17,6 +17,7 @@ ConditionUser=!root Wants=pipewire.service pipewire-session-manager.service After=pipewire.service pipewire-session-manager.service +BindsTo=pipewire.service Conflicts=pulseaudio.service Service
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/examples/video-play.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/examples/video-play.c
Changed
@@ -15,6 +15,8 @@ #include <spa/utils/result.h> #include <spa/param/video/format-utils.h> #include <spa/param/tag-utils.h> +#include <spa/param/dict-utils.h> +#include <spa/param/peer-utils.h> #include <spa/param/props.h> #include <spa/param/latency-utils.h> #include <spa/debug/format.h> @@ -270,6 +272,34 @@ } } +static void parse_peer_capability(struct data *data, const struct spa_pod *param) +{ + struct spa_peer_param_info info; + void *state = NULL; + + fprintf(stderr, "peer capability\n"); + while (spa_peer_param_parse(param, &info, sizeof(info), &state) == 1) { + struct spa_param_dict_info di; + + if (spa_param_dict_parse(info.param, &di, sizeof(di)) > 0) { + struct spa_dict dict; + struct spa_dict_item *items; + const struct spa_dict_item *it; + + if (spa_param_dict_info_parse(&di, sizeof(di), &dict, NULL) < 0) + return; + + items = alloca(sizeof(struct spa_dict_item) * dict.n_items); + if (spa_param_dict_info_parse(&di, sizeof(di), &dict, items) < 0) + return; + + spa_dict_for_each(it, &dict) + fprintf(stderr, "peer:%u %s: %s\n", info.peer_id, it->key, it->value); + + } + } +} + /* Be notified when the stream param changes. We're only looking at the * format changes. * @@ -294,8 +324,11 @@ void *d; int32_t mult, size, blocks; - if (param != NULL && id == SPA_PARAM_Tag) { - spa_debug_pod(0, NULL, param); + if (param != NULL && (id == SPA_PARAM_Tag || id == SPA_PARAM_PeerCapability)) { + if (id == SPA_PARAM_PeerCapability) + parse_peer_capability(data, param); + else + spa_debug_pod(0, NULL, param); return; } if (param != NULL && id == SPA_PARAM_Latency) {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/examples/video-src.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/examples/video-src.c
Changed
@@ -15,6 +15,7 @@ #include <spa/param/video/format-utils.h> #include <spa/param/tag-utils.h> +#include <spa/param/dict-utils.h> #include <spa/debug/pod.h> #include <spa/debug/format.h> @@ -219,7 +220,7 @@ const struct spa_pod *params5; uint32_t n_params = 0; - if (param != NULL && id == SPA_PARAM_Tag) { + if (param != NULL && (id == SPA_PARAM_Tag || id == SPA_PARAM_PeerCapability)) { spa_debug_pod(0, NULL, param); return; } @@ -290,7 +291,8 @@ int main(int argc, char *argv) { struct data data = { 0, }; - const struct spa_pod *params2; + const struct spa_pod *params3; + uint32_t n_params = 0; uint8_t buffer1024; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); @@ -318,7 +320,7 @@ PW_KEY_NODE_SUPPORTS_REQUEST, "1", NULL)); - params0 = spa_pod_builder_add_object(&b, + paramsn_params++ = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_video), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), @@ -336,7 +338,13 @@ spa_tag_build_add_dict(&b, &SPA_DICT_ITEMS( SPA_DICT_ITEM("my-tag-key", "my-special-tag-value"))); - params1 = spa_tag_build_end(&b, &f); + paramsn_params++ = spa_tag_build_end(&b, &f); + } + { + paramsn_params++ = spa_param_dict_build_dict(&b, SPA_PARAM_Capability, + &SPA_DICT_ITEMS( + SPA_DICT_ITEM("my-capability-key", "my-capability-value"))); + } pw_stream_add_listener(data.stream, @@ -349,7 +357,7 @@ PW_ID_ANY, PW_STREAM_FLAG_DRIVER | PW_STREAM_FLAG_MAP_BUFFERS, - params, 2); + params, n_params); pw_main_loop_run(data.loop);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/meson.build -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/meson.build
Changed
@@ -736,6 +736,7 @@ 'module-avb/acmp.c', 'module-avb/aecp.c', 'module-avb/aecp-aem.c', + 'module-avb/es-builder.c', 'module-avb/avdecc.c', 'module-avb/maap.c', 'module-avb/mmrp.c',
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/aecp-aem-descriptors.h -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/aecp-aem-descriptors.h
Changed
@@ -1,5 +1,6 @@ /* AVB support */ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki (alexandre.malki@kebag-logic.com) */ /* SPDX-License-Identifier: MIT */ #ifndef AVB_AECP_AEM_DESCRIPTORS_H @@ -45,6 +46,8 @@ #define AVB_AEM_DESC_SIGNAL_TRANSCODER 0x0023 #define AVB_AEM_DESC_CLOCK_DOMAIN 0x0024 #define AVB_AEM_DESC_CONTROL_BLOCK 0x0025 +/** IEEE 1722.1-2021 Table-7 has up to descriptor 0x0029, reserved for future */ +#define AVB_AEM_DESC_LAST_RESERVED_17221 0x0029 #define AVB_AEM_DESC_INVALID 0xffff struct avb_aem_desc_entity {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/descriptors.h -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/descriptors.h
Changed
@@ -1,15 +1,33 @@ /* PipeWire */ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki (alexandre.malki@kebag-logic.com) */ /* SPDX-License-Identifier: MIT */ #include "adp.h" #include "aecp-aem.h" #include "aecp-aem-descriptors.h" +#include "es-builder.h" #include "internal.h" +/** + * \todo This whole code needs to be re-factore, + * configuring the entity using such a "HARDCODED" + * header would does not allow an easy way to + * adjust parameters. + * + * Especially for the people involved in the project + * and do not have the programming skills to modify + * this file. + * + * \proposition use a YANG model directly derived from this + * or use the YAML for simplicity. + * + * Having the YANG would allow directly to know the + * capabilites/limits of the protocol + */ static inline void init_descriptors(struct server *server) { - server_add_descriptor(server, AVB_AEM_DESC_STRINGS, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_STRINGS, 0, sizeof(struct avb_aem_desc_strings), &(struct avb_aem_desc_strings) { @@ -17,7 +35,7 @@ .string_1 = "Configuration 1", .string_2 = "Wim Taymans", }); - server_add_descriptor(server, AVB_AEM_DESC_LOCALE, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_LOCALE, 0, sizeof(struct avb_aem_desc_locale), &(struct avb_aem_desc_locale) { @@ -25,7 +43,7 @@ .number_of_strings = htons(1), .base_strings = htons(0) }); - server_add_descriptor(server, AVB_AEM_DESC_ENTITY, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_ENTITY, 0, sizeof(struct avb_aem_desc_entity), &(struct avb_aem_desc_entity) { @@ -81,7 +99,7 @@ { htons(AVB_AEM_DESC_CLOCK_DOMAIN), htons(1) } } }; - server_add_descriptor(server, AVB_AEM_DESC_CONFIGURATION, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_CONFIGURATION, 0, sizeof(config), &config); struct { @@ -139,7 +157,7 @@ { .pull_frequency = htonl(192000) }, } }; - server_add_descriptor(server, AVB_AEM_DESC_AUDIO_UNIT, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_AUDIO_UNIT, 0, sizeof(audio_unit), &audio_unit); struct { @@ -178,7 +196,7 @@ htobe64(0x00a0060860000800ULL), }, }; - server_add_descriptor(server, AVB_AEM_DESC_STREAM_INPUT, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_STREAM_INPUT, 0, sizeof(stream_input_0), &stream_input_0); struct { @@ -216,7 +234,7 @@ htobe64(0x00a0060860000800ULL), }, }; - server_add_descriptor(server, AVB_AEM_DESC_STREAM_OUTPUT, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_STREAM_OUTPUT, 0, sizeof(stream_output_0), &stream_output_0); struct avb_aem_desc_avb_interface avb_interface = { @@ -237,7 +255,7 @@ }; strncpy(avb_interface.object_name, server->ifname, 63); memcpy(avb_interface.mac_address, server->mac_addr, 6); - server_add_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_AVB_INTERFACE, 0, sizeof(avb_interface), &avb_interface); struct avb_aem_desc_clock_source clock_source = { @@ -250,6 +268,6 @@ .clock_source_location_type = htons(AVB_AEM_DESC_STREAM_INPUT), .clock_source_location_index = htons(0), }; - server_add_descriptor(server, AVB_AEM_DESC_CLOCK_SOURCE, 0, + es_builder_add_descriptor(server, AVB_AEM_DESC_CLOCK_SOURCE, 0, sizeof(clock_source), &clock_source); }
View file
_service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/es-builder.c
Added
@@ -0,0 +1,81 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */ +/* SPDX-License-Identifier: MIT */ + + +#include "es-builder.h" +#include "aecp-aem-descriptors.h" + +/** + * \brief The goal of this modules is to create a an entity and + * attache the necessary status or resources to it so they + * do no have to be seperated and referenced somewhere else. + * + * In a sense, it encapsulates the descriptor, and the states + * information that will be altered either by a aecp/acmp commands + * or internal state changes reflected into the counters. + */ + +/** The callback type used for the different entity descriptor */ +typedef void* (*es_builder_cb_t) (struct server *server, uint16_t type, + uint16_t index, size_t size, void *ptr); + +/** Structure holding all necessary cb + * \todo for the future of compatibility between milan's version + * and plain AVB, add the right callback, that would reduce + * code complexity and increase reusability. + * As well as having multiple entity model defined using different + * entity on the same machine + */ +struct es_builder_st { + es_builder_cb_t build_descriptor_cb; +}; + +/** All callback that needs a status information */ +static const struct es_builder_st es_builderAVB_AEM_DESC_LAST_RESERVED_17221 = +{ +}; + +/** + * \brief, should be called when creating an a descriptor, it will attach + * the right state variable that are necessary for counters, stream info + * and so on... + */ +void es_builder_add_descriptor(struct server *server, uint16_t type, + uint16_t index, size_t size, void *ptr_aem) +{ + void *desc_ptr; + struct descriptor *d; + + if (!server) { + pw_log_error("Invalid server, it is empty %p\n", server); + spa_assert(0); + } + + if (type >= AVB_AEM_DESC_LAST_RESERVED_17221) { + pw_log_error("Invalid Type %u\n", type); + spa_assert(0); + } + + /* Look if the descriptor has a callback to attach more status data */ + if (!es_buildertype.build_descriptor_cb) { + if (!server_add_descriptor(server, type, index, size, ptr_aem)) { + pw_log_error("Could not allocate descriptor %u at " + "index %u the avb aem type\n", type, index); + + spa_assert(0); + } + } else { + desc_ptr = es_buildertype.build_descriptor_cb(server, type, + index, size, ptr_aem); + if (!desc_ptr) { + pw_log_error("Could not allocate specific descriptr " + "%u at index %u the avb aem type\n", + type, index); + + spa_assert(0); + } + d = (struct descriptor *) desc_ptr; + d->size = size; + } +}
View file
_service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/es-builder.h
Added
@@ -0,0 +1,19 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */ +/* SPDX-License-Identifier: MIT */ + + +#ifndef __ES_BUILDER_H__ +#define __ES_BUILDER_H__ + +#include "internal.h" + +/** + * This is a mandatory feature to add the necessary state information + * to create the right entity model + **/ +void es_builder_add_descriptor(struct server *server, uint16_t type, + uint16_t index, size_t size, void *ptr_aem); + + +#endif // __ES_BUILDER_H__
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/mrp.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/mrp.c
Changed
@@ -1,5 +1,7 @@ /* AVB support */ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ +/* SPDX-FileCopyrightText: Copyright © 2025 Kebag-Logic */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */ /* SPDX-License-Identifier: MIT */ #include <pipewire/pipewire.h> @@ -32,6 +34,16 @@ struct spa_hook_list listener_list; }; +enum fsm_lva { + FSM_LVA_ACTIVE, + FSM_LVA_PASSIVE +}; + +struct fsm_leave_all_timer { + enum fsm_lva state; + uint64_t leave_all_timeout; +}; + struct mrp { struct server *server; struct spa_hook server_listener; @@ -41,7 +53,7 @@ struct spa_list attributes; uint64_t periodic_timeout; - uint64_t leave_all_timeout; + struct fsm_leave_all_timer lva_timer; uint64_t join_timeout; }; @@ -60,6 +72,17 @@ mrp_emit_event(mrp, now, event); } +static void mrp_set_update_lva(struct mrp *mrp, uint64_t now, bool force_send) +{ + if (!force_send) { + mrp->lva_timer.leave_all_timeout = now + + (MRP_LVATIMER_MS + (pw_rand32() % (MRP_LVATIMER_MS / 2))) + * SPA_NSEC_PER_MSEC; + } else { + mrp->lva_timer.leave_all_timeout = now; + } +} + static void mrp_periodic(void *data, uint64_t now) { struct mrp *mrp = data; @@ -71,13 +94,15 @@ global_event(mrp, now, AVB_MRP_EVENT_PERIODIC); mrp->periodic_timeout = now + MRP_PERIODTIMER_MS * SPA_NSEC_PER_MSEC; } - if (now > mrp->leave_all_timeout) { - if (mrp->leave_all_timeout > 0) { + + + if (now > mrp->lva_timer.leave_all_timeout) { + /* 802.1Q-2014 Table 10-5 */ + mrp->lva_timer.state = FSM_LVA_ACTIVE; + if (mrp->lva_timer.leave_all_timeout > 0) { global_event(mrp, now, AVB_MRP_EVENT_RX_LVA); leave_all = true; } - mrp->leave_all_timeout = now + (MRP_LVATIMER_MS + (random() % (MRP_LVATIMER_MS / 2))) - * SPA_NSEC_PER_MSEC; } if (now > mrp->join_timeout) { @@ -89,7 +114,9 @@ } spa_list_for_each(a, &mrp->attributes, link) { - if (a->leave_timeout > 0 && now > a->leave_timeout) { + // 802.1Q Clause 10.7.4.2 + if (a->leave_timeout > 0 && now > a->leave_timeout && a->registrar_state == + AVB_MRP_LV) { a->leave_timeout = 0; avb_mrp_attribute_update_state(&a->attr, now, AVB_MRP_EVENT_LV_TIMER); } @@ -134,7 +161,7 @@ return -EPROTO; if (v->lva) - info->attr_event(data, now, attr_type, AVB_MRP_EVENT_RX_LVA); + info->attr_event(data, now, attr_type, AVB_MRP_ATTRIBUTE_EVENT_LVA); for (i = 0; i < num_values; i++) { if (i % 3 == 0) { @@ -160,6 +187,98 @@ return 0; } +const char *avb_applicant_state_name(uint8_t state) +{ + switch (state) { + case AVB_MRP_VO: + return "VO"; + case AVB_MRP_VP: + return "VP"; + case AVB_MRP_VN: + return "VN"; + case AVB_MRP_AN: + return "AN"; + case AVB_MRP_AA: + return "AA"; + case AVB_MRP_QA: + return "QA"; + case AVB_MRP_LA: + return "LA"; + case AVB_MRP_AO: + return "AO"; + case AVB_MRP_QO: + return "QO"; + case AVB_MRP_AP: + return "AP"; + case AVB_MRP_QP: + return "QP"; + case AVB_MRP_LO: + return "LO"; + } + + return "unknown-applicant-state"; +} + +const char *avb_registrar_state_name(uint8_t state) +{ + switch (state) { + case AVB_MRP_IN: + return "IN"; + case AVB_MRP_LV: + return "LV"; + case AVB_MRP_MT: + return "MT"; + } + + return "unknown-registrar-state"; +} + +const char *avb_mrp_event_name(uint8_t event) +{ + switch (event) { + case AVB_MRP_EVENT_BEGIN: + return "begin"; + case AVB_MRP_EVENT_NEW: + return "new"; + case AVB_MRP_EVENT_JOIN: + return "join"; + case AVB_MRP_EVENT_LV: + return "lv"; + case AVB_MRP_EVENT_TX: + return "tx"; + case AVB_MRP_EVENT_TX_LVA: + return "tx_lva"; + case AVB_MRP_EVENT_TX_LVAF: + return "tx_lvaf"; + case AVB_MRP_EVENT_RX_NEW: + return "rx_new"; + case AVB_MRP_EVENT_RX_JOININ: + return "rx_joinin"; + case AVB_MRP_EVENT_RX_IN: + return "rx_in"; + case AVB_MRP_EVENT_RX_JOINMT: + return "rx_joinmt"; + case AVB_MRP_EVENT_RX_MT: + return "rx_mt"; + case AVB_MRP_EVENT_RX_LV: + return "rx_lv"; + case AVB_MRP_EVENT_RX_LVA: + return "rx_lva"; + case AVB_MRP_EVENT_FLUSH: + return "flush"; + case AVB_MRP_EVENT_REDECLARE: + return "redeclare"; + case AVB_MRP_EVENT_PERIODIC: + return "periodic"; + case AVB_MRP_EVENT_LV_TIMER: + return "lv_timer"; + case AVB_MRP_EVENT_LVA_TIMER: + return "lva_timer"; + } + + return "unknown-event"; +} + const char *avb_mrp_notify_name(uint8_t notify) { switch(notify) { @@ -232,6 +351,22 @@ uint8_t notify = 0, state; uint8_t send = 0; + // Handle the LVA timer FSM + switch (event) { + case AVB_MRP_EVENT_RX_LVA: + mrp_set_update_lva(mrp, now, false); + mrp->lva_timer.state = FSM_LVA_PASSIVE;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/mrp.h -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/mrp.h
Changed
@@ -86,23 +86,29 @@ #define AVB_MRP_ATTRIBUTE_EVENT_JOINMT 3 #define AVB_MRP_ATTRIBUTE_EVENT_MT 4 #define AVB_MRP_ATTRIBUTE_EVENT_LV 5 +#define AVB_MRP_ATTRIBUTE_EVENT_LVA 6 -#define AVB_MRP_SEND_NEW 1 -#define AVB_MRP_SEND_JOININ 2 -#define AVB_MRP_SEND_IN 3 -#define AVB_MRP_SEND_JOINMT 4 -#define AVB_MRP_SEND_MT 5 -#define AVB_MRP_SEND_LV 6 +#define AVB_MRP_SEND_NEW 0 +#define AVB_MRP_SEND_JOININ 1 +#define AVB_MRP_SEND_IN 2 +#define AVB_MRP_SEND_JOINMT 3 +#define AVB_MRP_SEND_MT 4 +#define AVB_MRP_SEND_LV 5 +#define AVB_MRP_SEND_LVA 6 #define AVB_MRP_NOTIFY_NEW 1 #define AVB_MRP_NOTIFY_JOIN 2 #define AVB_MRP_NOTIFY_LEAVE 3 +const char *avb_applicant_state_name(uint8_t state); +const char *avb_registrar_state_name(uint8_t state); +const char *avb_mrp_event_name(uint8_t event); const char *avb_mrp_notify_name(uint8_t notify); const char *avb_mrp_send_name(uint8_t send); struct avb_mrp_attribute { uint8_t pending_send; + const char *name; void *user_data; };
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/msrp.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/msrp.c
Changed
@@ -1,5 +1,7 @@ /* AVB support */ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ +/* SPDX-FileCopyrightText: Copyright © 2025 Kebag-Logic */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */ /* SPDX-License-Identifier: MIT */ #include <unistd.h> @@ -351,6 +353,7 @@ a->msrp = msrp; a->attr.mrp = attr; a->attr.type = type; + attr->name = "MSRP"; spa_list_append(&msrp->attributes, &a->link); avb_mrp_attribute_add_listener(attr, &a->listener, &mrp_attr_events, a);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/mvrp.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-avb/mvrp.c
Changed
@@ -1,5 +1,7 @@ /* AVB support */ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ +/* SPDX-FileCopyrightText: Copyright © 2025 Kebag-Logic */ +/* SPDX-FileCopyrightText: Copyright © 2025 Alexandre Malki <alexandre.malki@kebag-logic.com> */ /* SPDX-License-Identifier: MIT */ #include <unistd.h> @@ -189,6 +191,7 @@ a = attr->user_data; a->attr.mrp = attr; a->attr.type = type; + attr->name = "MVRP"; spa_list_append(&mvrp->attributes, &a->link); avb_mrp_attribute_add_listener(attr, &a->listener, &mrp_attr_events, a);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-filter-chain.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-filter-chain.c
Changed
@@ -401,11 +401,13 @@ * - `filename` The IR to load or create. Possible values are: * - `/hilbert` creates a hilbert function(https://en.wikipedia.org/wiki/Hilbert_transform) * that can be used to phase shift the signal by +/-90 degrees. The - * `length` will be used as the number of coefficients. + * `length` will be used as the number of coefficients. The default latency + * if the length/2. * - `/dirac` creates a Dirac function(https://en.wikipedia.org/wiki/Dirac_delta_function) that - * can be used as gain. + * can be used as gain. The default latency is 0. * - A filename to load as the IR. This needs to be a file format supported - * by sndfile. + * by sndfile or be an inline IR with "/ir:<rate>,<value1>,<value2>". The default + * latency of file IRs is 0. * - filename, ... an array of filenames. The file with the closest samplerate match * with the graph samplerate will be used. * - `offset` The sample offset in the file as the start of the IR. @@ -414,7 +416,7 @@ * - `resample_quality` The resample quality in case the IR does not match the graph * samplerate. * - `latency` The extra latency in seconds to report. When left unspecified (or < 0.0) - * the convolver latency will be the length of the IR. + * the default IR latency will be used, the the filename argument. * * ### Delay *
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -2051,6 +2051,7 @@ flags |= PW_STREAM_FLAG_DONT_RECONNECT; if (direct_on_input_idx != SPA_ID_INVALID) { + dont_inhibit_auto_suspend = false; source_index = direct_on_input_idx; } else if (source_name != NULL) { if ((id = atoi(source_name)) != 0) @@ -4674,6 +4675,10 @@ pw_log_info("%s %s tag:%u name:%s", client->name, commandscommand.name, tag, name); + /* @NONE@ is used to clear the setting */ + if (spa_streq(name, "@NONE@")) + name = NULL; + if (name != NULL && (o = find_device(client, SPA_ID_INVALID, name, sink, NULL)) == NULL) return -ENOENT;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-sap.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-rtp-sap.c
Changed
@@ -981,7 +981,7 @@ } pw_net_get_ip(&impl->igmp_recovery.mcast_addr, addr, sizeof(addr), NULL, NULL); - pw_log_info("IGMP recovery triggered for %s", addr); + pw_log_debug("IGMP recovery triggered for %s", addr); /* Force IGMP membership refresh by leaving the group first, then rejoin */ if (impl->igmp_recovery.is_ipv6) { @@ -994,10 +994,10 @@ res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mr6, sizeof(mr6)); if (SPA_LIKELY(res == 0)) { - pw_log_info("left IPv6 multicast group"); + pw_log_debug("left IPv6 multicast group"); } else { if (errno == EADDRNOTAVAIL) { - pw_log_info("attempted to leave IPv6 multicast group, but " + pw_log_debug("attempted to leave IPv6 multicast group, but " "membership was already silently dropped"); } else { pw_log_warn("failed to leave IPv6 multicast group: %m"); @@ -1009,7 +1009,7 @@ if (res < 0) { pw_log_warn("failed to re-join IPv6 multicast group: %m"); } else { - pw_log_info("re-joined IPv6 multicast group successfully"); + pw_log_debug("re-joined IPv6 multicast group successfully"); } } else { struct ip_mreqn mr4; @@ -1021,10 +1021,10 @@ res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr4, sizeof(mr4)); if (SPA_LIKELY(res == 0)) { - pw_log_info("left IPv4 multicast group"); + pw_log_debug("left IPv4 multicast group"); } else { if (errno == EADDRNOTAVAIL) { - pw_log_info("attempted to leave IPv4 multicast group, but " + pw_log_debug("attempted to leave IPv4 multicast group, but " "membership was already silently dropped"); } else { pw_log_warn("failed to leave IPv4 multicast group: %m"); @@ -1036,7 +1036,7 @@ if (res < 0) { pw_log_warn("failed to re-join IPv4 multicast group: %m"); } else { - pw_log_info("re-joined IPv4 multicast group successfully"); + pw_log_debug("re-joined IPv4 multicast group successfully"); } }
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-source.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/modules/module-rtp-source.c
Changed
@@ -259,6 +259,19 @@ bool waiting; }; +static inline uint64_t get_time_ns(struct impl *impl) +{ + uint64_t res; + if (impl->stream) { + res = rtp_stream_get_nsec(impl->stream); + } else { + struct timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + res = SPA_TIMESPEC_TO_NSEC(&ts); + } + return res; +} + static int do_start(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { @@ -288,9 +301,10 @@ int suppressed; uint64_t current_time; - current_time = rtp_stream_get_nsec(impl->stream); + current_time = get_time_ns(impl); if (mask & SPA_IO_IN) { + if ((len = recv(fd, impl->buffer, impl->buffer_size, 0)) < 0) goto receive_error; @@ -349,10 +363,10 @@ res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mr6, sizeof(mr6)); if (SPA_LIKELY(res == 0)) { - pw_log_info("left IPv6 multicast group"); + pw_log_debug("left IPv6 multicast group"); } else { if (errno == EADDRNOTAVAIL) { - pw_log_info("attempted to leave IPv6 multicast group, but " + pw_log_debug("attempted to leave IPv6 multicast group, but " "membership was already silently dropped"); } else { pw_log_warn("failed to leave IPv6 multicast group: %m"); @@ -364,7 +378,7 @@ if (res < 0) { pw_log_warn("failed to re-join IPv6 multicast group: %m"); } else { - pw_log_info("re-joined IPv6 multicast group successfully"); + pw_log_debug("re-joined IPv6 multicast group successfully"); } } else { struct ip_mreqn mr4; @@ -376,10 +390,10 @@ res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mr4, sizeof(mr4)); if (SPA_LIKELY(res == 0)) { - pw_log_info("left IPv4 multicast group"); + pw_log_debug("left IPv4 multicast group"); } else { if (errno == EADDRNOTAVAIL) { - pw_log_info("attempted to leave IPv4 multicast group, but " + pw_log_debug("attempted to leave IPv4 multicast group, but " "membership was already silently dropped"); } else { pw_log_warn("failed to leave IPv4 multicast group: %m"); @@ -391,11 +405,11 @@ if (res < 0) { pw_log_warn("failed to re-join IPv4 multicast group: %m"); } else { - pw_log_info("re-joined IPv4 multicast group successfully"); + pw_log_debug("re-joined IPv4 multicast group successfully"); } } - current_time = rtp_stream_get_nsec(impl->stream); + current_time = get_time_ns(impl); SPA_ATOMIC_STORE(impl->last_packet_time, current_time); return res; @@ -420,7 +434,7 @@ * silently kicked out of the IGMP group (which causes data * to no longer arrive, thus leading to these states). */ - current_time = rtp_stream_get_nsec(impl->stream); + current_time = get_time_ns(impl); last_packet_time = SPA_ATOMIC_LOAD(impl->last_packet_time); elapsed_seconds = (current_time - last_packet_time) / SPA_NSEC_PER_SEC; @@ -433,7 +447,7 @@ } pw_net_get_ip(&impl->igmp_recovery.mcast_addr, addr, sizeof(addr), NULL, NULL); - pw_log_info("starting IGMP recovery for %s", addr); + pw_log_debug("starting IGMP recovery for %s", addr); /* Run the actual recovery in the data loop, since recovery involves * rejoining the socket to the IGMP group. By running this in the @@ -446,7 +460,7 @@ res = pw_loop_locked(impl->data_loop, rejoin_igmp_group, 1, NULL, 0, impl); if (SPA_LIKELY(res == 0)) { - pw_log_info("IGMP recovery for %s finished", addr); + pw_log_debug("IGMP recovery for %s finished", addr); } else { pw_log_error("error while finishing IGMP recovery for %s: %s", addr, spa_strerror(res));
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/impl-link.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/pipewire/impl-link.c
Changed
@@ -924,6 +924,7 @@ spa_list_remove(&this->input_link); pw_impl_port_emit_link_removed(port, this); + pw_impl_port_recalc_capability(port); pw_impl_port_recalc_latency(port); pw_impl_port_recalc_tag(port); @@ -956,6 +957,7 @@ spa_list_remove(&this->output_link); pw_impl_port_emit_link_removed(port, this); + pw_impl_port_recalc_capability(port); pw_impl_port_recalc_latency(port); pw_impl_port_recalc_tag(port); @@ -1138,6 +1140,14 @@ pw_impl_port_recalc_tag(this->output); } +static void input_port_capability_changed(void *data) +{ + struct impl *impl = data; + struct pw_impl_link *this = &impl->this; + if (!this->feedback) + pw_impl_port_recalc_capability(this->output); +} + static void output_port_latency_changed(void *data) { struct impl *impl = data; @@ -1154,12 +1164,21 @@ pw_impl_port_recalc_tag(this->input); } +static void output_port_capability_changed(void *data) +{ + struct impl *impl = data; + struct pw_impl_link *this = &impl->this; + if (!this->feedback) + pw_impl_port_recalc_capability(this->input); +} + static const struct pw_impl_port_events input_port_events = { PW_VERSION_IMPL_PORT_EVENTS, .param_changed = input_port_param_changed, .state_changed = input_port_state_changed, .latency_changed = input_port_latency_changed, .tag_changed = input_port_tag_changed, + .capability_changed = input_port_capability_changed, }; static const struct pw_impl_port_events output_port_events = { @@ -1168,6 +1187,7 @@ .state_changed = output_port_state_changed, .latency_changed = output_port_latency_changed, .tag_changed = output_port_tag_changed, + .capability_changed = output_port_capability_changed, }; static void node_result(struct impl *impl, void *obj, @@ -1576,6 +1596,8 @@ try_link_controls(impl, output, input); + pw_impl_port_recalc_capability(output); + pw_impl_port_recalc_capability(input); pw_impl_port_recalc_latency(output); pw_impl_port_recalc_latency(input); pw_impl_port_recalc_tag(output);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/impl-port.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/pipewire/impl-port.c
Changed
@@ -10,6 +10,8 @@ #include <spa/pod/parser.h> #include <spa/param/audio/format-utils.h> #include <spa/param/tag-utils.h> +#include <spa/param/dict-utils.h> +#include <spa/param/peer-utils.h> #include <spa/node/utils.h> #include <spa/utils/names.h> #include <spa/utils/string.h> @@ -762,6 +764,35 @@ return 0; } +static int process_capability_param(void *data, int seq, + uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param) +{ + struct pw_impl_port *this = data; + struct spa_param_dict_info info; + struct spa_pod *old; + + if (id != SPA_PARAM_Capability || param == NULL) + return -EINVAL; + if (spa_param_dict_parse(param, &info, sizeof(info)) < 0) + return 0; + + old = this->capthis->direction; + if (spa_param_dict_compare(old, param) == 0) + return 0; + + pw_log_debug("port %p: got %s capabilty %p", this, + pw_direction_as_string(this->direction), param); + if (param) + pw_log_pod(SPA_LOG_LEVEL_DEBUG, param); + + free(old); + this->capthis->direction = spa_pod_copy(param); + + pw_impl_port_emit_capability_changed(this); + + return 0; +} + static int process_latency_param(void *data, int seq, uint32_t id, uint32_t index, uint32_t next, struct spa_pod *param) { @@ -831,6 +862,7 @@ PW_IMPL_PORT_FLAG_BUFFERS); pw_impl_port_for_each_param(port, 0, SPA_PARAM_IO, 0, 0, NULL, check_param_io, port); + pw_impl_port_for_each_param(port, 0, SPA_PARAM_Capability, 0, 0, NULL, process_capability_param, port); pw_impl_port_for_each_param(port, 0, SPA_PARAM_Latency, 0, 0, NULL, process_latency_param, port); pw_impl_port_for_each_param(port, 0, SPA_PARAM_Tag, 0, 0, NULL, process_tag_param, port); } @@ -877,6 +909,15 @@ changed_idsn_changed_ids++ = id; switch (id) { + case SPA_PARAM_PeerCapability: + port->have_peer_capability_param = + SPA_FLAG_IS_SET(info->paramsi.flags, SPA_PARAM_INFO_WRITE); + break; + case SPA_PARAM_Capability: + if (port->node != NULL) + pw_impl_port_for_each_param(port, 0, id, 0, UINT32_MAX, + NULL, process_capability_param, port); + break; case SPA_PARAM_Latency: port->have_latency_param = SPA_FLAG_IS_SET(info->paramsi.flags, SPA_PARAM_INFO_WRITE); @@ -1918,6 +1959,66 @@ return pw_impl_port_set_param(port, SPA_PARAM_Tag, 0, port->tagdirection); } +int pw_impl_port_recalc_capability(struct pw_impl_port *port) +{ + struct pw_impl_link *l; + struct pw_impl_port *other; + struct spa_pod *param, *old; + struct spa_pod_dynamic_builder b = { 0 }; + struct spa_pod_frame f; + enum spa_direction direction; + uint8_t buffer1024; + int count = 0; + bool changed; + + if (port->destroying) + return 0; + + direction = SPA_DIRECTION_REVERSE(port->direction); + + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_peer_param_build_start(&b.b, &f, SPA_PARAM_PeerCapability); + + if (port->direction == PW_DIRECTION_OUTPUT) { + spa_list_for_each(l, &port->links, output_link) { + other = l->input; + spa_peer_param_build_add_param(&b.b, other->info.id, other->capother->direction); + count++; + } + } else { + spa_list_for_each(l, &port->links, input_link) { + other = l->output; + spa_peer_param_build_add_param(&b.b, other->info.id, other->capother->direction); + count++; + } + } + param = count == 0 ? NULL : spa_peer_param_build_end(&b.b, &f); + + old = port->capdirection; + + changed = spa_pod_memcmp(old, param); + + pw_log_info("port %d: %p %s %s cap %p %d", + port->info.id, port, changed ? "set" : "keep", + pw_direction_as_string(direction), param, port->have_peer_capability_param); + + if (changed) { + free(old); + port->capdirection = param ? spa_pod_copy(param) : NULL; + if (param) + pw_log_pod(SPA_LOG_LEVEL_INFO, param); + } + spa_pod_dynamic_builder_clean(&b); + + if (!changed) + return 0; + + if (!port->have_peer_capability_param) + return 0; + + return pw_impl_port_set_param(port, SPA_PARAM_PeerCapability, 0, port->capdirection); +} + SPA_EXPORT int pw_impl_port_is_linked(struct pw_impl_port *port) {
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/impl-port.h -> _service:download_files:pipewire-1.5.84.tar.bz2/src/pipewire/impl-port.h
Changed
@@ -36,7 +36,7 @@ /** Port events, use \ref pw_impl_port_add_listener */ struct pw_impl_port_events { -#define PW_VERSION_IMPL_PORT_EVENTS 3 +#define PW_VERSION_IMPL_PORT_EVENTS 4 uint32_t version; /** The port is destroyed */ @@ -74,6 +74,8 @@ void (*latency_changed) (void *data); /** tag changed. Since version 3 */ void (*tag_changed) (void *data); + /** capability changed. Since version 4 */ + void (*capability_changed) (void *data); }; /** Create a new port
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/private.h -> _service:download_files:pipewire-1.5.84.tar.bz2/src/pipewire/private.h
Changed
@@ -902,6 +902,7 @@ #define pw_impl_port_emit_param_changed(p,i) pw_impl_port_emit(p, param_changed, 1, i) #define pw_impl_port_emit_latency_changed(p) pw_impl_port_emit(p, latency_changed, 2) #define pw_impl_port_emit_tag_changed(p) pw_impl_port_emit(p, tag_changed, 3) +#define pw_impl_port_emit_capability_changed(p) pw_impl_port_emit(p, capability_changed, 4) #define PW_IMPL_PORT_IS_CONTROL(port) SPA_FLAG_MASK((port)->flags, \ PW_IMPL_PORT_FLAG_BUFFERS|PW_IMPL_PORT_FLAG_CONTROL,\ @@ -977,6 +978,9 @@ unsigned int have_tag_param:1; struct spa_pod *tag2; /**< tags */ + unsigned int have_peer_capability_param:1; + struct spa_pod *cap2; /**< capabilities */ + void *owner_data; /**< extra owner data */ void *user_data; /**< extra user data */ }; @@ -1332,6 +1336,7 @@ int pw_impl_port_use_buffers(struct pw_impl_port *port, struct pw_impl_port_mix *mix, uint32_t flags, struct spa_buffer **buffers, uint32_t n_buffers); +int pw_impl_port_recalc_capability(struct pw_impl_port *port); int pw_impl_port_recalc_latency(struct pw_impl_port *port); int pw_impl_port_recalc_tag(struct pw_impl_port *port);
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/stream.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/pipewire/stream.c
Changed
@@ -11,6 +11,7 @@ #include <spa/buffer/alloc.h> #include <spa/param/props.h> #include <spa/param/format-utils.h> +#include <spa/param/peer-utils.h> #include <spa/node/io.h> #include <spa/node/utils.h> #include <spa/utils/cleanup.h> @@ -103,14 +104,16 @@ uint64_t port_change_mask_all; struct spa_port_info port_info; struct pw_properties *port_props; -#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 PORT_Tag 6 -#define N_PORT_PARAMS 7 +#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 PORT_Tag 6 +#define PORT_Capability 7 +#define PORT_PeerCapability 8 +#define N_PORT_PARAMS 9 struct spa_param_info port_paramsN_PORT_PARAMS; struct spa_list param_list; @@ -144,6 +147,7 @@ struct spa_callbacks rt_callbacks; + unsigned int have_peer_capability:1; unsigned int disconnecting:1; unsigned int disconnect_core:1; unsigned int draining:1; @@ -196,6 +200,10 @@ return PORT_Latency; case SPA_PARAM_Tag: return PORT_Tag; + case SPA_PARAM_Capability: + return PORT_Capability; + case SPA_PARAM_PeerCapability: + return PORT_PeerCapability; default: return -1; } @@ -909,6 +917,21 @@ return 0; } +static void emit_dummy_peer_capability(struct stream *impl, bool empty) +{ + struct spa_pod *param = NULL; + uint8_t buffer1024; + if (!empty) { + struct spa_pod_frame f; + struct spa_pod_builder b; + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_peer_param_build_start(&b, &f, SPA_PARAM_PeerCapability); + spa_peer_param_build_add_param(&b, SPA_ID_INVALID, NULL); + param = spa_peer_param_build_end(&b, &f); + } + emit_param_changed(impl, SPA_PARAM_PeerCapability, param); +} + static int impl_port_set_param(void *object, enum spa_direction direction, uint32_t port_id, uint32_t id, uint32_t flags, @@ -916,7 +939,7 @@ { struct stream *impl = object; struct pw_stream *stream = &impl->this; - uint32_t user, fl = 0; + uint32_t user = 0, fl = 0; int res; const struct spa_pod *params1; uint32_t n_params = 0; @@ -936,7 +959,12 @@ n_params = param ? 1 : 0; switch (id) { + case SPA_PARAM_PeerCapability: + impl->have_peer_capability = true; + break; case SPA_PARAM_Latency: + if (!impl->have_peer_capability) + emit_dummy_peer_capability(impl, param == NULL); parse_latency(stream, param, &fl); break; } @@ -2015,6 +2043,8 @@ impl->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); impl->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE); impl->port_paramsPORT_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_WRITE); + impl->port_paramsPORT_Capability = SPA_PARAM_INFO(SPA_PARAM_Capability, 0); + impl->port_paramsPORT_PeerCapability = SPA_PARAM_INFO(SPA_PARAM_PeerCapability, SPA_PARAM_INFO_WRITE); impl->port_info.props = &impl->port_props->dict; impl->port_info.params = impl->port_params; impl->port_info.n_params = N_PORT_PARAMS;
View file
_service:download_files:pipewire-1.5.83.tar.bz2/src/tools/pw-cat.c -> _service:download_files:pipewire-1.5.84.tar.bz2/src/tools/pw-cat.c
Changed
@@ -91,11 +91,6 @@ typedef int (*fill_fn)(struct data *d, void *dest, unsigned int n_frames, bool *null_frame); -struct channelmap { - uint32_t n_channels; - uint32_t channelsMAX_CHANNELS; -}; - struct data { struct pw_main_loop *loop; struct pw_context *context; @@ -135,7 +130,7 @@ unsigned int bitrate; unsigned int rate; uint32_t channels; - struct channelmap channelmap; + struct spa_audio_layout_info channelmap; unsigned int stride; enum unit latency_unit; unsigned int latency_value; @@ -634,7 +629,7 @@ return NULL; } -static int channelmap_from_sf(struct channelmap *map) +static int channelmap_from_sf(struct spa_audio_layout_info *map) { static const enum spa_audio_channel table = { SF_CHANNEL_MAP_MONO = SPA_AUDIO_CHANNEL_MONO, @@ -663,78 +658,75 @@ uint32_t i; for (i = 0; i < map->n_channels; i++) { - if (map->channelsi < SPA_N_ELEMENTS(table)) - map->channelsi = tablemap->channelsi; + if (map->positioni < SPA_N_ELEMENTS(table)) + map->positioni = tablemap->positioni; else - map->channelsi = SPA_AUDIO_CHANNEL_UNKNOWN; + map->positioni = SPA_AUDIO_CHANNEL_UNKNOWN; } return 0; } -struct mapping { +struct mapping_alias { const char *name; - uint32_t channels; - uint32_t values32; + const char *alias; }; -static const struct mapping maps = +static const struct mapping_alias maps = { - { "mono", SPA_AUDIO_LAYOUT_Mono }, - { "stereo", SPA_AUDIO_LAYOUT_Stereo }, - { "surround-21", SPA_AUDIO_LAYOUT_2_1 }, - { "quad", SPA_AUDIO_LAYOUT_Quad }, - { "surround-22", SPA_AUDIO_LAYOUT_2_2 }, - { "surround-40", SPA_AUDIO_LAYOUT_4_0 }, - { "surround-31", SPA_AUDIO_LAYOUT_3_1 }, - { "surround-41", SPA_AUDIO_LAYOUT_4_1 }, - { "surround-50", SPA_AUDIO_LAYOUT_5_0 }, - { "surround-51", SPA_AUDIO_LAYOUT_5_1 }, - { "surround-51r", SPA_AUDIO_LAYOUT_5_1R }, - { "surround-70", SPA_AUDIO_LAYOUT_7_0 }, - { "surround-71", SPA_AUDIO_LAYOUT_7_1 }, + { "mono", "Mono" }, + { "stereo", "Stereo" }, + { "surround-21", "2.1" }, + { "quad", "Quad" }, + { "surround-22", "2.2" }, + { "surround-40", "4.0" }, + { "surround-31", "3.1" }, + { "surround-41", "4.1" }, + { "surround-50", "5.0" }, + { "surround-51", "5.1" }, + { "surround-51r", "5.1R" }, + { "surround-70", "7.0" }, + { "surround-71", "7.1" }, }; -static int parse_channelmap(const char *channel_map, struct channelmap *map) +static int parse_channelmap(const char *channel_map, struct spa_audio_layout_info *map) { + if (spa_audio_layout_info_parse_name(map, sizeof(*map), channel_map) >= 0) + return 0; + SPA_FOR_EACH_ELEMENT_VAR(maps, m) { - if (spa_streq(m->name, channel_map)) { - map->n_channels = m->channels; - spa_memcpy(map->channels, &m->values, - map->n_channels * sizeof(unsigned int)); - return 0; - } + if (spa_streq(m->name, channel_map)) + return spa_audio_layout_info_parse_name(map, sizeof(*map), m->alias); } - spa_audio_parse_position_n(channel_map, strlen(channel_map), - map->channels, SPA_N_ELEMENTS(map->channels), &map->n_channels); + map->position, SPA_N_ELEMENTS(map->position), &map->n_channels); return 0; } -static int channelmap_default(struct channelmap *map, int n_channels) +static int channelmap_default(struct spa_audio_layout_info *map, int n_channels) { switch(n_channels) { case 1: - parse_channelmap("mono", map); + parse_channelmap("Mono", map); break; case 2: - parse_channelmap("stereo", map); + parse_channelmap("Stereo", map); break; case 3: - parse_channelmap("surround-21", map); + parse_channelmap("2.1", map); break; case 4: - parse_channelmap("quad", map); + parse_channelmap("Quad", map); break; case 5: - parse_channelmap("surround-50", map); + parse_channelmap("5.0", map); break; case 6: - parse_channelmap("surround-51", map); + parse_channelmap("5.1", map); break; case 7: - parse_channelmap("surround-70", map); + parse_channelmap("7.0", map); break; case 8: - parse_channelmap("surround-71", map); + parse_channelmap("7.1", map); break; default: n_channels = 0; @@ -744,13 +736,13 @@ return 0; } -static void channelmap_print(struct channelmap *map) +static void channelmap_print(struct spa_audio_layout_info *map) { uint32_t i; char pos8; for (i = 0; i < map->n_channels; i++) { fprintf(stderr, "%s%s", i ? "," : "", - spa_type_audio_channel_make_short_name(map->channelsi, + spa_type_audio_channel_make_short_name(map->positioni, pos, sizeof(pos), "UNK")); } } @@ -1051,16 +1043,24 @@ OPT_VOLUME, }; +#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION +#define OPTIONS "hvprmdosR:P:q:aM:n:c" +#else +#define OPTIONS "hvprmdsR:P:q:aM:n:c" +#endif + static const struct option long_options = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, OPT_VERSION}, { "verbose", no_argument, NULL, 'v' }, - { "record", no_argument, NULL, 'r' }, { "playback", no_argument, NULL, 'p' }, + { "record", no_argument, NULL, 'r' }, { "midi", no_argument, NULL, 'm' }, { "dsd", no_argument, NULL, 'd' }, +#ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION { "encoded", no_argument, NULL, 'o' }, +#endif { "sysex", no_argument, NULL, 's' }, { "remote", required_argument, NULL, 'R' }, @@ -1121,7 +1121,7 @@ _(" --rate Sample rate (req. for rec) (default %u)\n" " --channels Number of channels (req. for rec) (default %u)\n" " --channel-map Channel map\n" - " one of: \"stereo\", \"surround-51\",... or\n" + " one of: \"Stereo\", \"5.1\",... or\n" " comma separated list of channel names: eg. \"FL,FR\"\n" " --format Sample format %s (req. for rec) (default %s)\n" " --volume Stream volume 0-1.0 (default %.3f)\n" @@ -1854,8 +1854,8 @@ bool def = false; if (sf_command(data->file, SFC_GET_CHANNEL_MAP_INFO, - data->channelmap.channels,
View file
_service:download_files:pipewire-1.5.83.tar.bz2/test/test-spa-utils.c -> _service:download_files:pipewire-1.5.84.tar.bz2/test/test-spa-utils.c
Changed
@@ -127,7 +127,9 @@ pwtest_int_eq(SPA_TYPE_OBJECT_ParamLatency, 0x4000b); pwtest_int_eq(SPA_TYPE_OBJECT_ParamProcessLatency, 0x4000c); pwtest_int_eq(SPA_TYPE_OBJECT_ParamTag, 0x4000d); - pwtest_int_eq(_SPA_TYPE_OBJECT_LAST, 0x4000e); + pwtest_int_eq(SPA_TYPE_OBJECT_PeerParam, 0x4000e); + pwtest_int_eq(SPA_TYPE_OBJECT_ParamDict, 0x4000f); + pwtest_int_eq(_SPA_TYPE_OBJECT_LAST, 0x40010); pwtest_int_eq(SPA_TYPE_VENDOR_PipeWire, 0x02000000); pwtest_int_eq(SPA_TYPE_VENDOR_Other, 0x7f000000);
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
.