Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 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 buffer[4096]; + 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 buffer[4096]; 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);
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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 @@ d[i][n] = sum; } } - for (i = 0; i < n_dst; i++) { - if (mix->lr4_info[i] > 0) - lr4_process(&mix->lr4[i], d[i], n_samples); - } + for (i = 0; i < n_dst; i++) + lr4_process(&mix->lr4[i], d[i], d[i], 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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][0]; @@ -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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][0]; @@ -251,33 +249,89 @@ else if (v0 == 1.0f && v1 == 1.0f) { for (n = 0; n < n_samples; n++) { float c = s[0][n] + s[1][n]; - d[0][n] = s[0][n]; - d[1][n] = s[1][n]; - d[2][n] = c * v2; - d[3][n] = c * v3; + float w = c * mix->widen; + d[0][n] = s[0][n] - w; + d[1][n] = s[1][n] - w; + d[2][n] = c; } - if (v3 > 0.0f) - lr4_process(&mix->lr4[3], d[3], n_samples); + lr4_process(&mix->lr4[3], d[3], d[2], v3, n_samples); + lr4_process(&mix->lr4[2], d[2], d[2], v2, n_samples); } else { for (n = 0; n < n_samples; n++) { float c = s[0][n] + s[1][n]; - d[0][n] = s[0][n] * v0; - d[1][n] = s[1][n] * v1; - d[2][n] = c * v2; - d[3][n] = c * v3; + float w = c * mix->widen; + d[0][n] = (s[0][n] - w) * v0; + d[1][n] = (s[1][n] - w) * v1; + d[2][n] = c; } - if (v3 > 0.0f) - lr4_process(&mix->lr4[3], d[3], n_samples); + lr4_process(&mix->lr4[3], d[3], d[2], v3, n_samples); + lr4_process(&mix->lr4[2], d[2], d[2], 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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][0]; + const float v1 = mix->matrix[1][1]; + const float v2 = (mix->matrix[2][0] + mix->matrix[2][1]) * 0.5f; + const float v3 = (mix->matrix[3][0] + mix->matrix[3][1]) * 0.5f; + const float v4 = mix->matrix[4][0]; + const float v5 = mix->matrix[5][1]; + + if (SPA_FLAG_IS_SET(mix->flags, CHANNELMIX_FLAG_ZERO)) { + for (i = 0; i < n_dst; i++) + memset(d[i], 0, n_samples * sizeof(float)); + } + else if (v0 == 1.0f && v1 == 1.0f) { + for (n = 0; n < n_samples; n++) { + float c = s[0][n] + s[1][n]; + float w = c * mix->widen; + float m = s[0][n] - s[1][n]; + d[0][n] = s[0][n] - w; + d[1][n] = s[1][n] - w; + d[3][n] = c; + d[5][n] = m; + } + lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples); + lr4_process(&mix->lr4[3], d[3], d[3], v3, n_samples); + + delay_convolve_run(mix->buffer[0], &mix->pos[0], BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d[4], d[5], v4, n_samples); + delay_convolve_run(mix->buffer[1], &mix->pos[1], BUFFER_SIZE, mix->delay, + mix->taps, mix->n_taps, d[5], d[5], -v5, n_samples); + } + else { + for (n = 0; n < n_samples; n++) { + float c = s[0][n] + s[1][n]; + float w = c * mix->widen; + float m = s[0][n] - s[1][n]; + d[0][n] = (s[0][n] - w) * v0; + d[1][n] = (s[1][n] - w) * v1; + d[3][n] = c; + d[5][n] = m; + } + lr4_process(&mix->lr4[2], d[2], d[3], v2, n_samples);
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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][0]; @@ -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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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(&sLFE[n]), llev)); in = _mm_mul_ps(_mm_load_ps(&sSL[n]), slev0); in = _mm_add_ps(in, ctr); - in = _mm_add_ps(in, _mm_load_ps(&sFL[n])); - in = _mm_mul_ps(in, v0); + in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFL[n]), v0)); _mm_store_ps(&dFL[n], in); in = _mm_mul_ps(_mm_load_ps(&sSR[n]), slev1); in = _mm_add_ps(in, ctr); - in = _mm_add_ps(in, _mm_load_ps(&sFR[n])); - in = _mm_mul_ps(in, v1); + in = _mm_add_ps(in, _mm_mul_ps(_mm_load_ps(&sFR[n]), v1)); _mm_store_ps(&dFR[n], in); } for(; n < n_samples; n++) { @@ -219,13 +217,11 @@ ctr = _mm_add_ss(ctr, _mm_mul_ss(_mm_load_ss(&sLFE[n]), llev)); in = _mm_mul_ss(_mm_load_ss(&sSL[n]), slev0); in = _mm_add_ss(in, ctr); - in = _mm_add_ss(in, _mm_load_ss(&sFL[n])); - in = _mm_mul_ss(in, v0); + in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFL[n]), v0)); _mm_store_ss(&dFL[n], in); in = _mm_mul_ss(_mm_load_ss(&sSR[n]), slev1); in = _mm_add_ss(in, ctr); - in = _mm_add_ss(in, _mm_load_ss(&sFR[n])); - in = _mm_mul_ss(in, v1); + in = _mm_add_ss(in, _mm_mul_ss(_mm_load_ss(&sFR[n]), v1)); _mm_store_ss(&dFR[n], 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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][0]); @@ -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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->matrix[0][2]);
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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_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->lr4[ic], BQ_LOWPASS, mix->lfe_cutoff / mix->freq); - mix->lr4_info[ic] = 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->lr4[ic], BQ_LOWPASS, mix->fc_cutoff / mix->freq); } else { - mix->lr4_info[ic] = 0; + mix->lr4[ic].active = false; } ic++; } @@ -467,6 +473,7 @@ for (j = 0; j < jc; j++) mix->matrix_orig[i][j] /= 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->taps[0] = 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_info[SPA_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 lr4[SPA_AUDIO_MAX_CHANNELS]; - void (*process) (struct channelmix *mix, uint32_t n_dst, void * SPA_RESTRICT dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_src], uint32_t n_samples); + float buffer[2][BUFFER_SIZE]; + uint32_t pos[2]; + uint32_t delay; + float taps[MAX_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 dst[n_dst], \ - uint32_t n_src, const void * SPA_RESTRICT src[n_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, &f[1]); + 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, &f[1]); param = spa_pod_builder_pop(&b, &f[0]); 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 dst[n_dst], - uint32_t n_src, const void * SPA_RESTRICT src[n_src],
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++) + dst[i] = src[i] * vol; + } + return; + } + for (i = 0; i < samples; i++) { float x, y, z; - x = data[i]; + x = src[i]; 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; - data[i] = z; + dst[i] = 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++) { + buffer[p] = src[i]; + dst[i] = 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; + + buffer[p] = src[i]; + for (j = 0; j < n_taps; j++) + sum += (taps[j] * buffer[((p - delay) - j) & (n_buffer-1)]); + dst[i] = 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); + taps[n] = 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; + taps[i] *= (1.0f - cosf(pk)) / pk; + } else { + taps[i] = 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 f[2]; +#endif switch (result.index) { +#if 0 case 0: spa_pod_builder_push_object(&b, &f[0], SPA_TYPE_OBJECT_Props, id); @@ -422,6 +425,7 @@ spa_pod_builder_pop(&b, &f[1]); param = spa_pod_builder_pop(&b, &f[0]); 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 = ep[i].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 buffer[1024]; - 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 buffer[1024]; - 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 buf[4096]; - 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)); - params[n_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)); + params[n_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 buf[4096]; - 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)); + params[n_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)); - params[n_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_buffer[i]) free(impl->rec_buffer[i]); @@ -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_data[MAX_SAMPLES]; @@ -136,11 +135,11 @@ uint32_t n_output; uint32_t n_control; uint32_t n_notify; - unsigned long input[MAX_PORTS]; - unsigned long output[MAX_PORTS]; - unsigned long control[MAX_PORTS]; - unsigned long notify[MAX_PORTS]; - float default_control[MAX_PORTS]; + unsigned long *input; + unsigned long *output; + unsigned long *control; + unsigned long *notify; + float *default_control; }; struct port { @@ -167,10 +166,10 @@ char name[256]; char *config; - struct port input_port[MAX_PORTS]; - struct port output_port[MAX_PORTS]; - struct port control_port[MAX_PORTS]; - struct port notify_port[MAX_PORTS]; + struct port *input_port; + struct port *output_port; + struct port *control_port; + struct port *notify_port; uint32_t n_hndl; void *hndl[MAX_HNDL]; @@ -207,23 +206,22 @@ struct spa_list link_list; uint32_t n_input; - struct graph_port input[MAX_PORTS]; + struct graph_port *input; uint32_t n_output; - struct graph_port output[MAX_PORTS]; + struct graph_port *output; uint32_t n_hndl; - struct graph_hndl hndl[MAX_HNDL]; + struct graph_hndl *hndl; uint32_t n_control; - struct port *control_port[MAX_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 *params[256]; - struct spa_pod_builder b; + uint32_t offsets[512]; + const struct spa_pod *params[512]; + 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); - params[n_params++] = spa_format_audio_raw_build(&b, + offsets[n_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++) - params[n_params++] = get_prop_info(graph, &b, i); + for (i = 0; i < graph->n_control; i++) { + offsets[n_params++] = b.b.state.offset; + get_prop_info(graph, &b.b, i); + } - params[n_params++] = get_props_param(graph, &b); + offsets[n_params++] = b.b.state.offset; + get_props_param(graph, &b.b); + + for (i = 0; i < n_params; i++) + params[i] = spa_pod_builder_deref(&b.b, offsets[i]); 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); - params[n_params++] = spa_format_audio_raw_build(&b, + spa_pod_dynamic_builder_init(&b, NULL, 0, 4096); + params[n_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 @@
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_str[32]; + struct spa_dict_item items[1] = { + 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 f[2]; + 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, &f[0]) < 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, &f[1]) < 0) + break; + if (opcode < n_opcodes) { + if ((ret = opcodes[opcode].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, &f[1]); + } +} + 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_demarshal[FOOTER_CORE_OPCODE_LAST] = { + [FOOTER_CORE_OPCODE_GENERATION] = (struct footer_demarshal){ .demarshal = demarshal_core_generation }, +}; + +const struct footer_demarshal footer_client_demarshal[FOOTER_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_demarshal[FOOTER_CORE_OPCODE_LAST]; +extern const struct footer_demarshal footer_client_demarshal[FOOTER_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 || name[0] == '\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.position[0] = SPA_AUDIO_CHANNEL_FL; + info.info.raw.position[1] = 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 ? "" : ",", values[i]);
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 items[5]; - char latency[32]; + struct spa_dict_item items[6]; + char latency[32], rate[32]; char attr_maxlength[32]; char attr_tlength[32]; char attr_prebuf[32]; @@ -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); items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); - items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); - items[2] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength); - items[3] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf); - items[4] = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq); - pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 5)); + items[1] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate); + items[2] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); + items[3] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength); + items[4] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf); + items[5] = 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 items[3]; - char latency[32]; + struct spa_dict_item items[4]; + char latency[32], rate[32]; char attr_maxlength[32]; char attr_fragsize[32]; 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); items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); - items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); - items[2] = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize); - pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 3)); + items[1] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_RATE, rate); + items[2] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); + items[3] = 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 && (params[n_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)
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 key[AES_CHUNK_SIZE]; /* Key for aes-cbc */ uint8_t iv[AES_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_str[32]; + struct spa_dict_item items[1] = { + 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_str[32]; + struct spa_dict_item items[1] = { + 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_str[32]; + struct spa_dict_item items[1] = { + 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_str[32]; + struct spa_dict_item items[1] = { + 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)
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->support[n_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 params[N_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 buffer[1024]; - 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->params[IDX_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); impl->params[IDX_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 buffer[4096]; - 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 buffer[4096]; - 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 buffer[1024]; - 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 buffer[1024]; - 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 params[N_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 buffer[1024]; - 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->params[IDX_PropInfo] = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); impl->params[IDX_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 line[1024]; char buf1[64]; char buf2[64]; char buf3[64]; @@ -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
.