Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 19
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Fri Dec 16 18:14:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.62 + +------------------------------------------------------------------- Sat Dec 3 00:09:52 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.61
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.61 +Version: 0.3.62 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.61.tar.gz/NEWS -> pipewire-0.3.62.tar.gz/NEWS
Changed
@@ -1,3 +1,80 @@ +# PipeWire 0.3.62 (2022-12-09) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - A regression in screensharing was fixed. It was caused by a race when + activating links and driver nodes. + - Video transform metadata was added so that cameras and screen sharing + can report the video orientation and transformations. + - Support for the PulseAudio module-gsettings was added to make paprefs + work. + - Support for bluetooth offloading was added. This allows for the bluetooth + reception, decoding and playback to happen completely in hardware. + This also requires some support in WirePlumber. + - Many bugfixes and improvements. + + +## PipeWire + - More work on stopping nodes in a more controlled way. + - Fix a race in starting nodes and drivers. In some cases the driver + node would already be started while the link to the peer node was not + ready yet. This caused regressions in screen sharing. The driver is + now only started after all the followers and links completed. + - Fix a case where a slow capture stream would not recycle buffers + anymore and stall. (#2874) + - Fix a subtle bug in pw_loop_invoke that could cause callbacks to be + delayed and cause crashes in some cases. + - Fix a case where IPC was done from the data-thread and could cause + crashes. + +## Tools + - Silence some expected errors in the pw-top output. + +## modules + - The filter-chain has seen some optimizations in the copy plugin and + the convolver. + - The zeroconf plugin will now only unpublish services from the server + that was removed. + - Fix a potential crash when stopping pw-loopback. + - Some harmless errors were turned into info messages. + - Fix some cases where pw_stream methods were called from the data-thread + that could cause segfaults. (#2633) + +## SPA + - There is now a video transform metadata that indicates how a video + frame was transformed (rotated/flipped). libcamera and the GStreamer + elements now have support for this metadata. + - The SPA volume plugin is now disabled from the default build. + - Handle missing control info in libcamera. + - Handle errors from loop better, don't call the callbacks on errors. + - Somewhat improve performance in some audioconvert AVX2 code for format + conversion. + - Fix PortConfig and EnumPortConfig params in audioconvert and + audioadapter to reflect what is actually going on instead of using + hardcoded values. + - Pass ignore-dB property correctly in all cases. + - Probing is now done in 48KHz again. (#2857) + +## Pulse-server + - IPv4 addresses are now added first to the list and exposed first with + zeroconf discover. + - module-gsettings was added to make paprefs work. + - The pulse.idle.timeout option was disabled by default and only enabled + for selected apps (speech-dispatcher) because it caused some problems + for other apps. (#2880) + +## JACK + - Only process valid ports. Could fix some crashes. (#2863) + +## Bluetooth + - Support was added for offloading bluetooth handling. Some hardware can + receive, decode and play the bluetooth audio directly in hardware. + + +Older versions: + # PipeWire 0.3.61 (2022-11-24) This is a bugfix release that is API and ABI compatible with previous @@ -65,9 +142,6 @@ - Add option to set node.passive on jack clients. Make some quirks for qsynth to make it suspend and fade out better. - -Older versions: - # PipeWire 0.3.60 (2022-11-10) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.61.tar.gz/meson.build -> pipewire-0.3.62.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.61', + version : '0.3.62', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.59.0', default_options : 'warning_level=3', @@ -301,6 +301,9 @@ flatpak_support = glib2_dep.found() cdata.set('HAVE_GLIB2', flatpak_support) +gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : get_option('gsettings')) +summary({'GIO (GSettings)': gio_dep.found()}, bool_yn: true, section: 'Misc dependencies') + gst_option = get_option('gstreamer') gst_deps_def = { 'glib-2.0': {'version': '>=2.32.0'},
View file
pipewire-0.3.61.tar.gz/meson_options.txt -> pipewire-0.3.62.tar.gz/meson_options.txt
Changed
@@ -177,9 +177,9 @@ type: 'feature', value: 'enabled') option('volume', - description: 'Enable volume spa plugin integration', + description: 'Build the legacy volume spa plugin', type: 'feature', - value: 'enabled') + value: 'disabled') option('vulkan', description: 'Enable vulkan spa plugin integration', type: 'feature', @@ -269,3 +269,7 @@ description: 'Enable code that depends on libreadline', type: 'feature', value: 'auto') +option('gsettings', + description: 'Enable code that depends on gsettings', + type: 'feature', + value: 'auto')
View file
pipewire-0.3.61.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.62.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -1144,6 +1144,8 @@ if (pw_map_item_is_free(item)) continue; p = item->data; + if (!p->valid) + continue; spa_list_for_each(mix, &p->mix, port_link) { if (SPA_LIKELY(mix->io != NULL)) mix->io->status = SPA_STATUS_NEED_DATA; @@ -1153,6 +1155,8 @@ if (pw_map_item_is_free(item)) continue; p = item->data; + if (!p->valid) + continue; prepare_output(p, frames); p->io.status = SPA_STATUS_NEED_DATA; }
View file
pipewire-0.3.61.tar.gz/spa/include/spa/buffer/meta.h -> pipewire-0.3.62.tar.gz/spa/include/spa/buffer/meta.h
Changed
@@ -39,16 +39,17 @@ enum spa_meta_type { SPA_META_Invalid, - SPA_META_Header, /**< struct spa_meta_header */ - SPA_META_VideoCrop, /**< struct spa_meta_region with cropping data */ - SPA_META_VideoDamage, /**< array of struct spa_meta_region with damage, where an invalid entry or end-of-array marks the end. */ - SPA_META_Bitmap, /**< struct spa_meta_bitmap */ - SPA_META_Cursor, /**< struct spa_meta_cursor */ - SPA_META_Control, /**< metadata contains a spa_meta_control - * associated with the data */ - SPA_META_Busy, /**< don't write to buffer when count > 0 */ - - _SPA_META_LAST, /**< not part of ABI/API */ + SPA_META_Header, /**< struct spa_meta_header */ + SPA_META_VideoCrop, /**< struct spa_meta_region with cropping data */ + SPA_META_VideoDamage, /**< array of struct spa_meta_region with damage, where an invalid entry or end-of-array marks the end. */ + SPA_META_Bitmap, /**< struct spa_meta_bitmap */ + SPA_META_Cursor, /**< struct spa_meta_cursor */ + SPA_META_Control, /**< metadata contains a spa_meta_control + * associated with the data */ + SPA_META_Busy, /**< don't write to buffer when count > 0 */ + SPA_META_VideoTransform, /**< struct spa_meta_transform */ + + _SPA_META_LAST, /**< not part of ABI/API */ }; /** @@ -161,6 +162,24 @@ uint32_t count; /**< number of users busy with the buffer */ }; +enum spa_meta_videotransform_value { + SPA_META_TRANSFORMATION_None = 0, /**< no transform */ + SPA_META_TRANSFORMATION_90, /**< 90 degree counter-clockwise */ + SPA_META_TRANSFORMATION_180, /**< 180 degree counter-clockwise */ + SPA_META_TRANSFORMATION_270, /**< 270 degree counter-clockwise */ + SPA_META_TRANSFORMATION_Flipped, /**< 180 degree flipped around the vertical axis. Equivalent + * to a reflexion through the vertical line splitting the + * bufffer in two equal sized parts */ + SPA_META_TRANSFORMATION_Flipped90, /**< flip then rotate around 90 degree counter-clockwise */ + SPA_META_TRANSFORMATION_Flipped180, /**< flip then rotate around 180 degree counter-clockwise */ + SPA_META_TRANSFORMATION_Flipped270, /**< flip then rotate around 270 degree counter-clockwise */ +}; + +/** a transformation of the buffer */ +struct spa_meta_videotransform { + uint32_t transform; /**< orientation transformation that was applied to the buffer */ +}; + /** * \} */
View file
pipewire-0.3.61.tar.gz/spa/include/spa/param/props.h -> pipewire-0.3.62.tar.gz/spa/include/spa/param/props.h
Changed
@@ -74,6 +74,7 @@ SPA_PROP_rate, SPA_PROP_quality, SPA_PROP_bluetoothAudioCodec, + SPA_PROP_bluetoothOffloadActive, SPA_PROP_START_Audio = 0x10000, /**< audio related properties */ SPA_PROP_waveType,
View file
pipewire-0.3.61.tar.gz/spa/include/spa/param/type-info.h -> pipewire-0.3.62.tar.gz/spa/include/spa/param/type-info.h
Changed
@@ -117,6 +117,7 @@ { SPA_PROP_rate, SPA_TYPE_Double, SPA_TYPE_INFO_PROPS_BASE "rate", NULL }, { SPA_PROP_quality, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "quality", NULL }, { SPA_PROP_bluetoothAudioCodec, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "bluetoothAudioCodec", spa_type_bluetooth_audio_codec }, + { SPA_PROP_bluetoothOffloadActive, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "bluetoothOffloadActive", NULL }, { SPA_PROP_waveType, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "waveType", NULL }, { SPA_PROP_frequency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "frequency", NULL },
View file
pipewire-0.3.61.tar.gz/spa/plugins/aec/aec-webrtc.cpp -> pipewire-0.3.62.tar.gz/spa/plugins/aec/aec-webrtc.cpp
Changed
@@ -100,7 +100,8 @@ } apm->high_pass_filter()->Enable(high_pass_filter); - // Always disable drift compensation since it requires drift sampling + // Always disable drift compensation since PipeWire will already do + // drift compensation on all sinks and sources linked to this echo-canceler apm->echo_cancellation()->enable_drift_compensation(false); apm->echo_cancellation()->Enable(true); // TODO: wire up supression levels to args
View file
pipewire-0.3.61.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.62.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -34,7 +34,7 @@ struct spa_i18n *acp_i18n; -#define DEFAULT_RATE 44100 +#define DEFAULT_RATE 48000 #define VOLUME_ACCURACY (PA_VOLUME_NORM/100) /* don't require volume adjustments to be perfectly correct. don't necessarily extend granularity in software unless the differences get greater than this level */ @@ -1348,7 +1348,6 @@ static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device *dev) { const char *mod_name; - bool ignore_dB = false; uint32_t i, port_index; int res; @@ -1365,7 +1364,7 @@ dev->device.flags |= ACP_DEVICE_ACTIVE; - find_mixer(impl, dev, NULL, ignore_dB); + find_mixer(impl, dev, NULL, impl->ignore_dB); /* Synchronize priority values, as it may have changed when setting the profile */ for (i = 0; i < impl->card.n_ports; i++) { @@ -1386,7 +1385,7 @@ if (dev->active_port) dev->active_port->port.flags |= ACP_PORT_ACTIVE; - if ((res = setup_mixer(impl, dev, ignore_dB)) < 0) + if ((res = setup_mixer(impl, dev, impl->ignore_dB)) < 0) return res; if (dev->read_volume) @@ -1533,7 +1532,6 @@ struct acp_card *card; const char *s, *profile_set = NULL, *profile = NULL; char device_id16; - bool ignore_dB = false; uint32_t profile_index; int res; @@ -1554,6 +1552,7 @@ impl->use_ucm = true; impl->auto_profile = true; impl->auto_port = true; + impl->ignore_dB = false; if (props) { if ((s = acp_dict_lookup(props, "api.alsa.use-ucm")) != NULL) @@ -1561,7 +1560,7 @@ if ((s = acp_dict_lookup(props, "api.alsa.soft-mixer")) != NULL) impl->soft_mixer = spa_atob(s); if ((s = acp_dict_lookup(props, "api.alsa.ignore-dB")) != NULL) - ignore_dB = spa_atob(s); + impl->ignore_dB = spa_atob(s); if ((s = acp_dict_lookup(props, "device.profile-set")) != NULL) profile_set = s; if ((s = acp_dict_lookup(props, "device.profile")) != NULL) @@ -1609,7 +1608,7 @@ goto error; } - impl->profile_set->ignore_dB = ignore_dB; + impl->profile_set->ignore_dB = impl->ignore_dB; pa_alsa_profile_set_probe(impl->profile_set, impl->ucm.mixers, device_id,
View file
pipewire-0.3.61.tar.gz/spa/plugins/alsa/acp/card.h -> pipewire-0.3.62.tar.gz/spa/plugins/alsa/acp/card.h
Changed
@@ -46,6 +46,7 @@ bool soft_mixer; bool auto_profile; bool auto_port; + bool ignore_dB; pa_alsa_ucm_config ucm; pa_alsa_profile_set *profile_set;
View file
pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -138,6 +138,27 @@ return 0; } +static int convert_enum_port_config(struct impl *this, + int seq, uint32_t id, uint32_t start, uint32_t num, + const struct spa_pod *filter, struct spa_pod_builder *builder) +{ + struct spa_pod *f1, *f2 = NULL; + int res; + + f1 = spa_pod_builder_add_object(builder, + SPA_TYPE_OBJECT_ParamPortConfig, id, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(this->direction)); + + if (filter) { + if ((res = spa_pod_filter(builder, &f2, f1, filter)) < 0) + return res; + } + else { + f2 = f1; + } + return spa_node_enum_params(this->convert, seq, id, start, num, f2); +} + static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, const struct spa_pod *filter) @@ -163,9 +184,25 @@ switch (id) { case SPA_PARAM_EnumPortConfig: + return convert_enum_port_config(this, seq, id, start, num, filter, &b.b); case SPA_PARAM_PortConfig: - res = spa_node_enum_params(this->convert, seq, id, start, num, filter); - return res; + if (this->passthrough) { + switch (result.index) { + case 0: + result.param = spa_pod_builder_add_object(&b.b, + SPA_TYPE_OBJECT_ParamPortConfig, id, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(this->direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id( + SPA_PARAM_PORT_CONFIG_MODE_passthrough)); + result.next++; + break; + default: + return 0; + } + } else { + return convert_enum_port_config(this, seq, id, start, num, filter, &b.b); + } + break; case SPA_PARAM_PropInfo: res = follower_enum_params(this, id, IDX_PropInfo, &result, filter, &b.b); @@ -813,9 +850,11 @@ this->started = true; break; case SPA_NODE_COMMAND_Suspend: + this->started = false; spa_log_debug(this->log, "%p: suspending", this); break; case SPA_NODE_COMMAND_Pause: + this->started = false; spa_log_debug(this->log, "%p: pausing", this); break; case SPA_NODE_COMMAND_Flush: @@ -847,10 +886,10 @@ break; case SPA_NODE_COMMAND_Suspend: configure_format(this, 0, NULL); - SPA_FALLTHROUGH + spa_log_debug(this->log, "%p: suspended", this); + break; case SPA_NODE_COMMAND_Pause: - this->started = false; - spa_log_debug(this->log, "%p: stopped", this); + spa_log_debug(this->log, "%p: paused", this); break; case SPA_NODE_COMMAND_Flush: spa_log_debug(this->log, "%p: flushed", this); @@ -1164,7 +1203,7 @@ spa_log_trace_fp(this->log, "%p: ready %d", this, status); if (!this->started) { - spa_log_warn(this->log, "%p: ready stopped node", this); + spa_log_info(this->log, "%p: ready stopped node", this); return -EIO; }
View file
pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -161,6 +161,7 @@ struct port *portsMAX_PORTS; uint32_t n_ports; + enum spa_direction direction; enum spa_param_port_config_mode mode; struct spa_audio_info format; @@ -378,55 +379,61 @@ switch (id) { case SPA_PARAM_EnumPortConfig: + { + struct dir *dir; switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp)); + dir = &this->dirSPA_DIRECTION_INPUT;; break; case 1: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_OUTPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp)); - break; - case 2: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert)); - break; - case 3: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_OUTPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_convert)); + dir = &this->dirSPA_DIRECTION_OUTPUT;; break; default: return 0; } + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamPortConfig, id, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(dir->direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_CHOICE_ENUM_Id(4, + SPA_PARAM_PORT_CONFIG_MODE_none, + SPA_PARAM_PORT_CONFIG_MODE_none, + SPA_PARAM_PORT_CONFIG_MODE_dsp, + SPA_PARAM_PORT_CONFIG_MODE_convert), + SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_CHOICE_Bool(false), + SPA_PARAM_PORT_CONFIG_control, SPA_POD_CHOICE_Bool(false)); break; - + } case SPA_PARAM_PortConfig: + { + struct dir *dir; + struct spa_pod_frame f1; + switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_INPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(this->dirSPA_DIRECTION_INPUT.mode)); + dir = &this->dirSPA_DIRECTION_INPUT;; break; case 1: - param = spa_pod_builder_add_object(&b, - SPA_TYPE_OBJECT_ParamPortConfig, id, - SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_OUTPUT), - SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(this->dirSPA_DIRECTION_OUTPUT.mode)); + dir = &this->dirSPA_DIRECTION_OUTPUT;; break; default: return 0; } + spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_ParamPortConfig, id); + spa_pod_builder_add(&b, + SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(dir->direction), + SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(dir->mode), + SPA_PARAM_PORT_CONFIG_monitor, SPA_POD_Bool(this->monitor), + SPA_PARAM_PORT_CONFIG_control, SPA_POD_Bool(dir->control), + 0); + + if (dir->have_format) { + spa_pod_builder_prop(&b, SPA_PARAM_PORT_CONFIG_format, 0); + spa_format_audio_raw_build(&b, SPA_PARAM_PORT_CONFIG_format, + &dir->format.info.raw); + } + param = spa_pod_builder_pop(&b, &f0); break; - + } case SPA_PARAM_PropInfo: { struct props *p = &this->props; @@ -1015,6 +1022,8 @@ init_port(this, direction, 0, 0, false, false, false); break; } + case SPA_PARAM_PORT_CONFIG_MODE_none: + break; default: return -ENOTSUP; } @@ -2906,7 +2915,9 @@ this->props.soft.n_volumes = this->props.n_channels; this->props.monitor.n_volumes = this->props.n_channels; + this->dirSPA_DIRECTION_INPUT.direction = SPA_DIRECTION_INPUT; this->dirSPA_DIRECTION_INPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT); + this->dirSPA_DIRECTION_OUTPUT.direction = SPA_DIRECTION_OUTPUT; this->dirSPA_DIRECTION_OUTPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT); this->node.iface = SPA_INTERFACE_INIT(
View file
pipewire-0.3.61.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.62.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c
Changed
@@ -156,11 +156,12 @@ conv_s24_to_f32d_1s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const int24_t *s = src; + const int8_t *s = src; float *d0 = dst0; uint32_t n, unrolled; __m128i in; __m128 out, factor = _mm_set1_ps(1.0f / S24_SCALE); + __m128i mask1 = _mm_setr_epi32(0*n_channels, 3*n_channels, 6*n_channels, 9*n_channels); if (SPA_IS_ALIGNED(d0, 16) && n_samples > 0) { unrolled = n_samples & ~3; @@ -171,23 +172,19 @@ unrolled = 0; for(n = 0; n < unrolled; n += 4) { - in = _mm_setr_epi32( - *((uint32_t*)&s0 * n_channels), - *((uint32_t*)&s1 * n_channels), - *((uint32_t*)&s2 * n_channels), - *((uint32_t*)&s3 * n_channels)); + in = _mm_i32gather_epi32((int*)s, mask1, 1); in = _mm_slli_epi32(in, 8); in = _mm_srai_epi32(in, 8); out = _mm_cvtepi32_ps(in); out = _mm_mul_ps(out, factor); _mm_store_ps(&d0n, out); - s += 4 * n_channels; + s += 12 * n_channels; } for(; n < n_samples; n++) { - out = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); + out = _mm_cvtsi32_ss(factor, s24_to_s32(*(int24_t*)s)); out = _mm_mul_ss(out, factor); _mm_store_ss(&d0n, out); - s += n_channels; + s += 3 * n_channels; } } @@ -195,11 +192,12 @@ conv_s24_to_f32d_2s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const int24_t *s = src; + const int8_t *s = src; float *d0 = dst0, *d1 = dst1; uint32_t n, unrolled; __m128i in2; __m128 out2, factor = _mm_set1_ps(1.0f / S24_SCALE); + __m128i mask1 = _mm_setr_epi32(0*n_channels, 3*n_channels, 6*n_channels, 9*n_channels); if (SPA_IS_ALIGNED(d0, 16) && SPA_IS_ALIGNED(d1, 16) && @@ -212,16 +210,8 @@ unrolled = 0; for(n = 0; n < unrolled; n += 4) { - in0 = _mm_setr_epi32( - *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 1*n_channels), - *((uint32_t*)&s0 + 2*n_channels), - *((uint32_t*)&s0 + 3*n_channels)); - in1 = _mm_setr_epi32( - *((uint32_t*)&s1 + 0*n_channels), - *((uint32_t*)&s1 + 1*n_channels), - *((uint32_t*)&s1 + 2*n_channels), - *((uint32_t*)&s1 + 3*n_channels)); + in0 = _mm_i32gather_epi32((int*)&s0, mask1, 1); + in1 = _mm_i32gather_epi32((int*)&s3, mask1, 1); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -238,27 +228,28 @@ _mm_store_ps(&d0n, out0); _mm_store_ps(&d1n, out1); - s += 4 * n_channels; + s += 12 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); - out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+0))); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+1))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); _mm_store_ss(&d0n, out0); _mm_store_ss(&d1n, out1); - s += n_channels; + s += 3 * n_channels; } } static void conv_s24_to_f32d_4s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { - const int24_t *s = src; + const int8_t *s = src; float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; __m128i in4; __m128 out4, factor = _mm_set1_ps(1.0f / S24_SCALE); + __m128i mask1 = _mm_setr_epi32(0*n_channels, 3*n_channels, 6*n_channels, 9*n_channels); if (SPA_IS_ALIGNED(d0, 16) && SPA_IS_ALIGNED(d1, 16) && @@ -273,26 +264,10 @@ unrolled = 0; for(n = 0; n < unrolled; n += 4) { - in0 = _mm_setr_epi32( - *((uint32_t*)&s0 + 0*n_channels), - *((uint32_t*)&s0 + 1*n_channels), - *((uint32_t*)&s0 + 2*n_channels), - *((uint32_t*)&s0 + 3*n_channels)); - in1 = _mm_setr_epi32( - *((uint32_t*)&s1 + 0*n_channels), - *((uint32_t*)&s1 + 1*n_channels), - *((uint32_t*)&s1 + 2*n_channels), - *((uint32_t*)&s1 + 3*n_channels)); - in2 = _mm_setr_epi32( - *((uint32_t*)&s2 + 0*n_channels), - *((uint32_t*)&s2 + 1*n_channels), - *((uint32_t*)&s2 + 2*n_channels), - *((uint32_t*)&s2 + 3*n_channels)); - in3 = _mm_setr_epi32( - *((uint32_t*)&s3 + 0*n_channels), - *((uint32_t*)&s3 + 1*n_channels), - *((uint32_t*)&s3 + 2*n_channels), - *((uint32_t*)&s3 + 3*n_channels)); + in0 = _mm_i32gather_epi32((int*)&s0, mask1, 1); + in1 = _mm_i32gather_epi32((int*)&s3, mask1, 1); + in2 = _mm_i32gather_epi32((int*)&s6, mask1, 1); + in3 = _mm_i32gather_epi32((int*)&s9, mask1, 1); in0 = _mm_slli_epi32(in0, 8); in1 = _mm_slli_epi32(in1, 8); @@ -319,13 +294,13 @@ _mm_store_ps(&d2n, out2); _mm_store_ps(&d3n, out3); - s += 4 * n_channels; + s += 12 * n_channels; } for(; n < n_samples; n++) { - out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*s)); - out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+1))); - out2 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+2))); - out3 = _mm_cvtsi32_ss(factor, s24_to_s32(*(s+3))); + out0 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+0))); + out1 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+1))); + out2 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+2))); + out3 = _mm_cvtsi32_ss(factor, s24_to_s32(*((int24_t*)s+3))); out0 = _mm_mul_ss(out0, factor); out1 = _mm_mul_ss(out1, factor); out2 = _mm_mul_ss(out2, factor); @@ -334,7 +309,7 @@ _mm_store_ss(&d1n, out1); _mm_store_ss(&d2n, out2); _mm_store_ss(&d3n, out3); - s += n_channels; + s += 3 * n_channels; } } @@ -361,12 +336,10 @@ const int32_t *s = src; float *d0 = dst0, *d1 = dst1, *d2 = dst2, *d3 = dst3; uint32_t n, unrolled; - __m256i in4, t4; + __m256i in4; __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE); - __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 0*n_channels+2, 4*n_channels, 4*n_channels+2); - __m256i mask2 = _mm256_setr_epi64x(1*n_channels, 1*n_channels+2, 5*n_channels, 5*n_channels+2); - __m256i mask3 = _mm256_setr_epi64x(2*n_channels, 2*n_channels+2, 6*n_channels, 6*n_channels+2); - __m256i mask4 = _mm256_setr_epi64x(3*n_channels, 3*n_channels+2, 7*n_channels, 7*n_channels+2); + __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels, + 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); if (SPA_IS_ALIGNED(d0, 32) && SPA_IS_ALIGNED(d1, 32) && @@ -377,19 +350,10 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask1, 4); - in1 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask2, 4); - in2 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask3, 4); - in3 = _mm256_i64gather_epi64((long long int *)&s0*n_channels, mask4, 4); - - t0 = _mm256_unpacklo_epi32(in0, in1); /* a0 a1 b0 b1 a4 a5 b4 b5 */ - t1 = _mm256_unpackhi_epi32(in0, in1); /* c0 c1 d0 d1 c4 c5 d4 d5 */ - t2 = _mm256_unpacklo_epi32(in2, in3); /* a2 a3 b2 b3 a6 a7 b6 b7 */ - t3 = _mm256_unpackhi_epi32(in2, in3); /* c2 c3 d2 d3 c6 c7 d6 d7 */ - in0 = _mm256_unpacklo_epi64(t0, t2); /* a0 a1 a2 a3 a4 a5 a6 a7 */ - in1 = _mm256_unpackhi_epi64(t0, t2); /* b0 b1 b2 b3 b4 b5 b6 b7 */ - in2 = _mm256_unpacklo_epi64(t1, t3); /* c0 c1 c2 c3 c4 c5 c6 c7 */ - in3 = _mm256_unpackhi_epi64(t1, t3); /* d0 d1 d2 d3 d4 d5 d6 d7 */ + in0 = _mm256_i32gather_epi32((int*)&s0, mask1, 4); + in1 = _mm256_i32gather_epi32((int*)&s1, mask1, 4); + in2 = _mm256_i32gather_epi32((int*)&s2, mask1, 4); + in3 = _mm256_i32gather_epi32((int*)&s3, mask1, 4); in0 = _mm256_srai_epi32(in0, 8); in1 = _mm256_srai_epi32(in1, 8); @@ -438,11 +402,10 @@ const int32_t *s = src; float *d0 = dst0, *d1 = dst1; uint32_t n, unrolled; - __m256i in4, t4; + __m256i in4; __m256 out4, factor = _mm256_set1_ps(1.0f / S24_SCALE); - __m256i perm = _mm256_setr_epi32(0, 2, 4, 6, 1, 3, 5, 7); - __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels); - __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); + __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels, + 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); if (SPA_IS_ALIGNED(d0, 32) && SPA_IS_ALIGNED(d1, 32)) @@ -451,14 +414,8 @@ unrolled = 0; for(n = 0; n < unrolled; n += 8) { - in0 = _mm256_i64gather_epi64((long long int *)s, mask1, 4); - in1 = _mm256_i64gather_epi64((long long int *)s, mask2, 4); - - t0 = _mm256_permutevar8x32_epi32(in0, perm); - t1 = _mm256_permutevar8x32_epi32(in1, perm); - - in0 = _mm256_permute2x128_si256(t0, t1, 0 | (2 << 4)); - in1 = _mm256_permute2x128_si256(t0, t1, 1 | (3 << 4)); + in0 = _mm256_i32gather_epi32((int*)&s0, mask1, 4); + in1 = _mm256_i32gather_epi32((int*)&s1, mask1, 4); in0 = _mm256_srai_epi32(in0, 8); in1 = _mm256_srai_epi32(in1, 8); @@ -495,8 +452,8 @@ uint32_t n, unrolled; __m256i in2; __m256 out2, factor = _mm256_set1_ps(1.0f / S24_SCALE); - __m256i mask1 = _mm256_setr_epi64x(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels); - __m256i mask2 = _mm256_setr_epi64x(4*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); + __m256i mask1 = _mm256_setr_epi32(0*n_channels, 1*n_channels, 2*n_channels, 3*n_channels, + 3*n_channels, 5*n_channels, 6*n_channels, 7*n_channels); if (SPA_IS_ALIGNED(d0, 32)) unrolled = n_samples & ~15; @@ -504,12 +461,8 @@ unrolled = 0; for(n = 0; n < unrolled; n += 16) { - in0 = _mm256_setr_m128i( - _mm256_i64gather_epi32(&s 0*n_channels, mask1, 4), - _mm256_i64gather_epi32(&s 0*n_channels, mask2, 4)); - in1 = _mm256_setr_m128i( - _mm256_i64gather_epi32(&s 8*n_channels, mask1, 4), - _mm256_i64gather_epi32(&s 8*n_channels, mask2, 4)); + in0 = _mm256_i32gather_epi32(&s0*n_channels, mask1, 4); + in1 = _mm256_i32gather_epi32(&s8*n_channels, mask1, 4); in0 = _mm256_srai_epi32(in0, 8); in1 = _mm256_srai_epi32(in1, 8);
View file
pipewire-0.3.61.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.62.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -79,11 +79,13 @@ struct props { enum spa_bluetooth_audio_codec codec; + bool offload_active; }; static void reset_props(struct props *props) { props->codec = 0; + props->offload_active = false; } struct impl; @@ -97,6 +99,7 @@ unsigned int mute:1; unsigned int save:1; unsigned int a2dp_duplex:1; + unsigned int offload_acquired:1; uint32_t n_channels; int64_t latency_offset; uint32_t channelsSPA_AUDIO_MAX_CHANNELS; @@ -407,6 +410,24 @@ .volume_changed = volume_changed, }; +static int node_offload_set_active(struct node *node, bool active) +{ + int res = 0; + + if (node->transport == NULL || !node->active) + return -ENOTSUP; + + if (active && !node->offload_acquired) + res = spa_bt_transport_acquire(node->transport, false); + else if (!active && node->offload_acquired) + res = spa_bt_transport_release(node->transport); + + if (res >= 0) + node->offload_acquired = active; + + return res; +} + static void get_channels(struct spa_bt_transport *t, bool a2dp_duplex, uint32_t *n_channels, uint32_t *channels) { const struct media_codec *codec; @@ -480,6 +501,7 @@ this->nodesid.impl = this; this->nodesid.active = true; + this->nodesid.offload_acquired = false; this->nodesid.a2dp_duplex = a2dp_duplex; get_channels(t, a2dp_duplex, &this->nodesid.n_channels, this->nodesid.channels); if (this->nodesid.transport) @@ -804,6 +826,7 @@ for (uint32_t i = 0; i < 2; i++) { struct node * node = &this->nodesi; + node_offload_set_active(node, false); if (node->transport) { spa_hook_remove(&node->transport_listener); node->transport = NULL; @@ -813,6 +836,8 @@ node->active = false; } } + + this->props.offload_active = false; } static bool validate_profile(struct impl *this, uint32_t profile, @@ -1674,7 +1699,7 @@ return true; } -static struct spa_pod *build_prop_info(struct impl *this, struct spa_pod_builder *b, uint32_t id) +static struct spa_pod *build_prop_info_codec(struct impl *this, struct spa_pod_builder *b, uint32_t id) { struct spa_pod_frame f2; struct spa_pod_choice *choice; @@ -1748,7 +1773,8 @@ return spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_Props, id, - SPA_PROP_bluetoothAudioCodec, SPA_POD_Id(p->codec)); + SPA_PROP_bluetoothAudioCodec, SPA_POD_Id(p->codec), + SPA_PROP_bluetoothOffloadActive, SPA_POD_Bool(p->offload_active)); } static int impl_enum_params(void *object, int seq, @@ -1841,7 +1867,14 @@ { switch (result.index) { case 0: - param = build_prop_info(this, &b, id); + param = build_prop_info_codec(this, &b, id); + break; + case 1: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_bluetoothOffloadActive), + SPA_PROP_INFO_description, SPA_POD_String("Bluetooth audio offload active"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(false)); break; default: return 0; @@ -2030,6 +2063,25 @@ return changed; } +static void apply_prop_offload_active(struct impl *this, bool active) +{ + bool old_value = this->props.offload_active; + + this->props.offload_active = active; + + for (int i = 0; i < 2; i++) { + node_offload_set_active(&this->nodesi, active); + if (!this->nodesi.offload_acquired) + this->props.offload_active = false; + } + + if (this->props.offload_active != old_value) { + this->info.change_mask |= SPA_DEVICE_CHANGE_MASK_PARAMS; + this->paramsIDX_Props.flags ^= SPA_PARAM_INFO_SERIAL; + emit_info(this, false); + } +} + static int impl_set_param(void *object, uint32_t id, uint32_t flags, const struct spa_pod *param) @@ -2104,19 +2156,23 @@ case SPA_PARAM_Props: { uint32_t codec_id = SPA_ID_INVALID; + bool offload_active = this->props.offload_active; if (param == NULL) return 0; if ((res = spa_pod_parse_object(param, SPA_TYPE_OBJECT_Props, NULL, - SPA_PROP_bluetoothAudioCodec, SPA_POD_OPT_Id(&codec_id))) < 0) { + SPA_PROP_bluetoothAudioCodec, SPA_POD_OPT_Id(&codec_id), + SPA_PROP_bluetoothOffloadActive, SPA_POD_OPT_Bool(&offload_active))) < 0) { spa_log_warn(this->log, "can't parse props"); spa_debug_pod(0, NULL, param); return res; } - spa_log_debug(this->log, "setting props codec:%d", codec_id); + spa_log_debug(this->log, "setting props codec:%d offload:%d", (int)codec_id, (int)offload_active); + + apply_prop_offload_active(this, offload_active); if (codec_id == SPA_ID_INVALID) return 0;
View file
pipewire-0.3.61.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.62.tar.gz/spa/plugins/bluez5/sco-sink.c
Changed
@@ -95,7 +95,6 @@ struct buffer buffersMAX_BUFFERS; uint32_t n_buffers; - struct spa_list free; struct spa_list ready; struct buffer *current_buffer;
View file
pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-source.cpp -> pipewire-0.3.62.tar.gz/spa/plugins/libcamera/libcamera-source.cpp
Changed
@@ -78,6 +78,7 @@ struct spa_list link; struct spa_buffer *outbuf; struct spa_meta_header *h; + struct spa_meta_videotransform *videotransform; void *ptr; }; @@ -589,6 +590,12 @@ SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); break; + case 1: + param = (struct spa_pod*)spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_ParamMeta, id, + SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform), + SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_videotransform))); + break; default: return 0; }
View file
pipewire-0.3.61.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.62.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp
Changed
@@ -74,7 +74,7 @@ return; StreamRoles roles; - roles.push_back(VideoRecording); + roles.push_back(StreamRole::VideoRecording); impl->config = impl->camera->generateConfiguration(roles); } @@ -500,28 +500,48 @@ 0); switch (ctrl_id->type()) { - case ControlTypeBool: + case ControlTypeBool: { + bool def; + if (ctrl_info.def().isNone()) + def = ctrl_info.min().get<bool>(); + else + def = ctrl_info.def().get<bool>(); + spa_pod_builder_add(&b, - SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool( - (bool)ctrl_info.def().get<bool>()), - 0); - break; - case ControlTypeFloat: + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool( + def), + 0); + } break; + case ControlTypeFloat: { + float min = ctrl_info.min().get<float>(); + float max = ctrl_info.max().get<float>(); + float def; + + if (ctrl_info.def().isNone()) + def = (min + max) / 2; + else + def = ctrl_info.def().get<float>(); + spa_pod_builder_add(&b, SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float( - (float)ctrl_info.def().get<float>(), - (float)ctrl_info.min().get<float>(), - (float)ctrl_info.max().get<float>()), + def, min, max), 0); - break; - case ControlTypeInteger32: + } break; + case ControlTypeInteger32: { + int32_t min = ctrl_info.min().get<int32_t>(); + int32_t max = ctrl_info.max().get<int32_t>(); + int32_t def; + + if (ctrl_info.def().isNone()) + def = (min + max) / 2; + else + def = ctrl_info.def().get<int32_t>(); + spa_pod_builder_add(&b, SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int( - (int32_t)ctrl_info.def().get<int32_t>(), - (int32_t)ctrl_info.min().get<int32_t>(), - (int32_t)ctrl_info.max().get<int32_t>()), + def, min, max), 0); - break; + } break; default: goto next; } @@ -678,6 +698,31 @@ return -ENOTSUP; } +static const struct { + Transform libcamera_transform; + uint32_t spa_transform_value; +} transform_map = { + { Transform::Identity, SPA_META_TRANSFORMATION_None }, + { Transform::Rot0, SPA_META_TRANSFORMATION_None }, + { Transform::HFlip, SPA_META_TRANSFORMATION_Flipped }, + { Transform::VFlip, SPA_META_TRANSFORMATION_Flipped180 }, + { Transform::HVFlip, SPA_META_TRANSFORMATION_180 }, + { Transform::Rot180, SPA_META_TRANSFORMATION_180 }, + { Transform::Transpose, SPA_META_TRANSFORMATION_Flipped90 }, + { Transform::Rot90, SPA_META_TRANSFORMATION_90 }, + { Transform::Rot270, SPA_META_TRANSFORMATION_270 }, + { Transform::Rot180Transpose, SPA_META_TRANSFORMATION_Flipped270 }, +}; + +static uint32_t libcamera_transform_to_spa_transform_value(Transform transform) +{ + for (const auto& t : transform_map) { + if (t.libcamera_transform == transform) + return t.spa_transform_value; + } + return SPA_META_TRANSFORMATION_None; +} + static int mmap_init(struct impl *impl, struct port *port, struct spa_buffer **buffers, uint32_t n_buffers) @@ -722,6 +767,16 @@ b->flags = BUFFER_FLAG_OUTSTANDING; b->h = (struct spa_meta_header*)spa_buffer_find_meta_data(buffersi, SPA_META_Header, sizeof(*b->h)); + b->videotransform = (struct spa_meta_videotransform*)spa_buffer_find_meta_data( + buffersi, SPA_META_VideoTransform, sizeof(*b->videotransform)); + if (b->videotransform) { + b->videotransform->transform = + libcamera_transform_to_spa_transform_value(impl->config->transform); + spa_log_debug(impl->log, "Setting videotransform for buffer %d to %u (from %s)", + i, b->videotransform->transform, transformToString(impl->config->transform)); + + } + d = buffersi->datas; for(j = 0; j < buffersi->n_datas; ++j) { dj.type = port->memtype;
View file
pipewire-0.3.61.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.62.tar.gz/spa/plugins/support/loop.c
Changed
@@ -89,7 +89,7 @@ uint8_t *buffer_data; uint8_t buffer_memDATAS_SIZE + MAX_ALIGN; - unsigned int flushing:1; + uint32_t flush_count; unsigned int polling:1; }; @@ -166,23 +166,39 @@ static void flush_items(struct impl *impl) { - uint32_t index; + uint32_t index, flush_count; + int32_t avail; int res; - impl->flushing = true; - while (spa_ringbuffer_get_read_index(&impl->buffer, &index) > 0) { + flush_count = ++impl->flush_count; + avail = spa_ringbuffer_get_read_index(&impl->buffer, &index); + while (avail > 0) { struct invoke_item *item; bool block; + spa_invoke_func_t func; item = SPA_PTROFF(impl->buffer_data, index & (DATAS_SIZE - 1), struct invoke_item); block = item->block; + func = item->func; spa_log_trace_fp(impl->log, "%p: flush item %p", impl, item); - item->res = item->func ? item->func(&impl->loop, - true, item->seq, item->data, item->size, - item->user_data) : 0; - - spa_ringbuffer_read_update(&impl->buffer, index + item->item_size); + /* first we remove the function from the item so that recursive + * calls don't call the callback again. We can't update the + * read index before we call the function because then the item + * might get overwritten. */ + item->func = NULL; + if (func) + item->res = func(&impl->loop, true, item->seq, item->data, + item->size, item->user_data); + + /* if this function did a recursive invoke, it now flushed the + * ringbuffer and we can exit */ + if (flush_count != impl->flush_count) + break; + + index += item->item_size; + avail -= item->item_size; + spa_ringbuffer_read_update(&impl->buffer, index); if (block) { if ((res = spa_system_eventfd_write(impl->system, impl->ack_fd, 1)) < 0) @@ -190,20 +206,21 @@ impl, impl->ack_fd, spa_strerror(res)); } } - impl->flushing = false; } static int loop_invoke_inthread(struct impl *impl, - spa_invoke_func_t func, - uint32_t seq, - const void *data, - size_t size, - bool block, - void *user_data) + spa_invoke_func_t func, + uint32_t seq, + const void *data, + size_t size, + bool block, + void *user_data) { - if (!impl->flushing) - flush_items(impl); + /* we should probably have a second ringbuffer for the in-thread pending + * callbacks. A recursive callback when flushing will insert itself + * before this one. */ + flush_items(impl); return func ? func(&impl->loop, true, seq, data, size, user_data) : 0; } @@ -222,6 +239,9 @@ int32_t filled; uint32_t avail, idx, offset, l0; + /* the ringbuffer can only be written to from one thread, if we are + * in the same thread as the loop, don't write into the ringbuffer + * but try to emit the calback right away after flushing what we have */ if (impl->thread == 0 || pthread_equal(impl->thread, pthread_self())) return loop_invoke_inthread(impl, func, seq, data, size, block, user_data); @@ -247,6 +267,7 @@ item->size = size; item->block = block; item->user_data = user_data; + item->res = 0; item->item_size = SPA_ROUND_UP_N(sizeof(struct invoke_item) + size, ITEM_ALIGN); spa_log_trace_fp(impl->log, "%p: add item %p filled:%d", impl, item, filled); @@ -585,10 +606,12 @@ uint64_t count = 0; int res; - if ((res = spa_system_eventfd_read(s->impl->system, source->fd, &count)) < 0) - spa_log_warn(s->impl->log, "%p: failed to read event fd:%d: %s", - source, source->fd, spa_strerror(res)); - + if ((res = spa_system_eventfd_read(s->impl->system, source->fd, &count)) < 0) { + if (res != -EAGAIN) + spa_log_warn(s->impl->log, "%p: failed to read event fd:%d: %s", + source, source->fd, spa_strerror(res)); + return; + } s->func.event(source->data, count); } @@ -651,10 +674,12 @@ int res; if (SPA_UNLIKELY((res = spa_system_timerfd_read(s->impl->system, - source->fd, &expirations)) < 0)) - spa_log_warn(s->impl->log, "%p: failed to read timer fd:%d: %s", - source, source->fd, spa_strerror(res)); - + source->fd, &expirations)) < 0)) { + if (res != -EAGAIN) + spa_log_warn(s->impl->log, "%p: failed to read timer fd:%d: %s", + source, source->fd, spa_strerror(res)); + return; + } s->func.timer(source->data, expirations); } @@ -731,10 +756,12 @@ struct source_impl *s = SPA_CONTAINER_OF(source, struct source_impl, source); int res, signal_number = 0; - if ((res = spa_system_signalfd_read(s->impl->system, source->fd, &signal_number)) < 0) - spa_log_warn(s->impl->log, "%p: failed to read signal fd:%d: %s", - source, source->fd, spa_strerror(res)); - + if ((res = spa_system_signalfd_read(s->impl->system, source->fd, &signal_number)) < 0) { + if (res != -EAGAIN) + spa_log_warn(s->impl->log, "%p: failed to read signal fd:%d: %s", + source, source->fd, spa_strerror(res)); + return; + } s->func.signal(source->data, signal_number); }
View file
pipewire-0.3.61.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.62.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -90,7 +90,7 @@ #pulse.default.frag = 96000/48000 # 2 seconds #pulse.default.tlength = 96000/48000 # 2 seconds #pulse.min.quantum = 256/48000 # 5ms - #pulse.idle.timeout = 5 # pause after 5s of underruns + #pulse.idle.timeout = 0 # don't pause after underruns #pulse.default.format = F32 #pulse.default.position = FL FR # These overrides are only applied when running in a vm. @@ -137,12 +137,12 @@ } { # speech dispatcher asks for too small latency and then underruns. - matches = { application.name = "~speech-dispatcher*" } + matches = { application.name = "~speech-dispatcher.*" } actions = { update-props = { - pulse.min.req = 1024/48000 # 21ms - pulse.min.quantum = 1024/48000 # 21ms - #pulse.idle.timeout = 0 + pulse.min.req = 512/48000 # 10.6ms + pulse.min.quantum = 512/48000 # 10.6ms + pulse.idle.timeout = 5 # pause after 5 seconds of underrun } } }
View file
pipewire-0.3.61.tar.gz/src/examples/video-dsp-play.c -> pipewire-0.3.62.tar.gz/src/examples/video-dsp-play.c
Changed
@@ -139,6 +139,8 @@ /* copy video image in texture */ sstride = buf->datas0.chunk->stride; + if (sstride == 0) + sstride = buf->datas0.chunk->size / data->position->video.size.height; src = sdata; dst = ddata;
View file
pipewire-0.3.61.tar.gz/src/examples/video-play-fixate.c -> pipewire-0.3.62.tar.gz/src/examples/video-play-fixate.c
Changed
@@ -257,6 +257,8 @@ /* copy video image in texture */ sstride = buf->datas0.chunk->stride; + if (sstride == 0) + sstride = buf->datas0.chunk->size / data->size.height; ostride = SPA_MIN(sstride, dstride); src = sdata;
View file
pipewire-0.3.61.tar.gz/src/examples/video-play-pull.c -> pipewire-0.3.62.tar.gz/src/examples/video-play-pull.c
Changed
@@ -206,6 +206,8 @@ } sstride = buf->datas0.chunk->stride; + if (sstride == 0) + sstride = buf->datas0.chunk->size / data->size.height; ostride = SPA_MIN(sstride, dstride); src = sdata;
View file
pipewire-0.3.61.tar.gz/src/examples/video-play-reneg.c -> pipewire-0.3.62.tar.gz/src/examples/video-play-reneg.c
Changed
@@ -136,6 +136,8 @@ /* copy video image in texture */ sstride = buf->datas0.chunk->stride; + if (sstride == 0) + sstride = buf->datas0.chunk->size / data->size.height; ostride = SPA_MIN(sstride, dstride); src = sdata;
View file
pipewire-0.3.61.tar.gz/src/examples/video-play.c -> pipewire-0.3.62.tar.gz/src/examples/video-play.c
Changed
@@ -204,6 +204,8 @@ } sstride = buf->datas0.chunk->stride; + if (sstride == 0) + sstride = buf->datas0.chunk->size / data->size.height; ostride = SPA_MIN(sstride, dstride); src = sdata;
View file
pipewire-0.3.61.tar.gz/src/gst/gstpipewirepool.c -> pipewire-0.3.62.tar.gz/src/gst/gstpipewirepool.c
Changed
@@ -115,6 +115,8 @@ data->crop = spa_buffer_find_meta_data (b->buffer, SPA_META_VideoCrop, sizeof(*data->crop)); if (data->crop) gst_buffer_add_video_crop_meta(buf); + data->videotransform = + spa_buffer_find_meta_data (b->buffer, SPA_META_VideoTransform, sizeof(*data->videotransform)); gst_mini_object_set_qdata (GST_MINI_OBJECT_CAST (buf), pool_data_quark,
View file
pipewire-0.3.61.tar.gz/src/gst/gstpipewirepool.h -> pipewire-0.3.62.tar.gz/src/gst/gstpipewirepool.h
Changed
@@ -57,6 +57,7 @@ GstBuffer *buf; gboolean queued; struct spa_meta_region *crop; + struct spa_meta_videotransform *videotransform; }; struct _GstPipeWirePool {
View file
pipewire-0.3.61.tar.gz/src/gst/gstpipewiresink.c -> pipewire-0.3.62.tar.gz/src/gst/gstpipewiresink.c
Changed
@@ -491,6 +491,7 @@ GstMemory *mem = gst_buffer_peek_memory (buffer, i); d->chunk->offset = mem->offset; d->chunk->size = mem->size; + d->chunk->stride = 0; } if ((res = pw_stream_queue_buffer (pwsink->stream, data->b)) < 0) {
View file
pipewire-0.3.61.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.62.tar.gz/src/gst/gstpipewiresrc.c
Changed
@@ -514,6 +514,25 @@ } } +static const char * const transform_map = { + SPA_META_TRANSFORMATION_None = "rotate-0", + SPA_META_TRANSFORMATION_90 = "rotate-90", + SPA_META_TRANSFORMATION_180 = "rotate-180", + SPA_META_TRANSFORMATION_270 = "rotate-270", + SPA_META_TRANSFORMATION_Flipped = "flip-rotate-0", + SPA_META_TRANSFORMATION_Flipped90 = "flip-rotate-270", + SPA_META_TRANSFORMATION_Flipped180 = "flip-rotate-180", + SPA_META_TRANSFORMATION_Flipped270 = "flip-rotate-90", +}; + +static const char *spa_transform_value_to_gst_image_orientation(uint32_t transform_value) +{ + if (transform_value >= SPA_N_ELEMENTS(transform_map)) + transform_value = SPA_META_TRANSFORMATION_None; + + return transform_maptransform_value; +} + static GstBuffer *dequeue_buffer(GstPipeWireSrc *pwsrc) { struct pw_buffer *b; @@ -521,6 +540,7 @@ GstPipeWirePoolData *data; struct spa_meta_header *h; struct spa_meta_region *crop; + struct spa_meta_videotransform *videotransform; guint i; b = pw_stream_dequeue_buffer (pwsrc->stream); @@ -568,6 +588,27 @@ meta->height = crop->region.size.height; } } + + videotransform = data->videotransform; + if (videotransform) { + if (pwsrc->transform_value != videotransform->transform) { + GstEvent *tag_event; + const char* tag_string; + + tag_string = + spa_transform_value_to_gst_image_orientation(videotransform->transform); + + GST_LOG_OBJECT (pwsrc, "got new videotransform: %u / %s", + videotransform->transform, tag_string); + + tag_event = gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION, + tag_string, NULL)); + gst_pad_push_event (GST_BASE_SRC_PAD (pwsrc), tag_event); + + pwsrc->transform_value = videotransform->transform; + } + } + for (i = 0; i < b->buffer->n_datas; i++) { struct spa_data *d = &b->buffer->datasi; GstMemory *pmem = gst_buffer_peek_memory (data->buf, i); @@ -913,7 +954,7 @@ pwsrc->negotiated = pwsrc->caps != NULL; if (pwsrc->negotiated) { - const struct spa_pod *params3; + const struct spa_pod *params4; struct spa_pod_builder b = { NULL }; uint8_t buffer512; uint32_t buffers = CLAMP (16, pwsrc->min_buffers, pwsrc->max_buffers); @@ -939,9 +980,13 @@ SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoCrop), SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_region))); + params3 = spa_pod_builder_add_object (&b, + SPA_TYPE_OBJECT_ParamMeta, SPA_PARAM_Meta, + SPA_PARAM_META_type, SPA_POD_Id(SPA_META_VideoTransform), + SPA_PARAM_META_size, SPA_POD_Int(sizeof (struct spa_meta_videotransform))); GST_DEBUG_OBJECT (pwsrc, "doing finish format"); - pw_stream_update_params (pwsrc->stream, params, 3); + pw_stream_update_params (pwsrc->stream, params, SPA_N_ELEMENTS(params)); } else { GST_WARNING_OBJECT (pwsrc, "finish format with error"); pw_stream_set_error (pwsrc->stream, -EINVAL, "unhandled format");
View file
pipewire-0.3.61.tar.gz/src/gst/gstpipewiresrc.h -> pipewire-0.3.62.tar.gz/src/gst/gstpipewiresrc.h
Changed
@@ -95,6 +95,8 @@ GstPipeWirePool *pool; GstClock *clock; GstClockTime last_time; + + enum spa_meta_videotransform_value transform_value; }; struct _GstPipeWireSrcClass {
View file
pipewire-0.3.61.tar.gz/src/modules/meson.build -> pipewire-0.3.62.tar.gz/src/modules/meson.build
Changed
@@ -289,6 +289,14 @@ cdata.set('HAVE_AVAHI', true) endif +if gio_dep.found() + pipewire_module_protocol_pulse_sources += + 'module-protocol-pulse/modules/module-gsettings.c', + + pipewire_module_protocol_pulse_deps += gio_dep + cdata.set('HAVE_GIO', true) +endif + if flatpak_support pipewire_module_protocol_pulse_deps += glib2_dep endif
View file
pipewire-0.3.61.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.62.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -1186,7 +1186,7 @@ struct timespec ts; struct pw_impl_port *p; - pw_log_trace("node %p: ready driver:%d exported:%d status:%d", node, + pw_log_trace_fp("node %p: ready driver:%d exported:%d status:%d", node, node->driver, node->exported, status); if (status & SPA_STATUS_HAVE_DATA) {
View file
pipewire-0.3.61.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.62.tar.gz/src/modules/module-echo-cancel.c
Changed
@@ -936,8 +936,13 @@ { struct impl *impl = data; - pw_log_error("error id:%u seq:%d res:%d (%s): %s", - id, seq, res, spa_strerror(res), message); + if (res == -ENOENT) { + pw_log_info("id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } else { + pw_log_warn("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } if (id == PW_ID_CORE && res == -EPIPE) pw_impl_module_schedule_destroy(impl->module);
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -505,6 +505,7 @@ unsigned int n_deps; unsigned int visited:1; + unsigned int disabled:1; }; struct link { @@ -521,6 +522,7 @@ const struct fc_descriptor *desc; void **hndl; uint32_t port; + unsigned next:1; }; struct graph_hndl { @@ -599,7 +601,7 @@ struct impl *impl = d; struct pw_buffer *in, *out; struct graph *graph = &impl->graph; - uint32_t i, insize = 0, outsize = 0, n_hndl = graph->n_hndl; + uint32_t i, j, insize = 0, outsize = 0, n_hndl = graph->n_hndl; int32_t stride = 0; struct graph_port *port; struct spa_data *bd; @@ -613,7 +615,7 @@ if (in == NULL || out == NULL) goto done; - for (i = 0; i < in->buffer->n_datas; i++) { + for (i = 0, j = 0; i < in->buffer->n_datas; i++) { uint32_t offs, size; bd = &in->buffer->datasi; @@ -621,12 +623,15 @@ offs = SPA_MIN(bd->chunk->offset, bd->maxsize); size = SPA_MIN(bd->chunk->size, bd->maxsize - offs); - port = i < graph->n_input ? &graph->inputi : NULL; - - if (port && port->desc) - port->desc->connect_port(*port->hndl, port->port, - SPA_PTROFF(bd->data, offs, void)); + while (j < graph->n_input) { + port = &graph->inputj++; + if (port->desc) + port->desc->connect_port(*port->hndl, port->port, + SPA_PTROFF(bd->data, offs, void)); + if (!port->next) + break; + } insize = i == 0 ? size : SPA_MIN(insize, size); stride = SPA_MAX(stride, bd->chunk->stride); } @@ -1849,7 +1854,7 @@ n_nodes++; } graph->n_input = 0; - graph->input = calloc(n_input * n_hndl, sizeof(struct graph_port)); + graph->input = calloc(n_input * 16 * n_hndl, sizeof(struct graph_port)); graph->n_output = 0; graph->output = calloc(n_output * n_hndl, sizeof(struct graph_port)); @@ -1869,8 +1874,8 @@ } else { struct spa_json it = *inputs; while (spa_json_get_string(&it, v, sizeof(v)) > 0) { - gp = &graph->inputgraph->n_input; if (spa_streq(v, "null")) { + gp = &graph->inputgraph->n_input++; gp->desc = NULL; pw_log_info("ignore input port %d", graph->n_input); } else if ((port = find_port(first, v, FC_PORT_INPUT)) == NULL) { @@ -1893,14 +1898,41 @@ res = -EBUSY; goto error; } - pw_log_info("input port %s%d:%s", + + if (d->flags & FC_DESCRIPTOR_COPY) { + for (j = 0; j < desc->n_output; j++) { + struct port *p = &port->node->output_portj; + struct link *link; + + gp = NULL; + spa_list_for_each(link, &p->link_list, output_link) { + struct port *peer = link->input; + + pw_log_info("copy input port %s%d:%s", + port->node->name, i, + d->portsport->p.name); + peer->external = graph->n_input; + gp = &graph->inputgraph->n_input++; + gp->desc = peer->node->desc->desc; + gp->hndl = &peer->node->hndli; + gp->port = peer->p; + gp->next = true; + } + if (gp != NULL) + gp->next = false; + } + port->node->disabled = true; + } else { + pw_log_info("input port %s%d:%s", port->node->name, i, d->portsport->p.name); - port->external = graph->n_input; - gp->desc = d; - gp->hndl = &port->node->hndli; - gp->port = port->p; + port->external = graph->n_input; + gp = &graph->inputgraph->n_input++; + gp->desc = d; + gp->hndl = &port->node->hndli; + gp->port = port->p; + gp->next = false; + } } - graph->n_input++; } } if (outputs == NULL) { @@ -1965,11 +1997,12 @@ desc = node->desc; d = desc->desc; - for (i = 0; i < n_hndl; i++) { - gh = &graph->hndlgraph->n_hndl++; - gh->hndl = &node->hndli; - gh->desc = d; - + if (!node->disabled) { + for (i = 0; i < n_hndl; i++) { + gh = &graph->hndlgraph->n_hndl++; + gh->hndl = &node->hndli; + gh->desc = d; + } } for (i = 0; i < desc->n_output; i++) { spa_list_for_each(link, &node->output_porti.link_list, output_link) @@ -2088,8 +2121,13 @@ { struct impl *impl = data; - pw_log_error("error id:%u seq:%d res:%d (%s): %s", - id, seq, res, spa_strerror(res), message); + if (res == -ENOENT) { + pw_log_info("message id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } else { + pw_log_warn("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } if (id == PW_ID_CORE && res == -EPIPE) pw_impl_module_schedule_destroy(impl->module);
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
@@ -101,6 +101,7 @@ static const struct fc_descriptor copy_desc = { .name = "copy", + .flags = FC_DESCRIPTOR_COPY, .n_ports = 2, .ports = copy_ports, @@ -260,14 +261,11 @@ static void bq_run(struct builtin *impl, unsigned long samples, int type) { struct biquad *bq = &impl->bq; - unsigned long i; float *out = impl->port0; float *in = impl->port1; float freq = impl->port20; float Q = impl->port30; float gain = impl->port40; - float x1, x2, y1, y2; - float b0, b1, b2, a1, a2; if (impl->freq != freq || impl->Q != Q || impl->gain != gain) { impl->freq = freq; @@ -275,30 +273,7 @@ impl->gain = gain; biquad_set(bq, type, freq * 2 / impl->rate, Q, gain); } - x1 = bq->x1; - x2 = bq->x2; - y1 = bq->y1; - y2 = bq->y2; - b0 = bq->b0; - b1 = bq->b1; - b2 = bq->b2; - a1 = bq->a1; - a2 = bq->a2; - for (i = 0; i < samples; i++) { - float x = ini; - float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; - outi = y; - x2 = x1; - x1 = x; - y2 = y1; - y1 = y; - } -#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 + dsp_ops_biquad_run(&dsp_ops, bq, out, in, samples); } /** bq_lowpass */
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/convolver.c -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/convolver.c
Changed
@@ -420,8 +420,6 @@ int convolver_run(struct convolver *conv, const float *input, float *output, int length) { - int i; - convolver1_run(conv->headConvolver, input, output, length); if (conv->tailInput) { @@ -431,24 +429,14 @@ int remaining = length - processed; int processing = SPA_MIN(remaining, conv->headBlockSize - (conv->tailInputFill % conv->headBlockSize)); - const int sumBegin = processed; - const int sumEnd = processed + processing; - - if (conv->tailPrecalculated0) { - int precalculatedPos = conv->precalculatedPos; - for (i = sumBegin; i < sumEnd; i++) { - outputi += conv->tailPrecalculated0precalculatedPos; - precalculatedPos++; - } - } - - if (conv->tailPrecalculated) { - int precalculatedPos = conv->precalculatedPos; - for (i = sumBegin; i < sumEnd; i++) { - outputi += conv->tailPrecalculatedprecalculatedPos; - precalculatedPos++; - } - } + if (conv->tailPrecalculated0) + fft_sum(&outputprocessed, &outputprocessed, + &conv->tailPrecalculated0conv->precalculatedPos, + processing); + if (conv->tailPrecalculated) + fft_sum(&outputprocessed, &outputprocessed, + &conv->tailPrecalculatedconv->precalculatedPos, + processing); conv->precalculatedPos += processing; fft_copy(conv->tailInput + conv->tailInputFill, input + processed, processing); @@ -467,7 +455,8 @@ if (conv->tailPrecalculated && conv->tailInputFill == conv->tailBlockSize) { SPA_SWAP(conv->tailPrecalculated, conv->tailOutput); - convolver1_run(conv->tailConvolver, conv->tailInput, conv->tailOutput, conv->tailBlockSize); + convolver1_run(conv->tailConvolver, conv->tailInput, + conv->tailOutput, conv->tailBlockSize); } if (conv->tailInputFill == conv->tailBlockSize) { conv->tailInputFill = 0;
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c
Changed
@@ -25,6 +25,7 @@ #include <string.h> #include <stdio.h> #include <math.h> +#include <float.h> #include <spa/utils/defs.h> @@ -98,3 +99,37 @@ } } } + +void dsp_biquad_run_c(struct dsp_ops *ops, struct biquad *bq, + float *out, const float *in, uint32_t n_samples) +{ + float x1, x2, y1, y2; + float b0, b1, b2, a1, a2; + uint32_t i; + + x1 = bq->x1; + x2 = bq->x2; + y1 = bq->y1; + y2 = bq->y2; + b0 = bq->b0; + b1 = bq->b1; + b2 = bq->b2; + a1 = bq->a1; + a2 = bq->a2; + for (i = 0; i < n_samples; i++) { + float x = ini; + float y = b0 * x + b1 * x1 + b2 * x2 - a1 * y1 - a2 * y2; + outi = y; + x2 = x1; + x1 = x; + y2 = y1; + y1 = y; + } +#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 +} +
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops.c -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/dsp-ops.c
Changed
@@ -42,6 +42,8 @@ void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, float gain, uint32_t n_src, uint32_t n_samples); + void (*biquad_run) (struct dsp_ops *ops, struct biquad *bq, + float *out, const float *in, uint32_t n_samples); }; static struct dsp_info dsp_table = @@ -50,11 +52,13 @@ { SPA_CPU_FLAG_SSE, .copy = dsp_copy_c, .mix_gain = dsp_mix_gain_sse, + .biquad_run = dsp_biquad_run_c, }, #endif { 0, .copy = dsp_copy_c, .mix_gain = dsp_mix_gain_c, + .biquad_run = dsp_biquad_run_c, }, }; @@ -86,6 +90,7 @@ ops->cpu_flags = info->cpu_flags; ops->copy = info->copy; ops->mix_gain = info->mix_gain; + ops->biquad_run = info->biquad_run; ops->free = impl_dsp_ops_free; return 0;
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/dsp-ops.h -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/dsp-ops.h
Changed
@@ -24,6 +24,8 @@ #include <spa/utils/defs.h> +#include "biquad.h" + struct dsp_ops { uint32_t cpu_flags; @@ -35,6 +37,8 @@ void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, float gain, uint32_t n_src, uint32_t n_samples); + void (*biquad_run) (struct dsp_ops *ops, struct biquad *bq, + float *out, const float *in, uint32_t n_samples); void (*free) (struct dsp_ops *ops); const void *priv; @@ -44,19 +48,24 @@ #define dsp_ops_copy(ops,...) (ops)->copy(ops, __VA_ARGS__) #define dsp_ops_mix_gain(ops,...) (ops)->mix_gain(ops, __VA_ARGS__) +#define dsp_ops_biquad_run(ops,...) (ops)->biquad_run(ops, __VA_ARGS__) #define dsp_ops_free(ops) (ops)->free(ops) #define MAKE_COPY_FUNC(arch) \ void dsp_copy_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \ - const void * SPA_RESTRICT src, uint32_t n_samples) + const void * SPA_RESTRICT src, uint32_t n_samples) #define MAKE_MIX_GAIN_FUNC(arch) \ void dsp_mix_gain_##arch(struct dsp_ops *ops, void * SPA_RESTRICT dst, \ const void * SPA_RESTRICT src, float gain, uint32_t n_src, uint32_t n_samples) +#define MAKE_BIQUAD_RUN_FUNC(arch) \ +void dsp_biquad_run_##arch (struct dsp_ops *ops, struct biquad *bq, \ + float *out, const float *in, uint32_t n_samples) MAKE_COPY_FUNC(c); MAKE_MIX_GAIN_FUNC(c); +MAKE_BIQUAD_RUN_FUNC(c); #if defined (HAVE_SSE) MAKE_MIX_GAIN_FUNC(sse); #endif
View file
pipewire-0.3.61.tar.gz/src/modules/module-filter-chain/plugin.h -> pipewire-0.3.62.tar.gz/src/modules/module-filter-chain/plugin.h
Changed
@@ -64,6 +64,7 @@ struct fc_descriptor { const char *name; #define FC_DESCRIPTOR_SUPPORTS_NULL_DATA (1ULL << 0) +#define FC_DESCRIPTOR_COPY (1ULL << 1) uint64_t flags; void (*free) (const struct fc_descriptor *desc);
View file
pipewire-0.3.61.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.62.tar.gz/src/modules/module-loopback.c
Changed
@@ -451,32 +451,31 @@ &impl->playback_listener, &out_stream_events, impl); + /* connect playback first to activate it before capture triggers it */ n_params = 0; spa_pod_builder_init(&b, buffer, sizeof(buffer)); paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, - &impl->capture_info); - - if ((res = pw_stream_connect(impl->capture, - PW_DIRECTION_INPUT, + &impl->playback_info); + if ((res = pw_stream_connect(impl->playback, + PW_DIRECTION_OUTPUT, PW_ID_ANY, PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS | - PW_STREAM_FLAG_RT_PROCESS, + PW_STREAM_FLAG_RT_PROCESS | + PW_STREAM_FLAG_TRIGGER, params, n_params)) < 0) return res; n_params = 0; spa_pod_builder_init(&b, buffer, sizeof(buffer)); paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, - &impl->playback_info); - - if ((res = pw_stream_connect(impl->playback, - PW_DIRECTION_OUTPUT, + &impl->capture_info); + if ((res = pw_stream_connect(impl->capture, + PW_DIRECTION_INPUT, PW_ID_ANY, PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS | - PW_STREAM_FLAG_RT_PROCESS | - PW_STREAM_FLAG_TRIGGER, + PW_STREAM_FLAG_RT_PROCESS, params, n_params)) < 0) return res; @@ -487,8 +486,13 @@ { struct impl *impl = data; - pw_log_error("error id:%u seq:%d res:%d (%s): %s", - id, seq, res, spa_strerror(res), message); + if (res == -ENOENT) { + pw_log_info("message id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } else { + pw_log_warn("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } if (id == PW_ID_CORE && res == -EPIPE) pw_impl_module_schedule_destroy(impl->module); @@ -513,11 +517,11 @@ static void impl_destroy(struct impl *impl) { - /* disconnect both streams before destroying any of them */ + /* deactivate both streams before destroying any of them */ if (impl->capture) - pw_stream_disconnect(impl->capture); + pw_stream_set_active(impl->capture, false); if (impl->playback) - pw_stream_disconnect(impl->playback); + pw_stream_set_active(impl->playback, false); if (impl->capture) pw_stream_destroy(impl->capture);
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
@@ -36,7 +36,6 @@ #include <pipewire/properties.h> #include <pipewire/work-queue.h> -#include "client.h" #include "defs.h" #include "format.h" #include "internal.h" @@ -84,14 +83,14 @@ spa_hook_list_append(&module->listener_list, listener, events, data); } -int module_load(struct client *client, struct module *module) +int module_load(struct module *module) { pw_log_info("load module index:%u name:%s", module->index, module->info->name); if (module->info->load == NULL) return -ENOTSUP; /* subscription event is sent when the module does a * module_emit_loaded() */ - return module->info->load(client, module); + return module->info->load(module); } void module_free(struct module *module) @@ -119,9 +118,6 @@ struct impl *impl = module->impl; int res = 0; - /* Note that client can be NULL (when the module is being unloaded - * internally and not by a client request */ - pw_log_info("unload module index:%u name:%s", module->index, module->info->name); if (module->info->unload) @@ -283,9 +279,8 @@ return spa_streq(module->info->name, name) ? 1 : 0; } -struct module *module_create(struct client *client, const char *name, const char *args) +struct module *module_create(struct impl *impl, const char *name, const char *args) { - struct impl *impl = client->impl; const struct module_info *info; struct module *module;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/module.h
Changed
@@ -29,7 +29,6 @@ #include <spa/param/audio/raw.h> #include <spa/utils/hook.h> -#include "client.h" #include "internal.h" struct module; @@ -41,7 +40,7 @@ unsigned int load_once:1; int (*prepare) (struct module *module); - int (*load) (struct client *client, struct module *module); + int (*load) (struct module *module); int (*unload) (struct module *module); const struct spa_dict *properties; @@ -78,9 +77,9 @@ #define module_emit_loaded(m,r) spa_hook_list_call(&m->listener_list, struct module_events, loaded, 0, r) #define module_emit_destroy(m) spa_hook_list_call(&(m)->listener_list, struct module_events, destroy, 0) -struct module *module_create(struct client *client, const char *name, const char *args); +struct module *module_create(struct impl *impl, const char *name, const char *args); void module_free(struct module *module); -int module_load(struct client *client, struct module *module); +int module_load(struct module *module); int module_unload(struct module *module); void module_schedule_unload(struct module *module);
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c
Changed
@@ -51,7 +51,7 @@ .destroy = module_destroy }; -static int module_always_sink_load(struct client *client, struct module *module) +static int module_always_sink_load(struct module *module) { struct module_always_sink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
@@ -391,7 +391,7 @@ check_initialized(data); } -static int module_combine_sink_load(struct client *client, struct module *module) +static int module_combine_sink_load(struct module *module) { struct module_combine_sink_data *data = module->user_data; struct pw_properties *props; @@ -402,9 +402,7 @@ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); const char *str; - data->core = pw_context_connect(module->impl->context, - pw_properties_copy(client->props), - 0); + data->core = pw_context_connect(module->impl->context, NULL, 0); if (data->core == NULL) return -errno;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
@@ -63,7 +63,7 @@ .destroy = module_destroy }; -static int module_echo_cancel_load(struct client *client, struct module *module) +static int module_echo_cancel_load(struct module *module) { struct module_echo_cancel_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-gsettings.c
Added
@@ -0,0 +1,298 @@ +/* PipeWire + * + * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <gio/gio.h> +#include <glib.h> + +#include <spa/debug/mem.h> +#include <pipewire/pipewire.h> +#include <pipewire/thread.h> + +#include "../module.h" + +#define NAME "gsettings" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +#define PA_GSETTINGS_MODULE_GROUP_SCHEMA "org.freedesktop.pulseaudio.module-group" +#define PA_GSETTINGS_MODULE_GROUPS_SCHEMA "org.freedesktop.pulseaudio.module-groups" +#define PA_GSETTINGS_MODULE_GROUPS_PATH "/org/freedesktop/pulseaudio/module-groups/" + +#define MAX_MODULES 10 + +struct module_gsettings_data { + struct module *module; + + GMainContext *context; + GMainLoop *loop; + struct spa_thread *thr; + + GSettings *settings; + gchar **group_names; + + struct spa_list groups; +}; + +struct group { + struct spa_list link; + char *name; + struct module *module; + struct spa_hook module_listener; +}; + +struct info { + bool enabled; + char *name; + char *moduleMAX_MODULES; + char *argsMAX_MODULES; +}; + +static void clean_info(const struct info *info) +{ + int i; + for (i = 0; i < MAX_MODULES; i++) { + g_free(info->modulei); + g_free(info->argsi); + } + g_free(info->name); +} + +static void unload_module(struct module_gsettings_data *d, struct group *g) +{ + spa_list_remove(&g->link); + g_free(g->name); + if (g->module) + module_unload(g->module); + free(g); +} + +static void unload_group(struct module_gsettings_data *d, const char *name) +{ + struct group *g, *t; + spa_list_for_each_safe(g, t, &d->groups, link) { + if (spa_streq(g->name, name)) + unload_module(d, g); + } +} +static void module_destroy(void *data) +{ + struct group *g = data; + if (g->module) { + spa_hook_remove(&g->module_listener); + g->module = NULL; + } +} + +static const struct module_events module_gsettings_events = { + VERSION_MODULE_EVENTS, + .destroy = module_destroy +}; + +static int load_group(struct module_gsettings_data *d, const struct info *info) +{ + struct group *g; + int i, res; + + for (i = 0; i < MAX_MODULES; i++) { + if (info->modulei == NULL || strlen(info->modulei) <= 0) + break; + + g = calloc(1, sizeof(struct group)); + if (g == NULL) + return -errno; + + g->name = strdup(info->name); + g->module = module_create(d->module->impl, info->modulei, info->argsi); + if (g->module == NULL) { + pw_log_info("can't create module:%s args:%s: %m", + info->modulei, info->argsi); + } else { + module_add_listener(g->module, &g->module_listener, + &module_gsettings_events, g); + if ((res = module_load(g->module)) < 0) { + pw_log_warn("can't load module:%s args:%s: %s", + info->modulei, info->argsi, + spa_strerror(res)); + } + } + spa_list_append(&d->groups, &g->link); + } + return 0; +} + +static int +do_handle_info(struct spa_loop *loop, + bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct module_gsettings_data *d = user_data; + const struct info *info = data; + + unload_group(d, info->name); + if (info->enabled) + load_group(d, info); + + clean_info(info); + return 0; +} + +static void handle_module_group(struct module_gsettings_data *d, gchar *name) +{ + struct impl *impl = d->module->impl; + GSettings *settings; + gchar p1024; + struct info info; + int i; + + snprintf(p, sizeof(p), PA_GSETTINGS_MODULE_GROUPS_PATH"%s/", name); + + settings = g_settings_new_with_path(PA_GSETTINGS_MODULE_GROUP_SCHEMA, p); + if (settings == NULL) + return; + + spa_zero(info); + info.name = strdup(p); + info.enabled = g_settings_get_boolean(settings, "enabled"); + + for (i = 0; i < MAX_MODULES; i++) { + snprintf(p, sizeof(p), "name%d", i); + info.modulei = g_settings_get_string(settings, p); + + snprintf(p, sizeof(p), "args%i", i); + info.argsi = g_settings_get_string(settings, p); + } + pw_loop_invoke(impl->loop, do_handle_info, 0, + &info, sizeof(info), false, d); + + g_object_unref(G_OBJECT(settings)); +} + +static void module_group_callback(GSettings *settings, gchar *key, gpointer user_data) +{ + struct module_gsettings_data *d = g_object_get_data(G_OBJECT(settings), "module-data"); + handle_module_group(d, user_data); +} + +static void *do_loop(void *user_data) +{ + struct module_gsettings_data *d = user_data; + + pw_log_info("enter"); + g_main_context_push_thread_default(d->context); + + d->loop = g_main_loop_new(d->context, FALSE); + + g_main_loop_run(d->loop); + + g_main_context_pop_thread_default(d->context); + g_main_loop_unref (d->loop); + d->loop = NULL; + pw_log_info("leave"); + + return NULL; +} + +static int module_gsettings_load(struct module *module) +{ + struct module_gsettings_data *data = module->user_data; + gchar **name; + + data->context = g_main_context_new(); + g_main_context_push_thread_default(data->context); + + data->settings = g_settings_new(PA_GSETTINGS_MODULE_GROUPS_SCHEMA); + if (data->settings == NULL) + return -EIO; + + data->group_names = g_settings_list_children(data->settings); + + for (name = data->group_names; *name; name++) { + GSettings *child = g_settings_get_child(data->settings, *name); + /* The child may have been removed between the + * g_settings_list_children() and g_settings_get_child() calls. */ + if (child == NULL) + continue; + + g_object_set_data(G_OBJECT(child), "module-data", data); + g_signal_connect(child, "changed", (GCallback) module_group_callback, *name); + handle_module_group(data, *name); + } + g_main_context_pop_thread_default(data->context); + + data->thr = pw_thread_utils_create(NULL, do_loop, data); + return 0; +} + +static gboolean +do_stop(gpointer data) +{ + struct module_gsettings_data *d = data; + if (d->loop) + g_main_loop_quit(d->loop); + return FALSE; +} + +static int module_gsettings_unload(struct module *module) +{ + struct module_gsettings_data *d = module->user_data; + struct group *g; + + g_main_context_invoke(d->context, do_stop, d); + pw_thread_utils_join(d->thr, NULL); + g_main_context_unref(d->context); + + spa_list_consume(g, &d->groups, link) + unload_module(d, g); + + g_strfreev(d->group_names); + g_object_unref(G_OBJECT(d->settings)); + return 0; +} + +static int module_gsettings_prepare(struct module * const module) +{ + PW_LOG_TOPIC_INIT(mod_topic); + + struct module_gsettings_data * const data = module->user_data; + spa_list_init(&data->groups); + data->module = module; + + return 0; +} + +static const struct spa_dict_item module_gsettings_info = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "GSettings Adapter" }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +DEFINE_MODULE_INFO(module_gsettings) = { + .name = "module-gsettings", + .load_once = true, + .prepare = module_gsettings_prepare, + .load = module_gsettings_load, + .unload = module_gsettings_unload, + .properties = &SPA_DICT_INIT_ARRAY(module_gsettings_info), + .data_size = sizeof(struct module_gsettings_data), +};
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
@@ -59,7 +59,7 @@ .destroy = module_destroy }; -static int module_ladspa_sink_load(struct client *client, struct module *module) +static int module_ladspa_sink_load(struct module *module) { struct module_ladspa_sink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
@@ -59,7 +59,7 @@ .destroy = module_destroy }; -static int module_ladspa_source_load(struct client *client, struct module *module) +static int module_ladspa_source_load(struct module *module) { struct module_ladspa_source_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
@@ -63,7 +63,7 @@ .destroy = module_destroy }; -static int module_loopback_load(struct client *client, struct module *module) +static int module_loopback_load(struct module *module) { struct module_loopback_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c
Changed
@@ -38,10 +38,10 @@ struct pw_array servers; }; -static int module_native_protocol_tcp_load(struct client *client, struct module *module) +static int module_native_protocol_tcp_load(struct module *module) { struct module_native_protocol_tcp_data *data = module->user_data; - struct impl *impl = client->impl; + struct impl *impl = module->impl; const char *address; int res;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
@@ -104,11 +104,11 @@ .error = module_null_sink_core_error, }; -static int module_null_sink_load(struct client *client, struct module *module) +static int module_null_sink_load(struct module *module) { struct module_null_sink_data *d = module->user_data; - d->core = pw_context_connect(module->impl->context, pw_properties_copy(client->props), 0); + d->core = pw_context_connect(module->impl->context, NULL, 0); if (d->core == NULL) return -errno;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c
Changed
@@ -64,7 +64,7 @@ .destroy = module_destroy }; -static int module_pipe_sink_load(struct client *client, struct module *module) +static int module_pipe_sink_load(struct module *module) { struct module_pipesink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c
Changed
@@ -64,7 +64,7 @@ .destroy = module_destroy }; -static int module_pipe_source_load(struct client *client, struct module *module) +static int module_pipe_source_load(struct module *module) { struct module_pipesrc_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c
Changed
@@ -55,7 +55,7 @@ .destroy = module_destroy }; -static int module_raop_discover_load(struct client *client, struct module *module) +static int module_raop_discover_load(struct module *module) { struct module_raop_discover_data *data = module->user_data;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
@@ -59,7 +59,7 @@ .destroy = module_destroy }; -static int module_remap_sink_load(struct client *client, struct module *module) +static int module_remap_sink_load(struct module *module) { struct module_remap_sink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
@@ -59,7 +59,7 @@ .destroy = module_destroy }; -static int module_remap_source_load(struct client *client, struct module *module) +static int module_remap_source_load(struct module *module) { struct module_remap_source_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink-input.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink-input.c
Changed
@@ -58,7 +58,7 @@ .destroy = module_destroy }; -static int module_roc_sink_input_load(struct client *client, struct module *module) +static int module_roc_sink_input_load(struct module *module) { struct module_roc_sink_input_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
@@ -58,7 +58,7 @@ .destroy = module_destroy }; -static int module_roc_sink_load(struct client *client, struct module *module) +static int module_roc_sink_load(struct module *module) { struct module_roc_sink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
@@ -58,7 +58,7 @@ .destroy = module_destroy }; -static int module_roc_source_load(struct client *client, struct module *module) +static int module_roc_source_load(struct module *module) { struct module_roc_source_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-recv.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-recv.c
Changed
@@ -57,7 +57,7 @@ .destroy = module_destroy }; -static int module_rtp_recv_load(struct client *client, struct module *module) +static int module_rtp_recv_load(struct module *module) { struct module_rtp_recv_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-send.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-rtp-send.c
Changed
@@ -58,7 +58,7 @@ .destroy = module_destroy }; -static int module_rtp_send_load(struct client *client, struct module *module) +static int module_rtp_send_load(struct module *module) { struct module_rtp_send_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c
Changed
@@ -58,10 +58,10 @@ .destroy = module_destroy }; -static int module_simple_protocol_tcp_load(struct client *client, struct module *module) +static int module_simple_protocol_tcp_load(struct module *module) { struct module_simple_protocol_tcp_data *data = module->user_data; - struct impl *impl = client->impl; + struct impl *impl = module->impl; char *args; size_t size; uint32_t i;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c
Changed
@@ -175,13 +175,13 @@ .done = on_core_done, }; -static int module_switch_on_connect_load(struct client *client, struct module *module) +static int module_switch_on_connect_load(struct module *module) { - struct impl *impl = client->impl; + struct impl *impl = module->impl; struct module_switch_on_connect_data *d = module->user_data; int res; - d->core = pw_context_connect(impl->context, pw_properties_copy(client->props), 0); + d->core = pw_context_connect(impl->context, NULL, 0); if (d->core == NULL) { res = -errno; goto error;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
@@ -62,7 +62,7 @@ .destroy = module_destroy }; -static int module_tunnel_sink_load(struct client *client, struct module *module) +static int module_tunnel_sink_load(struct module *module) { struct module_tunnel_sink_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
@@ -62,7 +62,7 @@ .destroy = module_destroy }; -static int module_tunnel_source_load(struct client *client, struct module *module) +static int module_tunnel_source_load(struct module *module) { struct module_tunnel_source_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c
Changed
@@ -51,7 +51,7 @@ .destroy = module_destroy }; -static int module_x11_bell_load(struct client *client, struct module *module) +static int module_x11_bell_load(struct module *module) { struct module_x11_bell_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c
Changed
@@ -57,7 +57,7 @@ .destroy = module_destroy }; -static int module_zeroconf_discover_load(struct client *client, struct module *module) +static int module_zeroconf_discover_load(struct module *module) { struct module_zeroconf_discover_data *data = module->user_data; FILE *f;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c
Changed
@@ -73,6 +73,7 @@ AvahiEntryGroup *entry_group; AvahiStringList *txt; + struct server *server; const char *service_type; enum service_subtype subtype; @@ -154,6 +155,7 @@ spa_list_remove(&s->link); spa_list_append(&s->userdata->pending, &s->link); s->published = false; + s->server = NULL; } static void unpublish_all_services(struct module_zeroconf_publish_data *d) @@ -397,7 +399,7 @@ return txt; } -static int find_port(struct service *s, int *proto, uint16_t *port) +static struct server *find_server(struct service *s, int *proto, uint16_t *port) { struct module_zeroconf_publish_data *d = s->userdata; struct impl *impl = d->module->impl; @@ -407,14 +409,15 @@ if (server->addr.ss_family == AF_INET) { *proto = AVAHI_PROTO_INET; *port = ntohs(((struct sockaddr_in*) &server->addr)->sin_port); - return 0; + return server; } else if (server->addr.ss_family == AF_INET6) { *proto = AVAHI_PROTO_INET6; *port = ntohs(((struct sockaddr_in6*) &server->addr)->sin6_port); - return 0; + return server; } } - return -ENODEV; + + return NULL; } static void publish_service(struct service *s) @@ -423,10 +426,11 @@ int proto; uint16_t port; - if (find_port(s, &proto, &port) < 0) + struct server *server = find_server(s, &proto, &port); + if (!server) return; - pw_log_debug("found proto:%d port:%d", proto, port); + pw_log_debug("found server:%p proto:%d port:%d", server, proto, port); if (!d->client || avahi_client_get_state(d->client) != AVAHI_CLIENT_S_RUNNING) return; @@ -499,6 +503,7 @@ spa_list_remove(&s->link); spa_list_append(&d->published, &s->link); + s->server = server; pw_log_info("created service: %s", s->service_name); return; @@ -626,7 +631,13 @@ { struct module_zeroconf_publish_data *d = data; pw_log_info("a server stopped, try republish"); - unpublish_all_services(d); + + struct service *s, *tmp; + spa_list_for_each_safe(s, tmp, &d->published, link) { + if (s->server == server) + unpublish_service(s); + } + publish_pending(d); } @@ -636,14 +647,13 @@ .server_stopped = impl_server_stopped, }; -static int module_zeroconf_publish_load(struct client *client, struct module *module) +static int module_zeroconf_publish_load(struct module *module) { struct module_zeroconf_publish_data *data = module->user_data; struct pw_loop *loop; int error; - data->core = pw_context_connect(module->impl->context, - pw_properties_copy(client->props), 0); + data->core = pw_context_connect(module->impl->context, NULL, 0); if (data->core == NULL) { pw_log_error("failed to connect to pipewire: %m"); return -errno;
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -85,7 +85,7 @@ #define DEFAULT_MIN_QUANTUM "256/48000" #define DEFAULT_FORMAT "F32" #define DEFAULT_POSITION " FL FR " -#define DEFAULT_IDLE_TIMEOUT "5" +#define DEFAULT_IDLE_TIMEOUT "0" #define MAX_FORMATS 32 /* The max amount of data we send in one block when capturing. In PulseAudio this @@ -5131,6 +5131,7 @@ .sync = on_load_module_manager_sync, }; + struct impl *impl = client->impl; const char *name, *argument; struct module *module; struct pending_module *pm; @@ -5145,7 +5146,7 @@ pw_log_info("%s %s name:%s argument:%s", client->name, commandscommand.name, name, argument); - module = module_create(client, name, argument); + module = module_create(impl, name, argument); if (module == NULL) return -errno; @@ -5159,7 +5160,7 @@ pw_log_debug("pending module %p: start tag:%d", pm, tag); - r = module_load(client, module); + r = module_load(module); module_add_listener(module, &pm->module_listener, &module_events, pm); client_add_listener(client, &pm->client_listener, &client_events, pm);
View file
pipewire-0.3.61.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.62.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -823,13 +823,14 @@ if (len < 2) return -ENOSPC; - snprintf(ip, sizeof(ip), ":::%d", res); - spa_assert_se(parse_ipv6_address(ip, (struct sockaddr_in6 *) &addr) == 0); - addrs0 = addr; - snprintf(ip, sizeof(ip), "0.0.0.0:%d", res); spa_assert_se(parse_ipv4_address(ip, (struct sockaddr_in *) &addr) == 0); + addrs0 = addr; + + snprintf(ip, sizeof(ip), ":::%d", res); + spa_assert_se(parse_ipv6_address(ip, (struct sockaddr_in6 *) &addr) == 0); addrs1 = addr; + return 2; }
View file
pipewire-0.3.61.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.62.tar.gz/src/modules/module-pulse-tunnel.c
Changed
@@ -189,6 +189,7 @@ uint32_t target_latency; uint32_t current_latency; uint32_t target_buffer; + struct spa_io_rate_match *rate_match; struct spa_dll dll; float max_error; unsigned resync:1; @@ -250,6 +251,28 @@ } } +static void update_rate(struct impl *impl, bool playback) +{ + float error, corr; + + if (impl->rate_match == NULL) + return; + + if (playback) + error = (float)impl->target_latency - (float)impl->current_latency; + else + error = (float)impl->current_latency - (float)impl->target_latency; + error = SPA_CLAMP(error, -impl->max_error, impl->max_error); + + corr = spa_dll_update(&impl->dll, error); + pw_log_debug("error:%f corr:%f current:%u target:%u", + error, corr, + impl->current_latency, impl->target_latency); + + SPA_FLAG_SET(impl->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE); + impl->rate_match->rate = corr; +} + static void playback_stream_process(void *d) { struct impl *impl = d; @@ -279,17 +302,7 @@ size, RINGBUFFER_SIZE); impl->resync = true; } else { - float error, corr; - - error = (float)impl->target_latency - (float)impl->current_latency; - error = SPA_CLAMP(error, -impl->max_error, impl->max_error); - - corr = spa_dll_update(&impl->dll, error); - pw_log_debug("filled:%u target:%u error:%f corr:%f %u %u", filled, - impl->target_buffer, error, corr, - impl->current_latency, impl->target_latency); - pw_stream_set_control(impl->stream, - SPA_PROP_rate, 1, &corr, NULL); + update_rate(impl, true); } spa_ringbuffer_write_data(&impl->ring, impl->buffer, RINGBUFFER_SIZE, @@ -326,24 +339,12 @@ if (avail < (int32_t)size) { memset(bd->data, 0, size); } else { - float error, corr; - if (avail > (int32_t)RINGBUFFER_SIZE) { avail = impl->target_buffer; index += avail - impl->target_buffer; } else { - error = (float)(impl->current_latency) - (float)impl->target_latency; - error = SPA_CLAMP(error, -impl->max_error, impl->max_error); - - corr = spa_dll_update(&impl->dll, error); - - pw_log_debug("avail:%u target:%u error:%f corr:%f %u %u", avail, - impl->target_buffer, error, corr, - impl->current_latency, impl->target_latency); - pw_stream_set_control(impl->stream, - SPA_PROP_rate, 1, &corr, NULL); + update_rate(impl, false); } - spa_ringbuffer_read_data(&impl->ring, impl->buffer, RINGBUFFER_SIZE, index & RINGBUFFER_MASK, @@ -359,10 +360,21 @@ pw_stream_queue_buffer(impl->stream, buf); } +static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + switch (id) { + case SPA_IO_RateMatch: + impl->rate_match = area; + break; + } +} + static const struct pw_stream_events playback_stream_events = { PW_VERSION_STREAM_EVENTS, .destroy = stream_destroy, .state_changed = stream_state_changed, + .io_changed = stream_io_changed, .process = playback_stream_process }; @@ -370,6 +382,7 @@ PW_VERSION_STREAM_EVENTS, .destroy = stream_destroy, .state_changed = stream_state_changed, + .io_changed = stream_io_changed, .process = capture_stream_process };
View file
pipewire-0.3.61.tar.gz/src/modules/module-rtp-sink.c -> pipewire-0.3.62.tar.gz/src/modules/module-rtp-sink.c
Changed
@@ -306,8 +306,17 @@ &iov1, tosend); n = sendmsg(impl->rtp_fd, &msg, MSG_NOSIGNAL); - if (n < 0) - pw_log_warn("sendmsg() failed: %m"); + if (n < 0) { + switch (errno) { + case ECONNREFUSED: + case ECONNRESET: + pw_log_debug("remote end not listening"); + break; + default: + pw_log_warn("sendmsg() failed: %m"); + break; + } + } impl->seq++; impl->timestamp += tosend / impl->frame_size;
View file
pipewire-0.3.61.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.62.tar.gz/src/modules/module-rtp-source.c
Changed
@@ -214,6 +214,7 @@ struct spa_ringbuffer ring; uint8_t bufferBUFFER_SIZE; + struct spa_io_rate_match *rate_match; struct spa_dll dll; uint32_t target_buffer; float max_error; @@ -269,8 +270,10 @@ pw_log_debug("avail:%u target:%u error:%f corr:%f", avail, sess->target_buffer, error, corr); - pw_stream_set_control(sess->stream, - SPA_PROP_rate, 1, &corr, NULL); + if (sess->rate_match) { + SPA_FLAG_SET(sess->rate_match->flags, SPA_IO_RATE_MATCH_FLAG_ACTIVE); + sess->rate_match->rate = corr; + } } spa_ringbuffer_read_data(&sess->ring, sess->buffer, @@ -308,10 +311,21 @@ } } +static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct session *sess = data; + switch (id) { + case SPA_IO_RateMatch: + sess->rate_match = area; + break; + } +} + static const struct pw_stream_events out_stream_events = { PW_VERSION_STREAM_EVENTS, .destroy = stream_destroy, .state_changed = on_stream_state_changed, + .io_changed = stream_io_changed, .process = stream_process };
View file
pipewire-0.3.61.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.62.tar.gz/src/pipewire/impl-link.c
Changed
@@ -622,8 +622,8 @@ pw_log_debug("%p: activate activated:%d state:%s", this, impl->activated, pw_link_state_as_string(this->info.state)); - if (impl->activated || !this->prepared || !impl->inode->active || - !impl->inode->added || !impl->onode->active) + if (impl->activated || !this->prepared || + !impl->inode->active || !impl->onode->active) return 0; if (!impl->io_set) { @@ -812,7 +812,7 @@ spa_list_remove(&this->rt.out_mix.rt_link); spa_list_remove(&this->rt.in_mix.rt_link); - if (this->input->node != this->output->node) { + if (impl->inode != impl->onode) { struct pw_node_activation_state *state; spa_list_remove(&this->rt.target.link);
View file
pipewire-0.3.61.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.62.tar.gz/src/pipewire/impl-node.c
Changed
@@ -158,12 +158,51 @@ this->rt.driver_target.node = NULL; } +static int +do_node_add(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct pw_impl_node *this = user_data; + struct pw_impl_node *driver = this->driver_node; + + this->added = true; + if (this->source.loop == NULL) { + struct spa_system *data_system = this->context->data_system; + uint64_t dummy; + int res; + + /* clear the eventfd in case it was written to while the node was stopped */ + res = spa_system_eventfd_read(data_system, this->source.fd, &dummy); + if (SPA_UNLIKELY(res != -EAGAIN && res != 0)) + pw_log_warn("%p: read failed %m", this); + + spa_loop_add_source(loop, &this->source); + add_node(this, driver); + } + return 0; +} + +static int +do_node_remove(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct pw_impl_node *this = user_data; + if (this->source.loop != NULL) { + spa_loop_remove_source(loop, &this->source); + remove_node(this); + } + this->added = false; + return 0; +} + static void node_deactivate(struct pw_impl_node *this) { struct pw_impl_port *port; struct pw_impl_link *link; pw_log_debug("%p: deactivate", this); + + /* make sure the node doesn't get woken up while not active */ + pw_loop_invoke(this->data_loop, do_node_remove, 1, NULL, 0, true, this); + spa_list_for_each(port, &this->input_ports, link) { spa_list_for_each(link, &port->links, input_link) pw_impl_link_deactivate(link); @@ -200,7 +239,7 @@ return res; } -static void node_activate_outputs(struct pw_impl_node *this) +static void node_activate(struct pw_impl_node *this) { struct pw_impl_port *port; @@ -210,13 +249,6 @@ spa_list_for_each(link, &port->links, output_link) pw_impl_link_activate(link); } -} - -static void node_activate_inputs(struct pw_impl_node *this) -{ - struct pw_impl_port *port; - - pw_log_debug("%p: activate", this); spa_list_for_each(port, &this->input_ports, link) { struct pw_impl_link *link; spa_list_for_each(link, &port->links, input_link) @@ -229,9 +261,7 @@ struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); int res = 0; - /* First activate the outputs so that when the node starts pushing, - * we can process the outputs */ - node_activate_outputs(this); + node_activate(this); if (impl->pending_state >= PW_NODE_STATE_RUNNING) return 0; @@ -243,6 +273,10 @@ impl->pending_play = true; res = spa_node_send_command(this->node, &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Start)); + } else { + /* driver nodes will wait until all other nodes are started before + * they are started */ + res = EBUSY; } if (res < 0) @@ -325,34 +359,6 @@ } } -static int -do_node_add(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct pw_impl_node *this = user_data; - struct pw_impl_node *driver = this->driver_node; - - if (this->source.loop == NULL) { - spa_loop_add_source(loop, &this->source); - add_node(this, driver); - } - this->added = true; - return 0; -} - -static int -do_node_remove(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct pw_impl_node *this = user_data; - if (this->source.loop != NULL) { - spa_loop_remove_source(loop, &this->source); - remove_node(this); - } - this->added = false; - return 0; -} - static void node_update_state(struct pw_impl_node *node, enum pw_node_state state, int res, char *error) { struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); @@ -375,10 +381,6 @@ pw_loop_invoke(node->data_loop, do_node_remove, 1, NULL, 0, true, node); } } - if (res >= 0) { - /* now activate the inputs */ - node_activate_inputs(node); - } break; case PW_NODE_STATE_IDLE: case PW_NODE_STATE_SUSPENDED: @@ -807,17 +809,9 @@ struct impl *impl = user_data; struct pw_impl_node *driver = *(struct pw_impl_node **)data; struct pw_impl_node *node = &impl->this; - int res; pw_log_trace("%p: driver:%p->%p", node, node->driver_node, driver); - if ((res = spa_node_set_io(node->node, - SPA_IO_Position, - &driver->rt.activation->position, - sizeof(struct spa_io_position))) < 0) { - pw_log_debug("%p: set position: %s", node, spa_strerror(res)); - } - pw_log_trace("%p: set position %p", node, &driver->rt.activation->position); node->rt.position = &driver->rt.activation->position; @@ -843,6 +837,8 @@ { struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct pw_impl_node *old = node->driver_node; + int res; + bool was_driving; if (driver == NULL) driver = node; @@ -865,8 +861,16 @@ old->name, old->info.id, driver->name, driver->info.id); } + was_driving = node->driving; node->driving = node->driver && driver == node; + /* When a node was driver (and is waiting for all nodes to complete + * the Start command) cancel the pending state and let the new driver + * calculate a new state so that the Start command is sent to the + * node */ + if (was_driving && !node->driving) + impl->pending_state = node->info.state; + pw_log_debug("%p: driver %p driving:%u", node, driver, node->driving); pw_log_info("(%s-%u) -> change driver (%s-%d -> %s-%d)", @@ -876,6 +880,13 @@ node->driver_node = driver; node->moved = true; + if ((res = spa_node_set_io(node->node, + SPA_IO_Position, + &driver->rt.activation->position, + sizeof(struct spa_io_position))) < 0) { + pw_log_debug("%p: set position: %s", node, spa_strerror(res)); + } + pw_loop_invoke(node->data_loop, do_move_nodes, SPA_ID_INVALID, &driver, sizeof(struct pw_impl_node *), true, impl); @@ -1110,28 +1121,30 @@ a->status = PW_NODE_ACTIVATION_AWAKE; a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts); - if (!this->added) { - /* This should not happen here. We activate the input - * links after we add the node to the graph. */ - pw_log_warn("%p: scheduling non-active node", this); - return -EIO; - } pw_log_trace_fp("%p: process %"PRIu64, this, a->awake_time); /* when transport sync is not supported, just clear the flag */ if (!this->transport_sync) a->pending_sync = false; - spa_list_for_each(p, &this->rt.input_mix, rt.node_link) - spa_node_process(p->mix); + if (this->added) { + spa_list_for_each(p, &this->rt.input_mix, rt.node_link) + spa_node_process(p->mix); - status = spa_node_process(this->node); - a->state0.status = status; + status = spa_node_process(this->node); - if (status & SPA_STATUS_HAVE_DATA) { - spa_list_for_each(p, &this->rt.output_mix, rt.node_link) - spa_node_process(p->mix); + if (status & SPA_STATUS_HAVE_DATA) { + spa_list_for_each(p, &this->rt.output_mix, rt.node_link) + spa_node_process(p->mix); + } + } else { + /* This can happen when we deactivated the node but some links are + * still not shut down. We simply don't schedule the node and make + * sure we trigger the peers in resume_node below. */ + pw_log_debug("%p: scheduling non-active node %s", this, this->name); + status = SPA_STATUS_HAVE_DATA; } + a->state0.status = status; if (SPA_UNLIKELY(this == this->driver_node && !this->exported)) { spa_system_clock_gettime(data_system, CLOCK_MONOTONIC, &ts); @@ -1636,7 +1649,11 @@ node->driver, node->exported, driver, status, node->added); if (!node->added) { - pw_log_warn("%p: ready non-active node", node); + /* This can happen when we are stopping a node and removed it from the + * graph but we still have not completed the Pause/Suspend command on + * the node. In that case, the node might still emit ready events, + * which we should simply ignore here. */ + pw_log_info("%p: ready non-active node %s in state %d", node, node->name, node->info.state); return -EIO; } @@ -2155,6 +2172,10 @@ enum pw_node_state state = SPA_PTR_TO_INT(data); char *error = NULL; + /* driver nodes added -EBUSY. This is then not an error */ + if (res == -EBUSY) + res = 0; + impl->pending_id = SPA_ID_INVALID; impl->pending_play = false; @@ -2242,9 +2263,13 @@ pw_work_queue_cancel(impl->work, node, impl->pending_id); node->info.state = impl->pending_state; } + /* driver nodes return EBUSY to add a -EBUSY to the work queue. This + * will wait until all previous items in the work queue are + * completed */ impl->pending_state = state; impl->pending_id = pw_work_queue_add(impl->work, - node, res, on_state_complete, SPA_INT_TO_PTR(state)); + node, res == EBUSY ? -EBUSY : res, + on_state_complete, SPA_INT_TO_PTR(state)); } return res; } @@ -2255,9 +2280,9 @@ bool old = node->active; if (old != active) { - pw_log_debug("%p: %s registered:%d", node, + pw_log_debug("%p: %s registered:%d exported:%d", node, active ? "activate" : "deactivate", - node->registered); + node->registered, node->exported); node->active = active; pw_impl_node_emit_active_changed(node, active);
View file
pipewire-0.3.61.tar.gz/src/pipewire/stream.c -> pipewire-0.3.62.tar.gz/src/pipewire/stream.c
Changed
@@ -324,7 +324,8 @@ { uint32_t index; - if (SPA_FLAG_IS_SET(buffer->flags, BUFFER_FLAG_QUEUED)) + if (SPA_FLAG_IS_SET(buffer->flags, BUFFER_FLAG_QUEUED) || + buffer->id >= stream->n_buffers) return -EINVAL; SPA_FLAG_SET(buffer->flags, BUFFER_FLAG_QUEUED); @@ -921,6 +922,9 @@ if (impl->disconnecting && n_buffers > 0) return -EIO; + if (n_buffers > MAX_BUFFERS) + return -EINVAL; + prot = PROT_READ | (direction == SPA_DIRECTION_OUTPUT ? PROT_WRITE : 0); clear_buffers(stream); @@ -956,6 +960,7 @@ pw_log_debug("%p: got buffer id:%d datas:%d, mapped size %d", stream, i, buffersi->n_datas, size); } + impl->n_buffers = n_buffers; for (i = 0; i < n_buffers; i++) { struct buffer *b = &impl->buffersi; @@ -972,9 +977,6 @@ pw_stream_emit_add_buffer(stream, &b->this); } - - impl->n_buffers = n_buffers; - return 0; } @@ -1000,6 +1002,7 @@ if (io->status == SPA_STATUS_HAVE_DATA && (b = get_buffer(stream, io->buffer_id)) != NULL) { /* push new buffer */ + pw_log_trace_fp("%p: push %d %p", stream, b->id, io); if (queue_push(impl, &impl->dequeued, b) == 0) { copy_position(impl, impl->dequeued.incount); if (b->busy) @@ -1007,13 +1010,15 @@ call_process(impl); } } - if (io->status != SPA_STATUS_NEED_DATA) { + if (io->status != SPA_STATUS_NEED_DATA || io->buffer_id == SPA_ID_INVALID) { /* pop buffer to recycle */ if ((b = queue_pop(impl, &impl->queued))) { pw_log_trace_fp("%p: recycle buffer %d", stream, b->id); - } else if (io->status == -EPIPE) - return io->status; - io->buffer_id = b ? b->id : SPA_ID_INVALID; + io->buffer_id = b->id; + } else { + pw_log_trace_fp("%p: no buffers to recycle", stream); + io->buffer_id = SPA_ID_INVALID; + } io->status = SPA_STATUS_NEED_DATA; } if (impl->driving && impl->using_trigger)
View file
pipewire-0.3.61.tar.gz/src/tools/pw-top.c -> pipewire-0.3.62.tar.gz/src/tools/pw-top.c
Changed
@@ -663,11 +663,20 @@ { struct data *data = _data; - pw_log_error("error id:%u seq:%d res:%d (%s): %s", - id, seq, res, spa_strerror(res), message); - - if (id == PW_ID_CORE && res == -EPIPE) - pw_main_loop_quit(data->loop); + if (id == PW_ID_CORE) { + switch (res) { + case -EPIPE: + pw_main_loop_quit(data->loop); + break; + default: + pw_log_error("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + break; + } + } else { + pw_log_info("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + } } static void on_core_done(void *_data, uint32_t id, int seq)
View file
pipewire-0.3.61.tar.gz/test/test-spa-buffer.c -> pipewire-0.3.62.tar.gz/test/test-spa-buffer.c
Changed
@@ -47,7 +47,8 @@ pwtest_int_eq(SPA_META_Cursor, 5); pwtest_int_eq(SPA_META_Control, 6); pwtest_int_eq(SPA_META_Busy, 7); - pwtest_int_eq(_SPA_META_LAST, 8); + pwtest_int_eq(SPA_META_VideoTransform, 8); + pwtest_int_eq(_SPA_META_LAST, 9); return PWTEST_PASS; } @@ -64,6 +65,7 @@ pwtest_int_eq(sizeof(struct spa_meta_region), 16U); pwtest_int_eq(sizeof(struct spa_meta_bitmap), 20U); pwtest_int_eq(sizeof(struct spa_meta_cursor), 28U); + pwtest_int_eq(sizeof(struct spa_meta_videotransform), 4U); return PWTEST_PASS; #else @@ -75,6 +77,7 @@ fprintf(stderr, "%zd\n", sizeof(struct spa_meta_region)); fprintf(stderr, "%zd\n", sizeof(struct spa_meta_bitmap)); fprintf(stderr, "%zd\n", sizeof(struct spa_meta_cursor)); + fprintf(stderr, "%zd\n", sizeof(struct spa_meta_videotransform)); return PWTEST_SKIP; #endif }
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
.