Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 5
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Thu Mar 3 11:50:58 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.48 + +------------------------------------------------------------------- Fri Feb 18 14:59:46 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.47
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.47 +Version: 0.3.48 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.47.tar.gz/NEWS -> pipewire-0.3.48.tar.gz/NEWS
Changed
@@ -1,3 +1,81 @@ +# PipeWire 0.3.48 (2022-03-03) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix IEC958 passthrough again. + - Fix pulse-server crashes when playing a sample. + - Support for more a more advanced upmixing algorithm. + - filter-chain now supports arbitrary many ports. + - Fix multichannel support in WINE. (with new WirePlumber). + - Many bugfixes and improvements. + + +## PipeWire + - The work queue is now created in the context so we can fail early and + avoid further error checking in various places. + - Fix a potential use after free with threaded loops. + - The protocol now has a message footer. This is used to pass around + global state such as the last registered object serial number. This can + be used to detect when a client tries to bind to old (but reused) + object ids. This avoids some races in the session manager but also + when binding objects. + - The zero-denormals CPU flag is now not touched anymore unless explicitly + selected by the user. Denormals are avoided in filter-chain now in + software. If the zero-denormals are now only configured in the data + thread. This should fix issues with luajit. (#2160) + - Configuration parsing will not actually fail on errors. + - pw-top now correctly clips unicode characters. + - Many places now use a dynamic POD builder to support arbitrary large + property sets. + - pw-stream now support PropInfo parameters so that they can announce + custom properties. + - Serial number are now also set on metadata and session-manager objects. + +## SPA + - audioadapter is now smarter when trying to fixate the format. It will + use the PortConfig format to fill in any wildcards. This results in + the least amount of conversions when the stream can handle it. It also + is part of a fix (also requires a session manager fix) for WINE + multichannel support. (#876). + - Fix 5.1 to 2 channels mixing. It was using the volume of the stereo + pair on all channels. + - Fix some weird volume issues when a source is capturing and + channelmixing. + - Add stereo to 7.1 upmixing. + - The channelmix parameters can be changed at runtime now. + - Many improvements to the upmixing algorithms. Rear channels are now + constructed from the ambient sound and can have delay and phase shift + applied to them to improve spacialization. The stereo channels can + be filtered so that the dialog is more concentrated in the center + channel. (#861) + +## modules + - Module X11 bell received cleanups and improvements. + - The module now has a private method to schedule unload later. This + simplifies cleanup in many modules. + - module-filter-chain now handles arbitrary many ports and control + ports. (#2179) + - Fix a bug in RAOP where it was reading from the wrong port. (#2183) + +## pulse-server + - Nodes with the DONT_MOVE property should fail with -EINVAL when + they are moved. + - Fix a segfault when playing a sample. (#2151) + - The _FIX flags in pulse-server also now ignore the configured + sample format, just like pulseaudio does. (#876) + - Fix IEC958 passthrough again. It got accidentally broken since + 0.3.45 with a fix for another issue. (#1442) + - Fix module-null-sink device.description. (#2166) + +## Bluetooth + - Don't try to connect HSP/HFP when no backend is available. + + +Older versions: + + # PipeWire 0.3.47 (2022-02-18) This is a bugfix release that is API and ABI compatible with previous @@ -13,8 +91,6 @@ proxy. This might access invalid memory and cause infinite loops in older wireplumber. -Older versions: - # PipeWire 0.3.46 (2022-02-17) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.47.tar.gz/meson.build -> pipewire-0.3.48.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.47', + version : '0.3.48', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.59.0', default_options : 'warning_level=3', @@ -221,18 +221,6 @@ cdata.set(h.get(1), cc.has_header(h.get(0))) endforeach -check_functions = - 'gettid', '#include <unistd.h>', '-D_GNU_SOURCE', - 'memfd_create', '#include <sys/mman.h>', '-D_GNU_SOURCE', - 'getrandom', '#include <stddef.h>\n#include <sys/random.h>', '-D_GNU_SOURCE', - 'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', - - -foreach f : check_functions - cdata.set('HAVE_' + f.get(0).to_upper(), - cc.has_function(f.get(0), prefix: f.get(1), args: f.get(2))) -endforeach - cdata.set('HAVE_PIDFD_OPEN', cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '') @@ -292,6 +280,9 @@ summary({'X11 (x11-bell)': x11_dep.found()}, bool_yn: true, section: 'Misc dependencies') +xfixes_dep = dependency('xfixes', required : get_option('x11-xfixes'), version: '>= 6') +cdata.set('HAVE_XFIXES_6', xfixes_dep.found()) + canberra_dep = dependency('libcanberra', required : get_option('libcanberra')) summary({'libcanberra (x11-bell)': canberra_dep.found()}, bool_yn: true, section: 'Misc dependencies') @@ -380,6 +371,22 @@ summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true) cdata.set('HAVE_LILV', lilv_lib.found()) +check_functions = + 'gettid', '#include <unistd.h>', '-D_GNU_SOURCE', , + 'memfd_create', '#include <sys/mman.h>', '-D_GNU_SOURCE', , + 'getrandom', '#include <stddef.h>\n#include <sys/random.h>', '-D_GNU_SOURCE', , + 'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', , + 'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep, + + +foreach f : check_functions + cdata.set('HAVE_' + f.get(0).to_upper(), + cc.has_function(f.get(0), + prefix: f.get(1), + args: f.get(2), + dependencies: f.get(3))) +endforeach + installed_tests_metadir = pipewire_datadir / 'installed-tests' / pipewire_name installed_tests_execdir = pipewire_libexecdir / 'installed-tests' / pipewire_name installed_tests_enabled = get_option('installed_tests').allowed()
View file
pipewire-0.3.47.tar.gz/meson_options.txt -> pipewire-0.3.48.tar.gz/meson_options.txt
Changed
@@ -229,6 +229,10 @@ description: 'Enable code that depends on X11', type: 'feature', value: 'auto') +option('x11-xfixes', + description: 'Enable code that depends on XFixes', + type: 'feature', + value: 'auto') option('libcanberra', description: 'Enable code that depends on libcanberra', type: 'feature',
View file
pipewire-0.3.47.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.48.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -5328,7 +5328,7 @@ res = is_def2 - is_def1; else if ((*o1)->port.priority != (*o2)->port.priority) res = (*o2)->port.priority - (*o1)->port.priority; - else if ((res = strcmp((*o1)->port.alias1, (*o2)->port.alias1) == 0)) { + else if ((res = strcmp((*o1)->port.alias1, (*o2)->port.alias1)) == 0) { res = (*o1)->port.node_id - (*o2)->port.node_id; if (res == 0) res = (*o1)->port.system_id - (*o2)->port.system_id;
View file
pipewire-0.3.48.tar.gz/spa/include/spa/pod/dynamic.h
Added
@@ -0,0 +1,81 @@ +/* Simple Plugin API + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_POD_DYNAMIC_H +#define SPA_POD_DYNAMIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <spa/pod/builder.h> + +struct spa_pod_dynamic_builder { + struct spa_pod_builder b; + void *data; + uint32_t extend; + uint32_t _padding; +}; + +static int spa_pod_dynamic_builder_overflow(void *data, uint32_t size) +{ + struct spa_pod_dynamic_builder *d = (struct spa_pod_dynamic_builder*)data; + int32_t old_size = d->b.size; + int32_t new_size = SPA_ROUND_UP_N(size, d->extend); + void *old_data = d->b.data; + + if (old_data == d->data) + d->b.data = NULL; + if ((d->b.data = realloc(d->b.data, new_size)) == NULL) + return -errno; + if (old_data == d->data && d->b.data != old_data && old_size > 0) + memcpy(d->b.data, old_data, old_size); + d->b.size = new_size; + return 0; +} + +static inline void spa_pod_dynamic_builder_init(struct spa_pod_dynamic_builder *builder, + void *data, uint32_t size, uint32_t extend) +{ + static const struct spa_pod_builder_callbacks spa_pod_dynamic_builder_callbacks = { + SPA_VERSION_POD_BUILDER_CALLBACKS, + .overflow = spa_pod_dynamic_builder_overflow + }; + builder->b = SPA_POD_BUILDER_INIT(data, size); + spa_pod_builder_set_callbacks(&builder->b, &spa_pod_dynamic_builder_callbacks, builder); + builder->extend = extend; + builder->data = data; +} + +static inline void spa_pod_dynamic_builder_clean(struct spa_pod_dynamic_builder *builder) +{ + if (builder->data != builder->b.data) + free(builder->b.data); +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_POD_DYNAMIC_H */
View file
pipewire-0.3.47.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c -> pipewire-0.3.48.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c
Changed
@@ -4742,6 +4742,10 @@ int count = 0; f = open_memstream(&ptr, &size); + if (f == NULL) { + pa_log("failed to open memstream: %m"); + return -1; + } if (p->output_mappings) PA_IDXSET_FOREACH(m, p->output_mappings, idx) { @@ -4816,6 +4820,8 @@ size_t size; f = open_memstream(&ptr, &size); + if (f == NULL) + return; pa_assert(db_fix->min_step <= db_fix->max_step); nsteps = db_fix->max_step - db_fix->min_step + 1;
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -36,6 +36,7 @@ #include <spa/buffer/alloc.h> #include <spa/pod/parser.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/param/param.h> #include <spa/param/audio/format-utils.h> #include <spa/param/latency-utils.h> @@ -68,6 +69,7 @@ struct spa_hook follower_listener; uint32_t follower_flags; struct spa_audio_info follower_current_format; + struct spa_audio_info default_format; struct spa_handle *hnd_convert; struct spa_node *convert; @@ -141,8 +143,8 @@ const struct spa_pod *filter) { struct impl *this = object; - struct spa_pod_builder b = { 0 }; uint8_t buffer4096; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; int res; @@ -157,7 +159,7 @@ spa_log_debug(this->log, "%p: %d id:%u", this, seq, id); - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); switch (id) { case SPA_PARAM_EnumPortConfig: @@ -165,35 +167,38 @@ res = spa_node_enum_params(this->convert, seq, id, start, num, filter); return res; case SPA_PARAM_PropInfo: - if ((res = follower_enum_params(this, - id, IDX_PropInfo, &result, filter, &b)) != 1) - return res; + res = follower_enum_params(this, + id, IDX_PropInfo, &result, filter, &b.b); break; case SPA_PARAM_Props: - if ((res = follower_enum_params(this, - id, IDX_Props, &result, filter, &b)) != 1) - return res; + res = follower_enum_params(this, + id, IDX_Props, &result, filter, &b.b); break; case SPA_PARAM_ProcessLatency: - if ((res = follower_enum_params(this, - id, IDX_ProcessLatency, &result, filter, &b)) != 1) - return res; + res = follower_enum_params(this, + id, IDX_ProcessLatency, &result, filter, &b.b); break; case SPA_PARAM_EnumFormat: case SPA_PARAM_Format: case SPA_PARAM_Latency: - if ((res = spa_node_port_enum_params_sync(this->follower, + res = spa_node_port_enum_params_sync(this->follower, this->direction, 0, - id, &result.next, filter, &result.param, &b)) != 1) - return res; + id, &result.next, filter, &result.param, &b.b); break; default: return -ENOENT; } - spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + if (res == 1) { + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count != num) + if (res != 1) + return res; + + if (count != num) goto next; return 0; @@ -522,6 +527,31 @@ return 0; } +static int format_audio_raw_parse_opt(const struct spa_pod *format, struct spa_audio_info_raw *info) +{ + struct spa_pod *position = NULL; + uint32_t media_type, media_subtype; + int res; + if ((res = spa_format_parse(format, &media_type, &media_subtype)) < 0) + return res; + if (media_type != SPA_MEDIA_TYPE_audio || + media_subtype != SPA_MEDIA_SUBTYPE_raw) + return -ENOTSUP; + + spa_zero(*info); + res = spa_pod_parse_object(format, + SPA_TYPE_OBJECT_Format, NULL, + SPA_FORMAT_AUDIO_format, SPA_POD_OPT_Id(&info->format), + 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 (position == NULL || + !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) + SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); + + return res; +} + static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) { @@ -569,6 +599,12 @@ SPA_PARAM_PORT_CONFIG_format, SPA_POD_OPT_Pod(&format)) < 0) return -EINVAL; + if (format) { + struct spa_audio_info info; + if (format_audio_raw_parse_opt(format, &info.info.raw) >= 0) + this->default_format = info; + } + switch (mode) { case SPA_PARAM_PORT_CONFIG_MODE_none: return -ENOTSUP; @@ -634,10 +670,44 @@ return res; } +static struct spa_pod *merge_objects(struct impl *this, struct spa_pod_builder *b, uint32_t id, + struct spa_pod_object *o1, struct spa_pod_object *o2) +{ + const struct spa_pod_prop *p1, *p2; + struct spa_pod_frame f; + struct spa_pod_builder_state state; + int res = 0; + + if (o2 == NULL || SPA_POD_TYPE(o1) != SPA_POD_TYPE(o2)) + return (struct spa_pod*)o1; + + spa_pod_builder_push_object(b, &f, o1->body.type, o1->body.id); + p2 = NULL; + SPA_POD_OBJECT_FOREACH(o1, p1) { + p2 = spa_pod_object_find_prop(o2, p2, p1->key); + if (p2 != NULL) { + spa_pod_builder_get_state(b, &state); + res = spa_pod_filter_prop(b, p1, p2); + if (res < 0) + spa_pod_builder_reset(b, &state); + } + if (p2 == NULL || res < 0) + spa_pod_builder_raw_padded(b, p1, SPA_POD_PROP_SIZE(p1)); + } + p1 = NULL; + SPA_POD_OBJECT_FOREACH(o2, p2) { + p1 = spa_pod_object_find_prop(o1, p1, p2->key); + if (p1 != NULL) + continue; + spa_pod_builder_raw_padded(b, p2, SPA_POD_PROP_SIZE(p2)); + } + return spa_pod_builder_pop(b, &f); +} + static int negotiate_format(struct impl *this) { uint32_t state; - struct spa_pod *format; + struct spa_pod *format, *def; uint8_t buffer4096; struct spa_pod_builder b = { 0 }; int res; @@ -669,7 +739,6 @@ goto done; } } - if (this->convert) { state = 0; if ((res = spa_node_port_enum_params_sync(this->convert, @@ -688,6 +757,13 @@ goto done; } + def = spa_format_audio_raw_build(&b, + SPA_PARAM_Format, &this->default_format.info.raw); + + format = merge_objects(this, &b, SPA_PARAM_Format, + (struct spa_pod_object*)format, + (struct spa_pod_object*)def); + spa_pod_fixate(format); res = configure_format(this, 0, format);
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops-c.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops-c.c
Changed
@@ -25,10 +25,10 @@ #include "channelmix-ops.h" void -channelmix_copy_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_copy_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; @@ -51,10 +51,10 @@ #define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch) void -channelmix_f32_n_m_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_n_m_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, j, n; + uint32_t i, j, n, n_dst = mix->dst_chan, n_src = mix->src_chan; float **d = (float **) dst; const float **s = (const float **) src; @@ -78,10 +78,8 @@ din = sum; } } - for (i = 0; i < n_dst; i++) { - if (mix->lr4_infoi > 0) - lr4_process(&mix->lr4i, di, n_samples); - } + for (i = 0; i < n_dst; i++) + lr4_process(&mix->lr4i, di, di, 1.0f, n_samples); } } @@ -89,8 +87,8 @@ #define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN) void -channelmix_f32_1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **)dst; @@ -118,8 +116,8 @@ } void -channelmix_f32_2_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_2_1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **)dst; @@ -140,8 +138,8 @@ } void -channelmix_f32_4_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_4_1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **)dst; @@ -166,8 +164,8 @@ } void -channelmix_f32_3p1_1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_3p1_1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **)dst; @@ -193,10 +191,10 @@ #define MASK_QUAD _M(FL)|_M(FR)|_M(RL)|_M(RR)|_M(UNKNOWN) void -channelmix_f32_2_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_2_4_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; const float v0 = mix->matrix00; @@ -233,10 +231,10 @@ #define MASK_3_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE) void -channelmix_f32_2_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_2_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; const float v0 = mix->matrix00; @@ -251,33 +249,89 @@ else if (v0 == 1.0f && v1 == 1.0f) { for (n = 0; n < n_samples; n++) { float c = s0n + s1n; - d0n = s0n; - d1n = s1n; - d2n = c * v2; - d3n = c * v3; + float w = c * mix->widen; + d0n = s0n - w; + d1n = s1n - w; + d2n = c; } - if (v3 > 0.0f) - lr4_process(&mix->lr43, d3, n_samples); + lr4_process(&mix->lr43, d3, d2, v3, n_samples); + lr4_process(&mix->lr42, d2, d2, v2, n_samples); } else { for (n = 0; n < n_samples; n++) { float c = s0n + s1n; - d0n = s0n * v0; - d1n = s1n * v1; - d2n = c * v2; - d3n = c * v3; + float w = c * mix->widen; + d0n = (s0n - w) * v0; + d1n = (s1n - w) * v1; + d2n = c; } - if (v3 > 0.0f) - lr4_process(&mix->lr43, d3, n_samples); + lr4_process(&mix->lr43, d3, d2, v3, n_samples); + lr4_process(&mix->lr42, d2, d2, v2, n_samples); } } #define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) void -channelmix_f32_2_5p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_2_5p1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) +{ + uint32_t i, n, n_dst = mix->dst_chan; + float **d = (float **)dst; + const float **s = (const float **)src; + const float v0 = mix->matrix00; + const float v1 = mix->matrix11; + const float v2 = (mix->matrix20 + mix->matrix21) * 0.5f; + const float v3 = (mix->matrix30 + mix->matrix31) * 0.5f; + const float v4 = mix->matrix40; + const float v5 = mix->matrix51; + + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { + for (i = 0; i < n_dst; i++) + memset(di, 0, n_samples * sizeof(float)); + } + else if (v0 == 1.0f && v1 == 1.0f) { + for (n = 0; n < n_samples; n++) { + float c = s0n + s1n; + float w = c * mix->widen; + float m = s0n - s1n; + d0n = s0n - w; + d1n = s1n - w; + d3n = c; + d5n = m; + } + lr4_process(&mix->lr42, d2, d3, v2, n_samples); + lr4_process(&mix->lr43, d3, d3, v3, n_samples); + + delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d4, d5, v4, n_samples); + delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d5, d5, -v5, n_samples); + } + else { + for (n = 0; n < n_samples; n++) { + float c = s0n + s1n; + float w = c * mix->widen; + float m = s0n - s1n; + d0n = (s0n - w) * v0; + d1n = (s1n - w) * v1; + d3n = c; + d5n = m; + } + lr4_process(&mix->lr42, d2, d3, v2, n_samples); + lr4_process(&mix->lr43, d3, d3, v3, n_samples); + + delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d4, d5, v4, n_samples); + delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d5, d5, -v5, n_samples); + } +} + +void +channelmix_f32_2_7p1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; const float v0 = mix->matrix00; @@ -286,6 +340,8 @@ const float v3 = (mix->matrix30 + mix->matrix31) * 0.5f; const float v4 = mix->matrix40; const float v5 = mix->matrix51; + const float v6 = mix->matrix60; + const float v7 = mix->matrix71; if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { for (i = 0; i < n_dst; i++) @@ -294,33 +350,49 @@ else if (v0 == 1.0f && v1 == 1.0f && v4 == 1.0f && v5 == 1.0f) { for (n = 0; n < n_samples; n++) { float c = s0n + s1n; - d0n = d4n = s0n; - d1n = d5n = s1n; - d2n = c * v2; - d3n = c * v3; + float w = c * mix->widen; + float m = s0n - s1n; + d0n = s0n - w; + d1n = s1n - w; + d3n = c; + d4n = s0n; + d5n = s1n; + d7n = m; } - if (v3 > 0.0f) - lr4_process(&mix->lr43, d3, n_samples); + lr4_process(&mix->lr42, d2, d3, v2, n_samples); + lr4_process(&mix->lr43, d3, d3, v3, n_samples); + + delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d6, d7, v6, n_samples); + delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d7, d7, -v7, n_samples); } else { for (n = 0; n < n_samples; n++) { float c = s0n + s1n; - d0n = s0n * v0; - d1n = s1n * v1; - d2n = c * v2; - d3n = c * v3; + float w = c * mix->widen; + float m = s0n - s1n; + d0n = (s0n - w) * v0; + d1n = (s1n - w) * v1; + d3n = c; d4n = s0n * v4; d5n = s1n * v5; + d7n = m; } - if (v3 > 0.0f) - lr4_process(&mix->lr43, d3, n_samples); + lr4_process(&mix->lr42, d2, d3, v2, n_samples); + lr4_process(&mix->lr43, d3, d3, v3, n_samples); + + delay_convolve_run(mix->buffer0, &mix->pos0, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d6, d7, v6, n_samples); + delay_convolve_run(mix->buffer1, &mix->pos1, BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d7, d7, -v7, n_samples); } } /* FL+FR+FC+LFE+SL+SR -> FL+FR */ void -channelmix_f32_5p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **) dst; @@ -347,10 +419,10 @@ /* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/ void -channelmix_f32_5p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const float v0 = mix->matrix00; @@ -376,10 +448,10 @@ /* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/ void -channelmix_f32_5p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_4_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const float clev = mix->matrix02; @@ -408,8 +480,8 @@ /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR */ void -channelmix_f32_7p1_2_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_7p1_2_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n; float **d = (float **) dst; @@ -438,10 +510,10 @@ /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+FC+LFE*/ void -channelmix_f32_7p1_3p1_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_7p1_3p1_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const float v0 = mix->matrix00; @@ -467,10 +539,10 @@ /* FL+FR+FC+LFE+SL+SR+RL+RR -> FL+FR+RL+RR*/ void -channelmix_f32_7p1_4_c(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_7p1_4_c(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n; + uint32_t i, n, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const float v0 = mix->matrix00;
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops-sse.c
Changed
@@ -26,10 +26,10 @@ #include <xmmintrin.h> -void channelmix_copy_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +void channelmix_copy_sse(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n, unrolled; + uint32_t i, n, unrolled, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; @@ -71,10 +71,10 @@ } void -channelmix_f32_2_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_2_4_sse(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n, unrolled; + uint32_t i, n, unrolled, n_dst = mix->dst_chan; float **d = (float **)dst; const float **s = (const float **)src; const float m00 = mix->matrix00; @@ -139,8 +139,8 @@ /* FL+FR+FC+LFE+SL+SR -> FL+FR */ void -channelmix_f32_5p1_2_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_2_sse(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { uint32_t n, unrolled; float **d = (float **) dst; @@ -205,13 +205,11 @@ ctr = _mm_add_ps(ctr, _mm_mul_ps(_mm_load_ps(&sLFEn), llev)); in = _mm_mul_ps(_mm_load_ps(&sSLn), slev0); in = _mm_add_ps(in, ctr); - in = _mm_add_ps(in, _mm_load_ps(&sFLn)); - in = _mm_mul_ps(in, v0); + in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFLn), v0)); _mm_store_ps(&dFLn, in); in = _mm_mul_ps(_mm_load_ps(&sSRn), slev1); in = _mm_add_ps(in, ctr); - in = _mm_add_ps(in, _mm_load_ps(&sFRn)); - in = _mm_mul_ps(in, v1); + in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFRn), v1)); _mm_store_ps(&dFRn, in); } for(; n < n_samples; n++) { @@ -219,13 +217,11 @@ ctr = _mm_add_ss(ctr, _mm_mul_ss(_mm_load_ss(&sLFEn), llev)); in = _mm_mul_ss(_mm_load_ss(&sSLn), slev0); in = _mm_add_ss(in, ctr); - in = _mm_add_ss(in, _mm_load_ss(&sFLn)); - in = _mm_mul_ss(in, v0); + in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFLn), v0)); _mm_store_ss(&dFLn, in); in = _mm_mul_ss(_mm_load_ss(&sSRn), slev1); in = _mm_add_ss(in, ctr); - in = _mm_add_ss(in, _mm_load_ss(&sFRn)); - in = _mm_mul_ss(in, v1); + in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFRn), v1)); _mm_store_ss(&dFRn, in); } } @@ -233,10 +229,10 @@ /* FL+FR+FC+LFE+SL+SR -> FL+FR+FC+LFE*/ void -channelmix_f32_5p1_3p1_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_3p1_sse(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n, unrolled; + uint32_t i, n, unrolled, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const __m128 v0 = _mm_set1_ps(mix->matrix00); @@ -311,10 +307,10 @@ /* FL+FR+FC+LFE+SL+SR -> FL+FR+RL+RR*/ void -channelmix_f32_5p1_4_sse(struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples) +channelmix_f32_5p1_4_sse(struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples) { - uint32_t i, n, unrolled; + uint32_t i, n, unrolled, n_dst = mix->dst_chan; float **d = (float **) dst; const float **s = (const float **) src; const __m128 clev = _mm_set1_ps(mix->matrix02);
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
@@ -35,6 +35,7 @@ #define VOLUME_NORM 1.0f #include "channelmix-ops.h" +#include "hilbert.h" #undef SPA_LOG_TOPIC_DEFAULT #define SPA_LOG_TOPIC_DEFAULT log_topic @@ -51,8 +52,8 @@ #define ANY ((uint32_t)-1) #define EQ ((uint32_t)-2) -typedef void (*channelmix_func_t) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples); +typedef void (*channelmix_func_t) (struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples); static const struct channelmix_info { uint32_t src_chan; @@ -84,6 +85,7 @@ { 2, MASK_STEREO, 4, MASK_QUAD, channelmix_f32_2_4_c, 0, "f32_2_4_c" }, { 2, MASK_STEREO, 4, MASK_3_1, channelmix_f32_2_3p1_c, 0, "f32_2_3p1_c" }, { 2, MASK_STEREO, 6, MASK_5_1, channelmix_f32_2_5p1_c, 0, "f32_2_5p1_c" }, + { 2, MASK_STEREO, 8, MASK_7_1, channelmix_f32_2_7p1_c, 0, "f32_2_7p1_c" }, #if defined (HAVE_SSE) { 6, MASK_5_1, 2, MASK_STEREO, channelmix_f32_5p1_2_sse, SPA_CPU_FLAG_SSE, "f32_5p1_2_sse" }, #endif @@ -214,8 +216,10 @@ keep |= FRONT; if (mix->lfe_cutoff > 0.0f) keep |= _MASK(LFE); + else + keep &= ~_MASK(LFE); - spa_log_debug(mix->log, "unassigned downmix %08" PRIx64, unassigned); + spa_log_debug(mix->log, "unassigned downmix %08" PRIx64 " %08" PRIx64, unassigned, keep); if (unassigned & FRONT){ if ((dst_mask & STEREO) == STEREO){ @@ -452,11 +456,13 @@ } maxsum = SPA_MAX(maxsum, sum); if (i == _CH(LFE) && mix->lfe_cutoff > 0.0f) { - spa_log_debug(mix->log, "channel %d is LFE", ic); + spa_log_debug(mix->log, "channel %d is LFE cutoff:%f", ic, mix->lfe_cutoff); lr4_set(&mix->lr4ic, BQ_LOWPASS, mix->lfe_cutoff / mix->freq); - mix->lr4_infoic = 1; + } else if (i == _CH(FC) && mix->fc_cutoff > 0.0f) { + spa_log_debug(mix->log, "channel %d is FC cutoff:%f", ic, mix->fc_cutoff); + lr4_set(&mix->lr4ic, BQ_LOWPASS, mix->fc_cutoff / mix->freq); } else { - mix->lr4_infoic = 0; + mix->lr4ic.active = false; } ic++; } @@ -467,6 +473,7 @@ for (j = 0; j < jc; j++) mix->matrix_origij /= maxsum; } + return 0; } @@ -542,11 +549,22 @@ if (info == NULL) return -ENOTSUP; - spa_log_debug(mix->log, "selected %s", info->name); - mix->free = impl_channelmix_free; mix->process = info->process; mix->set_volume = impl_channelmix_set_volume; mix->cpu_flags = info->cpu_flags; + mix->delay = mix->rear_delay * mix->freq / 1000.0f; + + spa_log_debug(mix->log, "selected %s delay:%d options:%08x", info->name, mix->delay, + mix->options); + + if (mix->hilbert_taps > 0) { + mix->n_taps = SPA_CLAMP(mix->hilbert_taps, 15u, 255u) | 1; + blackman_window(mix->taps, mix->n_taps); + hilbert_generate(mix->taps, mix->n_taps); + } else { + mix->n_taps = 1; + mix->taps0 = 1.0f; + } return make_matrix(mix); }
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix-ops.h -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix-ops.h
Changed
@@ -33,6 +33,7 @@ extern struct spa_log_topic *log_topic; #include "crossover.h" +#include "delay.h" #define VOLUME_MIN 0.0f #define VOLUME_NORM 1.0f @@ -45,6 +46,10 @@ #define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) #define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) +#define BUFFER_SIZE 4096 + +#define BUFFER_SIZE 4096 +#define MAX_TAPS 255 struct channelmix { uint32_t src_chan; @@ -69,11 +74,20 @@ float freq; /* sample frequency */ float lfe_cutoff; /* in Hz, 0 is disabled */ - uint32_t lr4_infoSPA_AUDIO_MAX_CHANNELS; + float fc_cutoff; /* in Hz, 0 is disabled */ + float rear_delay; /* in ms, 0 is disabled */ + float widen; /* stereo widen. 0 is disabled */ + uint32_t hilbert_taps; /* to phase shift, 0 disabled */ struct lr4 lr4SPA_AUDIO_MAX_CHANNELS; - void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, uint32_t n_samples); + float buffer2BUFFER_SIZE; + uint32_t pos2; + uint32_t delay; + float tapsMAX_TAPS; + uint32_t n_taps; + + void (*process) (struct channelmix *mix, void * SPA_RESTRICT dst, + const void * SPA_RESTRICT src, uint32_t n_samples); void (*set_volume) (struct channelmix *mix, float volume, bool mute, uint32_t n_channel_volumes, float *channel_volumes); void (*free) (struct channelmix *mix); @@ -87,10 +101,9 @@ #define channelmix_set_volume(mix,...) (mix)->set_volume(mix, __VA_ARGS__) #define channelmix_free(mix) (mix)->free(mix) -#define DEFINE_FUNCTION(name,arch) \ -void channelmix_##name##_##arch(struct channelmix *mix, \ - uint32_t n_dst, void * SPA_RESTRICT dstn_dst, \ - uint32_t n_src, const void * SPA_RESTRICT srcn_src, \ +#define DEFINE_FUNCTION(name,arch) \ +void channelmix_##name##_##arch(struct channelmix *mix, \ + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, \ uint32_t n_samples); #define CHANNELMIX_OPS_MAX_ALIGN 16 @@ -104,6 +117,7 @@ DEFINE_FUNCTION(f32_2_4, c); DEFINE_FUNCTION(f32_2_3p1, c); DEFINE_FUNCTION(f32_2_5p1, c); +DEFINE_FUNCTION(f32_2_7p1, c); DEFINE_FUNCTION(f32_5p1_2, c); DEFINE_FUNCTION(f32_5p1_3p1, c); DEFINE_FUNCTION(f32_5p1_4, c);
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/channelmix.c
Changed
@@ -145,6 +145,7 @@ struct spa_cpu *cpu; uint32_t quantum_limit; + enum spa_direction direction; struct spa_io_position *io_position; struct spa_hook_list hooks; @@ -360,7 +361,7 @@ if ((res = channelmix_init(&this->mix)) < 0) return res; - remap_volumes(this, src_info); + remap_volumes(this, this->direction == SPA_DIRECTION_INPUT ? src_info : dst_info); set_volume(this); emit_props_changed(this); @@ -467,13 +468,21 @@ case 8: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"), + SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 9: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_name, SPA_POD_String("channelmix.normalize"), SPA_PROP_INFO_description, SPA_POD_String("Normalize Volumes"), SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool( SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_NORMALIZE)), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 9: + case 10: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_name, SPA_POD_String("channelmix.mix-lfe"), @@ -482,7 +491,7 @@ SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_MIX_LFE)), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 10: + case 11: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix"), @@ -491,21 +500,49 @@ SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_UPMIX)), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 11: + case 12: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_name, SPA_POD_String("channelmix.lfe-cutoff"), - SPA_PROP_INFO_description, SPA_POD_String("LFE cutoff frequency"), + SPA_PROP_INFO_description, SPA_POD_String("LFE cutoff frequency (Hz)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( this->mix.lfe_cutoff, 0.0, 1000.0), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 12: + case 13: param = spa_pod_builder_add_object(&b, SPA_TYPE_OBJECT_PropInfo, id, - SPA_PROP_INFO_name, SPA_POD_String("channelmix.disable"), - SPA_PROP_INFO_description, SPA_POD_String("Disable Channel mixing"), - SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->disabled), + SPA_PROP_INFO_name, SPA_POD_String("channelmix.fc-cutoff"), + SPA_PROP_INFO_description, SPA_POD_String("FC cutoff frequency (Hz)"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( + this->mix.fc_cutoff, 0.0, 48000.0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 14: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.rear-delay"), + SPA_PROP_INFO_description, SPA_POD_String("Rear channels delay (ms)"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( + this->mix.rear_delay, 0.0, 1000.0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 15: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.stereo-widen"), + SPA_PROP_INFO_description, SPA_POD_String("Stereo widen"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( + this->mix.widen, 0.0, 1.0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 16: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"), + SPA_PROP_INFO_description, SPA_POD_String("Taps for phase shift of rear"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int( + this->mix.hilbert_taps, 0, MAX_TAPS), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; default: @@ -546,6 +583,8 @@ 0); spa_pod_builder_prop(&b, SPA_PROP_params, 0); spa_pod_builder_push_struct(&b, &f1); + spa_pod_builder_string(&b, "channelmix.disable"); + spa_pod_builder_bool(&b, this->props.disabled); spa_pod_builder_string(&b, "channelmix.normalize"); spa_pod_builder_bool(&b, SPA_FLAG_IS_SET(this->mix.options, CHANNELMIX_OPTION_NORMALIZE)); @@ -557,8 +596,14 @@ CHANNELMIX_OPTION_UPMIX)); spa_pod_builder_string(&b, "channelmix.lfe-cutoff"); spa_pod_builder_float(&b, this->mix.lfe_cutoff); - spa_pod_builder_string(&b, "channelmix.disable"); - spa_pod_builder_bool(&b, this->props.disabled); + spa_pod_builder_string(&b, "channelmix.fc-cutoff"); + spa_pod_builder_float(&b, this->mix.fc_cutoff); + spa_pod_builder_string(&b, "channelmix.rear-delay"); + spa_pod_builder_float(&b, this->mix.rear_delay); + spa_pod_builder_string(&b, "channelmix.stereo-widen"); + spa_pod_builder_float(&b, this->mix.widen); + spa_pod_builder_string(&b, "channelmix.hilbert-taps"); + spa_pod_builder_int(&b, this->mix.hilbert_taps); spa_pod_builder_pop(&b, &f1); param = spa_pod_builder_pop(&b, &f0); break; @@ -584,23 +629,34 @@ static int channelmix_set_param(struct impl *this, const char *k, const char *s) { - if (spa_streq(k, "channelmix.normalize")) + if (spa_streq(k, "channelmix.disable")) + this->props.disabled = spa_atob(s); + else if (spa_streq(k, "channelmix.normalize")) SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_NORMALIZE, spa_atob(s)); else if (spa_streq(k, "channelmix.mix-lfe")) SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_MIX_LFE, spa_atob(s)); else if (spa_streq(k, "channelmix.upmix")) SPA_FLAG_UPDATE(this->mix.options, CHANNELMIX_OPTION_UPMIX, spa_atob(s)); else if (spa_streq(k, "channelmix.lfe-cutoff")) - this->mix.lfe_cutoff = atoi(s); - else if (spa_streq(k, "channelmix.disable")) - this->props.disabled = spa_atob(s); - return 0; + spa_atof(s, &this->mix.lfe_cutoff); + else if (spa_streq(k, "channelmix.fc-cutoff")) + spa_atof(s, &this->mix.fc_cutoff); + else if (spa_streq(k, "channelmix.rear-delay")) + spa_atof(s, &this->mix.rear_delay); + else if (spa_streq(k, "channelmix.stereo-widen")) + spa_atof(s, &this->mix.widen); + else if (spa_streq(k, "channelmix.hilbert-taps")) + spa_atou32(s, &this->mix.hilbert_taps, 0); + else + return 0; + return 1; } static int parse_prop_params(struct impl *this, struct spa_pod *params) { struct spa_pod_parser prs; struct spa_pod_frame f; + int changed = 0; spa_pod_parser_pod(&prs, params); if (spa_pod_parser_push_struct(&prs, &f) < 0) @@ -633,9 +689,11 @@ continue; spa_log_info(this->log, "key:'%s' val:'%s'", name, value); - channelmix_set_param(this, name, value); + changed += channelmix_set_param(this, name, value); } - return 0; + if (changed) + channelmix_init(&this->mix); + return changed; } static int apply_props(struct impl *this, const struct spa_pod *param) @@ -714,7 +772,7 @@ } } if (changed) { - struct port *port = GET_IN_PORT(this, 0); + struct port *port = GET_PORT(this, this->direction, 0); if (have_soft_volume) p->have_soft_volume = true; else if (have_channel_volume) @@ -1292,8 +1350,7 @@ } static int channelmix_process_control(struct impl *this, struct port *ctrlport, - uint32_t n_dst, void * SPA_RESTRICT dstn_dst, - uint32_t n_src, const void * SPA_RESTRICT srcn_src, + void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_samples) { struct spa_pod_control *c, *prev = NULL; @@ -1336,10 +1393,10 @@ spa_log_trace_fp(this->log, "%p: process %d %d", this, c->offset, chunk); - channelmix_process(&this->mix, n_dst, dst, n_src, src, chunk); - for (i = 0; i < n_src; i++) + channelmix_process(&this->mix, dst, src, chunk); + for (i = 0; i < this->mix.src_chan; i++) si += chunk; - for (i = 0; i < n_dst; i++) + for (i = 0; i < this->mix.dst_chan; i++) di += chunk; avail_samples -= chunk; @@ -1352,7 +1409,7 @@ * remaining samples */ spa_log_trace_fp(this->log, "%p: remain %d", this, avail_samples); if (avail_samples > 0) - channelmix_process(&this->mix, n_dst, dst, n_src, src, avail_samples); + channelmix_process(&this->mix, dst, src, avail_samples); return 1; } @@ -1444,14 +1501,14 @@ if (!is_passthrough) { if (ctrlport->ctrl != NULL) { /* if return value is 1, the sequence has been processed */ - if (channelmix_process_control(this, ctrlport, n_dst_datas, dst_datas, - n_src_datas, src_datas, n_samples) == 1) { + if (channelmix_process_control(this, ctrlport, dst_datas, + src_datas, n_samples) == 1) { ctrlio->status = SPA_STATUS_OK; ctrlport->ctrl = NULL; } } else { - channelmix_process(&this->mix, n_dst_datas, dst_datas, - n_src_datas, src_datas, n_samples); + channelmix_process(&this->mix, dst_datas, + src_datas, n_samples); } } } @@ -1571,6 +1628,8 @@ props_reset(&this->props); this->mix.options = CHANNELMIX_OPTION_NORMALIZE; + this->mix.log = this->log; + this->mix.rear_delay = 12.0f; for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; @@ -1579,6 +1638,12 @@ this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s)); else if (spa_streq(k, "clock.quantum-limit")) spa_atou32(s, &this->quantum_limit, 0); + else if (spa_streq(k, "factory.mode")) { + if (spa_streq(s, "merge")) + this->direction = SPA_DIRECTION_OUTPUT; + else + this->direction = SPA_DIRECTION_INPUT; + } else channelmix_set_param(this, k, s);
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/crossover.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/crossover.c
Changed
@@ -5,6 +5,9 @@ #include "config.h" +#include <float.h> +#include <string.h> + #include "crossover.h" void lr4_set(struct lr4 *lr4, enum biquad_type type, float freq) @@ -16,9 +19,10 @@ lr4->y2 = 0; lr4->z1 = 0; lr4->z2 = 0; + lr4->active = true; } -void lr4_process(struct lr4 *lr4, float *data, int samples) +void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples) { float lx1 = lr4->x1; float lx2 = lr4->x2; @@ -31,11 +35,22 @@ float lb2 = lr4->bq.b2; float la1 = lr4->bq.a1; float la2 = lr4->bq.a2; - int i; + + if (vol == 0.0f) { + memset(dst, 0, samples * sizeof(float)); + return; + } else if (!lr4->active) { + if (src != dst || vol != 1.0f) { + for (i = 0; i < samples; i++) + dsti = srci * vol; + } + return; + } + for (i = 0; i < samples; i++) { float x, y, z; - x = datai; + x = srci; y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2; z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2; lx2 = lx1; @@ -44,13 +59,14 @@ ly1 = y; lz2 = lz1; lz1 = z; - datai = z; + dsti = z * vol; } - - lr4->x1 = lx1; - lr4->x2 = lx2; - lr4->y1 = ly1; - lr4->y2 = ly2; - lr4->z1 = lz1; - lr4->z2 = lz2; +#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x)) + lr4->x1 = F(lx1); + lr4->x2 = F(lx2); + lr4->y1 = F(ly1); + lr4->y2 = F(ly2); + lr4->z1 = F(lz1); + lr4->z2 = F(lz2); +#undef F }
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/crossover.h -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/crossover.h
Changed
@@ -6,6 +6,8 @@ #ifndef CROSSOVER_H_ #define CROSSOVER_H_ +#include <stdbool.h> + #include "biquad.h" /* An LR4 filter is two biquads with the same parameters connected in series: * @@ -19,10 +21,11 @@ float x1, x2; float y1, y2; float z1, z2; + bool active; }; void lr4_set(struct lr4 *lr4, enum biquad_type type, float freq); -void lr4_process(struct lr4 *lr4, float *data, int samples); +void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples); #endif /* CROSSOVER_H_ */
View file
pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/delay.h
Added
@@ -0,0 +1,72 @@ +/* Spa + * + * Copyright © 2022 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef DELAY_H +#define DELAY_H + +#ifdef __cplusplus +extern "C" { +#endif + +static inline void delay_run(float *buffer, uint32_t *pos, + uint32_t n_buffer, uint32_t delay, + float *dst, const float *src, const float vol, uint32_t n_samples) +{ + uint32_t i; + uint32_t p = *pos; + + for (i = 0; i < n_samples; i++) { + bufferp = srci; + dsti = buffer(p - delay) & (n_buffer-1) * vol; + p = (p + 1) & (n_buffer-1); + } + *pos = p; +} + +static inline void delay_convolve_run(float *buffer, uint32_t *pos, + uint32_t n_buffer, uint32_t delay, + const float *taps, uint32_t n_taps, + float *dst, const float *src, const float vol, uint32_t n_samples) +{ + uint32_t i, j; + uint32_t p = *pos; + + for (i = 0; i < n_samples; i++) { + float sum = 0.0f; + + bufferp = srci; + for (j = 0; j < n_taps; j++) + sum += (tapsj * buffer((p - delay) - j) & (n_buffer-1)); + dsti = sum * vol; + + p = (p + 1) & (n_buffer-1); + } + *pos = p; +} + +#ifdef __cplusplus +} +#endif + +#endif /* DELAY_H */
View file
pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/hilbert.h
Added
@@ -0,0 +1,69 @@ +/* Hilbert function + * + * Copyright © 2021 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef HILBERT_H +#define HILBERT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <errno.h> +#include <stddef.h> +#include <math.h> + +static inline void blackman_window(float *taps, int n_taps) +{ + int n; + for (n = 0; n < n_taps; n++) { + float w = 2 * M_PI * n / (n_taps-1); + tapsn = 0.3635819 - 0.4891775 * cos(w) + + 0.1365995 * cos(2 * w) - 0.0106411 * cos(3 * w); + } +} + +static inline int hilbert_generate(float *taps, int n_taps) +{ + int i; + + if ((n_taps & 1) == 0) + return -EINVAL; + + for (i = 0; i < n_taps; i++) { + int k = -(n_taps / 2) + i; + if (k & 1) { + float pk = M_PI * k; + tapsi *= (1.0f - cosf(pk)) / pk; + } else { + tapsi = 0.0f; + } + } + return 0; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* HILBERT_H */
View file
pipewire-0.3.47.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.48.tar.gz/spa/plugins/audioconvert/merger.c
Changed
@@ -386,10 +386,13 @@ case SPA_PARAM_Props: { +#if 0 struct props *p = &this->props; struct spa_pod_frame f2; +#endif switch (result.index) { +#if 0 case 0: spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_Props, id); @@ -422,6 +425,7 @@ spa_pod_builder_pop(&b, &f1); param = spa_pod_builder_pop(&b, &f0); break; +#endif default: return 0; }
View file
pipewire-0.3.47.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.48.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -1469,9 +1469,17 @@ dbus_message_iter_get_basic(&iter, &uuid); profile = spa_bt_profile_from_uuid(uuid); - if (profile && (device->profiles & profile) == 0) { - spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid); - device->profiles |= profile; + + /* Only add A2DP profiles if HSP/HFP backed is none. + * This allows BT device to connect instantly instead of waiting for + * profile timeout, because all available profiles are connected. + */ + if (monitor->backend_selection != BACKEND_NONE || (monitor->backend_selection == BACKEND_NONE && + profile & (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_A2DP_SOURCE))) { + if (profile && (device->profiles & profile) == 0) { + spa_log_debug(monitor->log, "device %p: add UUID=%s", device, uuid); + device->profiles |= profile; + } } dbus_message_iter_next(&iter); }
View file
pipewire-0.3.47.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.48.tar.gz/spa/plugins/support/loop.c
Changed
@@ -75,6 +75,7 @@ struct spa_system *system; struct spa_list source_list; + struct spa_list destroy_list; struct spa_hook_list hooks_list; int poll_fd; @@ -325,6 +326,14 @@ impl->thread = 0; } +static inline void process_destroy(struct impl *impl) +{ + struct source_impl *source, *tmp; + spa_list_for_each_safe(source, tmp, &impl->destroy_list, link) + free(source); + spa_list_init(&impl->destroy_list); +} + static int loop_iterate(void *object, int timeout) { struct impl *impl = object; @@ -354,11 +363,14 @@ } for (i = 0; i < nfds; i++) { struct spa_source *s = epi.data; - if (SPA_LIKELY(s && s->rmask)) { + if (SPA_LIKELY(s && s->rmask && s->loop)) { s->priv = NULL; s->func(s); } } + if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list))) + process_destroy(impl); + return nfds; } @@ -712,7 +724,7 @@ spa_system_close(impl->impl->system, source->fd); source->fd = -1; } - free(source); + spa_list_insert(&impl->impl->destroy_list, &impl->link); } static const struct spa_loop_methods impl_loop = { @@ -783,6 +795,8 @@ spa_list_consume(source, &impl->source_list, link) loop_destroy_source(impl, &source->source); + process_destroy(impl); + spa_system_close(impl->system, impl->ack_fd); spa_system_close(impl->system, impl->poll_fd); @@ -844,6 +858,7 @@ impl->poll_fd = res; spa_list_init(&impl->source_list); + spa_list_init(&impl->destroy_list); spa_hook_list_init(&impl->hooks_list); impl->buffer_data = SPA_PTR_ALIGN(impl->buffer_mem, MAX_ALIGN, uint8_t);
View file
pipewire-0.3.47.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -85,4 +85,8 @@ #channelmix.mix-lfe = true #channelmix.upmix = false #channelmix.lfe-cutoff = 0 + #channelmix.fc-cutoff = 0 + #channelmix.rear-delay = 12.0 + #channelmix.stereo-widen = 0.0 + #channelmix.hilbert-taps = 0 }
View file
pipewire-0.3.47.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/client.conf.in
Changed
@@ -75,4 +75,8 @@ #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0 + #channelmix.fc-cutoff = 0 + #channelmix.rear-delay = 12.0 + #channelmix.stereo-widen = 0.0 + #channelmix.hilbert-taps = 0 }
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/demonic.conf
Changed
@@ -46,8 +46,7 @@ #audio.format = F32 #audio.rate = 48000 audio.channels = 2 - #audio.position = FL FR - node.name = "filter-chain-demonic" + audio.position = FL FR node.description = "Demonic example" media.name = "Demonic example" filter.graph = { @@ -89,9 +88,11 @@ outputs = "rev2:Out L" } capture.props = { + node.name = "effect_input.filter-chain-demonic" #media.class = Audio/Sink } playback.props = { + node.name = "effect_output.filter-chain-demonic" #media.class = Audio/Source } }
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/duplicate-FL.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/duplicate-FL.conf
Changed
@@ -6,7 +6,6 @@ context.modules = { name = libpipewire-module-filter-chain args = { - node.name = "remap-FL-to-FL-FR" node.description = "Remap example" media.name = "Remap example" filter.graph = { @@ -37,10 +36,12 @@ outputs = "copyOL:Out" "copyOR:Out" } capture.props = { + node.name = "remap_input.remap-FL-to-FL-FR" audio.position = FL stream.dont-remix = true } playback.props = { + node.name = "remap_output.remap-FL-to-FL-FR" audio.position = FL FR } }
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf
Changed
@@ -26,7 +26,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_output.dolby_surround" node.description = "Dolby Surround Sink" media.name = "Dolby Surround Sink" filter.graph = { @@ -51,11 +50,13 @@ outputs = "enc:Lt" "enc:Rt" } capture.props = { + node.name = "effect_input.dolby_surround" media.class = Audio/Sink audio.channels = 6 audio.position = FL FR FC LFE SL SR } playback.props = { + node.name = "effect_output.dolby_surround" node.passive = true audio.channels = 2 audio.position = FL FR
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-eq6.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-eq6.conf
Changed
@@ -26,7 +26,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_output.eq6" node.description = "Equalizer Sink" media.name = "Equalizer Sink" filter.graph = { @@ -77,9 +76,11 @@ } capture.props = { + node.name = "effect_input.eq6" media.class = Audio/Sink } playback.props = { + node.name = "effect_output.eq6" node.passive = true } }
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf
Changed
@@ -27,7 +27,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_output.matrix_spatialiser" node.description = "Matrix Spatialiser" media.name = "Matrix Spatialiser" filter.graph = { @@ -45,16 +44,15 @@ inputs = "matrix:Input L" "matrix:Input R" outputs = "matrix:Output L" "matrix:Output R" } + audio.channels = 2 + audio.position = FL FR capture.props = { + node.name = "effect_input.matrix_spatialiser" media.class = Audio/Sink - audio.channels = 2 - audio.position = FL FR } playback.props = { - #media.class = Audio/Source - #node.passive = true - audio.channels = 2 - audio.position = FL FR + node.name = "effect_output.matrix_spatialiser" + node.passive = true } } }
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf
Changed
@@ -26,7 +26,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_output.virtual-surround-5.1-kemar" node.description = "Virtual Surround Sink" media.name = "Virtual Surround Sink" filter.graph = { @@ -182,11 +181,13 @@ } capture.props = { + node.name = "effect_input.virtual-surround-5.1-kemar" media.class = Audio/Sink audio.channels = 6 audio.position = FL FR FC LFE SL SR } playback.props = { + node.name = "effect_output.virtual-surround-5.1-kemar" node.passive = true audio.channels = 2 audio.position = FL FR
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf
Changed
@@ -26,7 +26,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_output.virtual-surround-7.1-hesuvi" node.description = "Virtual Surround Sink" media.name = "Virtual Surround Sink" filter.graph = { @@ -106,11 +105,13 @@ outputs = "mixL:Out" "mixR:Out" } capture.props = { + node.name = "effect_input.virtual-surround-7.1-hesuvi" media.class = Audio/Sink audio.channels = 8 audio.position = FL FR FC LFE RL RR SL SR } playback.props = { + node.name = "effect_output.virtual-surround-7.1-hesuvi" node.passive = true audio.channels = 2 audio.position = FL FR
View file
pipewire-0.3.47.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.48.tar.gz/src/daemon/filter-chain/source-rnnoise.conf
Changed
@@ -26,7 +26,6 @@ { name = libpipewire-module-filter-chain args = { - node.name = "effect_input.rnnoise" node.description = "Noise Canceling source" media.name = "Noise Canceling source" filter.graph = { @@ -42,10 +41,13 @@ } } + audio.position = FL FR capture.props = { + node.name = "effect_input.rnnoise" node.passive = true } playback.props = { + node.name = "effect_output.rnnoise" media.class = Audio/Source } }
View file
pipewire-0.3.47.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/minimal.conf.in
Changed
@@ -20,7 +20,7 @@ #mem.mlock-all = false #clock.power-of-two-quantum = true #log.level = 2 - #cpu.zero.denormals = true + #cpu.zero.denormals = false core.daemon = true # listening for socket connections core.name = pipewire-0 # core name and socket name @@ -206,6 +206,10 @@ #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0 + #channelmix.fc-cutoff = 0 + #channelmix.rear-delay = 12.0 + #channelmix.stereo-widen = 0.0 + #channelmix.hilbert-taps = 0 channelmix.disable = true #node.param.Props = { # params = @@ -261,6 +265,10 @@ #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0 + #channelmix.fc-cutoff = 0 + #channelmix.rear-delay = 12.0 + #channelmix.stereo-widen = 0.0 + #channelmix.hilbert-taps = 0 channelmix.disable = true #node.param.Props = { # params = @@ -286,6 +294,42 @@ #} } } + # This creates a new Source node. It will have input ports + # that you can link, to provide audio for this source. + #{ factory = adapter + # args = { + # factory.name = support.null-audio-sink + # node.name = "my-mic" + # node.description = "Microphone" + # media.class = "Audio/Source/Virtual" + # audio.position = "FL,FR" + # adapter.auto-port-config = { + # mode = dsp + # monitor = true + # position = preserve # unknown, aux, preserve + # } + # } + #} + # This creates a new link between the source and the virtual + # source ports. + #{ factory = link-factory + # args = { + # link.output.node = system + # link.output.port = capture_1 + # link.input.node = my-mic + # link.input.port = input_FL + # link.passive = true + # } + #} + #{ factory = link-factory + # args = { + # link.output.node = system + # link.output.port = capture_2 + # link.input.node = my-mic + # link.input.port = input_FR + # link.passive = true + # } + #} context.exec =
View file
pipewire-0.3.47.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -85,6 +85,10 @@ #channelmix.mix-lfe = false #channelmix.upmix = false #channelmix.lfe-cutoff = 0 + #channelmix.fc-cutoff = 0 + #channelmix.rear-delay = 12.0 + #channelmix.stereo-widen = 0.0 + #channelmix.hilbert-taps = 0 } # client/stream specific properties
View file
pipewire-0.3.47.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.48.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -20,7 +20,7 @@ #mem.mlock-all = false #clock.power-of-two-quantum = true #log.level = 2 - #cpu.zero.denormals = true + #cpu.zero.denormals = false core.daemon = true # listening for socket connections core.name = pipewire-0 # core name and socket name
View file
pipewire-0.3.47.tar.gz/src/modules/meson.build -> pipewire-0.3.48.tar.gz/src/modules/meson.build
Changed
@@ -197,6 +197,7 @@ 'module-protocol-native/portal-screencast.c', 'module-protocol-native/protocol-native.c', 'module-protocol-native/v0/protocol-native.c', + 'module-protocol-native/protocol-footer.c', 'module-protocol-native/connection.c' , include_directories : configinc, install : true, @@ -489,7 +490,7 @@ install : true, install_dir : modules_install_dir, install_rpath: modules_install_dir, - dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, canberra_dep, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, x11_dep, xfixes_dep, canberra_dep, ) endif summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules')
View file
pipewire-0.3.47.tar.gz/src/modules/module-client-device/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-device/protocol-native.c
Changed
@@ -32,7 +32,7 @@ #include <pipewire/extensions/protocol-native.h> -#define MAX_DICT 256 +#define MAX_DICT 1024 #define MAX_PARAM_INFO 128 static inline void push_item(struct spa_pod_builder *b, const struct spa_dict_item *item)
View file
pipewire-0.3.47.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -33,6 +33,7 @@ #include <spa/node/node.h> #include <spa/node/utils.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/pod/parser.h> #include <spa/debug/types.h> @@ -293,7 +294,7 @@ { struct node *this = object; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; bool found = false; @@ -321,14 +322,15 @@ if (result.index < start) continue; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, param, filter) != 0) - continue; - - pw_log_debug("%p: %d param %u", this, seq, result.index); - spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) { + pw_log_debug("%p: %d param %u", this, seq, result.index); + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == num) + if (count == num) break; } return found ? 0 : -ENOENT; @@ -563,7 +565,7 @@ struct node *this = object; struct port *port; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; bool found = false; @@ -597,14 +599,15 @@ if (result.index < start) continue; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, param, filter) < 0) - continue; - - pw_log_debug("%p: %d param %u", this, seq, result.index); - spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) { + pw_log_debug("%p: %d param %u", this, seq, result.index); + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == num) + if (count == num) break; } return found ? 0 : -ENOENT;
View file
pipewire-0.3.47.tar.gz/src/modules/module-client-node/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/protocol-native.c
Changed
@@ -33,8 +33,8 @@ #include <pipewire/extensions/protocol-native.h> #include <pipewire/extensions/client-node.h> -#define MAX_DICT 256 -#define MAX_PARAMS 128 +#define MAX_DICT 1024 +#define MAX_PARAMS 4096 #define MAX_PARAM_INFO 128 #define MAX_BUFFERS 64 #define MAX_METAS 16u
View file
pipewire-0.3.47.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.48.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -31,6 +31,7 @@ #include <sys/mman.h> #include <spa/pod/parser.h> +#include <spa/pod/dynamic.h> #include <spa/node/utils.h> #include <spa/utils/result.h> #include <spa/debug/types.h> @@ -301,7 +302,7 @@ if (change_mask & PW_CLIENT_NODE_UPDATE_PARAMS) { uint32_t i, idx, id; uint8_t buf4096; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; for (i = 0; i < node->info.n_params; i++) { struct spa_pod *param; @@ -311,14 +312,17 @@ continue; for (idx = 0;;) { - spa_pod_builder_init(&b, buf, sizeof(buf)); - if (spa_node_enum_params_sync(node->node, - id, &idx, - NULL, ¶m, &b) != 1) - break; + spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 4096); - params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1)); - paramsn_params++ = spa_pod_copy(param); + res = spa_node_enum_params_sync(node->node, + id, &idx, NULL, ¶m, &b.b); + if (res == 1) { + params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1)); + paramsn_params++ = spa_pod_copy(param); + } + spa_pod_dynamic_builder_clean(&b); + if (res != 1) + break; } } } @@ -356,7 +360,7 @@ if (change_mask & PW_CLIENT_NODE_PORT_UPDATE_PARAMS) { uint32_t i, idx, id; uint8_t buf4096; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; for (i = 0; i < port->info.n_params; i++) { struct spa_pod *param; @@ -366,15 +370,20 @@ continue; for (idx = 0;;) { - spa_pod_builder_init(&b, buf, sizeof(buf)); - if (spa_node_port_enum_params_sync(port->node->node, + spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 4096); + + res = spa_node_port_enum_params_sync(port->node->node, port->direction, port->port_id, - id, &idx, - NULL, ¶m, &b) != 1) + id, &idx, NULL, ¶m, &b.b); + if (res == 1) { + params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1)); + paramsn_params++ = spa_pod_copy(param); + } + spa_pod_dynamic_builder_clean(&b); + + if (res != 1) break; - params = realloc(params, sizeof(struct spa_pod *) * (n_params + 1)); - paramsn_params++ = spa_pod_copy(param); } } }
View file
pipewire-0.3.47.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.48.tar.gz/src/modules/module-echo-cancel.c
Changed
@@ -151,7 +151,6 @@ struct pw_context *context; struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; uint32_t id; @@ -194,7 +193,6 @@ unsigned int sink_ready:1; unsigned int do_disconnect:1; - unsigned int unloading:1; uint32_t max_buffer_size; uint32_t buffer_delay; @@ -203,19 +201,6 @@ struct spa_plugin_loader *loader; }; -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static void process(struct impl *impl) { struct pw_buffer *cout; @@ -774,7 +759,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_core_events core_events = { @@ -787,7 +772,7 @@ struct impl *impl = d; spa_hook_remove(&impl->core_listener); impl->core = NULL; - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_proxy_events core_proxy_events = { @@ -812,9 +797,6 @@ pw_properties_free(impl->source_props); pw_properties_free(impl->sink_props); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); - for (i = 0; i < impl->info.channels; i++) { if (impl->rec_bufferi) free(impl->rec_bufferi); @@ -830,7 +812,6 @@ static void module_destroy(void *data) { struct impl *impl = data; - impl->unloading = true; spa_hook_remove(&impl->module_listener); impl_destroy(impl); } @@ -931,12 +912,6 @@ impl->id = id; impl->module = module; impl->context = context; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't create work queue: %m"); - goto error; - } if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) pw_properties_setf(props, PW_KEY_NODE_GROUP, "echo-cancel-%u", id); @@ -1020,14 +995,16 @@ else aec_props = pw_properties_new(NULL, NULL); - if (spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info)) { - pw_log_error("codec plugin %s create failed", impl->aec->name); - res = -ENOENT; - goto error; - } + res = spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info); pw_properties_free(aec_props); + if (res < 0) { + pw_log_error("codec plugin %s create failed: %s", impl->aec->name, + spa_strerror(res)); + goto error; + } + if (impl->aec->latency) { unsigned int num, denom, req_num, req_denom; unsigned int factor = 0;
View file
pipewire-0.3.47.tar.gz/src/modules/module-example-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-example-sink.c
Changed
@@ -399,11 +399,6 @@ impl->module = module; impl->context = context; impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto error; - } if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
View file
pipewire-0.3.47.tar.gz/src/modules/module-example-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-example-source.c
Changed
@@ -419,11 +419,6 @@ impl->module = module; impl->context = context; impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto error; - } if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
View file
pipewire-0.3.47.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.48.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -39,6 +39,7 @@ #include <spa/utils/string.h> #include <spa/utils/json.h> #include <spa/param/profiler.h> +#include <spa/pod/dynamic.h> #include <spa/debug/pod.h> #include <pipewire/utils.h> @@ -107,8 +108,6 @@ #include <pipewire/pipewire.h> #define MAX_HNDL 64 -#define MAX_PORTS 64 -#define MAX_CONTROLS 256 #define MAX_SAMPLES 8192 static float silence_dataMAX_SAMPLES; @@ -136,11 +135,11 @@ uint32_t n_output; uint32_t n_control; uint32_t n_notify; - unsigned long inputMAX_PORTS; - unsigned long outputMAX_PORTS; - unsigned long controlMAX_PORTS; - unsigned long notifyMAX_PORTS; - float default_controlMAX_PORTS; + unsigned long *input; + unsigned long *output; + unsigned long *control; + unsigned long *notify; + float *default_control; }; struct port { @@ -167,10 +166,10 @@ char name256; char *config; - struct port input_portMAX_PORTS; - struct port output_portMAX_PORTS; - struct port control_portMAX_PORTS; - struct port notify_portMAX_PORTS; + struct port *input_port; + struct port *output_port; + struct port *control_port; + struct port *notify_port; uint32_t n_hndl; void *hndlMAX_HNDL; @@ -207,23 +206,22 @@ struct spa_list link_list; uint32_t n_input; - struct graph_port inputMAX_PORTS; + struct graph_port *input; uint32_t n_output; - struct graph_port outputMAX_PORTS; + struct graph_port *output; uint32_t n_hndl; - struct graph_hndl hndlMAX_HNDL; + struct graph_hndl *hndl; uint32_t n_control; - struct port *control_portMAX_CONTROLS; + struct port **control_port; }; struct impl { struct pw_context *context; struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; @@ -244,26 +242,12 @@ struct spa_audio_info_raw playback_info; unsigned int do_disconnect:1; - unsigned int unloading:1; long unsigned rate; struct graph graph; }; -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static void capture_destroy(void *d) { struct impl *impl = d; @@ -628,26 +612,13 @@ .param_changed = param_changed }; -static int builder_overflow(void *data, uint32_t size) -{ - struct spa_pod_builder *b = data; - b->size = SPA_ROUND_UP_N(size, 4096); - if ((b->data = realloc(b->data, b->size)) == NULL) - return -errno; - return 0; -} - -static const struct spa_pod_builder_callbacks builder_callbacks = { - SPA_VERSION_POD_BUILDER_CALLBACKS, - .overflow = builder_overflow -}; - static int setup_streams(struct impl *impl) { int res; uint32_t i, n_params; - const struct spa_pod *params256; - struct spa_pod_builder b; + uint32_t offsets512; + const struct spa_pod *params512; + struct spa_pod_dynamic_builder b; struct graph *graph = &impl->graph; impl->capture = pw_stream_new(impl->core, @@ -671,16 +642,22 @@ &out_stream_events, impl); n_params = 0; - spa_pod_builder_init(&b, NULL, 0); - spa_pod_builder_set_callbacks(&b, &builder_callbacks, &b); + spa_pod_dynamic_builder_init(&b, NULL, 0, 4096); - paramsn_params++ = spa_format_audio_raw_build(&b, + offsetsn_params++ = b.b.state.offset; + spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->capture_info); - for (i = 0; i < graph->n_control; i++) - paramsn_params++ = get_prop_info(graph, &b, i); + for (i = 0; i < graph->n_control; i++) { + offsetsn_params++ = b.b.state.offset; + get_prop_info(graph, &b.b, i); + } - paramsn_params++ = get_props_param(graph, &b); + offsetsn_params++ = b.b.state.offset; + get_props_param(graph, &b.b); + + for (i = 0; i < n_params; i++) + paramsi = spa_pod_builder_deref(&b.b, offsetsi); res = pw_stream_connect(impl->capture, PW_DIRECTION_INPUT, @@ -689,14 +666,14 @@ PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS, params, n_params); - free(b.data); + + spa_pod_dynamic_builder_clean(&b); if (res < 0) return res; n_params = 0; - spa_pod_builder_init(&b, NULL, 0); - spa_pod_builder_set_callbacks(&b, &builder_callbacks, &b); - paramsn_params++ = spa_format_audio_raw_build(&b, + spa_pod_dynamic_builder_init(&b, NULL, 0, 4096); + paramsn_params++ = spa_format_audio_raw_build(&b.b, SPA_PARAM_EnumFormat, &impl->playback_info); res = pw_stream_connect(impl->playback, @@ -707,7 +684,7 @@ PW_STREAM_FLAG_RT_PROCESS | PW_STREAM_FLAG_TRIGGER, params, n_params); - free(b.data); + spa_pod_dynamic_builder_clean(&b); if (res < 0) return res; @@ -741,7 +718,6 @@ { struct fc_plugin *pl = NULL; struct plugin *hndl; - int res = 0; const struct spa_support *support; uint32_t n_support; @@ -765,6 +741,11 @@ pl = load_lv2_plugin(support, n_support, path, NULL); } #endif + else { + pl = NULL; + errno = EINVAL; + } + if (pl == NULL) goto exit; @@ -784,9 +765,7 @@ spa_list_append(&impl->plugin_list, &hndl->link); return hndl; - exit: - errno = -res; return NULL; } @@ -797,6 +776,11 @@ spa_list_remove(&desc->link); plugin_unref(desc->plugin); + free(desc->input); + free(desc->output); + free(desc->control); + free(desc->default_control); + free(desc->notify); free(desc); } @@ -806,7 +790,7 @@ struct plugin *hndl; struct descriptor *desc; const struct fc_descriptor *d; - uint32_t i; + uint32_t i, n_input, n_output, n_control, n_notify; unsigned long p; int res; @@ -832,6 +816,7 @@ desc = calloc(1, sizeof(*desc)); desc->ref = 1; desc->plugin = hndl; + spa_list_init(&desc->link); if ((d = hndl->plugin->make_desc(hndl->plugin, label)) == NULL) { pw_log_error("cannot find label %s", label); @@ -841,6 +826,27 @@ desc->desc = d; snprintf(desc->label, sizeof(desc->label), "%s", label); + n_input = n_output = n_control = n_notify = 0; + for (p = 0; p < d->n_ports; p++) { + struct fc_port *fp = &d->portsp; + if (FC_IS_PORT_AUDIO(fp->flags)) { + if (FC_IS_PORT_INPUT(fp->flags)) + n_input++; + else if (FC_IS_PORT_OUTPUT(fp->flags)) + n_output++; + } else if (FC_IS_PORT_CONTROL(fp->flags)) { + if (FC_IS_PORT_INPUT(fp->flags)) + n_control++; + else if (FC_IS_PORT_OUTPUT(fp->flags)) + n_notify++; + } + } + desc->input = calloc(n_input, sizeof(unsigned long)); + desc->output = calloc(n_output, sizeof(unsigned long)); + desc->control = calloc(n_control, sizeof(unsigned long)); + desc->default_control = calloc(n_control, sizeof(float)); + desc->notify = calloc(n_notify, sizeof(unsigned long)); + for (p = 0; p < d->n_ports; p++) { struct fc_port *fp = &d->portsp; @@ -884,9 +890,7 @@ return desc; exit: - if (hndl != NULL) - plugin_unref(hndl); - free(desc); + descriptor_unref(desc); errno = -res; return NULL; } @@ -1095,6 +1099,11 @@ node->desc = desc; snprintf(node->name, sizeof(node->name), "%s", name); + node->input_port = calloc(desc->n_input, sizeof(struct port)); + node->output_port = calloc(desc->n_output, sizeof(struct port)); + node->control_port = calloc(desc->n_control, sizeof(struct port)); + node->notify_port = calloc(desc->n_notify, sizeof(struct port)); + for (i = 0; i < desc->n_input; i++) { struct port *port = &node->input_porti; port->node = node; @@ -1154,6 +1163,10 @@ d->cleanup(node->hndli); } descriptor_unref(node->desc); + free(node->input_port); + free(node->output_port); + free(node->control_port); + free(node->notify_port); free(node); } @@ -1221,16 +1234,13 @@ struct port *port; struct graph_port *gp; struct graph_hndl *gh; - uint32_t i, j, n_input, n_output, n_hndl = 0; + uint32_t i, j, n_nodes, n_input, n_output, n_control, n_hndl = 0; int res; unsigned long p; struct descriptor *desc; const struct fc_descriptor *d; char v256; - graph->n_input = 0; - graph->n_output = 0; - first = spa_list_first(&graph->node_list, struct node, link); last = spa_list_last(&graph->node_list, struct node, link); @@ -1272,11 +1282,16 @@ res = -EINVAL; goto error; } + if (n_hndl > MAX_HNDL) { + pw_log_error("too many channels"); + res = -EINVAL; + goto error; + } pw_log_info("using %d instances %d %d", n_hndl, n_input, n_output); - /* now go over all nodes and create instances. We can also link - * the control and notify ports already */ - graph->n_control = 0; + /* now go over all nodes and create instances. */ + n_control = 0; + n_nodes = 0; spa_list_for_each(node, &graph->node_list, link) { float *sd = silence_data, *dd = discard_data; @@ -1313,11 +1328,8 @@ if (d->activate) d->activate(node->hndli); } - /* collect all control ports on the graph */ - for (j = 0; j < desc->n_control; j++) { - graph->control_portgraph->n_control = &node->control_portj; - graph->n_control++; - } + n_control += desc->n_control; + n_nodes++; } pw_log_info("suggested rate:%lu capture:%d playback:%d", impl->rate, impl->capture_info.rate, impl->playback_info.rate); @@ -1327,6 +1339,11 @@ if (impl->playback_info.rate == 0) impl->playback_info.rate = impl->rate; + graph->n_input = 0; + graph->input = calloc(n_input * n_hndl, sizeof(struct graph_port)); + graph->n_output = 0; + graph->output = calloc(n_output * n_hndl, sizeof(struct graph_port)); + /* now collect all input and output ports for all the handles. */ for (i = 0; i < n_hndl; i++) { if (inputs == NULL) { @@ -1429,6 +1446,9 @@ /* order all nodes based on dependencies */ graph->n_hndl = 0; + graph->hndl = calloc(n_nodes * n_hndl, sizeof(struct graph_hndl)); + graph->n_control = 0; + graph->control_port = calloc(n_control, sizeof(struct port *)); while (true) { if ((node = find_next_node(graph)) == NULL) break; @@ -1447,6 +1467,12 @@ for (i = 0; i < desc->n_output; i++) setup_output_port(graph, &node->output_porti); + + /* collect all control ports on the graph */ + for (i = 0; i < desc->n_control; i++) { + graph->control_portgraph->n_control = &node->control_porti; + graph->n_control++; + } } return 0; @@ -1539,6 +1565,10 @@ link_free(link); spa_list_consume(node, &graph->node_list, link) node_free(node); + free(graph->input); + free(graph->output); + free(graph->hndl); + free(graph->control_port); } static void core_error(void *data, uint32_t id, int seq, int res, const char *message) @@ -1549,7 +1579,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_core_events core_events = { @@ -1562,7 +1592,7 @@ struct impl *impl = d; spa_hook_remove(&impl->core_listener); impl->core = NULL; - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_proxy_events core_proxy_events = { @@ -1579,8 +1609,6 @@ pw_core_disconnect(impl->core); pw_properties_free(impl->capture_props); pw_properties_free(impl->playback_props); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); graph_free(&impl->graph); free(impl); } @@ -1588,7 +1616,6 @@ static void module_destroy(void *data) { struct impl *impl = data; - impl->unloading = true; spa_hook_remove(&impl->module_listener); impl_destroy(impl); } @@ -1688,12 +1715,7 @@ impl->module = module; impl->context = context; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't create work queue: %m"); - goto error; - } + impl->rate = 48000; impl->graph.impl = impl; spa_list_init(&impl->plugin_list);
View file
pipewire-0.3.47.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.48.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
@@ -24,6 +24,7 @@ #include "config.h" +#include <float.h> #include <math.h> #ifdef HAVE_SNDFILE #include <sndfile.h> @@ -303,10 +304,12 @@ y2 = y1; y1 = y; } - bq->x1 = x1; - bq->x2 = x2; - bq->y1 = y1; - bq->y2 = y2; +#define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x)) + bq->x1 = F(x1); + bq->x2 = F(x2); + bq->y1 = F(y1); + bq->y2 = F(y2); +#undef F } /** bq_lowpass */
View file
pipewire-0.3.47.tar.gz/src/modules/module-link-factory.c -> pipewire-0.3.48.tar.gz/src/modules/module-link-factory.c
Changed
@@ -510,7 +510,6 @@ struct pw_context *context = pw_impl_module_get_context(module); struct pw_impl_factory *factory; struct factory_data *data; - int res; PW_LOG_TOPIC_INIT(mod_topic); @@ -530,12 +529,6 @@ data->module = module; data->context = context; data->work = pw_context_get_work_queue(context); - if (data->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - pw_impl_factory_destroy(factory); - return res; - } spa_list_init(&data->link_list);
View file
pipewire-0.3.47.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.48.tar.gz/src/modules/module-loopback.c
Changed
@@ -81,7 +81,6 @@ struct pw_context *context; struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; @@ -100,22 +99,8 @@ struct spa_audio_info_raw playback_info; unsigned int do_disconnect:1; - unsigned int unloading:1; }; -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static void capture_destroy(void *d) { struct impl *impl = d; @@ -312,7 +297,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_core_events core_events = { @@ -325,7 +310,7 @@ struct impl *impl = d; spa_hook_remove(&impl->core_listener); impl->core = NULL; - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_proxy_events core_proxy_events = { @@ -342,15 +327,12 @@ pw_core_disconnect(impl->core); pw_properties_free(impl->capture_props); pw_properties_free(impl->playback_props); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); free(impl); } static void module_destroy(void *data) { struct impl *impl = data; - impl->unloading = true; spa_hook_remove(&impl->module_listener); impl_destroy(impl); } @@ -447,12 +429,6 @@ impl->module = module; impl->context = context; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto error; - } if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) pw_properties_setf(props, PW_KEY_NODE_GROUP, "loopback-%u", id);
View file
pipewire-0.3.47.tar.gz/src/modules/module-metadata/metadata.c -> pipewire-0.3.48.tar.gz/src/modules/module-metadata/metadata.c
Changed
@@ -259,6 +259,15 @@ struct pw_properties *properties) { struct impl *impl; + char serial_str32; + struct spa_dict_item items1 = { + SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str), + }; + struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items); + static const char * const keys = { + PW_KEY_OBJECT_SERIAL, + NULL + }; if (properties == NULL) properties = pw_properties_new(NULL, NULL); @@ -285,6 +294,10 @@ impl->resource = resource; impl->metadata = (struct pw_metadata*)resource; + spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64, + pw_global_get_serial(impl->global)); + pw_global_update_keys(impl->global, &extra_props, keys); + pw_context_add_listener(context, &impl->context_listener, &context_events, impl);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -57,6 +57,7 @@ #include "modules/module-protocol-native/connection.h" #include "modules/module-protocol-native/defs.h" +#include "modules/module-protocol-native/protocol-footer.h" #define NAME "protocol-native" @@ -115,6 +116,8 @@ int ref; + struct footer_core_global_state footer_state; + unsigned int connected:1; unsigned int disconnecting:1; unsigned int need_flush:1; @@ -151,6 +154,8 @@ struct pw_protocol_native_connection *connection; struct spa_hook conn_listener; + struct footer_client_global_state footer_state; + unsigned int busy:1; unsigned int need_flush:1; @@ -164,7 +169,7 @@ "%s: id:%d op:%d size:%d seq:%d", prefix, msg->id, msg->opcode, msg->size, msg->seq); - if ((pod = spa_pod_from_data(msg->data, msg->size, 0, msg->size)) != NULL) + if ((pod = get_first_pod_from_data(msg->data, msg->size, 0)) != NULL) spa_debug_pod(0, NULL, pod); else hex = true; @@ -172,6 +177,49 @@ spa_debug_mem(0, msg->data, msg->size); } +static void pre_demarshal(struct pw_protocol_native_connection *conn, + const struct pw_protocol_native_message *msg, + void *object, const struct footer_demarshal *opcodes, size_t n_opcodes) +{ + struct spa_pod *footer = NULL; + struct spa_pod_parser parser; + struct spa_pod_frame f2; + uint32_t opcode; + int ret; + + footer = pw_protocol_native_connection_get_footer(conn, msg); + if (footer == NULL) + return; /* No valid footer. Ignore silently. */ + + /* + * Version 3 footer + * + * spa_pod Struct { Id opcode, Struct { ... }* } + */ + + spa_pod_parser_pod(&parser, footer); + if (spa_pod_parser_push_struct(&parser, &f0) < 0) { + pw_log_error("malformed message footer"); + return; + } + + while (1) { + if (spa_pod_parser_get_id(&parser, &opcode) < 0) + break; + if (spa_pod_parser_push_struct(&parser, &f1) < 0) + break; + if (opcode < n_opcodes) { + if ((ret = opcodesopcode.demarshal(object, &parser)) < 0) + pw_log_error("failed processing message footer (opcode %u): %d (%s)", + opcode, ret, spa_strerror(ret)); + } else { + /* Ignore (don't log errors), in case we need to extend this later. */ + pw_log_debug("unknown message footer opcode %u", opcode); + } + spa_pod_parser_pop(&parser, &f1); + } +} + static int process_messages(struct client_data *data) { @@ -213,6 +261,9 @@ if (debug_messages) debug_msg("<<<<<< in", msg, false); + pre_demarshal(conn, msg, client, footer_client_demarshal, + SPA_N_ELEMENTS(footer_client_demarshal)); + resource = pw_impl_client_find_resource(client, msg->id); if (resource == NULL) { pw_resource_errorf(client->core_resource, @@ -767,6 +818,9 @@ if (debug_messages) debug_msg("<<<<<< in", msg, false); + pre_demarshal(conn, msg, this, footer_core_demarshal, + SPA_N_ELEMENTS(footer_core_demarshal)); + proxy = pw_core_find_proxy(this, msg->id); if (proxy == NULL || proxy->zombie) { if (proxy == NULL) @@ -1225,11 +1279,25 @@ return pw_protocol_native_connection_get_fd(impl->connection, index); } +static void assert_single_pod(struct spa_pod_builder *builder) +{ + /* + * Check the invariant that the message we just marshaled + * consists of at most one POD. + */ + struct spa_pod *pod = builder->data; + spa_assert(builder->data == NULL || + builder->state.offset < sizeof(struct spa_pod) || + builder->state.offset == SPA_POD_SIZE(pod)); +} + static int impl_ext_end_proxy(struct pw_proxy *proxy, struct spa_pod_builder *builder) { struct pw_core *core = proxy->core; struct client *impl = SPA_CONTAINER_OF(core->conn, struct client, this); + assert_single_pod(builder); + marshal_core_footers(&impl->footer_state, core, builder); return core->send_seq = pw_protocol_native_connection_end(impl->connection, builder); } @@ -1257,6 +1325,8 @@ { struct client_data *data = resource->client->user_data; struct pw_impl_client *client = resource->client; + assert_single_pod(builder); + marshal_client_footers(&data->footer_state, client, builder); return client->send_seq = pw_protocol_native_connection_end(data->connection, builder); } static const struct pw_protocol_native_ext protocol_ext_impl = {
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/connection.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/connection.c
Changed
@@ -45,6 +45,7 @@ #include <spa/debug/pod.h> #include "connection.h" +#include "defs.h" #define MAX_BUFFER_SIZE (1024 * 32) #define MAX_FDS 1024u @@ -598,6 +599,38 @@ return 1; } +/** Get footer data from the tail of the current packet. + * + * \param conn the connection + * \param msg current message + * \return footer POD, or NULL if no valid footer present + * + * \memberof pw_protocol_native_connection + */ +struct spa_pod *pw_protocol_native_connection_get_footer(struct pw_protocol_native_connection *conn, + const struct pw_protocol_native_message *msg) +{ + struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this); + struct spa_pod *pod; + + if (impl->version != 3) + return NULL; + + /* + * Protocol version 3 footer: a single SPA POD + */ + + /* Footer immediately follows the message POD, if it is present */ + if ((pod = get_first_pod_from_data(msg->data, msg->size, 0)) == NULL) + return NULL; + pod = get_first_pod_from_data(msg->data, msg->size, SPA_POD_SIZE(pod)); + if (pod == NULL) + return NULL; + pw_log_trace("connection %p: recv message footer, size:%zu", + conn, (size_t)SPA_POD_SIZE(pod)); + return pod; +} + static inline void *begin_write(struct pw_protocol_native_connection *conn, uint32_t size) { struct impl *impl = SPA_CONTAINER_OF(conn, struct impl, this);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/connection.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/connection.h
Changed
@@ -102,6 +102,9 @@ void pw_protocol_native_connection_enter(struct pw_protocol_native_connection *conn); void pw_protocol_native_connection_leave(struct pw_protocol_native_connection *conn); +struct spa_pod *pw_protocol_native_connection_get_footer(struct pw_protocol_native_connection *conn, + const struct pw_protocol_native_message *msg); + #ifdef __cplusplus } /* extern "C" */ #endif
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/defs.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/defs.h
Changed
@@ -30,3 +30,14 @@ const struct spa_dict *props, void (*done_callback) (void *data, int res), void *data); + +static inline void *get_first_pod_from_data(void *data, size_t maxsize, off_t offset) +{ + void *pod; + if (offset + sizeof(struct spa_pod) > maxsize) + return NULL; + pod = SPA_PTROFF(data, offset, void); + if (offset + SPA_POD_SIZE(pod) > maxsize) + return NULL; + return pod; +}
View file
pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-footer.c
Added
@@ -0,0 +1,152 @@ +/* PipeWire + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <errno.h> + +#include <spa/pod/builder.h> +#include <spa/pod/parser.h> +#include <spa/utils/result.h> + +#include <pipewire/private.h> + +#include "connection.h" +#include "protocol-footer.h" +#include "defs.h" + +PW_LOG_TOPIC_EXTERN(mod_topic); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct footer_builder { + struct spa_pod_builder *builder; + struct spa_pod_frame outer; + struct spa_pod_frame inner; + unsigned int started:1; +}; + +#define FOOTER_BUILDER_INIT(builder) (struct footer_builder) { builder } + +static void start_footer_entry(struct footer_builder *fb, uint32_t opcode) +{ + if (!fb->started) { + spa_pod_builder_push_struct(fb->builder, &fb->outer); + fb->started = true; + } + + spa_pod_builder_id(fb->builder, opcode); + spa_pod_builder_push_struct(fb->builder, &fb->inner); +} + +static void end_footer_entry(struct footer_builder *fb) +{ + spa_pod_builder_pop(fb->builder, &fb->inner); +} + +static void end_footer(struct footer_builder *fb) +{ + if (!fb->started) + return; + + spa_pod_builder_pop(fb->builder, &fb->outer); +} + +void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core, + struct spa_pod_builder *builder) +{ + struct footer_builder fb = FOOTER_BUILDER_INIT(builder); + + if (core->recv_generation != state->last_recv_generation) { + state->last_recv_generation = core->recv_generation; + + pw_log_trace("core %p: send client registry generation:%"PRIu64, + core, core->recv_generation); + + start_footer_entry(&fb, FOOTER_CLIENT_OPCODE_GENERATION); + spa_pod_builder_long(fb.builder, core->recv_generation); + end_footer_entry(&fb); + } + + end_footer(&fb); +} + +void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client, + struct spa_pod_builder *builder) +{ + struct footer_builder fb = FOOTER_BUILDER_INIT(builder); + + if (client->context->generation != client->sent_generation) { + client->sent_generation = client->context->generation; + + pw_log_trace("impl-client %p: send server registry generation:%"PRIu64, + client, client->context->generation); + + start_footer_entry(&fb, FOOTER_CORE_OPCODE_GENERATION); + spa_pod_builder_long(fb.builder, client->context->generation); + end_footer_entry(&fb); + } + + end_footer(&fb); +} + +int demarshal_core_generation(void *object, struct spa_pod_parser *parser) +{ + struct pw_core *core = object; + int64_t generation; + + if (spa_pod_parser_get_long(parser, &generation) < 0) + return -EINVAL; + + core->recv_generation = SPA_MAX(core->recv_generation, + (uint64_t)generation); + + pw_log_trace("core %p: recv server registry generation:%"PRIu64, + core, generation); + + return 0; +} + +int demarshal_client_generation(void *object, struct spa_pod_parser *parser) +{ + struct pw_impl_client *client = object; + int64_t generation; + + if (spa_pod_parser_get_long(parser, &generation) < 0) + return -EINVAL; + + client->recv_generation = SPA_MAX(client->recv_generation, + (uint64_t)generation); + + pw_log_trace("impl-client %p: recv client registry generation:%"PRIu64, + client, generation); + + return 0; +} + +const struct footer_demarshal footer_core_demarshalFOOTER_CORE_OPCODE_LAST = { + FOOTER_CORE_OPCODE_GENERATION = (struct footer_demarshal){ .demarshal = demarshal_core_generation }, +}; + +const struct footer_demarshal footer_client_demarshalFOOTER_CLIENT_OPCODE_LAST = { + FOOTER_CLIENT_OPCODE_GENERATION = (struct footer_demarshal){ .demarshal = demarshal_client_generation }, +};
View file
pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-footer.h
Added
@@ -0,0 +1,59 @@ +/* PipeWire + * + * Copyright © 2018 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +/* + * Protocol footer. + * + * For passing around general state data that is not associated with + * messages sent to objects. + */ + +enum { + FOOTER_CORE_OPCODE_GENERATION = 0, + FOOTER_CORE_OPCODE_LAST +}; + +enum { + FOOTER_CLIENT_OPCODE_GENERATION = 0, + FOOTER_CLIENT_OPCODE_LAST +}; + +struct footer_core_global_state { + uint64_t last_recv_generation; +}; + +struct footer_client_global_state { +}; + +struct footer_demarshal { + int (*demarshal)(void *object, struct spa_pod_parser *parser); +}; + +extern const struct footer_demarshal footer_core_demarshalFOOTER_CORE_OPCODE_LAST; +extern const struct footer_demarshal footer_client_demarshalFOOTER_CLIENT_OPCODE_LAST; + +void marshal_core_footers(struct footer_core_global_state *state, struct pw_core *core, + struct spa_pod_builder *builder); +void marshal_client_footers(struct footer_client_global_state *state, struct pw_impl_client *client, + struct spa_pod_builder *builder);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-native/protocol-native.c
Changed
@@ -34,9 +34,9 @@ #include "connection.h" -#define MAX_DICT 256 +#define MAX_DICT 1024 #define MAX_PARAM_INFO 128 -#define MAX_PERMISSIONS 1024 +#define MAX_PERMISSIONS 4096 PW_LOG_TOPIC_EXTERN(mod_topic); #define PW_LOG_TOPIC_DEFAULT mod_topic
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/collect.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/collect.c
Changed
@@ -279,13 +279,13 @@ { struct spa_pod *copy = spa_pod_copy(p->param); spa_pod_fixate(copy); - format_parse_param(copy, &dev_info->ss, &dev_info->map, + format_parse_param(copy, true, &dev_info->ss, &dev_info->map, &defs->sample_spec, &defs->channel_map); free(copy); break; } case SPA_PARAM_Format: - format_parse_param(p->param, &dev_info->ss, &dev_info->map, + format_parse_param(p->param, true, &dev_info->ss, &dev_info->map, NULL, NULL); break;
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/defs.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/defs.h
Changed
@@ -260,5 +260,6 @@ #define METADATA_CONFIG_DEFAULT_SINK "default.configured.audio.sink" #define METADATA_CONFIG_DEFAULT_SOURCE "default.configured.audio.source" #define METADATA_TARGET_NODE "target.node" +#define METADATA_TARGET_OBJECT "target.object" #endif /* PULSE_SERVER_DEFS_H */
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c
Changed
@@ -252,7 +252,9 @@ if (name == NULL || name0 == '\0') return -EPROTO; - f = open_memstream(&ptr, &size); + if ((f = open_memstream(&ptr, &size)) == NULL) + return -errno; + fprintf(f, "{"); fprintf(f, " \"mute\": %s", mute ? "true" : "false"); if (vol.channels > 0) {
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/format.c
Changed
@@ -443,7 +443,8 @@ return res; } -int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, struct channel_map *map, +int format_parse_param(const struct spa_pod *param, bool collect, + struct sample_spec *ss, struct channel_map *map, const struct sample_spec *def_ss, const struct channel_map *def_map) { struct spa_audio_info info = { 0 }; @@ -471,11 +472,17 @@ { struct spa_audio_info_iec958 iec; + if (collect) + break; + if (spa_format_audio_iec958_parse(param, &iec) < 0) return -ENOTSUP; info.info.raw.format = SPA_AUDIO_FORMAT_S16; info.info.raw.rate = iec.rate; + info.info.raw.channels = 2; + info.info.raw.position0 = SPA_AUDIO_CHANNEL_FL; + info.info.raw.position1 = SPA_AUDIO_CHANNEL_FR; break; } default: @@ -612,7 +619,9 @@ size_t size; FILE *f; - f = open_memstream(&ptr, &size); + if ((f = open_memstream(&ptr, &size)) == NULL) + return -errno; + fprintf(f, ""); for (i = 1; i < n_values; i++) fprintf(f, "%s %d", i == 1 ? "" : ",", valuesi);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/format.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/format.h
Changed
@@ -205,7 +205,7 @@ void channel_map_parse(const char *str, struct channel_map *map); bool channel_map_valid(const struct channel_map *map); -int format_parse_param(const struct spa_pod *param, struct sample_spec *ss, +int format_parse_param(const struct spa_pod *param, bool collect, struct sample_spec *ss, struct channel_map *map, const struct sample_spec *def_ss, const struct channel_map *def_map);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/message-handler.c
Changed
@@ -65,7 +65,7 @@ r = open_memstream(response, &size); if (r == NULL) - return -ENOMEM; + return -errno; fputc('', r); for (i = 0; i < n_codecs; ++i) { @@ -100,7 +100,7 @@ r = open_memstream(response, &size); if (r == NULL) - return -ENOMEM; + return -errno; fputc('', r); spa_list_for_each(o, &m->object_list, link) {
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c
Changed
@@ -59,7 +59,9 @@ const char *str; size_t size; - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); if ((str = pw_properties_get(module->props, "sink_name")) != NULL) fprintf(f, " sink.name = \"%s\"", str);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
@@ -72,7 +72,9 @@ char *args; size_t size; - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); /* Can't just serialise this dict because the "null" method gets * interpreted as a JSON null */
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
@@ -78,7 +78,9 @@ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " filter.graph = {");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
@@ -78,7 +78,9 @@ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " filter.graph = {");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
@@ -75,7 +75,9 @@ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); if (data->info.channels != 0) { fprintf(f, " audio.channels = %u", data->info.channels);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
@@ -219,10 +219,7 @@ if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - if ((str = pw_properties_get(props, "device.description")) != NULL) { - pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); - pw_properties_set(props, "device.description", NULL); - } else { + if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL) { const char *name, *class; name = pw_properties_get(props, PW_KEY_NODE_NAME);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
@@ -72,7 +72,9 @@ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " capture.props = {");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
@@ -72,7 +72,9 @@ pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " capture.props = { ");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
@@ -73,7 +73,9 @@ pw_properties_setf(data->sink_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &data->roc_props->dict, 0); fprintf(f, " } sink.props = {");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
@@ -73,7 +73,9 @@ pw_properties_setf(data->source_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &data->roc_props->dict, 0); fprintf(f, " } source.props = {");
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c
Changed
@@ -68,7 +68,9 @@ uint32_t i; FILE *f; - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); if (data->info.rate != 0) fprintf(f, " \"audio.rate\": %u,", data->info.rate);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
@@ -76,7 +76,9 @@ pw_properties_setf(data->stream_props, "pulse.module.id", "%u", module->index); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " pulse.server.address = \"%s\" ", server);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
@@ -76,7 +76,9 @@ server = pw_properties_get(module->props, "server"); - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0); fprintf(f, " pulse.server.address = \"%s\" ", server);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c
Changed
@@ -59,7 +59,9 @@ const char *str; size_t size; - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + fprintf(f, "{"); if ((str = pw_properties_get(module->props, "sink")) != NULL) fprintf(f, " sink.name = \"%s\"", str);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/operation.c
Changed
@@ -66,15 +66,27 @@ free(o); } +struct operation *operation_find(struct client *client, uint32_t tag) +{ + struct operation *o; + spa_list_for_each(o, &client->operations, link) { + if (o->tag == tag) + return o; + } + return NULL; +} + void operation_complete(struct operation *o) { struct client *client = o->client; pw_log_info("%s: tag:%u complete", client->name, o->tag); + spa_list_remove(&o->link); + if (o->callback) o->callback(o->data, client, o->tag); else reply_simple_ack(client, o->tag); - operation_free(o); + free(o); }
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/operation.h
Changed
@@ -43,6 +43,7 @@ int operation_new_cb(struct client *client, uint32_t tag, void (*callback) (void *data, struct client *client, uint32_t tag), void *data); +struct operation *operation_find(struct client *client, uint32_t tag); void operation_free(struct operation *o); void operation_complete(struct operation *o);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pending-sample.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pending-sample.c
Changed
@@ -29,6 +29,7 @@ #include "client.h" #include "internal.h" #include "log.h" +#include "operation.h" #include "pending-sample.h" #include "sample-play.h" @@ -36,10 +37,14 @@ { struct client * const client = ps->client; struct impl * const impl = client->impl; + struct operation *o; spa_list_remove(&ps->link); spa_hook_remove(&ps->listener); pw_work_queue_cancel(impl->work_queue, ps, SPA_ID_INVALID); + if ((o = operation_find(client, ps->tag)) != NULL) + operation_free(o); + sample_play_destroy(ps->play); }
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pending-sample.h -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pending-sample.h
Changed
@@ -39,6 +39,8 @@ struct sample_play *play; struct spa_hook listener; uint32_t tag; + unsigned ready:1; + unsigned done:1; }; void pending_sample_free(struct pending_sample *ps);
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -192,8 +192,11 @@ reply_set_client_name(client, client->connect_tag); client->connect_tag = SPA_ID_INVALID; } + + client->ref++; spa_list_consume(o, &client->operations, link) operation_complete(o); + client_unref(client); } static struct stream *find_stream(struct client *client, uint32_t index) @@ -445,8 +448,8 @@ { struct spa_fraction lat; uint64_t lat_usec; - struct spa_dict_item items5; - char latency32; + struct spa_dict_item items6; + char latency32, rate32; char attr_maxlength32; char attr_tlength32; char attr_prebuf32; @@ -463,17 +466,19 @@ lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); + snprintf(rate, sizeof(rate), "1/%u", lat.denom); snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength); snprintf(attr_tlength, sizeof(attr_tlength), "%u", s->attr.tlength); snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", s->attr.prebuf); snprintf(attr_minreq, sizeof(attr_minreq), "%u", s->attr.minreq); items0 = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); - items1 = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); - items2 = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength); - items3 = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf); - items4 = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq); - pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 5)); + items1 = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate); + items2 = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); + items3 = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength); + items4 = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf); + items5 = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq); + pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 6)); if (s->attr.prebuf > 0) s->in_prebuf = true; @@ -594,8 +599,8 @@ static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr) { - struct spa_dict_item items3; - char latency32; + struct spa_dict_item items4; + char latency32, rate32; char attr_maxlength32; char attr_fragsize32; struct spa_fraction lat; @@ -610,14 +615,16 @@ lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); + snprintf(rate, sizeof(rate), "1/%u", lat.denom); snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength); snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", s->attr.fragsize); items0 = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); - items1 = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); - items2 = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize); - pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 3)); + items1 = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate); + items2 = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); + items3 = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize); + pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 4)); return lat_usec; } @@ -999,8 +1006,10 @@ stream->killed = true; destroy_stream = true; break; - case PW_STREAM_STATE_CONNECTING: case PW_STREAM_STATE_PAUSED: + stream->id = pw_stream_get_node_id(stream->stream); + break; + case PW_STREAM_STATE_CONNECTING: case PW_STREAM_STATE_STREAMING: break; } @@ -1055,7 +1064,7 @@ if (id != SPA_PARAM_Format || param == NULL) return; - if ((res = format_parse_param(param, &stream->ss, &stream->map, NULL, NULL)) < 0) { + if ((res = format_parse_param(param, false, &stream->ss, &stream->map, NULL, NULL)) < 0) { pw_stream_set_error(stream->stream, res, "format not supported"); return; } @@ -1073,7 +1082,6 @@ if (stream->create_tag != SPA_ID_INVALID) { struct pw_manager_object *peer; - stream->id = pw_stream_get_node_id(stream->stream); if (stream->volume_set) { pw_stream_set_control(stream->stream, @@ -1556,7 +1564,7 @@ n_valid_formats++; } } - if (n_params < MAX_FORMATS && + else if (n_params < MAX_FORMATS && (paramsn_params = format_build_param(&b, SPA_PARAM_EnumFormat, &ss, ss.channels > 0 ? &map : NULL)) != NULL) { @@ -2324,6 +2332,13 @@ return o; } +static void sample_play_finish(struct pending_sample *ps) +{ + struct client *client = ps->client; + pending_sample_free(ps); + client_unref(client); +} + static void sample_play_ready_reply(void *data, struct client *client, uint32_t tag) { struct pending_sample *ps = data; @@ -2333,6 +2348,8 @@ pw_log_info("%s PLAY_SAMPLE tag:%u index:%u", client->name, ps->tag, index); + ps->ready = true; + reply = reply_new(client, ps->tag); if (client->version >= 13) message_put(reply, @@ -2340,6 +2357,9 @@ TAG_INVALID); client_queue_message(client, reply); + + if (ps->done) + sample_play_finish(ps); } static void sample_play_ready(void *data, uint32_t id) @@ -2352,10 +2372,9 @@ static void on_sample_done(void *obj, void *data, int res, uint32_t id) { struct pending_sample *ps = obj; - struct client *client = ps->client; - - pending_sample_free(ps); - client_unref(client); + ps->done = true; + if (ps->ready) + sample_play_finish(ps); } static void sample_play_done(void *data, int res) @@ -4609,7 +4628,9 @@ struct pw_manager_object *o, *dev, *dev_default; uint32_t index, index_device; int target_id; + int64_t target_serial; const char *name_device; + struct pw_node_info *info; struct selector sel; int res; bool sink = command == COMMAND_MOVE_SINK_INPUT; @@ -4636,6 +4657,12 @@ if (o == NULL) return -ENOENT; + info = o->info; + if (info == NULL || info->props == NULL) + return -EINVAL; + if (spa_atob(spa_dict_lookup(info->props, PW_KEY_NODE_DONT_RECONNECT))) + return -EINVAL; + if ((dev = find_device(client, index_device, name_device, sink, NULL)) == NULL) return -ENOENT; @@ -4647,8 +4674,10 @@ * forgetting target.node. Follow that behavior here. */ target_id = -1; + target_serial = -1; } else { target_id = dev->id; + target_serial = dev->serial; } if ((res = pw_manager_set_metadata(manager, client->metadata_default, @@ -4657,6 +4686,12 @@ SPA_TYPE_INFO_BASE"Id", "%d", target_id)) < 0) return res; + if ((res = pw_manager_set_metadata(manager, client->metadata_default, + o->id, + METADATA_TARGET_OBJECT, + SPA_TYPE_INFO_BASE"Id", "%"PRIi64, target_serial)) < 0) + return res; + return reply_simple_ack(client, tag); } @@ -5330,8 +5365,6 @@ impl->props = props; impl->work_queue = pw_context_get_work_queue(context); - if (impl->work_queue == NULL) - goto error_free; spa_list_init(&impl->servers); impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.48.tar.gz/src/modules/module-protocol-simple.c
Changed
@@ -848,10 +848,6 @@ pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props)); impl->work_queue = pw_context_get_work_queue(context); - if (impl->work_queue == NULL) { - res = -errno; - goto error_free; - } if ((res = parse_params(impl)) < 0) goto error_free;
View file
pipewire-0.3.47.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.48.tar.gz/src/modules/module-pulse-tunnel.c
Changed
@@ -48,6 +48,7 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> +#include <pipewire/private.h> #include <pulse/pulseaudio.h> #include "module-protocol-pulse/format.h" @@ -95,7 +96,6 @@ struct pw_properties *props; struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; @@ -121,23 +121,8 @@ pa_stream *pa_stream; unsigned int do_disconnect:1; - unsigned int unloading:1; }; -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} - -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static void cork_stream(struct impl *impl, bool cork) { pa_operation *operation; @@ -174,7 +159,7 @@ switch (state) { case PW_STREAM_STATE_ERROR: case PW_STREAM_STATE_UNCONNECTED: - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); break; case PW_STREAM_STATE_PAUSED: cork_stream(impl, true); @@ -613,7 +598,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_core_events core_events = { @@ -626,7 +611,7 @@ struct impl *impl = d; spa_hook_remove(&impl->core_listener); impl->core = NULL; - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_proxy_events core_proxy_events = { @@ -655,8 +640,6 @@ pw_properties_free(impl->stream_props); pw_properties_free(impl->props); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); free(impl->buffer); free(impl); } @@ -664,7 +647,6 @@ static void module_destroy(void *data) { struct impl *impl = data; - impl->unloading = true; spa_hook_remove(&impl->module_listener); impl_destroy(impl); } @@ -779,12 +761,6 @@ impl->module = module; impl->context = context; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto error; - } spa_ringbuffer_init(&impl->ring); impl->buffer = calloc(1, RINGBUFFER_SIZE);
View file
pipewire-0.3.47.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop-discover.c
Changed
@@ -71,7 +71,6 @@ struct pw_impl_module *module; struct spa_hook module_listener; - struct pw_work_queue *work; struct pw_properties *properties; @@ -80,8 +79,6 @@ AvahiServiceBrowser *sink_browser; struct spa_list tunnel_list; - - unsigned int unloading:1; }; struct tunnel_info { @@ -103,20 +100,6 @@ static int start_client(struct impl *impl); -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} - -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static struct tunnel *make_tunnel(struct impl *impl, const struct tunnel_info *info) { struct tunnel *t; @@ -168,8 +151,6 @@ if (impl->avahi_poll) pw_avahi_poll_free(impl->avahi_poll); pw_properties_free(impl->properties); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); free(impl); } @@ -340,7 +321,11 @@ } - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) { + pw_log_error("Can't open memstream: %m"); + goto done; + } + fprintf(f, "{"); pw_properties_serialize_dict(f, &props->dict, 0); fprintf(f, " stream.props = {"); @@ -465,7 +450,7 @@ } return; error: - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static int start_client(struct impl *impl) @@ -476,7 +461,7 @@ client_callback, impl, &res)) == NULL) { pw_log_error("can't create client: %s", avahi_strerror(res)); - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); return -EIO; } return 0; @@ -521,10 +506,6 @@ impl->context = context; impl->properties = props; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) - goto error_errno; - pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
View file
pipewire-0.3.47.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -58,6 +58,7 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> +#include <pipewire/private.h> #include "module-raop/rtsp-client.h" @@ -134,7 +135,6 @@ struct pw_impl_module *module; struct pw_loop *loop; - struct pw_work_queue *work; struct spa_hook module_listener; @@ -160,7 +160,6 @@ char *password; unsigned int do_disconnect:1; - unsigned int unloading:1; uint8_t keyAES_CHUNK_SIZE; /* Key for aes-cbc */ uint8_t ivAES_CHUNK_SIZE; /* Initialization vector for cbc */ @@ -196,20 +195,6 @@ uint32_t filled; }; -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} - -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static void stream_destroy(void *d) { struct impl *impl = d; @@ -599,6 +584,10 @@ received = ntp_now(CLOCK_MONOTONIC); bytes = read(impl->timing_fd, packet, sizeof(packet)); + if (bytes < 0) { + pw_log_debug("error reading timing packet: %m"); + return; + } if (bytes != sizeof(packet)) { pw_log_warn("discarding short (%zd < %zd) timing packet", bytes, sizeof(bytes)); @@ -624,7 +613,11 @@ uint32_t hdr; uint16_t seq, num; - bytes = read(impl->timing_fd, packet, sizeof(packet)); + bytes = read(impl->control_fd, packet, sizeof(packet)); + if (bytes < 0) { + pw_log_debug("error reading control packet: %m"); + return; + } if (bytes != sizeof(packet)) { pw_log_warn("discarding short (%zd < %zd) control packet", bytes, sizeof(bytes)); @@ -1260,7 +1253,7 @@ switch (state) { case PW_STREAM_STATE_ERROR: case PW_STREAM_STATE_UNCONNECTED: - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); break; case PW_STREAM_STATE_PAUSED: rtsp_do_flush(impl); @@ -1394,7 +1387,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_core_events core_events = { @@ -1407,7 +1400,7 @@ struct impl *impl = d; spa_hook_remove(&impl->core_listener); impl->core = NULL; - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static const struct pw_proxy_events core_proxy_events = { @@ -1428,15 +1421,12 @@ pw_properties_free(impl->stream_props); pw_properties_free(impl->props); free(impl->password); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); free(impl); } static void module_destroy(void *data) { struct impl *impl = data; - impl->unloading = true; spa_hook_remove(&impl->module_listener); impl_destroy(impl); } @@ -1587,12 +1577,6 @@ impl->module = module; impl->context = context; impl->loop = pw_context_get_main_loop(context); - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto error; - } if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) pw_properties_set(props, PW_KEY_NODE_GROUP, "pipewire.dummy");
View file
pipewire-0.3.47.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.48.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
@@ -478,7 +478,8 @@ struct message *msg; int cseq; - f = open_memstream((char**)&msg, &len); + if ((f = open_memstream((char**)&msg, &len)) == NULL) + return -errno; fseek(f, sizeof(*msg), SEEK_SET);
View file
pipewire-0.3.47.tar.gz/src/modules/module-roc-sink.c -> pipewire-0.3.48.tar.gz/src/modules/module-roc-sink.c
Changed
@@ -96,7 +96,6 @@ struct module_roc_sink_data { struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; struct pw_properties *props; struct pw_context *module_context; @@ -110,7 +109,6 @@ struct pw_properties *capture_props; unsigned int do_disconnect:1; - unsigned int unloading:1; roc_address local_addr; roc_address remote_source_addr; @@ -124,20 +122,6 @@ int remote_repair_port; }; -static void do_unload_module(void *obj, void *d, int res, uint32_t id) -{ - struct module_roc_sink_data *data = d; - pw_impl_module_destroy(data->module); -} - -static void unload_module(struct module_roc_sink_data *data) -{ - if (!data->unloading) { - data->unloading = true; - pw_work_queue_add(data->work, data, 0, do_unload_module, data); - } -} - static void stream_destroy(void *d) { struct module_roc_sink_data *data = d; @@ -189,7 +173,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(data); + pw_impl_module_schedule_destroy(data->module); } static const struct pw_core_events core_events = { @@ -205,7 +189,7 @@ switch (state) { case PW_STREAM_STATE_UNCONNECTED: pw_log_info("stream disconnected, unloading"); - unload_module(data); + pw_impl_module_schedule_destroy(data->module); break; case PW_STREAM_STATE_ERROR: pw_log_error("stream error: %s", error); @@ -227,7 +211,7 @@ struct module_roc_sink_data *data = d; spa_hook_remove(&data->core_listener); data->core = NULL; - unload_module(data); + pw_impl_module_schedule_destroy(data->module); } static const struct pw_proxy_events core_proxy_events = { @@ -244,8 +228,6 @@ pw_properties_free(data->capture_props); pw_properties_free(data->props); - if (data->work) - pw_work_queue_cancel(data->work, data, SPA_ID_INVALID); if (data->sender) roc_sender_close(data->sender); if (data->context) @@ -259,7 +241,6 @@ static void module_destroy(void *d) { struct module_roc_sink_data *data = d; - data->unloading = true; spa_hook_remove(&data->module_listener); impl_destroy(data); } @@ -416,12 +397,6 @@ data->module = module; data->module_context = context; - data->work = pw_context_get_work_queue(context); - if (data->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto out; - } if ((str = pw_properties_get(props, "sink.name")) != NULL) { pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
View file
pipewire-0.3.47.tar.gz/src/modules/module-roc-source.c -> pipewire-0.3.48.tar.gz/src/modules/module-roc-source.c
Changed
@@ -100,7 +100,6 @@ struct module_roc_source_data { struct pw_impl_module *module; - struct pw_work_queue *work; struct spa_hook module_listener; struct pw_properties *props; struct pw_context *module_context; @@ -114,7 +113,6 @@ struct pw_properties *playback_props; unsigned int do_disconnect:1; - unsigned int unloading:1; roc_address local_addr; roc_address local_source_addr; @@ -129,20 +127,6 @@ int sess_latency_msec; }; -static void do_unload_module(void *obj, void *d, int res, uint32_t id) -{ - struct module_roc_source_data *data = d; - pw_impl_module_destroy(data->module); -} - -static void unload_module(struct module_roc_source_data *data) -{ - if (!data->unloading) { - data->unloading = true; - pw_work_queue_add(data->work, data, 0, do_unload_module, data); - } -} - static void stream_destroy(void *d) { struct module_roc_source_data *data = d; @@ -202,7 +186,7 @@ if (roc_receiver_read(impl->receiver, &frame) != 0) { /* Handle EOF and error */ pw_log_error("Failed to read from roc source"); - unload_module(data); + pw_impl_module_schedule_destroy(impl->module); return; } @@ -219,7 +203,7 @@ id, seq, res, spa_strerror(res), message); if (id == PW_ID_CORE && res == -EPIPE) - unload_module(data); + pw_impl_module_schedule_destroy(data->module); } static const struct pw_core_events core_events = { @@ -235,7 +219,7 @@ switch (state) { case PW_STREAM_STATE_UNCONNECTED: pw_log_info("stream disconnected, unloading"); - unload_module(data); + pw_impl_module_schedule_destroy(data->module); break; case PW_STREAM_STATE_ERROR: pw_log_error("stream error: %s", error); @@ -257,7 +241,7 @@ struct module_roc_source_data *data = d; spa_hook_remove(&data->core_listener); data->core = NULL; - unload_module(data); + pw_impl_module_schedule_destroy(data->module); } static const struct pw_proxy_events core_proxy_events = { @@ -274,8 +258,6 @@ pw_properties_free(data->playback_props); pw_properties_free(data->props); - if (data->work) - pw_work_queue_cancel(data->work, data, SPA_ID_INVALID); if (data->receiver) roc_receiver_close(data->receiver); if (data->context) @@ -289,7 +271,6 @@ static void module_destroy(void *d) { struct module_roc_source_data *data = d; - data->unloading = true; spa_hook_remove(&data->module_listener); impl_destroy(data); } @@ -461,12 +442,6 @@ data->module = module; data->module_context = context; - data->work = pw_context_get_work_queue(context); - if (data->work == NULL) { - res = -errno; - pw_log_error( "can't get work queue: %m"); - goto out; - } if ((str = pw_properties_get(props, "source.name")) != NULL) { pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
View file
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint-link.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint-link.c
Changed
@@ -389,6 +389,15 @@ struct pw_properties *properties) { struct impl *impl; + char serial_str32; + struct spa_dict_item items1 = { + SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str), + }; + struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items); + static const char * const keys = { + PW_KEY_OBJECT_SERIAL, + NULL + }; impl = calloc(1, sizeof(*impl)); if (impl == NULL) { @@ -407,6 +416,10 @@ } impl->resource = resource; + spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64, + pw_global_get_serial(impl->global)); + pw_global_update_keys(impl->global, &extra_props, keys); + spa_list_init(&impl->cached_params); /* handle destroy events */
View file
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint-stream.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint-stream.c
Changed
@@ -380,6 +380,15 @@ struct pw_properties *properties) { struct impl *impl; + char serial_str32; + struct spa_dict_item items1 = { + SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str), + }; + struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items); + static const char * const keys = { + PW_KEY_OBJECT_SERIAL, + NULL + }; impl = calloc(1, sizeof(*impl)); if (impl == NULL) { @@ -398,6 +407,10 @@ } impl->resource = resource; + spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64, + pw_global_get_serial(impl->global)); + pw_global_update_keys(impl->global, &extra_props, keys); + spa_list_init(&impl->cached_params); /* handle destroy events */
View file
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/endpoint.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/endpoint.c
Changed
@@ -389,6 +389,15 @@ struct pw_properties *properties) { struct impl *impl; + char serial_str32; + struct spa_dict_item items1 = { + SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str), + }; + struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items); + static const char * const keys = { + PW_KEY_OBJECT_SERIAL, + NULL + }; impl = calloc(1, sizeof(*impl)); if (impl == NULL) { @@ -407,6 +416,10 @@ } impl->resource = resource; + spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64, + pw_global_get_serial(impl->global)); + pw_global_update_keys(impl->global, &extra_props, keys); + spa_list_init(&impl->cached_params); /* handle destroy events */
View file
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/protocol-native.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/protocol-native.c
Changed
@@ -32,8 +32,8 @@ #include <pipewire/extensions/session-manager.h> #include <pipewire/extensions/protocol-native.h> -#define MAX_DICT 256 -#define MAX_PARAMS 128 +#define MAX_DICT 1024 +#define MAX_PARAMS 4096 #define MAX_PARAM_INFO 128 static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict)
View file
pipewire-0.3.47.tar.gz/src/modules/module-session-manager/session.c -> pipewire-0.3.48.tar.gz/src/modules/module-session-manager/session.c
Changed
@@ -378,6 +378,15 @@ struct pw_properties *properties) { struct impl *impl; + char serial_str32; + struct spa_dict_item items1 = { + SPA_DICT_ITEM_INIT(PW_KEY_OBJECT_SERIAL, serial_str), + }; + struct spa_dict extra_props = SPA_DICT_INIT_ARRAY(items); + static const char * const keys = { + PW_KEY_OBJECT_SERIAL, + NULL + }; impl = calloc(1, sizeof(*impl)); if (impl == NULL) { @@ -396,6 +405,10 @@ } impl->resource = resource; + spa_scnprintf(serial_str, sizeof(serial_str), "%"PRIu64, + pw_global_get_serial(impl->global)); + pw_global_update_keys(impl->global, &extra_props, keys); + spa_list_init(&impl->cached_params); /* handle destroy events */
View file
pipewire-0.3.47.tar.gz/src/modules/module-x11-bell.c -> pipewire-0.3.48.tar.gz/src/modules/module-x11-bell.c
Changed
@@ -38,10 +38,15 @@ #include <X11/Xlib-xcb.h> #include <X11/XKBlib.h> +#ifdef HAVE_XFIXES_6 +#include <X11/extensions/Xfixes.h> +#endif + #include <canberra.h> -#include "pipewire/pipewire.h" -#include "pipewire/impl.h" +#include <pipewire/pipewire.h> +#include <pipewire/impl.h> +#include <pipewire/private.h> /** \page page_module_x11_bell PipeWire Module: X11 Bell * @@ -81,21 +86,30 @@ struct impl { struct pw_context *context; struct pw_thread_loop *thread_loop; + struct pw_loop *thread_loop_loop; struct pw_loop *loop; struct spa_source *source; struct pw_properties *properties; + struct pw_impl_module *module; struct spa_hook module_listener; Display *display; - int xkb_event_base; }; -static int play_sample(struct impl *impl, const char *sample) +static int play_sample(struct impl *impl) { - int res; + const char *sample = NULL; ca_context *ca; + int res; + + if (impl->properties) + sample = pw_properties_get(impl->properties, "sample.name"); + if (sample == NULL) + sample = "bell-window-system"; + + pw_log_debug("play sample %s", sample); if ((res = ca_context_create(&ca)) < 0) { pw_log_error("canberra context create error: %s", ca_strerror(res)); @@ -113,6 +127,8 @@ CA_PROP_CANBERRA_CACHE_CONTROL, "permanent", NULL)) < 0) { pw_log_warn("can't play sample (%s): %s", sample, ca_strerror(res)); + res = -EIO; + goto exit_destroy; } exit_destroy: @@ -120,11 +136,17 @@ exit: return res; } + +static int do_play_sample(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + play_sample(user_data); + return 0; +} + static void display_io(void *data, int fd, uint32_t mask) { struct impl *impl = data; XEvent e; - const char *sample = NULL; while (XPending(impl->display)) { XNextEvent(impl->display, &e); @@ -132,60 +154,64 @@ if (((XkbEvent*) &e)->any.xkb_type != XkbBellNotify) continue; - if (impl->properties) - sample = pw_properties_get(impl->properties, "sample.name"); - if (sample == NULL) - sample = "bell-window-system"; - - pw_log_debug("play sample %s", sample); - play_sample(impl, sample); + pw_loop_invoke(impl->thread_loop_loop, do_play_sample, 0, NULL, 0, false, impl); } } -static void x11_close(struct impl *impl) +#ifdef HAVE_XSETIOERROREXITHANDLER +static void x11_io_error_exit_handler(Display *display, void *data) { - if (impl->source) { - pw_loop_destroy_source(impl->loop, impl->source); - impl->source = NULL; - } - if (impl->display) { - XCloseDisplay(impl->display); - impl->display = NULL; - } + struct impl *impl = data; + + spa_assert(display == impl->display); + + pw_log_warn("X11 display (%s) has encountered a fatal I/O error", DisplayString(display)); + + pw_loop_destroy_source(impl->loop, impl->source); + impl->source = NULL; + + pw_impl_module_schedule_destroy(impl->module); } +#endif static int x11_connect(struct impl *impl, const char *name) { - int res, major, minor; + int major, minor; unsigned int auto_ctrls, auto_values; if (!(impl->display = XOpenDisplay(name))) { - pw_log_warn("XOpenDisplay() failed"); - res = -EIO; - goto error; + pw_log_error("XOpenDisplay() failed"); + return -EIO; } impl->source = pw_loop_add_io(impl->loop, ConnectionNumber(impl->display), SPA_IO_IN, false, display_io, impl); + if (!impl->source) + return -errno; + +#ifdef HAVE_XSETIOERROREXITHANDLER + XSetIOErrorExitHandler(impl->display, x11_io_error_exit_handler, impl); +#endif + +#ifdef HAVE_XFIXES_6 + XFixesSetClientDisconnectMode(impl->display, XFixesClientDisconnectFlagTerminate); +#endif major = XkbMajorVersion; minor = XkbMinorVersion; if (!XkbLibraryVersion(&major, &minor)) { - pw_log_warn("XkbLibraryVersion() failed"); - res = -EIO; - goto error; + pw_log_error("XkbLibraryVersion() failed"); + return -EIO; } major = XkbMajorVersion; minor = XkbMinorVersion; - if (!XkbQueryExtension(impl->display, NULL, &impl->xkb_event_base, - NULL, &major, &minor)) { - res = -EIO; - pw_log_warn("XkbQueryExtension() failed"); - goto error; + if (!XkbQueryExtension(impl->display, NULL, NULL, NULL, &major, &minor)) { + pw_log_error("XkbQueryExtension() failed"); + return -EIO; } XkbSelectEvents(impl->display, XkbUseCoreKbd, XkbBellNotifyMask, XkbBellNotifyMask); @@ -193,28 +219,24 @@ XkbSetAutoResetControls(impl->display, XkbAudibleBellMask, &auto_ctrls, &auto_values); XkbChangeEnabledControls(impl->display, XkbUseCoreKbd, XkbAudibleBellMask, 0); - res = 0; -error: - if (res < 0) - x11_close(impl); - return res; + return 0; } static void module_destroy(void *data) { struct impl *impl = data; - spa_hook_remove(&impl->module_listener); + if (impl->module) + spa_hook_remove(&impl->module_listener); - if (impl->thread_loop) - pw_thread_loop_lock(impl->thread_loop); + if (impl->source) + pw_loop_destroy_source(impl->loop, impl->source); - x11_close(impl); + if (impl->display) + XCloseDisplay(impl->display); - if (impl->thread_loop) { - pw_thread_loop_unlock(impl->thread_loop); + if (impl->thread_loop) pw_thread_loop_destroy(impl->thread_loop); - } pw_properties_free(impl->properties); @@ -252,15 +274,18 @@ pw_log_debug("module %p: new", impl); impl->context = context; + impl->loop = pw_context_get_main_loop(context); + impl->thread_loop = pw_thread_loop_new("X11 Bell", NULL); if (impl->thread_loop == NULL) { res = -errno; pw_log_error("can't create thread loop: %m"); goto error; } - impl->loop = pw_thread_loop_get_loop(impl->thread_loop); + impl->thread_loop_loop = pw_thread_loop_get_loop(impl->thread_loop); impl->properties = args ? pw_properties_new_string(args) : NULL; + impl->module = module; pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_x11_bell_info)); @@ -279,9 +304,9 @@ * to pipewire eventually and will then block the mainloop. */ pw_thread_loop_start(impl->thread_loop); - pw_thread_loop_lock(impl->thread_loop); - x11_connect(impl, name); - pw_thread_loop_unlock(impl->thread_loop); + res = x11_connect(impl, name); + if (res < 0) + goto error; return 0; error: @@ -289,3 +314,52 @@ return res; } + +static int x11_error_handler(Display *display, XErrorEvent *error) +{ + pw_log_warn("X11 error handler called on display %s with error %d", + DisplayString(display), error->error_code); + return 0; +} + +static int x11_io_error_handler(Display *display) +{ + pw_log_warn("X11 I/O error handler called on display %s", DisplayString(display)); + return 0; +} + +__attribute__((constructor)) +static void set_x11_handlers(void) +{ + { + XErrorHandler prev = XSetErrorHandler(NULL); + XErrorHandler def = XSetErrorHandler(x11_error_handler); + + if (prev != def) + XSetErrorHandler(prev); + } + + { + XIOErrorHandler prev = XSetIOErrorHandler(NULL); + XIOErrorHandler def = XSetIOErrorHandler(x11_io_error_handler); + + if (prev != def) + XSetIOErrorHandler(prev); + } +} + +__attribute__((destructor)) +static void restore_x11_handlers(void) +{ + { + XErrorHandler prev = XSetErrorHandler(NULL); + if (prev != x11_error_handler) + XSetErrorHandler(prev); + } + + { + XIOErrorHandler prev = XSetIOErrorHandler(NULL); + if (prev != x11_io_error_handler) + XSetIOErrorHandler(prev); + } +}
View file
pipewire-0.3.47.tar.gz/src/modules/module-zeroconf-discover.c -> pipewire-0.3.48.tar.gz/src/modules/module-zeroconf-discover.c
Changed
@@ -73,7 +73,6 @@ struct pw_impl_module *module; struct spa_hook module_listener; - struct pw_work_queue *work; struct pw_properties *properties; @@ -83,8 +82,6 @@ AvahiServiceBrowser *source_browser; struct spa_list tunnel_list; - - unsigned int unloading:1; }; struct tunnel_info { @@ -106,20 +103,6 @@ static int start_client(struct impl *impl); -static void do_unload_module(void *obj, void *data, int res, uint32_t id) -{ - struct impl *impl = data; - pw_impl_module_destroy(impl->module); -} - -static void unload_module(struct impl *impl) -{ - if (!impl->unloading) { - impl->unloading = true; - pw_work_queue_add(impl->work, impl, 0, do_unload_module, impl); - } -} - static struct tunnel *make_tunnel(struct impl *impl, const struct tunnel_info *info) { struct tunnel *t; @@ -173,8 +156,6 @@ if (impl->avahi_poll) pw_avahi_poll_free(impl->avahi_poll); pw_properties_free(impl->properties); - if (impl->work) - pw_work_queue_cancel(impl->work, impl, SPA_ID_INVALID); free(impl); } @@ -348,7 +329,11 @@ _("%s on %s"), desc, fqdn); } - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) { + pw_log_error("Can't open memstream: %m"); + goto done; + } + fprintf(f, "{"); pw_properties_serialize_dict(f, &props->dict, 0); fprintf(f, " stream.props = {"); @@ -483,7 +468,7 @@ } return; error: - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); } static int start_client(struct impl *impl) @@ -494,7 +479,7 @@ client_callback, impl, &res)) == NULL) { pw_log_error("can't create client: %s", avahi_strerror(res)); - unload_module(impl); + pw_impl_module_schedule_destroy(impl->module); return -EIO; } return 0; @@ -539,10 +524,6 @@ impl->context = context; impl->properties = props; - impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) - goto error_errno; - pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
View file
pipewire-0.3.47.tar.gz/src/pipewire/conf.c -> pipewire-0.3.48.tar.gz/src/pipewire/conf.c
Changed
@@ -863,23 +863,24 @@ struct pw_properties *conf, const char *section) { struct data data = { .context = context }; + int res; if (spa_streq(section, "context.spa-libs")) - pw_context_conf_section_for_each(context, section, + res = pw_context_conf_section_for_each(context, section, parse_spa_libs, &data); else if (spa_streq(section, "context.modules")) - pw_context_conf_section_for_each(context, section, + res = pw_context_conf_section_for_each(context, section, parse_modules, &data); else if (spa_streq(section, "context.objects")) - pw_context_conf_section_for_each(context, section, + res = pw_context_conf_section_for_each(context, section, parse_objects, &data); else if (spa_streq(section, "context.exec")) - pw_context_conf_section_for_each(context, section, + res = pw_context_conf_section_for_each(context, section, parse_exec, &data); else - data.count = -EINVAL; + res = -EINVAL; - return data.count; + return res == 0 ? data.count : res; } static int update_props(void *user_data, const char *location, const char *key, @@ -895,9 +896,10 @@ const char *section, struct pw_properties *props) { struct data data = { .context = context, .props = props }; - pw_context_conf_section_for_each(context, section, + int res; + res = pw_context_conf_section_for_each(context, section, update_props, &data); - return data.count; + return res == 0 ? data.count : res; } struct match {
View file
pipewire-0.3.47.tar.gz/src/pipewire/context.c -> pipewire-0.3.48.tar.gz/src/pipewire/context.c
Changed
@@ -178,6 +178,22 @@ impl); } +static int do_data_loop_setup(struct spa_loop *loop, bool async, uint32_t seq, + const void *data, size_t size, void *user_data) +{ + struct pw_context *this = user_data; + const char *str; + struct spa_cpu *cpu; + + cpu = spa_support_find(this->support, this->n_support, SPA_TYPE_INTERFACE_CPU); + + if ((str = pw_properties_get(this->properties, SPA_KEY_CPU_ZERO_DENORMALS)) != NULL && + cpu != NULL) { + pw_log_info("setting zero denormals: %s", str); + spa_cpu_zero_denormals(cpu, spa_atob(str)); + } + return 0; +} /** Create a new context object * @@ -290,9 +306,6 @@ if (pw_properties_get(properties, PW_KEY_CPU_MAX_ALIGN) == NULL) pw_properties_setf(properties, PW_KEY_CPU_MAX_ALIGN, "%u", spa_cpu_get_max_align(cpu)); - if ((str = pw_properties_get(properties, SPA_KEY_CPU_ZERO_DENORMALS)) == NULL) - str = "true"; - spa_cpu_zero_denormals(cpu, spa_atob(str)); } if (getenv("PIPEWIRE_DEBUG") == NULL && @@ -330,6 +343,12 @@ this->data_system = this->data_loop->system; this->main_loop = main_loop; + this->work_queue = pw_work_queue_new(this->main_loop); + if (this->work_queue == NULL) { + res = -errno; + goto error_free; + } + init_plugin_loader(impl); this->supportn_support++ = SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_System, this->main_loop->system); @@ -389,6 +408,9 @@ if ((res = pw_data_loop_start(this->data_loop_impl)) < 0) goto error_free; + pw_data_loop_invoke(this->data_loop_impl, + do_data_loop_setup, 0, NULL, 0, false, this); + context_set_freewheel(this, false); pw_settings_expose(this); @@ -520,8 +542,6 @@ SPA_EXPORT struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context) { - if (context->work_queue == NULL) - context->work_queue = pw_work_queue_new(context->main_loop); return context->work_queue; }
View file
pipewire-0.3.47.tar.gz/src/pipewire/filter.c -> pipewire-0.3.48.tar.gz/src/pipewire/filter.c
Changed
@@ -35,6 +35,7 @@ #include <spa/utils/ringbuffer.h> #include <spa/utils/string.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/debug/format.h> #include <spa/debug/types.h> #include <spa/debug/pod.h> @@ -146,9 +147,10 @@ uint32_t change_mask_all; struct spa_node_info info; struct spa_list param_list; -#define IDX_Props 0 -#define IDX_ProcessLatency 1 -#define N_NODE_PARAMS 2 +#define IDX_PropInfo 0 +#define IDX_Props 1 +#define IDX_ProcessLatency 2 +#define N_NODE_PARAMS 3 struct spa_param_info paramsN_NODE_PARAMS; struct spa_process_latency_info process_latency; @@ -173,6 +175,8 @@ static int get_param_index(uint32_t id) { switch (id) { + case SPA_PARAM_PropInfo: + return IDX_PropInfo; case SPA_PARAM_Props: return IDX_Props; case SPA_PARAM_ProcessLatency: @@ -398,7 +402,7 @@ { struct spa_result_node_params result; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; uint32_t count = 0; struct param *p; bool found = false; @@ -425,13 +429,14 @@ found = true; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, param, filter) != 0) - continue; - - spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) { + spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == num) + if (count == num) break; } return found ? 0 : -ENOENT; @@ -1493,6 +1498,7 @@ impl->info.max_output_ports = UINT32_MAX; impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0; impl->info.props = &filter->properties->dict; + impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); impl->paramsIDX_ProcessLatency = SPA_PARAM_INFO(SPA_PARAM_ProcessLatency, 0); impl->info.params = impl->params;
View file
pipewire-0.3.47.tar.gz/src/pipewire/global.c -> pipewire-0.3.48.tar.gz/src/pipewire/global.c
Changed
@@ -139,6 +139,7 @@ { struct pw_resource *registry; struct pw_context *context = global->context; + struct pw_impl_client *client; if (global->registered) return -EEXIST; @@ -146,10 +147,12 @@ spa_list_append(&context->global_list, &global->link); global->registered = true; + global->generation = ++context->generation; + spa_list_for_each(registry, &context->registry_resource_list, link) { uint32_t permissions = pw_global_get_permissions(global, registry->client); - pw_log_debug("registry %p: global %d %08x serial:%"PRIu64, - registry, global->id, permissions, global->serial); + pw_log_debug("registry %p: global %d %08x serial:%"PRIu64" generation:%"PRIu64, + registry, global->id, permissions, global->serial, global->generation); if (PW_PERM_IS_R(permissions)) pw_registry_resource_global(registry, global->id, @@ -159,6 +162,25 @@ &global->properties->dict); } + /* Ensure a message is sent also to clients without registries, to force + * generation number update. */ + spa_list_for_each(client, &context->client_list, link) { + uint32_t permissions; + + if (client->sent_generation >= context->generation) + continue; + if (!client->core_resource) + continue; + + permissions = pw_global_get_permissions(global, client); + if (PW_PERM_IS_R(permissions)) { + pw_log_debug("impl-client %p: (no registry) global %d %08x serial:%"PRIu64 + " generation:%"PRIu64, client, global->id, permissions, global->serial, + global->generation); + pw_core_resource_done(client->core_resource, global->id, 0); + } + } + pw_log_debug("%p: registered %u", global, global->id); pw_context_emit_global_added(context, global); @@ -352,8 +374,7 @@ } else if (do_show) { pw_log_debug("client %p: resource %p show global %d serial:%"PRIu64, - client, resource, global->id, - global->serial); + client, resource, global->id, global->serial); pw_registry_resource_global(resource, global->id, new_permissions,
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-client.c
Changed
@@ -228,6 +228,18 @@ pw_global_update_keys(client->global, client->info.props, keys); pw_global_register(client->global); +#ifdef OLD_MEDIA_SESSION_WORKAROUND + /* + * XXX: temporary workaround for pipewire-media-session, see #2159 + */ + if (spa_streq(spa_dict_lookup(client->info.props, PW_KEY_APP_NAME), + "pipewire-media-session")) { + client->recv_generation = UINT64_MAX; + pw_log_info("impl-client %p: enable old pipewire-media-session workaround", + client); + } +#endif + return 0; } @@ -737,6 +749,9 @@ if ((global = pw_context_find_global(context, global_id)) == NULL) return -ENOENT; + if (client->recv_generation != 0 && global->generation > client->recv_generation) + return -ESTALE; + perms = pw_global_get_permissions(global, client); if ((perms & permissions) != permissions) return -EPERM;
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-core.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-core.c
Changed
@@ -64,6 +64,9 @@ if (!PW_PERM_IS_R(permissions)) goto error_no_id; + if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation) + goto error_stale_id; + if (!spa_streq(global->type, type)) goto error_wrong_interface; @@ -75,6 +78,12 @@ return NULL; +error_stale_id: + pw_log_debug("registry %p: not binding stale global " + "id %u to %u, generation:%"PRIu64" recv-generation:%"PRIu64, + resource, id, new_id, global->generation, resource->client->recv_generation); + pw_resource_errorf_id(resource, new_id, -ESTALE, "no global %u any more", id); + goto error_exit_clean; error_no_id: pw_log_debug("registry %p: no global with id %u to bind to %u", resource, id, new_id); pw_resource_errorf_id(resource, new_id, -ENOENT, "no global %u", id); @@ -110,6 +119,9 @@ if (!PW_PERM_IS_R(permissions)) goto error_no_id; + if (resource->client->recv_generation != 0 && global->generation > resource->client->recv_generation) + goto error_stale_id; + if (id == PW_ID_CORE || !PW_PERM_IS_X(permissions)) goto error_not_allowed; @@ -118,6 +130,13 @@ pw_global_destroy(global); return 0; +error_stale_id: + pw_log_debug("registry %p: not destroying stale global " + "id %u, generation:%"PRIu64" recv-generation:%"PRIu64, + resource, id, global->generation, resource->client->recv_generation); + pw_resource_errorf(resource, -ESTALE, "no global %u any more", id); + res = -ESTALE; + goto error_exit; error_no_id: pw_log_debug("registry %p: no global with id %u to destroy", resource, id); pw_resource_errorf(resource, -ENOENT, "no global %u", id);
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-device.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-device.c
Changed
@@ -27,6 +27,7 @@ #include <spa/debug/types.h> #include <spa/monitor/utils.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/utils/string.h> #include "pipewire/impl.h" @@ -324,7 +325,7 @@ if (pi->user == 1) { struct pw_param *p; uint8_t buffer4096; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; struct spa_result_device_params result; uint32_t count = 0; @@ -339,14 +340,15 @@ if (result.index < index) continue; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, p->param, filter) != 0) - continue; - - pw_log_debug("%p: %d param %u", device, seq, result.index); - result_device_params(&user_data, seq, 0, SPA_RESULT_TYPE_DEVICE_PARAMS, &result); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_pod_filter(&b.b, &result.param, p->param, filter) == 0) { + pw_log_debug("%p: %d param %u", device, seq, result.index); + result_device_params(&user_data, seq, 0, SPA_RESULT_TYPE_DEVICE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == max) + if (count == max) break; } res = 0;
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-link.c
Changed
@@ -1209,8 +1209,6 @@ this->user_data = SPA_PTROFF(impl, sizeof(struct impl), void); impl->work = pw_context_get_work_queue(context); - if (impl->work == NULL) - goto error_work_queue; this->context = context; this->properties = properties; @@ -1309,10 +1307,6 @@ res = -errno; pw_log_debug("alloc failed: %m"); goto error_exit; -error_work_queue: - res = -errno; - pw_log_debug("work queue failed: %m"); - goto error_free; error_output_mix: pw_log_error("%p: can't get output mix %d (%s)", this, res, spa_strerror(res)); goto error_free;
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-module.c
Changed
@@ -44,6 +44,7 @@ struct impl { struct pw_impl_module this; void *hnd; + uint32_t destroy_work_id; }; #define pw_module_resource_info(r,...) pw_resource_call(r,struct pw_module_events,info,0,__VA_ARGS__) @@ -220,6 +221,7 @@ goto error_no_mem; impl->hnd = hnd; + impl->destroy_work_id = SPA_ID_INVALID; hnd = NULL; this = &impl->this; @@ -336,6 +338,10 @@ spa_hook_list_clean(&module->listener_list); + if (impl->destroy_work_id != SPA_ID_INVALID) + pw_work_queue_cancel(pw_context_get_work_queue(module->context), + module, SPA_ID_INVALID); + if (!pw_in_valgrind() && dlclose(impl->hnd) != 0) pw_log_warn("%p: dlclose failed: %s", module, dlerror()); free(impl); @@ -398,3 +404,20 @@ { spa_hook_list_append(&module->listener_list, listener, events, data); } + +static void do_destroy_module(void *obj, void *data, int res, uint32_t id) +{ + pw_impl_module_destroy(obj); +} + +SPA_EXPORT +void pw_impl_module_schedule_destroy(struct pw_impl_module *module) +{ + struct impl *impl = SPA_CONTAINER_OF(module, struct impl, this); + + if (impl->destroy_work_id != SPA_ID_INVALID) + return; + + impl->destroy_work_id = pw_work_queue_add(pw_context_get_work_queue(module->context), + module, 0, do_destroy_module, NULL); +}
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-node.c
Changed
@@ -32,6 +32,7 @@ #include <spa/support/system.h> #include <spa/pod/parser.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/node/utils.h> #include <spa/debug/types.h> #include <spa/utils/string.h> @@ -1236,10 +1237,6 @@ } impl->work = pw_context_get_work_queue(this->context); - if (impl->work == NULL) { - res = -errno; - goto error_clean; - } impl->pending_id = SPA_ID_INVALID; this->data_loop = context->data_loop; @@ -1971,7 +1968,7 @@ if (pi->user == 1) { struct pw_param *p; uint8_t buffer4096; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; @@ -1986,14 +1983,16 @@ if (result.index < index) continue; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, p->param, filter) != 0) - continue; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); - pw_log_debug("%p: %d param %u", node, seq, result.index); - result_node_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + if (spa_pod_filter(&b.b, &result.param, p->param, filter) == 0) { + pw_log_debug("%p: %d param %u", node, seq, result.index); + result_node_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == max) + if (count == max) break; } res = 0;
View file
pipewire-0.3.47.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.48.tar.gz/src/pipewire/impl-port.c
Changed
@@ -34,6 +34,7 @@ #include <spa/utils/string.h> #include <spa/debug/types.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include "pipewire/impl.h" #include "pipewire/private.h" @@ -229,17 +230,19 @@ { uint32_t idx = 0; uint8_t buffer1024; - struct spa_pod_builder b; + struct spa_pod_dynamic_builder b; struct spa_pod *param; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_node_port_enum_params_sync(port->mix, pw_direction_reverse(port->direction), 0, - SPA_PARAM_Format, &idx, NULL, ¶m, &b) == 1) { + SPA_PARAM_Format, &idx, NULL, ¶m, &b.b) == 1) { spa_node_port_set_param(port->mix, port->direction, port_id, SPA_PARAM_Format, 0, param); } + spa_pod_dynamic_builder_clean(&b); } spa_list_append(&port->mix_list, &mix->link); @@ -1216,7 +1219,7 @@ if (pi->user == 1) { struct pw_param *p; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; @@ -1231,14 +1234,16 @@ if (result.index < index) continue; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, p->param, filter) != 0) - continue; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); - pw_log_debug("%p: %d param %u", port, seq, result.index); - result_port_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + if (spa_pod_filter(&b.b, &result.param, p->param, filter) >= 0) { + pw_log_debug("%p: %d param %u", port, seq, result.index); + result_port_params(&user_data, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == max) + if (count == max) break; } res = 0;
View file
pipewire-0.3.47.tar.gz/src/pipewire/meson.build -> pipewire-0.3.48.tar.gz/src/pipewire/meson.build
Changed
@@ -91,6 +91,7 @@ install_headers(pipewire_headers, subdir : pipewire_headers_dir) libpipewire_c_args = + '-DOLD_MEDIA_SESSION_WORKAROUND=1' if build_machine.system() != 'freebsd'
View file
pipewire-0.3.47.tar.gz/src/pipewire/private.h -> pipewire-0.3.48.tar.gz/src/pipewire/private.h
Changed
@@ -299,6 +299,8 @@ struct pw_protocol *protocol; /**< protocol in use */ int recv_seq; /**< last received sequence number */ int send_seq; /**< last sender sequence number */ + uint64_t recv_generation; /**< last received registry generation */ + uint64_t sent_generation; /**< last sent registry generation */ void *user_data; /**< extra user data */ @@ -334,6 +336,7 @@ pw_global_bind_func_t func; /**< bind function */ void *object; /**< object associated with the interface */ uint64_t serial; /**< increasing serial number */ + uint64_t generation; /**< registry generation number */ struct spa_list resource_list; /**< The list of resources of this global */ @@ -430,6 +433,7 @@ uint64_t stamp; uint64_t serial; + uint64_t generation; /**< registry generation number */ struct pw_map globals; /**< map of globals */ struct spa_list core_impl_list; /**< list of core_imp */ @@ -1001,6 +1005,7 @@ struct pw_protocol_client *conn; /**< the protocol client connection */ int recv_seq; /**< last received sequence number */ int send_seq; /**< last protocol result code */ + uint64_t recv_generation; /**< last received registry generation */ unsigned int removed:1; unsigned int destroyed:1; @@ -1279,6 +1284,8 @@ int pw_settings_expose(struct pw_context *context); void pw_settings_clean(struct pw_context *context); +void pw_impl_module_schedule_destroy(struct pw_impl_module *module); + /** \endcond */ #ifdef __cplusplus
View file
pipewire-0.3.47.tar.gz/src/pipewire/stream.c -> pipewire-0.3.48.tar.gz/src/pipewire/stream.c
Changed
@@ -34,6 +34,7 @@ #include <spa/node/utils.h> #include <spa/utils/ringbuffer.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/debug/format.h> #include <spa/debug/types.h> #include <spa/debug/pod.h> @@ -135,8 +136,9 @@ uint32_t change_mask_all; struct spa_node_info info; -#define IDX_Props 0 -#define N_NODE_PARAMS 1 +#define IDX_PropInfo 0 +#define IDX_Props 1 +#define N_NODE_PARAMS 2 struct spa_param_info paramsN_NODE_PARAMS; uint32_t media_type; @@ -173,6 +175,8 @@ static int get_param_index(uint32_t id) { switch (id) { + case SPA_PARAM_PropInfo: + return IDX_PropInfo; case SPA_PARAM_Props: return IDX_Props; default: @@ -483,7 +487,7 @@ struct stream *d = object; struct spa_result_node_params result; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + struct spa_pod_dynamic_builder b; uint32_t count = 0; struct param *p; bool found = false; @@ -510,13 +514,14 @@ found = true; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - if (spa_pod_filter(&b, &result.param, param, filter) != 0) - continue; - - spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + if (spa_pod_filter(&b.b, &result.param, param, filter) == 0) { + spa_node_emit_result(&d->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - if (++count == num) + if (count == num) break; } return found ? 0 : -ENOENT; @@ -1724,6 +1729,7 @@ if (!impl->process_rt) impl->info.flags |= SPA_NODE_FLAG_ASYNC; impl->info.props = &stream->properties->dict; + impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); impl->info.params = impl->params; impl->info.n_params = N_NODE_PARAMS;
View file
pipewire-0.3.47.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.48.tar.gz/src/tools/pw-cli.c
Changed
@@ -40,7 +40,7 @@ #define FNM_EXTMATCH 0 #endif -#define spa_debug(fmt,...) printf(fmt, ## __VA_ARGS__) +#define spa_debug(fmt,...) printf(fmt"\n", ## __VA_ARGS__) #include <spa/utils/result.h> #include <spa/utils/string.h>
View file
pipewire-0.3.47.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.48.tar.gz/src/tools/pw-loopback.c
Changed
@@ -202,7 +202,11 @@ } - f = open_memstream(&args, &size); + if ((f = open_memstream(&args, &size)) == NULL) { + fprintf(stderr, "can't open memstream: %m\n"); + goto exit; + } + fprintf(f, "{"); if (opt_remote != NULL)
View file
pipewire-0.3.47.tar.gz/src/tools/pw-top.c -> pipewire-0.3.48.tar.gz/src/tools/pw-top.c
Changed
@@ -241,9 +241,8 @@ return buf; } -static void print_node(struct data *d, struct driver *i, struct node *n) +static void print_node(struct data *d, struct driver *i, struct node *n, int y) { - char line1024; char buf164; char buf264; char buf364; @@ -264,7 +263,7 @@ waiting = (n->measurement.awake - n->measurement.signal) / 1000000000.f, busy = (n->measurement.finish - n->measurement.awake) / 1000000000.f, - snprintf(line, sizeof(line), "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s", + mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s", n->measurement.status != 3 ? "!" : " ", n->id, frac.num, frac.denom, @@ -275,13 +274,12 @@ i->xrun_count + n->errors, n->driver == n ? "" : " + ", n->name); - - wprintw(d->win, "%.*s\n", COLS-1, line); } static void do_refresh(struct data *d) { struct node *n, *t, *f; + int y = 1; wclear(d->win); wattron(d->win, A_REVERSE); @@ -293,15 +291,25 @@ if (n->driver != n) continue; - print_node(d, &n->info, n); + print_node(d, &n->info, n, y++); + if(y > LINES) + break; spa_list_for_each(f, &d->node_list, link) { if (f->driver != n || f == n) continue; - print_node(d, &n->info, f); + print_node(d, &n->info, f, y++); + if(y > LINES) + break; + } } + + // Clear from last line to the end of the window to hide text wrapping from the last node + wmove(d->win, y, 0); + wclrtobot(d->win); + wrefresh(d->win); }
View file
pipewire-0.3.47.tar.gz/test/test-loop.c -> pipewire-0.3.48.tar.gz/test/test-loop.c
Changed
@@ -227,11 +227,45 @@ return PWTEST_PASS; } +PWTEST(thread_loop_destroy_between_poll_and_lock) +{ + pw_init(NULL, NULL); + + struct pw_thread_loop *thread_loop = pw_thread_loop_new("uaf", NULL); + pwtest_ptr_notnull(thread_loop); + + struct pw_loop *loop = pw_thread_loop_get_loop(thread_loop); + pwtest_ptr_notnull(loop); + + int evfd = eventfd(0, 0); + pwtest_errno_ok(evfd); + + struct spa_source *source = pw_loop_add_io(loop, evfd, SPA_IO_IN, true, NULL, NULL); + pwtest_ptr_notnull(source); + + pw_thread_loop_start(thread_loop); + + pw_thread_loop_lock(thread_loop); + { + write(evfd, &(uint64_t){1}, sizeof(uint64_t)); + sleep(1); + pw_loop_destroy_source(loop, source); + } + pw_thread_loop_unlock(thread_loop); + + pw_thread_loop_destroy(thread_loop); + + pw_deinit(); + + return PWTEST_PASS; +} + PWTEST_SUITE(support) { pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG); pwtest_add(pwtest_loop_recurse1, PWTEST_NOARG); pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG); + pwtest_add(thread_loop_destroy_between_poll_and_lock, PWTEST_NOARG); return PWTEST_PASS; }
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
.