Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 30
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed Jul 26 14:05:18 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.74 + +------------------------------------------------------------------- Thu Jun 29 10:47:58 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.72
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.72 +Version: 0.3.74 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.72.tar.gz/.gitignore -> pipewire-0.3.74.tar.gz/.gitignore
Changed
@@ -1,7 +1,5 @@ .* -.tarball-version -.version -.*.swp +!.gitlab ABOUT-NLS *~ *.tar.gz
View file
pipewire-0.3.72.tar.gz/.gitlab/ci/check_missing_headers.sh -> pipewire-0.3.74.tar.gz/.gitlab/ci/check_missing_headers.sh
Changed
@@ -5,12 +5,12 @@ LIST="" -for i in $(find spa/include -name '*.h' | sed s#spa/include/##); +for i in $(find spa/include -name '*.h' -a -not -path 'spa/include/spa/utils/cleanup.h' | sed s#spa/include/##); do -f "$PREFIX/include/spa-0.2/$i" || LIST="$i $LIST" done -for i in $(find src/pipewire -name '*.h' -a -not -name '*private.h' | sed s#src/##); +for i in $(find src/pipewire -name '*.h' -a -not -name '*private.h' -a -not -name 'cleanup.h' | sed s#src/##); do -f "$PREFIX/include/pipewire-0.3/$i" || LIST="$i $LIST" done
View file
pipewire-0.3.72.tar.gz/NEWS -> pipewire-0.3.74.tar.gz/NEWS
Changed
@@ -1,3 +1,112 @@ +# PipeWire 0.3.74 (2023-07-12) + +This is a quick bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a critical bug where audio to bluetooth devices would cut out + randomly. (#3316) + - Improve RAOP compatibility. + - Avoid crashes after an update. + - Small fixes and improvements. + + +## PipeWire + - Mix info on port is now created explicitly. + - Remove the node as a driver peer when stopping. This caused some problem + with playback on and other remote bluetooth devices. (#3316) + - Work on avoiding crashes when loading new modules that use internal API + with old libpipewire. This is typical after an update where the old library is + still loaded by an application but when a new stream is created, updated + modules are loaded. (#3243) + +## Modules + - The RTP source module now has an option to ignore the SSRC, which is + useful to continue to receive the stream when the sender is restarted. + - The native protocol will refuse to load twice now instead of silently + ignoring the error. + - module-raop is compatible with more devices. (#3247) + +## SPA + - plugins will now warn when running out of buffers. This is always a bad + thing. + - Merge scope based cleanup macros. + - Add ratelimit function. + +Older versions: + + +# PipeWire 0.3.73 (2023-07-06) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fixes an ALSA resume after suspend error. + - Handle and disable seemingly wrong hires timestamps from ALSA. + - Filter-chain now has loadable plugin modules. The LV2 and sofa plugins are + moved to a separate .so file to make things more modular. + - Rate changes in the graph should now be handled more gracefully by loopback + and filter-chain. + - A regression in the rtp-sap module was fixed where it would in some cases + fail to start. + - A potential crash in the peaks resampler was fixed. + - Many cleanups and other small bug fixes. + + +## PipeWire + - Fix a potential segfault when no fallback driver was set in the config. + - Improve OPUS detection. + - Add ASYNC flag to pw-filter and pw-stream when queue/dequeue is not called + from the process function. This ensure we allocate an extra buffer. + - Discard pending process callbacks when disconnecting. (#3314) + - Cleanups and improvements to the debug environment variable parsing. + - The graph rate was tweaked to better handle very low rates such as those + requested by pavucontrol when it does the signal monitoring. + +## Modules + - An example filter module was added. + - Filter-chain and loopback now disable the resamplers if no rate is specified + and will always follow the graph rate. + - Improve setup of filter-chain. The graph is now created when starting + because this ensure the target graph rate is known. + - Filter-chain can now link notify ports to control ports in the graph. + - Filter-chain now has loadable plugin modules. The LV2 and sofa plugins are + moved to a separate .so file. + - A regression in the rtp-sap module was fixed where it would in some cases + fail to start. + - Module-rt now has options to disable rlimits, portal and rtkit. + - module-raop-discover now has an options to set the latency. (#3247) + +## Tools + - pw-cat now supports overriding all stream properties. + +## SPA + - Disable rate negotiation when the resampler is disabled. We will always + follow the graph rate. + - Set device.icon property for UCM ports as well. + - Improve ALSA recover when using hires timestamps. This fixes some problems + after resume from suspend. (#3315) + - ALSA will now warn and disable hires timestamp when they seem wrong. + They can also be disabled manually with a property. + - V4l2 will now gracefully handle ENOTTY when enumerating frame sizes and + frame rates. (#3325) + - A potential crash in the peaks resampler was fixed. (#3320) + +## pulse-server + - A client crash in pavucontrol is avoided by always setting a card name. + - The graph rate is now taken correctly when using the FIX flags. (#3317) + - An option was added to ignore the FIX flags of a stream. Also the + documentation for those options was updated. (#3317) + - module-raop-discover now support latency_msec. (#3247) + +## Bluetooth + - Remove an assert and issue a warning/recover instead when a buffer is too + small. + +## GStreamer + - The device provider does locking when destroying the registry. + # PipeWire 0.3.72 (2023-06-26) This is a bugfix release that is API and ABI compatible with previous @@ -101,9 +210,6 @@ ## GStreamer - Fill default strides instead of 0 on pipewire video buffers. (#3236) -Older versions: - - # PipeWire 0.3.71 (2023-05-17) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.72.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.74.tar.gz/doc/pipewire-modules.dox
Changed
@@ -56,6 +56,7 @@ - \subpage page_module_client_node - \subpage page_module_combine_stream - \subpage page_module_echo_cancel +- \subpage page_module_example_filter - \subpage page_module_example_sink - \subpage page_module_example_source - \subpage page_module_fallback_sink
View file
pipewire-0.3.72.tar.gz/meson.build -> pipewire-0.3.74.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.72', + version : '0.3.74', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -82,9 +82,9 @@ '-Wno-missing-field-initializers', '-Wno-unused-parameter', '-Wno-pedantic', - '-Wold-style-declaration', '-Wdeprecated-declarations', '-Wunused-result', + '-Werror=return-type', cc_flags = common_flags + @@ -93,6 +93,10 @@ # '-DSPA_DEBUG_MEMCPY', '-Werror=implicit-function-declaration', '-Werror=int-conversion', + '-Werror=old-style-declaration', + '-Werror=old-style-definition', + '-Werror=missing-parameter-type', + '-Werror=strict-prototypes', add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c') @@ -295,7 +299,6 @@ cdata.set('HAVE_SNDFILE', sndfile_dep.found()) libmysofa_dep = dependency('libmysofa', required : get_option('libmysofa')) summary({'libmysofa': libmysofa_dep.found()}, bool_yn: true, section: 'filter-chain') -cdata.set('HAVE_LIBMYSOFA', libmysofa_dep.found()) pulseaudio_dep = dependency('libpulse', required : get_option('libpulse')) summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons') avahi_dep = dependency('avahi-client', required : get_option('avahi')) @@ -403,7 +406,6 @@ lilv_lib = dependency('lilv-0', required: get_option('lv2')) summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true) -cdata.set('HAVE_LILV', lilv_lib.found()) libffado_dep = dependency('libffado', required: get_option('libffado')) summary({'ffado': libffado_dep.found()}, bool_yn: true)
View file
pipewire-0.3.72.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.74.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -11,6 +11,7 @@ #include <math.h> #include <jack/jack.h> +#include <jack/intclient.h> #include <jack/session.h> #include <jack/thread.h> #include <jack/midiport.h> @@ -20,9 +21,11 @@ #include <spa/support/cpu.h> #include <spa/param/audio/format-utils.h> #include <spa/param/video/format-utils.h> +#include <spa/param/latency-utils.h> #include <spa/debug/types.h> #include <spa/debug/pod.h> #include <spa/utils/json.h> +#include <spa/utils/result.h> #include <spa/utils/string.h> #include <spa/utils/ringbuffer.h> @@ -297,6 +300,7 @@ char *load_init; /* initialization string */ jack_uuid_t session_id; /* requested session_id */ + struct pw_loop *l; struct pw_data_loop *loop; struct pw_properties *props; @@ -586,14 +590,6 @@ return mix; } -static struct mix *ensure_mix(struct client *c, struct port *port, uint32_t mix_id) -{ - struct mix *mix; - if ((mix = find_mix(c, port, mix_id)) != NULL) - return mix; - return create_mix(c, port, mix_id, SPA_ID_INVALID); -} - static int clear_buffers(struct client *c, struct mix *mix) { struct port *port = mix->port; @@ -1239,7 +1235,7 @@ static void client_remove_source(struct client *c) { if (c->socket_source) { - pw_loop_destroy_source(c->loop->loop, c->socket_source); + pw_loop_destroy_source(c->l, c->socket_source); c->socket_source = NULL; } } @@ -1867,7 +1863,7 @@ c, readfd, writefd, c->node_id); close(writefd); - c->socket_source = pw_loop_add_io(c->loop->loop, + c->socket_source = pw_loop_add_io(c->l, readfd, SPA_IO_ERR | SPA_IO_HUP, true, on_rtsocket_condition, c); @@ -2027,7 +2023,7 @@ case SPA_NODE_COMMAND_Suspend: case SPA_NODE_COMMAND_Pause: if (c->started) { - pw_loop_update_io(c->loop->loop, + pw_loop_update_io(c->l, c->socket_source, SPA_IO_ERR | SPA_IO_HUP); c->started = false; @@ -2036,7 +2032,7 @@ case SPA_NODE_COMMAND_Start: if (!c->started) { - pw_loop_update_io(c->loop->loop, + pw_loop_update_io(c->l, c->socket_source, SPA_IO_IN | SPA_IO_ERR | SPA_IO_HUP); c->started = true; @@ -2482,7 +2478,7 @@ res = -EINVAL; goto done; } - if ((mix = ensure_mix(c, p, mix_id)) == NULL) { + if ((mix = find_mix(c, p, mix_id)) == NULL) { res = -ENOMEM; goto done; } @@ -2632,7 +2628,7 @@ goto exit; } - if ((mix = ensure_mix(c, p, mix_id)) == NULL) { + if ((mix = find_mix(c, p, mix_id)) == NULL) { res = -ENOMEM; goto exit; } @@ -3645,6 +3641,7 @@ &thread_utils_impl, client); client->loop = pw_context_get_data_loop(client->context.context); + client->l = pw_data_loop_get_loop(client->loop); pw_data_loop_stop(client->loop); pw_context_set_object(client->context.context, @@ -4736,6 +4733,13 @@ param_latency_other(c, p, ¶msn_params++, &b); pw_thread_loop_lock(c->context.loop); + if (create_mix(c, p, SPA_ID_INVALID, SPA_ID_INVALID) == NULL) { + res = -errno; + pw_log_warn("can't create mix for port %s: %m", port_name); + pw_thread_loop_unlock(c->context.loop); + goto error_free; + } + freeze_callbacks(c); pw_client_node_port_update(c->node,
View file
pipewire-0.3.72.tar.gz/spa/examples/adapter-control.c -> pipewire-0.3.74.tar.gz/spa/examples/adapter-control.c
Changed
@@ -176,7 +176,7 @@ return res; } -int init_data(struct data *data) +static int init_data(struct data *data) { int res; const char *str;
View file
pipewire-0.3.72.tar.gz/spa/examples/example-control.c -> pipewire-0.3.74.tar.gz/spa/examples/example-control.c
Changed
@@ -457,7 +457,7 @@ return -EBADF; } -int init_data(struct data *data) +static int init_data(struct data *data) { int res; const char *str;
View file
pipewire-0.3.72.tar.gz/spa/include/meson.build -> pipewire-0.3.74.tar.gz/spa/include/meson.build
Changed
@@ -14,5 +14,8 @@ spa_headers = 'spa' # used by doxygen install_subdir('spa', - install_dir : get_option('includedir') / spa_name + install_dir : get_option('includedir') / spa_name, + exclude_files : + 'utils/cleanup.h', + , )
View file
pipewire-0.3.74.tar.gz/spa/include/spa/utils/cleanup.h
Added
@@ -0,0 +1,98 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_UTILS_CLEANUP_H +#define SPA_UTILS_CLEANUP_H + +#if !defined(__has_attribute) || !__has_attribute(__cleanup__) +#error "attribute `cleanup` is required" +#endif + +#define spa_cleanup(func) __attribute__((__cleanup__(func))) + +#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \ +typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \ +static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \ +{ \ + __VA_ARGS__ \ +} + +#define spa_auto(name) \ + spa_cleanup(_spa_auto_cleanup_func_ ## name) \ + _spa_auto_cleanup_type_ ## name + +#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) \ +typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \ +static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \ +{ \ + __VA_ARGS__ \ +} + +#define spa_autoptr(name) \ + spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \ + _spa_autoptr_cleanup_type_ ## name + +#define spa_exchange(var, new_value) \ +__extension__ ({ \ + __typeof__(var) _old_value = (var); \ + (var) = (new_value); \ + _old_value; \ +}) + +#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL)) +#define spa_steal_fd(fd) spa_exchange((fd), -1) + +/* ========================================================================== */ + +#include <stdlib.h> + +#define spa_clear_ptr(ptr, destructor) \ +__extension__ ({ \ + __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \ + if (_old_value) \ + destructor(_old_value); \ + (void) 0; \ +}) + +static inline void _spa_autofree_cleanup_func(void *p) +{ + free(*(void **) p); +} +#define spa_autofree spa_cleanup(_spa_autofree_cleanup_func) + +/* ========================================================================== */ + +#include <unistd.h> + +#define spa_clear_fd(fd) \ +__extension__ ({ \ + int _old_value = spa_steal_fd(fd), _res = 0; \ + if (_old_value >= 0) \ + _res = close(_old_value); \ + _res; \ +}) + +static inline void _spa_autoclose_cleanup_func(int *fd) +{ + spa_clear_fd(*fd); +} +#define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func) + +/* ========================================================================== */ + +#include <stdio.h> + +SPA_DEFINE_AUTOPTR_CLEANUP(FILE, FILE, { + spa_clear_ptr(*thing, fclose); +}) + +/* ========================================================================== */ + +#include <dirent.h> + +SPA_DEFINE_AUTOPTR_CLEANUP(DIR, DIR, { + spa_clear_ptr(*thing, closedir); +}) + +#endif /* SPA_UTILS_CLEANUP_H */
View file
pipewire-0.3.74.tar.gz/spa/include/spa/utils/ratelimit.h
Added
@@ -0,0 +1,43 @@ +/* Ratelimit */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_RATELIMIT_H +#define SPA_RATELIMIT_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <inttypes.h> +#include <stddef.h> + +struct spa_ratelimit { + uint64_t interval; + uint64_t begin; + unsigned burst; + unsigned n_printed; + unsigned n_missed; +}; + +static inline int spa_ratelimit_test(struct spa_ratelimit *r, uint64_t now) +{ + unsigned missed = 0; + if (r->begin + r->interval < now) { + missed = r->n_missed; + r->begin = now; + r->n_printed = 0; + r->n_missed = 0; + } else if (r->n_printed >= r->burst) { + r->n_missed++; + return -1; + } + r->n_printed++; + return missed; +} + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_RATELIMIT_H */
View file
pipewire-0.3.72.tar.gz/spa/include/spa/utils/ringbuffer.h -> pipewire-0.3.74.tar.gz/spa/include/spa/utils/ringbuffer.h
Changed
@@ -85,7 +85,7 @@ * \param len number of bytes to read */ static inline void -spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf, +spa_ringbuffer_read_data(struct spa_ringbuffer *rbuf SPA_UNUSED, const void *buffer, uint32_t size, uint32_t offset, void *data, uint32_t len) { @@ -135,7 +135,7 @@ * \param len number of bytes to write */ static inline void -spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf, +spa_ringbuffer_write_data(struct spa_ringbuffer *rbuf SPA_UNUSED, void *buffer, uint32_t size, uint32_t offset, const void *data, uint32_t len) {
View file
pipewire-0.3.72.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/acp/alsa-ucm.c
Changed
@@ -991,6 +991,40 @@ } } +static void ucm_add_port_props( + pa_device_port *port, + bool is_sink) +{ + const char *icon; + + if (is_sink) { + switch (port->type) { + case PA_DEVICE_PORT_TYPE_HEADPHONES: + icon = "audio-headphones"; + break; + case PA_DEVICE_PORT_TYPE_HDMI: + icon = "video-display"; + break; + case PA_DEVICE_PORT_TYPE_SPEAKER: + default: + icon = "audio-speakers"; + break; + } + } else { + switch (port->type) { + case PA_DEVICE_PORT_TYPE_HEADSET: + icon = "audio-headset"; + break; + case PA_DEVICE_PORT_TYPE_MIC: + default: + icon = "audio-input-microphone"; + break; + } + } + + pa_proplist_sets(port->proplist, "device.icon_name", icon); +} + static void ucm_add_port_combination( pa_hashmap *hash, pa_alsa_ucm_mapping_context *context, @@ -1097,6 +1131,7 @@ pa_hashmap_put(ports, port->name, port); pa_log_debug("Add port %s: %s", port->name, port->description); + ucm_add_port_props(port, is_sink); if (num == 1) { /* To keep things simple and not worry about stacking controls, we only support hardware volumes on non-combination
View file
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -128,6 +128,8 @@ state->props.use_chmap = spa_atob(s); } else if (spa_streq(k, "api.alsa.multi-rate")) { state->multi_rate = spa_atob(s); + } else if (spa_streq(k, "api.alsa.htimestamp")) { + state->htimestamp = spa_atob(s); } else if (spa_streq(k, "latency.internal.rate")) { state->process_latency.rate = atoi(s); } else if (spa_streq(k, "latency.internal.ns")) { @@ -310,13 +312,21 @@ case 14: param = spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String("api.alsa.htimestamp"), + SPA_PROP_INFO_description, SPA_POD_String("Use hires timestamps"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(state->htimestamp), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + case 15: + param = spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_name, SPA_POD_String("latency.internal.rate"), SPA_PROP_INFO_description, SPA_POD_String("Internal latency in samples"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(state->process_latency.rate, 0, 65536), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 15: + case 16: param = spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_name, SPA_POD_String("latency.internal.ns"), @@ -325,7 +335,7 @@ 0LL, 2 * SPA_NSEC_PER_SEC), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; - case 16: + case 17: param = spa_pod_builder_add_object(b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_name, SPA_POD_String("clock.name"), @@ -394,6 +404,9 @@ spa_pod_builder_string(b, "api.alsa.multi-rate"); spa_pod_builder_bool(b, state->multi_rate); + spa_pod_builder_string(b, "api.alsa.htimestamp"); + spa_pod_builder_bool(b, state->htimestamp); + spa_pod_builder_string(b, "latency.internal.rate"); spa_pod_builder_int(b, state->process_latency.rate); @@ -490,6 +503,7 @@ snd_config_update_free_global(); state->multi_rate = true; + state->htimestamp = true; for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; const char *s = info->itemsi.value; @@ -1957,7 +1971,6 @@ return do_start(state); } -#if 0 static int get_avail(struct state *state, uint64_t current_time, snd_pcm_uframes_t *delay) { int res, missed; @@ -1967,7 +1980,7 @@ if ((res = alsa_recover(state, avail)) < 0) return res; if ((avail = snd_pcm_avail(state->hndl)) < 0) { - if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) { + if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { spa_log_warn(state->log, "%s: (%d missed) snd_pcm_avail after recover: %s", state->props.device, missed, snd_strerror(avail)); } @@ -1977,48 +1990,50 @@ state->alsa_recovering = false; } *delay = avail; - return avail; -} -#else -static int get_avail(struct state *state, uint64_t current_time, snd_pcm_uframes_t *delay) -{ - int res, missed; - snd_pcm_uframes_t avail; - snd_htimestamp_t tstamp; - uint64_t then; + if (state->htimestamp) { + snd_pcm_uframes_t havail; + snd_htimestamp_t tstamp; + uint64_t then; - avail = snd_pcm_avail(state->hndl); - if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) { - if ((res = alsa_recover(state, res)) < 0) - return res; - if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) { - if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) { + if ((res = snd_pcm_htimestamp(state->hndl, &havail, &tstamp)) < 0) { + if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { spa_log_warn(state->log, "%s: (%d missed) snd_pcm_htimestamp error: %s", state->props.device, missed, snd_strerror(res)); } - avail = state->threshold * 2; + return avail; } - } else { - state->alsa_recovering = false; - } - *delay = avail; - - if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) { - int64_t diff; + avail = havail; + *delay = havail; + if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) { + int64_t diff; - if (then < current_time) - diff = ((int64_t)(current_time - then)) * state->rate / SPA_NSEC_PER_SEC; - else - diff = -((int64_t)(then - current_time)) * state->rate / SPA_NSEC_PER_SEC; + if (then < current_time) + diff = ((int64_t)(current_time - then)) * state->rate / SPA_NSEC_PER_SEC; + else + diff = -((int64_t)(then - current_time)) * state->rate / SPA_NSEC_PER_SEC; - spa_log_trace_fp(state->log, "%"PRIu64" %"PRIu64" %"PRIi64, current_time, then, diff); + spa_log_trace_fp(state->log, "%"PRIu64" %"PRIu64" %"PRIi64, current_time, then, diff); - *delay += diff; + if (SPA_ABS(diff) < state->threshold * 3) { + *delay += SPA_CLAMP(diff, -((int64_t)state->threshold), (int64_t)state->threshold); + state->htimestamp_error = 0; + } else { + if (++state->htimestamp_error > MAX_HTIMESTAMP_ERROR) { + spa_log_error(state->log, "%s: wrong htimestamps from driver, disabling", + state->props.device); + state->htimestamp_error = 0; + state->htimestamp = false; + } + else if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { + spa_log_warn(state->log, "%s: (%d missed) impossible htimestamp diff:%"PRIi64, + state->props.device, missed, diff); + } + } + } } - return SPA_MIN(avail, state->buffer_frames); + return avail; } -#endif static int get_status(struct state *state, uint64_t current_time, snd_pcm_uframes_t *avail, snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target) @@ -2238,7 +2253,7 @@ else lev = SPA_LOG_LEVEL_INFO; - if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) { + if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { spa_log_lev(state->log, lev, "%s: follower avail:%lu delay:%ld " "target:%ld thr:%u, resync (%d missed)", state->props.device, avail, delay, @@ -2263,6 +2278,7 @@ if (SPA_UNLIKELY((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0)) { spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s", state->props.device, snd_strerror(res)); + alsa_recover(state, res); return res; } spa_log_trace_fp(state->log, "%p: begin offset:%ld avail:%ld threshold:%d", @@ -2474,7 +2490,7 @@ else lev = SPA_LOG_LEVEL_INFO; - if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) { + if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { spa_log_lev(state->log, lev, "%s: follower delay:%ld target:%ld thr:%u, " "resync (%d missed)", state->props.device, delay, target, state->threshold, missed); @@ -2500,6 +2516,7 @@ if ((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &to_read)) < 0) { spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s", state->props.device, snd_strerror(res)); + alsa_recover(state, res); return res; } spa_log_trace_fp(state->log, "%p: begin offs:%ld frames:%ld to_read:%ld thres:%d", state, @@ -2726,7 +2743,7 @@ if (!state->disable_tsched && (state->next_time > current_time + SPA_NSEC_PER_SEC || current_time > state->next_time + SPA_NSEC_PER_SEC)) { - if ((missed = ratelimit_test(&state->rate_limit, current_time)) >= 0) { + if ((missed = spa_ratelimit_test(&state->rate_limit, current_time)) >= 0) { spa_log_error(state->log, "%s: impossible timeout %lu %lu %lu %" PRIu64" %"PRIu64" %"PRIi64" %d %"PRIi64" (%d missed)", state->props.device, avail, delay, target,
View file
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -21,6 +21,7 @@ #include <spa/utils/list.h> #include <spa/utils/json.h> #include <spa/utils/dll.h> +#include <spa/utils/ratelimit.h> #include <spa/node/node.h> #include <spa/node/utils.h> @@ -40,6 +41,8 @@ #define DEFAULT_CHANNELS 2u #define DEFAULT_USE_CHMAP false +#define MAX_HTIMESTAMP_ERROR 64 + struct props { char device64; char device_name128; @@ -79,13 +82,6 @@ uint32_t rate; }; -struct ratelimit { - uint64_t interval; - uint64_t begin; - unsigned burst; - unsigned n_printed, n_missed; -}; - struct state { struct spa_handle handle; struct spa_node node; @@ -95,7 +91,7 @@ struct spa_loop *data_loop; FILE *log_file; - struct ratelimit rate_limit; + struct spa_ratelimit rate_limit; uint32_t card_index; struct card *card; @@ -185,6 +181,7 @@ uint32_t start_delay; uint32_t min_delay; uint32_t max_delay; + uint32_t htimestamp_error; uint32_t duration; unsigned int alsa_started:1; @@ -201,6 +198,7 @@ unsigned int is_iec958:1; unsigned int is_hdmi:1; unsigned int multi_rate:1; + unsigned int htimestamp:1; uint64_t iec958_codecs; @@ -344,22 +342,6 @@ return i; } -static inline int ratelimit_test(struct ratelimit *r, uint64_t now) -{ - unsigned missed = 0; - if (r->begin + r->interval < now) { - missed = r->n_missed; - r->begin = now; - r->n_printed = 0; - r->n_missed = 0; - } else if (r->n_printed >= r->burst) { - r->n_missed++; - return -1; - } - r->n_printed++; - return missed; -} - /* This function is also as snd_pcm_channel_area_addr() since 1.2.6 which is not yet * in ubuntu and I can't figure out how to do the ALSA version check. */ static inline void *channel_area_addr(const snd_pcm_channel_area_t *area, snd_pcm_uframes_t offset)
View file
pipewire-0.3.72.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-udev.c
Changed
@@ -14,6 +14,7 @@ #include <libudev.h> #include <alsa/asoundlib.h> +#include <spa/utils/cleanup.h> #include <spa/utils/type.h> #include <spa/utils/keys.h> #include <spa/utils/names.h> @@ -228,27 +229,24 @@ static int check_device_pcm_class(const char *devname) { - FILE *f; char pathPATH_MAX; char buf16; size_t sz; /* Check device class */ - spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class", - devname); - f = fopen(path, "re"); + spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class", devname); + + spa_autoptr(FILE) f = fopen(path, "re"); if (f == NULL) return -errno; sz = fread(buf, 1, sizeof(buf) - 1, f); bufsz = '\0'; - fclose(f); return spa_strstartswith(buf, "modem") ? -ENXIO : 0; } static int get_num_pcm_devices(unsigned int card_id) { char prefix32; - DIR *snd = NULL; struct dirent *entry; int num_dev = 0; int res; @@ -257,7 +255,8 @@ spa_scnprintf(prefix, sizeof(prefix), "pcmC%uD", card_id); - if ((snd = opendir("/dev/snd")) == NULL) + spa_autoptr(DIR) snd = opendir("/dev/snd"); + if (snd == NULL) return -errno; while ((errno = 0, entry = readdir(snd)) != NULL) { @@ -271,20 +270,13 @@ ++num_dev; } } - if (errno != 0) - res = -errno; - else - res = num_dev; - closedir(snd); - return res; + return errno != 0 ? -errno : num_dev; } static int check_device_available(struct impl *this, struct device *device, int *num_pcm) { char pathPATH_MAX; - DIR *card = NULL, *pcm = NULL; - FILE *f; char buf16; size_t sz; struct dirent *entry, *entry_pcm; @@ -314,7 +306,8 @@ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id); - if ((card = opendir(path)) == NULL) + spa_autoptr(DIR) card = opendir(path); + if (card == NULL) goto done; while ((errno = 0, entry = readdir(card)) != NULL) { @@ -330,7 +323,9 @@ /* Check busy status */ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s", (unsigned int)device->id, entry->d_name); - if ((pcm = opendir(path)) == NULL) + + spa_autoptr(DIR) pcm = opendir(path); + if (pcm == NULL) goto done; while ((errno = 0, entry_pcm = readdir(pcm)) != NULL) { @@ -341,12 +336,11 @@ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s/%s/status", (unsigned int)device->id, entry->d_name, entry_pcm->d_name); - f = fopen(path, "re"); + spa_autoptr(FILE) f = fopen(path, "re"); if (f == NULL) goto done; sz = fread(buf, 1, 6, f); bufsz = '\0'; - fclose(f); if (!spa_strstartswith(buf, "closed")) { spa_log_debug(this->log, "card %u pcm device %s busy", @@ -359,9 +353,6 @@ } if (errno != 0) goto done; - - closedir(pcm); - pcm = NULL; } if (errno != 0) goto done; @@ -371,10 +362,7 @@ spa_log_info(this->log, "card %u: failed to find busy status (%s)", (unsigned int)device->id, spa_strerror(-errno)); } - if (card) - closedir(card); - if (pcm) - closedir(pcm); + return res; } @@ -519,7 +507,7 @@ static bool check_access(struct impl *this, struct device *device) { char path128, prefix32; - DIR *snd = NULL; + spa_autoptr(DIR) snd = NULL; struct dirent *entry; bool accessible = false; @@ -544,7 +532,6 @@ break; } } - closedir(snd); } if (accessible != device->accessible)
View file
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -1893,11 +1893,13 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control)); } else { + struct spa_pod_frame f1; uint32_t rate = this->io_position ? this->io_position->clock.target_rate.denom : DEFAULT_RATE; - *param = spa_pod_builder_add_object(builder, - SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat, + spa_pod_builder_push_object(builder, &f0, + SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); + spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_CHOICE_ENUM_Id(25, @@ -1926,10 +1928,18 @@ SPA_AUDIO_FORMAT_U8, SPA_AUDIO_FORMAT_ULAW, SPA_AUDIO_FORMAT_ALAW), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( - rate, 1, INT32_MAX), + 0); + if (!this->props.resample_disabled) { + spa_pod_builder_add(builder, + SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( + rate, 1, INT32_MAX), + 0); + } + spa_pod_builder_add(builder, SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( - DEFAULT_CHANNELS, 1, SPA_AUDIO_MAX_CHANNELS)); + DEFAULT_CHANNELS, 1, SPA_AUDIO_MAX_CHANNELS), + 0); + *param = spa_pod_builder_pop(builder, &f0); } break; default: @@ -2205,7 +2215,7 @@ return res; } if (info.info.raw.format == 0 || - info.info.raw.rate == 0 || + (!this->props.resample_disabled && info.info.raw.rate == 0) || info.info.raw.channels == 0 || info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) { spa_log_error(this->log, "invalid format:%d rate:%d channels:%d", @@ -2288,8 +2298,9 @@ struct buffer *b; if (spa_list_is_empty(&port->queue)) { - spa_log_trace_fp(this->log, "%p: out of buffers on port %d %d", - this, port->id, port->n_buffers); + if (port->n_buffers > 0) + spa_log_warn(this->log, "%p: out of buffers on port %d %d", + this, port->id, port->n_buffers); return NULL; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/crossover.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/crossover.c
Changed
@@ -22,17 +22,16 @@ void lr4_process(struct lr4 *lr4, float *dst, const float *src, const float vol, int samples) { - float lx1 = lr4->x1; - float lx2 = lr4->x2; - float ly1 = lr4->y1; - float ly2 = lr4->y2; - float lz1 = lr4->z1; - float lz2 = lr4->z2; - float lb0 = lr4->bq.b0; - float lb1 = lr4->bq.b1; - float lb2 = lr4->bq.b2; - float la1 = lr4->bq.a1; - float la2 = lr4->bq.a2; + float x1 = lr4->x1; + float x2 = lr4->x2; + float y1 = lr4->y1; + float y2 = lr4->y2; + float b0 = lr4->bq.b0; + float b1 = lr4->bq.b1; + float b2 = lr4->bq.b2; + float a1 = lr4->bq.a1; + float a2 = lr4->bq.a2; + float x, y, z; int i; if (vol == 0.0f) { @@ -47,24 +46,19 @@ } for (i = 0; i < samples; i++) { - float x, y, z; - x = srci; - y = lb0*x + lb1*lx1 + lb2*lx2 - la1*ly1 - la2*ly2; - z = lb0*y + lb1*ly1 + lb2*ly2 - la1*lz1 - la2*lz2; - lx2 = lx1; - lx1 = x; - ly2 = ly1; - ly1 = y; - lz2 = lz1; - lz1 = z; + x = srci; + y = b0 * x + x1; + x1 = b1 * x - a1 * y + x2; + x2 = b2 * x - a2 * y; + z = b0 * y + y1; + y1 = b1 * y - a1 * z + y2; + y2 = b2 * y - a2 * z; dsti = z * vol; } #define F(x) (-FLT_MIN < (x) && (x) < FLT_MIN ? 0.0f : (x)) - lr4->x1 = F(lx1); - lr4->x2 = F(lx2); - lr4->y1 = F(ly1); - lr4->y2 = F(ly2); - lr4->z1 = F(lz1); - lr4->z2 = F(lz2); + lr4->x1 = F(x1); + lr4->x2 = F(x2); + lr4->y1 = F(y1); + lr4->y2 = F(y2); #undef F }
View file
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/fmt-ops-avx2.c
Changed
@@ -132,7 +132,7 @@ } } -void +static void 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) { @@ -308,8 +308,7 @@ conv_s24_to_f32d_1s_avx2(conv, &dsti, &s3*i, n_channels, n_samples); } - -void +static void conv_s32_to_f32d_4s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { @@ -375,7 +374,7 @@ } } -void +static void conv_s32_to_f32d_2s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) { @@ -423,7 +422,7 @@ } } -void +static void conv_s32_to_f32d_1s_avx2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) {
View file
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/fmt-ops-sse2.c
Changed
@@ -315,8 +315,7 @@ conv_s24_to_f32d_1s_sse2(conv, &dsti, &s3*i, n_channels, n_samples); } - -void +static void conv_s32_to_f32d_1s_sse2(void *data, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src, uint32_t n_channels, uint32_t n_samples) {
View file
pipewire-0.3.72.tar.gz/spa/plugins/audioconvert/resample-peaks.c -> pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/resample-peaks.c
Changed
@@ -39,13 +39,14 @@ end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate; end = end > i_count ? end - i_count : 0; - chunk = SPA_MIN(end, *in_len); + chunk = SPA_MIN(end, *in_len - i); - m = peaks_abs_max(&pd->peaks, &si, chunk - i, m); + m = peaks_abs_max(&pd->peaks, &si, chunk, m); i += chunk; + i_count += chunk; - if (i == end) { + if (chunk == end) { do++ = m; m = 0.0f; o_count++; @@ -56,9 +57,9 @@ *out_len = o; *in_len = i; pd->o_count = o_count; - pd->i_count = i_count + i; + pd->i_count = i_count; - while (pd->i_count >= r->i_rate) { + while (pd->i_count >= r->i_rate && pd->o_count >= r->o_rate) { pd->i_count -= r->i_rate; pd->o_count -= r->o_rate; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.74.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -786,8 +786,9 @@ outb = dequeue_buffer(this, outport); if (SPA_UNLIKELY(outb == NULL)) { - spa_log_trace(this->log, "%p: out of buffers (%d)", this, - outport->n_buffers); + if (outport->n_buffers > 0) + spa_log_warn(this->log, "%p: out of buffers (%d)", this, + outport->n_buffers); return -EPIPE; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.74.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
@@ -722,7 +722,9 @@ outb = dequeue_buffer(this, outport); if (SPA_UNLIKELY(outb == NULL)) { - spa_log_trace(this->log, "%p: out of buffers", this); + if (outport->n_buffers > 0) + spa_log_warn(this->log, "%p: out of buffers (%d)", this, + outport->n_buffers); return -EPIPE; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -216,8 +216,10 @@ return NULL; t = spa_bt_transport_create(backend->monitor, pathfd, sizeof(struct transport_data)); - if (t == NULL) - goto finish; + if (t == NULL) { + free(pathfd); + return NULL; + } spa_bt_transport_set_implementation(t, &sco_transport_impl, t); t->device = rfcomm->device; @@ -248,7 +250,6 @@ spa_bt_transport_add_listener(t, &rfcomm->transport_listener, &transport_events, rfcomm); -finish: return t; } @@ -2707,7 +2708,7 @@ } } -void set_battery_level(unsigned int level, void *user_data) +static void set_battery_level(unsigned int level, void *user_data) { struct impl *backend = user_data;
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/backend-ofono.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-ofono.c
Changed
@@ -307,7 +307,7 @@ .release = ofono_audio_release, }; -bool activate_transport(struct spa_bt_transport *t, const void *data) +static bool activate_transport(struct spa_bt_transport *t, const void *data) { struct impl *backend = (void *)data; struct transport_data *td = t->user_data;
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -208,15 +208,15 @@ static int device_start_timer(struct spa_bt_device *device); static int device_stop_timer(struct spa_bt_device *device); +static void media_codec_switch_free(struct spa_bt_media_codec_switch *sw); + // Working with BlueZ Battery Provider. // Developed using https://github.com/dgreid/adhd/commit/655b58f as an example of DBus calls. // Name of battery, formatted as /org/freedesktop/pipewire/battery/org/bluez/hciX/dev_XX_XX_XX_XX_XX_XX static char *battery_get_name(const char *device_path) { - char *path = malloc(strlen(PIPEWIRE_BATTERY_PROVIDER) + strlen(device_path) + 1); - sprintf(path, PIPEWIRE_BATTERY_PROVIDER "%s", device_path); - return path; + return spa_aprintf(PIPEWIRE_BATTERY_PROVIDER "%s", device_path); } // Unregister virtual battery of device @@ -1287,10 +1287,6 @@ return d; } -static int device_stop_timer(struct spa_bt_device *device); - -static void media_codec_switch_free(struct spa_bt_media_codec_switch *sw); - static void device_clear_sub(struct spa_bt_device *device) { battery_remove(device); @@ -3269,7 +3265,6 @@ struct spa_bt_monitor *monitor = transport->monitor; DBusMessage *m; DBusMessageIter it2; - DBusError err; const char *interface = BLUEZ_MEDIA_TRANSPORT_INTERFACE; const char *name = "Volume"; int res = 0; @@ -3298,8 +3293,6 @@ dbus_message_iter_append_basic(&it1, DBUS_TYPE_UINT16, &value); dbus_message_iter_close_container(&it0, &it1); - dbus_error_init(&err); - ret = dbus_connection_send_with_reply(monitor->conn, m, &transport->volume_call, -1); dbus_message_unref(m); @@ -3513,7 +3506,6 @@ { struct spa_bt_monitor *monitor = transport->monitor; DBusMessage *m; - DBusError err; dbus_bool_t ret; struct spa_bt_transport *t_linked; @@ -3539,8 +3531,6 @@ if (m == NULL) return -ENOMEM; - dbus_error_init(&err); - ret = dbus_connection_send_with_reply(monitor->conn, m, &transport->acquire_call, -1); dbus_message_unref(m);
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/iso-io.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/iso-io.c
Changed
@@ -308,7 +308,7 @@ free(group); } -struct stream *stream_create(struct spa_bt_transport *t, struct group *group) +static struct stream *stream_create(struct spa_bt_transport *t, struct group *group) { struct stream *stream; void *codec_data = NULL;
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/media-source.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/media-source.c
Changed
@@ -1342,6 +1342,9 @@ spa_bt_decode_buffer_set_target_latency(&port->buffer, samples); } +#define WARN_ONCE(cond, ...) \ + if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } } + static void process_buffering(struct impl *this) { struct port *port = &this->port; @@ -1364,13 +1367,21 @@ struct spa_data *datas; uint32_t data_size; + buffer = spa_list_first(&port->free, struct buffer, link); + datas = buffer->buf->datas; + data_size = samples * port->frame_size; + WARN_ONCE(datas0.maxsize < data_size && !this->following, + this->log, "source buffer too small (%u < %u)", + datas0.maxsize, data_size); + + data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas0.maxsize, port->frame_size)); + avail = SPA_MIN(avail, data_size); spa_bt_decode_buffer_read(&port->buffer, avail); - buffer = spa_list_first(&port->free, struct buffer, link); spa_list_remove(&buffer->link); spa_log_trace(this->log, "dequeue %d", buffer->id); @@ -1381,10 +1392,6 @@ buffer->h->dts_offset = 0; } - datas = buffer->buf->datas; - - spa_assert(datas0.maxsize >= data_size); - datas0.chunk->offset = 0; datas0.chunk->size = data_size; datas0.chunk->stride = port->frame_size;
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/meson.build
Changed
@@ -118,16 +118,14 @@ if ldac_dep.found() ldac_args = codec_args - ldac_dep = ldac_dep if ldac_abr_dep.found() ldac_args += '-DENABLE_LDAC_ABR' - ldac_dep += ldac_abr_dep endif bluez_codec_ldac = shared_library('spa-codec-bluez5-ldac', 'a2dp-codec-ldac.c', 'media-codecs.c' , include_directories : configinc , c_args : ldac_args, - dependencies : spa_dep, ldac_dep , + dependencies : spa_dep, ldac_dep, ldac_abr_dep , install : true, install_dir : spa_plugindir / 'bluez5') endif @@ -144,7 +142,6 @@ if get_option('bluez5-codec-opus').allowed() and opus_dep.found() opus_args = codec_args - opus_dep = opus_dep bluez_codec_opus = shared_library('spa-codec-bluez5-opus', 'a2dp-codec-opus.c', 'media-codecs.c' , include_directories : configinc ,
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/midi-enum.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/midi-enum.c
Changed
@@ -202,7 +202,7 @@ return 0; } -Bluez5GattDescriptor1 *find_dsc(struct impl *impl, MidiEnumCharacteristicProxy *chr) +static Bluez5GattDescriptor1 *find_dsc(struct impl *impl, MidiEnumCharacteristicProxy *chr) { const char *path = g_dbus_proxy_get_object_path(G_DBUS_PROXY(chr)); Bluez5GattDescriptor1 *found = NULL;;
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/modemmanager.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/modemmanager.c
Changed
@@ -771,7 +771,7 @@ return this->modem.path != NULL; } -unsigned int mm_supported_features() +unsigned int mm_supported_features(void) { return SPA_BT_HFP_AG_FEATURE_REJECT_CALL | SPA_BT_HFP_AG_FEATURE_ENHANCED_CALL_STATUS; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/modemmanager.h -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/modemmanager.h
Changed
@@ -71,7 +71,7 @@ const struct mm_ops *ops, void *user_data); void mm_unregister(void *data); bool mm_is_available(void *modemmanager); -unsigned int mm_supported_features(); +unsigned int mm_supported_features(void); bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error); bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error); bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error); @@ -79,60 +79,60 @@ const char *mm_get_incoming_call_number(void *modemmanager); struct spa_list *mm_get_calls(void *modemmanager); #else -void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info, +static inline void *mm_register(struct spa_log *log, void *dbus_connection, const struct spa_dict *info, const struct mm_ops *ops, void *user_data) { return NULL; } -void mm_unregister(void *data) +static inline void mm_unregister(void *data) { } -bool mm_is_available(void *modemmanager) +static inline bool mm_is_available(void *modemmanager) { return false; } -unsigned int mm_supported_features(void) +static inline unsigned int mm_supported_features(void) { return 0; } -bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error) +static inline bool mm_answer_call(void *modemmanager, void *user_data, enum cmee_error *error) { if (error) *error = CMEE_OPERATION_NOT_SUPPORTED; return false; } -bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error) +static inline bool mm_hangup_call(void *modemmanager, void *user_data, enum cmee_error *error) { if (error) *error = CMEE_OPERATION_NOT_SUPPORTED; return false; } -bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error) +static inline bool mm_do_call(void *modemmanager, const char* number, void *user_data, enum cmee_error *error) { if (error) *error = CMEE_OPERATION_NOT_SUPPORTED; return false; } -bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error) +static inline bool mm_send_dtmf(void *modemmanager, const char *dtmf, void *user_data, enum cmee_error *error) { if (error) *error = CMEE_OPERATION_NOT_SUPPORTED; return false; } -const char *mm_get_incoming_call_number(void *modemmanager) +static inline const char *mm_get_incoming_call_number(void *modemmanager) { return NULL; } -struct spa_list *mm_get_calls(void *modemmanager) +static inline struct spa_list *mm_get_calls(void *modemmanager) { return NULL; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.74.tar.gz/spa/plugins/bluez5/sco-source.c
Changed
@@ -1298,6 +1298,9 @@ return samples; } +#define WARN_ONCE(cond, ...) \ + if (SPA_UNLIKELY(cond)) { static bool __once; if (!__once) { __once = true; spa_log_warn(__VA_ARGS__); } } + static void process_buffering(struct impl *this) { struct port *port = &this->port; @@ -1318,21 +1321,25 @@ struct spa_data *datas; uint32_t data_size; + buffer = spa_list_first(&port->free, struct buffer, link); + datas = buffer->buf->datas; + data_size = samples * port->frame_size; + WARN_ONCE(datas0.maxsize < data_size && !this->following, + this->log, "source buffer too small (%u < %u)", + datas0.maxsize, data_size); + + data_size = SPA_MIN(data_size, SPA_ROUND_DOWN(datas0.maxsize, port->frame_size)); + avail = SPA_MIN(avail, data_size); spa_bt_decode_buffer_read(&port->buffer, avail); - buffer = spa_list_first(&port->free, struct buffer, link); spa_list_remove(&buffer->link); spa_log_trace(this->log, "dequeue %d", buffer->id); - datas = buffer->buf->datas; - - spa_assert(datas0.maxsize >= data_size); - datas0.chunk->offset = 0; datas0.chunk->size = data_size; datas0.chunk->stride = port->frame_size;
View file
pipewire-0.3.72.tar.gz/spa/plugins/control/mixer.c -> pipewire-0.3.74.tar.gz/spa/plugins/control/mixer.c
Changed
@@ -623,7 +623,9 @@ /* get output buffer */ if ((outb = dequeue_buffer(this, outport)) == NULL) { - spa_log_trace(this->log, NAME " %p: out of buffers", this); + if (outport->n_buffers > 0) + spa_log_warn(this->log, NAME " %p: out of buffers (%d)", + this, outport->n_buffers); return -EPIPE; }
View file
pipewire-0.3.72.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.74.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp
Changed
@@ -53,9 +53,7 @@ if (impl->config) return; - StreamRoles roles; - roles.push_back(StreamRole::VideoRecording); - impl->config = impl->camera->generateConfiguration(roles); + impl->config = impl->camera->generateConfiguration({ StreamRole::VideoRecording }); } static int spa_libcamera_buffer_recycle(struct impl *impl, struct port *port, uint32_t buffer_id)
View file
pipewire-0.3.72.tar.gz/spa/plugins/support/cpu.c -> pipewire-0.3.74.tar.gz/spa/plugins/support/cpu.c
Changed
@@ -39,7 +39,7 @@ uint32_t vm_type; }; -char *spa_cpu_read_file(const char *name, char *buffer, size_t len) +static char *spa_cpu_read_file(const char *name, char *buffer, size_t len) { int n, fd;
View file
pipewire-0.3.72.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-0.3.74.tar.gz/spa/plugins/v4l2/v4l2-utils.c
Changed
@@ -627,7 +627,7 @@ } do_frmsize: if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMESIZES, &port->frmsize)) < 0) { - if (errno == EINVAL) + if (errno == EINVAL || errno == ENOTTY) goto next_fmtdesc; res = -errno; @@ -745,7 +745,7 @@ while (true) { if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMEINTERVALS, &port->frmival)) < 0) { res = -errno; - if (errno == EINVAL) { + if (errno == EINVAL || errno == ENOTTY) { port->frmsize.index++; port->next_frmsize = true; if (port->frmival.index == 0)
View file
pipewire-0.3.72.tar.gz/src/gst/gstpipewiredeviceprovider.c -> pipewire-0.3.74.tar.gz/src/gst/gstpipewiredeviceprovider.c
Changed
@@ -665,9 +665,11 @@ { GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider); + pw_thread_loop_lock (self->core->loop); GST_DEBUG_OBJECT (self, "stopping provider"); g_clear_pointer ((struct pw_proxy**)&self->registry, pw_proxy_destroy); + pw_thread_loop_unlock (self->core->loop); g_clear_pointer (&self->core, gst_pipewire_core_release); }
View file
pipewire-0.3.72.tar.gz/src/modules/flatpak-utils.h -> pipewire-0.3.74.tar.gz/src/modules/flatpak-utils.h
Changed
@@ -5,6 +5,8 @@ #ifndef FLATPAK_UTILS_H #define FLATPAK_UTILS_H +#include "config.h" + #include <stdio.h> #include <string.h> #include <fcntl.h> @@ -20,6 +22,7 @@ #include <glib.h> #endif +#include <spa/utils/cleanup.h> #include <spa/utils/result.h> #include <pipewire/log.h> @@ -60,8 +63,8 @@ { #if defined(__linux__) char root_path2048; - int root_fd, info_fd, res; struct stat stat_buf; + int res; if (app_id) *app_id = NULL; @@ -69,8 +72,9 @@ *devices = NULL; snprintf(root_path, sizeof(root_path), "/proc/%d/root", (int)pid); - root_fd = openat (AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); - if (root_fd == -1) { + + spa_autoclose int root_fd = openat(AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); + if (root_fd < 0) { res = -errno; if (res == -EACCES) { struct statfs buf; @@ -88,9 +92,9 @@ pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res)); return res; } - info_fd = openat (root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY); - close (root_fd); - if (info_fd == -1) { + + spa_autoclose int info_fd = openat(root_fd, ".flatpak-info", O_RDONLY | O_CLOEXEC | O_NOCTTY); + if (info_fd < 0) { if (errno == ENOENT) { pw_log_debug("no .flatpak-info, client on the host"); /* No file => on the host */ @@ -126,7 +130,7 @@ pw_log_error("PID %d .flatpak-info parsing failed: %s", (int)pid, spa_strerror(res)); } - close(info_fd); + return 1; #else return 0;
View file
pipewire-0.3.72.tar.gz/src/modules/meson.build -> pipewire-0.3.74.tar.gz/src/modules/meson.build
Changed
@@ -11,6 +11,7 @@ 'module-client-node.c', 'module-combine-stream.c', 'module-echo-cancel.c', + 'module-example-filter.c', 'module-example-sink.c', 'module-example-source.c', 'module-fallback-sink.c', @@ -116,21 +117,12 @@ 'module-filter-chain/biquad.c', 'module-filter-chain/ladspa_plugin.c', 'module-filter-chain/builtin_plugin.c', - 'module-filter-chain/sofa_plugin.c', 'module-filter-chain/convolver.c' filter_chain_dependencies = - mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep, libmysofa_dep + mathlib, dl_lib, pipewire_dep, sndfile_dep, audioconvert_dep -if lilv_lib.found() - filter_chain_sources += - 'module-filter-chain/lv2_plugin.c' - - filter_chain_dependencies += lilv_lib -endif - - pipewire_module_filter_chain = shared_library('pipewire-module-filter-chain', filter_chain_sources, include_directories : configinc, @@ -141,9 +133,30 @@ dependencies : filter_chain_dependencies, ) -pipewire_module_echo_cancel_sources = - 'module-echo-cancel.c', - +if libmysofa_dep.found() +pipewire_module_filter_chain_sofa = shared_library('pipewire-module-filter-chain-sofa', + 'module-filter-chain/sofa_plugin.c', + 'module-filter-chain/convolver.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + link_with : simd_dependencies, + dependencies : filter_chain_dependencies, libmysofa_dep +) +endif + +if lilv_lib.found() +pipewire_module_filter_chain_lv2 = shared_library('pipewire-module-filter-chain-lv2', + 'module-filter-chain/lv2_plugin.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : filter_chain_dependencies, lilv_lib +) +endif + pipewire_module_combine_stream = shared_library('pipewire-module-combine-stream', 'module-combine-stream.c' , @@ -155,7 +168,7 @@ ) pipewire_module_echo_cancel = shared_library('pipewire-module-echo-cancel', - pipewire_module_echo_cancel_sources, + 'module-echo-cancel.c' , include_directories : configinc, install : true, install_dir : modules_install_dir, @@ -203,7 +216,8 @@ summary({'ffado-driver': build_module_ffado_driver}, bool_yn: true, section: 'Optional Modules') opus_custom_h = cc.has_header('opus/opus_custom.h', dependencies: opus_dep) -if opus_custom_h +# One would imagine that opus_dep is a requirement but for some reason it's not, so we need to manually check that +if opus_dep.found() and opus_custom_h opus_custom_dep = declare_dependency(compile_args: '-DHAVE_OPUS_CUSTOM', dependencies: opus_dep) else opus_custom_dep = dependency('', required: false) @@ -438,6 +452,15 @@ dependencies : pipewire_module_protocol_deps, ) +pipewire_module_example_filter = shared_library('pipewire-module-example-filter', + 'module-example-filter.c' , + include_directories : configinc, + install : false, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : spa_dep, mathlib, dl_lib, pipewire_dep, +) + pipewire_module_example_sink = shared_library('pipewire-module-example-sink', 'module-example-sink.c' , include_directories : configinc,
View file
pipewire-0.3.72.tar.gz/src/modules/module-avb/acmp.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/acmp.h
Changed
@@ -75,5 +75,6 @@ #define AVB_PACKET_ACMP_GET_STATUS(p) AVB_PACKET_GET_SUB2(&(p)->hdr) struct avb_acmp *avb_acmp_register(struct server *server); +void avb_acmp_unregister(struct avb_acmp *acmp); #endif /* AVB_ACMP_H */
View file
pipewire-0.3.72.tar.gz/src/modules/module-avb/adp.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/adp.h
Changed
@@ -81,5 +81,6 @@ #define AVB_PACKET_ADP_GET_VALID_TIME(p) AVB_PACKET_GET_SUB2(&(p)->hdr) struct avb_adp *avb_adp_register(struct server *server); +void avb_adp_unregister(struct avb_adp *adp); #endif /* AVB_ADP_H */
View file
pipewire-0.3.72.tar.gz/src/modules/module-avb/avb.c -> pipewire-0.3.74.tar.gz/src/modules/module-avb/avb.c
Changed
@@ -2,6 +2,7 @@ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ /* SPDX-License-Identifier: MIT */ +#include "avb.h" #include "internal.h" #include <spa/support/cpu.h>
View file
pipewire-0.3.72.tar.gz/src/modules/module-avb/avb.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/avb.h
Changed
@@ -5,6 +5,8 @@ #ifndef PIPEWIRE_AVB_H #define PIPEWIRE_AVB_H +#include <stddef.h> + #ifdef __cplusplus extern "C" { #endif
View file
pipewire-0.3.72.tar.gz/src/modules/module-avb/descriptors.h -> pipewire-0.3.74.tar.gz/src/modules/module-avb/descriptors.h
Changed
@@ -2,11 +2,12 @@ /* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans */ /* SPDX-License-Identifier: MIT */ +#include "adp.h" #include "aecp-aem.h" #include "aecp-aem-descriptors.h" #include "internal.h" -void init_descriptors(struct server *server) +static inline void init_descriptors(struct server *server) { server_add_descriptor(server, AVB_AEM_DESC_STRINGS, 0, sizeof(struct avb_aem_desc_strings),
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-device/client-device.h -> pipewire-0.3.74.tar.gz/src/modules/module-client-device/client-device.h
Changed
@@ -13,7 +13,7 @@ #define CLIENT_DEVICE_USAGE ""PW_KEY_DEVICE_NAME"=<string>" -struct pw_device * +struct pw_impl_device * pw_client_device_new(struct pw_resource *resource, struct pw_properties *properties);
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-device/resource-device.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-device/resource-device.c
Changed
@@ -17,6 +17,8 @@ #include <pipewire/impl.h> +#include "client-device.h" + struct impl { struct pw_context *context; struct pw_impl_device *device;
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -86,6 +86,7 @@ struct pw_impl_client_node this; struct pw_context *context; + struct pw_mempool *context_pool; struct spa_node node; @@ -98,6 +99,7 @@ struct pw_resource *resource; struct pw_impl_client *client; + struct pw_mempool *client_pool; struct spa_source data_source; @@ -217,14 +219,12 @@ mix->n_buffers = 0; } -static struct mix *ensure_mix(struct impl *impl, struct port *p, uint32_t mix_id) +static struct mix *create_mix(struct impl *impl, struct port *p, uint32_t mix_id) { struct mix *mix; - if ((mix = find_mix(p, mix_id)) == NULL) + if ((mix = find_mix(p, mix_id)) == NULL || mix->valid) return NULL; - if (mix->valid) - return mix; mix_init(mix, p, mix_id); return mix; } @@ -238,7 +238,7 @@ struct pw_memblock *m; id = SPA_PTR_TO_UINT32(d->data); - m = pw_mempool_find_id(impl->client->pool, id); + m = pw_mempool_find_id(impl->client_pool, id); if (m) { pw_log_debug("%p: mem %d", impl, m->id); pw_memblock_unref(m); @@ -356,11 +356,11 @@ if (impl->this.flags & 1) return 0; - old = pw_mempool_find_tag(impl->client->pool, tag, sizeof(tag)); + old = pw_mempool_find_tag(impl->client_pool, tag, sizeof(tag)); if (data) { - mm = pw_mempool_import_map(impl->client->pool, - impl->context->pool, data, size, tag); + mm = pw_mempool_import_map(impl->client_pool, + impl->context_pool, data, size, tag); if (mm == NULL) return -errno; @@ -659,11 +659,11 @@ if ((mix = find_mix(port, mix_id)) == NULL || !mix->valid) return -EINVAL; - old = pw_mempool_find_tag(impl->client->pool, tag, sizeof(tag)); + old = pw_mempool_find_tag(impl->client_pool, tag, sizeof(tag)); if (data) { - mm = pw_mempool_import_map(impl->client->pool, - impl->context->pool, data, size, tag); + mm = pw_mempool_import_map(impl->client_pool, + impl->context_pool, data, size, tag); if (mm == NULL) return -errno; @@ -726,15 +726,12 @@ direction == SPA_DIRECTION_INPUT ? "input" : "output", port_id, mix_id, buffers, n_buffers, flags); + if (direction == SPA_DIRECTION_OUTPUT) + mix_id = SPA_ID_INVALID; + if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid) return -EINVAL; - if (direction == SPA_DIRECTION_OUTPUT) { - mix_id = SPA_ID_INVALID; - if ((mix = find_mix(p, mix_id)) == NULL || !mix->valid) - return -EINVAL; - } - clear_buffers(impl, mix); if (n_buffers > 0) { @@ -766,7 +763,7 @@ else return -EINVAL; - if ((mem = pw_mempool_find_ptr(impl->context->pool, baseptr)) == NULL) + if ((mem = pw_mempool_find_ptr(impl->context_pool, baseptr)) == NULL) return -EINVAL; endptr = SPA_PTROFF(baseptr, buffersi->n_datas * sizeof(struct spa_chunk), void); @@ -776,7 +773,7 @@ for (j = 0; j < buffersi->n_datas; j++) { struct spa_data *d = &buffersi->datasj; if (d->type == SPA_DATA_MemPtr) { - if ((m = pw_mempool_find_ptr(impl->context->pool, d->data)) == NULL || + if ((m = pw_mempool_find_ptr(impl->context_pool, d->data)) == NULL || m != mem) return -EINVAL; endptr = SPA_MAX(endptr, SPA_PTROFF(d->data, d->maxsize, void)); @@ -785,7 +782,7 @@ if (endptr > SPA_PTROFF(baseptr, mem->size, void)) return -EINVAL; - m = pw_mempool_import_block(impl->client->pool, mem); + m = pw_mempool_import_block(impl->client_pool, mem); if (m == NULL) return -errno; @@ -823,7 +820,7 @@ flags |= PW_MEMBLOCK_FLAG_WRITABLE; spa_log_debug(impl->log, "mem %d type:%d fd:%d", j, d->type, (int)d->fd); - m = pw_mempool_import(impl->client->pool, + m = pw_mempool_import(impl->client_pool, flags, d->type, d->fd); if (m == NULL) return -errno; @@ -1206,14 +1203,14 @@ struct impl *impl = data; struct pw_memblock *m; - m = pw_mempool_import_block(impl->client->pool, peer->activation); + m = pw_mempool_import_block(impl->client_pool, peer->activation); if (m == NULL) { pw_log_warn("%p: can't ensure mem: %m", impl); return; } - pw_log_debug("%p: peer %p/%p id:%u added mem_id:%u", impl, peer, - impl->this.node, peer->info.id, m->id); + pw_log_debug("%p: peer %p/%p id:%u added mem_id:%u %p %d", impl, peer, + impl->this.node, peer->info.id, m->id, m, m->ref); if (impl->resource == NULL) return; @@ -1231,7 +1228,7 @@ struct impl *impl = data; struct pw_memblock *m; - m = pw_mempool_find_fd(impl->client->pool, peer->activation->fd); + m = pw_mempool_find_fd(impl->client_pool, peer->activation->fd); if (m == NULL) { pw_log_warn("%p: unknown peer %p fd:%d", impl, peer, peer->source.fd); @@ -1261,7 +1258,7 @@ pw_log_debug("%p: %d", &impl->node, node_id); - impl->activation = pw_mempool_import_block(client->pool, node->activation); + impl->activation = pw_mempool_import_block(impl->client_pool, node->activation); if (impl->activation == NULL) { pw_log_debug("%p: can't import block: %m", &impl->node); return; @@ -1295,7 +1292,7 @@ size = sizeof(struct spa_io_buffers) * AREA_SIZE; - area = pw_mempool_alloc(impl->context->pool, + area = pw_mempool_alloc(impl->context_pool, PW_MEMBLOCK_FLAG_READWRITE | PW_MEMBLOCK_FLAG_MAP | PW_MEMBLOCK_FLAG_SEAL, @@ -1348,12 +1345,9 @@ spa_hook_remove(&impl->node_listener); - while ((mm = pw_mempool_find_tag(impl->client->pool, tag, sizeof(uint32_t))) != NULL) + while ((mm = pw_mempool_find_tag(impl->client_pool, tag, sizeof(uint32_t))) != NULL) pw_memmap_free(mm); - if (impl->resource) - pw_resource_destroy(impl->resource); - if (impl->activation) pw_memblock_free(impl->activation); @@ -1363,6 +1357,9 @@ } pw_array_clear(&impl->io_areas); + if (impl->resource) + pw_resource_destroy(impl->resource); + pw_map_clear(&impl->ports0); pw_map_clear(&impl->ports1); pw_map_clear(&impl->io_map); @@ -1380,7 +1377,7 @@ uint32_t idx, pos, len; struct pw_memblock *area; - if ((m = ensure_mix(impl, port, mix->port.port_id)) == NULL) + if ((m = create_mix(impl, port, mix->port.port_id)) == NULL) return -ENOMEM; mix->id = pw_map_insert_new(&impl->io_map, NULL); @@ -1573,7 +1570,7 @@ SPA_TYPE_INTERFACE_Node, SPA_VERSION_NODE, &impl_port_mix, p); - ensure_mix(impl, p, SPA_ID_INVALID); + create_mix(impl, p, SPA_ID_INVALID); pw_map_insert_at(&impl->portsp->direction, p->id, p); return; @@ -1675,6 +1672,7 @@ this = &impl->this; impl->context = context; + impl->context_pool = pw_context_get_mempool(context); impl->data_source.fd = -1; pw_log_debug("%p: new", &impl->node); @@ -1682,6 +1680,7 @@ impl_init(impl, NULL, support, n_support); impl->resource = resource; impl->client = client; + impl->client_pool = pw_impl_client_get_mempool(client); this->flags = do_register ? 0 : 1; pw_map_init(&impl->ports0, 64, 64); @@ -1700,6 +1699,11 @@ if (this->node == NULL) goto error_no_node; + if (this->node->data_loop == NULL) { + errno = EIO; + goto error_no_node; + } + impl->data_loop = this->node->data_loop->loop; impl->data_system = this->node->data_loop->system;
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -39,8 +39,6 @@ struct mix { struct spa_list link; struct pw_impl_port *port; - uint32_t mix_id; - uint32_t peer_id; struct pw_impl_port_mix mix; struct pw_array buffers; }; @@ -151,9 +149,10 @@ { pw_log_debug("port %p: mix init %d.%d", port, port->port_id, mix_id); mix->port = port; - mix->mix_id = mix_id; - mix->peer_id = peer_id; - pw_impl_port_init_mix(port, &mix->mix); + mix->mix.id = mix_id; + mix->mix.peer_id = peer_id; + if (mix_id != SPA_ID_INVALID) + pw_impl_port_init_mix(port, &mix->mix); pw_array_init(&mix->buffers, 32); pw_array_ensure_size(&mix->buffers, sizeof(struct buffer) * 64); } @@ -165,7 +164,7 @@ spa_list_for_each(mix, &data->mixdirection, link) { if (mix->port->port_id == port_id && - mix->mix_id == mix_id) { + mix->mix.id == mix_id) { pw_log_debug("port %p: found mix %d:%d.%d", mix->port, direction, port_id, mix_id); return mix; @@ -174,16 +173,10 @@ return NULL; } -static struct mix *create_mix(struct node_data *data, - enum spa_direction direction, uint32_t port_id, +static struct mix *create_mix(struct node_data *data, struct pw_impl_port *port, uint32_t mix_id, uint32_t peer_id) { struct mix *mix; - struct pw_impl_port *port; - - port = pw_impl_node_find_port(data->node, direction, port_id); - if (port == NULL) - return NULL; if (spa_list_is_empty(&data->free_mix)) { if ((mix = calloc(1, sizeof(*mix))) == NULL) @@ -193,21 +186,11 @@ spa_list_remove(&mix->link); } mix_init(mix, port, mix_id, peer_id); - spa_list_append(&data->mixdirection, &mix->link); + spa_list_append(&data->mixport->direction, &mix->link); return mix; } -static struct mix *ensure_mix(struct node_data *data, - enum spa_direction direction, uint32_t port_id, - uint32_t mix_id) -{ - struct mix *mix; - if ((mix = find_mix(data, direction, port_id, mix_id))) - return mix; - return create_mix(data, direction, port_id, mix_id, SPA_ID_INVALID); -} - static int client_node_transport(void *_data, int readfd, int writefd, uint32_t mem_id, uint32_t offset, uint32_t size) { @@ -542,7 +525,7 @@ pw_log_debug("port %p: clear %zd buffers mix:%d", port, pw_array_get_len(&mix->buffers, struct buffer *), - mix->mix_id); + mix->mix.id); if ((res = pw_impl_port_use_buffers(port, &mix->mix, 0, NULL, 0)) < 0) { pw_log_error("port %p: error clear buffers %s", port, spa_strerror(res)); @@ -614,7 +597,7 @@ struct mix *mix; int res, prot; - mix = ensure_mix(data, direction, port_id, mix_id); + mix = find_mix(data, direction, port_id, mix_id); if (mix == NULL) { res = -ENOENT; goto error_exit; @@ -744,8 +727,10 @@ error_exit_cleanup: clear_buffers(data, mix); error_exit: - pw_log_error("port %p: use_buffers: %d %s", mix, res, spa_strerror(res)); - pw_proxy_errorf(proxy, res, "port_use_buffers error: %s", spa_strerror(res)); + pw_log_error("port %p: use_buffers(%u:%u:%d): %d %s", mix, + direction, port_id, mix_id, res, spa_strerror(res)); + pw_proxy_errorf(proxy, res, "port_use_buffers(%u:%u:%d) error: %s", + direction, port_id, mix_id, spa_strerror(res)); return res; } @@ -767,7 +752,7 @@ int res = 0; uint32_t tag5 = { data->remote_id, direction, port_id, mix_id, id }; - mix = ensure_mix(data, direction, port_id, mix_id); + mix = find_mix(data, direction, port_id, mix_id); if (mix == NULL) { res = -ENOENT; goto exit; @@ -874,18 +859,22 @@ pw_loop_invoke(data->data_loop, do_activate_link, SPA_ID_INVALID, NULL, 0, false, link); - pw_log_debug("node %p: link %p: fd:%d id:%u state %p required %d, pending %d", - node, link, signalfd, - link->target.activation->position.clock.id, + pw_log_debug("node %p: add link %p: memid:%u fd:%d id:%u state:%p pending:%d/%d", + node, link, memid, signalfd, node_id, &link->target.activation->state0, - link->target.activation->state0.required, - link->target.activation->state0.pending); + link->target.activation->state0.pending, + link->target.activation->state0.required); } else { link = find_activation(&data->links, node_id); if (link == NULL) { res = -ENOENT; goto error_exit; } + pw_log_debug("node %p: remove link %p: id:%u state:%p pending:%d/%d", + node, link, node_id, + &link->target.activation->state0, + link->target.activation->state0.pending, + link->target.activation->state0.required); clear_link(data, link); } return res; @@ -898,7 +887,7 @@ static void clear_mix(struct node_data *data, struct mix *mix) { - pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix_id); + pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix.id); spa_node_port_set_io(mix->port->mix, mix->mix.port.direction, mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0); @@ -909,7 +898,8 @@ pw_array_clear(&mix->buffers); spa_list_append(&data->free_mix, &mix->link); - pw_impl_port_release_mix(mix->port, &mix->mix); + if (mix->mix.id != SPA_ID_INVALID) + pw_impl_port_release_mix(mix->port, &mix->mix); } static int client_node_port_set_mix_info(void *_data, @@ -928,9 +918,13 @@ return -EINVAL; clear_mix(data, mix); } else { + struct pw_impl_port *port; if (mix != NULL) return -EEXIST; - mix = create_mix(data, direction, port_id, mix_id, peer_id); + port = pw_impl_node_find_port(data->node, direction, port_id); + if (port == NULL) + return -ENOENT; + mix = create_mix(data, port, mix_id, peer_id); if (mix == NULL) return -errno; } @@ -956,6 +950,7 @@ static void do_node_init(struct node_data *data) { struct pw_impl_port *port; + struct mix *mix; pw_log_debug("%p: node %p init", data, data->node); add_node_update(data, PW_CLIENT_NODE_UPDATE_PARAMS | @@ -965,11 +960,17 @@ SPA_NODE_CHANGE_MASK_PARAMS); spa_list_for_each(port, &data->node->input_ports, link) { + mix = create_mix(data, port, SPA_ID_INVALID, SPA_ID_INVALID); + if (mix == NULL) + pw_log_error("%p: failed to create port mix: %m", data->node); add_port_update(data, port, PW_CLIENT_NODE_PORT_UPDATE_PARAMS | PW_CLIENT_NODE_PORT_UPDATE_INFO); } spa_list_for_each(port, &data->node->output_ports, link) { + mix = create_mix(data, port, SPA_ID_INVALID, SPA_ID_INVALID); + if (mix == NULL) + pw_log_error("%p: failed to create port mix: %m", data->node); add_port_update(data, port, PW_CLIENT_NODE_PORT_UPDATE_PARAMS | PW_CLIENT_NODE_PORT_UPDATE_INFO); @@ -1051,6 +1052,21 @@ add_port_update(d, port, change_mask); } +static void node_port_added(void *data, struct pw_impl_port *port) +{ + struct node_data *d = data; + struct mix *mix; + + pw_log_debug("added %p", d); + + if (d->client_node == NULL) + return; + + mix = create_mix(d, port, SPA_ID_INVALID, SPA_ID_INVALID); + if (mix == NULL) + pw_log_error("%p: failed to create port mix: %m", d->node); +} + static void node_port_removed(void *data, struct pw_impl_port *port) { struct node_data *d = data; @@ -1099,6 +1115,7 @@ .free = node_free, .info_changed = node_info_changed, .port_info_changed = node_port_info_changed, + .port_added = node_port_added, .port_removed = node_port_removed, .active_changed = node_active_changed, .event = node_event, @@ -1176,6 +1193,9 @@ struct pw_proxy *client_node; struct node_data *data; + if (node->data_loop == NULL) + goto error; + user_data_size = SPA_ROUND_UP_N(user_data_size, __alignof__(struct node_data)); client_node = pw_core_create_object(core,
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/client-node.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/client-node.c
Changed
@@ -15,13 +15,14 @@ #include <spa/node/node.h> #include <spa/node/utils.h> #include <spa/node/io.h> +#include <spa/node/type-info.h> #include <spa/pod/filter.h> #include <spa/utils/keys.h> +#include <spa/utils/result.h> #define PW_ENABLE_DEPRECATED #include "pipewire/pipewire.h" -#include "pipewire/private.h" #include "pipewire/context.h" #include "modules/spa/spa-node.h" @@ -130,6 +131,7 @@ bool client_reuse; struct pw_context *context; + struct pw_mempool *context_pool; struct node node; @@ -335,7 +337,7 @@ static int send_clock_update(struct node *this) { - struct pw_impl_client *client = this->resource->client; + struct pw_impl_client *client = pw_resource_get_client(this->resource); uint32_t type = pw_protocol_native0_name_to_v2(client, SPA_TYPE_INFO_NODE_COMMAND_BASE "ClockUpdate"); struct timespec ts; int64_t now; @@ -468,7 +470,7 @@ } for (i = 0; i < port->n_params; i++) { port->paramsi = paramsi ? - pw_protocol_native0_pod_from_v2(this->resource->client, paramsi) : NULL; + pw_protocol_native0_pod_from_v2(pw_resource_get_client(this->resource), paramsi) : NULL; if (port->paramsi && spa_pod_is_object_id(port->paramsi, SPA_PARAM_Format)) port->have_format = true; @@ -661,7 +663,7 @@ if (data) { - if ((mem = pw_mempool_find_ptr(impl->context->pool, data)) == NULL) + if ((mem = pw_mempool_find_ptr(impl->context_pool, data)) == NULL) return -EINVAL; mem_offset = SPA_PTRDIFF(data, mem->map->ptr); @@ -744,7 +746,7 @@ else return -EINVAL; - if ((mem = pw_mempool_find_ptr(impl->context->pool, baseptr)) == NULL) + if ((mem = pw_mempool_find_ptr(impl->context_pool, baseptr)) == NULL) return -EINVAL; data_size = 0; @@ -910,8 +912,7 @@ struct node *this = object; struct impl *impl = this->impl; struct pw_impl_node *n = impl->this.node; - - return impl_node_process_input(n->node); + return impl_node_process_input(pw_impl_node_get_implementation(n)); } static int handle_node_message(struct node *this, struct pw_client_node0_message *message) @@ -1363,9 +1364,10 @@ } convert_properties(properties); - pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", client->global->id); + pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", pw_global_get_id(pw_impl_client_get_global(client))); impl->context = context; + impl->context_pool = pw_context_get_mempool(context); impl->fds0 = impl->fds1 = -1; pw_log_debug("client-node %p: new", impl);
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/client-node.h -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/client-node.h
Changed
@@ -43,6 +43,16 @@ struct spa_command_node0_clock_update_body body; }; +enum spa_node0_event { + SPA_NODE0_EVENT_START = SPA_TYPE_VENDOR_PipeWire, + SPA_NODE0_EVENT_RequestClockUpdate, +}; + +enum spa_node0_command { + SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire, + SPA_NODE0_COMMAND_ClockUpdate, +}; + #define SPA_COMMAND_NODE0_CLOCK_UPDATE_INIT(type,change_mask,rate,ticks,monotonic_time,offset,scale,state,flags,latency) \ SPA_COMMAND_INIT_FULL(struct spa_command_node0_clock_update, \ sizeof(struct spa_command_node0_clock_update_body), 0, type, \
View file
pipewire-0.3.72.tar.gz/src/modules/module-client-node/v0/transport.c -> pipewire-0.3.74.tar.gz/src/modules/module-client-node/v0/transport.c
Changed
@@ -10,7 +10,6 @@ #include <spa/node/io.h> #include <pipewire/impl.h> -#include <pipewire/private.h> #include "ext-client-node.h" @@ -190,7 +189,7 @@ trans = &impl->trans; impl->offset = 0; - impl->mem = pw_mempool_alloc(context->pool, + impl->mem = pw_mempool_alloc(pw_context_get_mempool(context), PW_MEMBLOCK_FLAG_READWRITE | PW_MEMBLOCK_FLAG_MAP | PW_MEMBLOCK_FLAG_SEAL,
View file
pipewire-0.3.72.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-combine-stream.c
Changed
@@ -818,6 +818,7 @@ } else { direction = PW_DIRECTION_INPUT; s->stream_events.process = stream_input_process; + flags |= PW_STREAM_FLAG_ASYNC; } pw_stream_add_listener(s->stream,
View file
pipewire-0.3.74.tar.gz/src/modules/module-example-filter.c
Added
@@ -0,0 +1,639 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "config.h" + +#include <spa/utils/result.h> +#include <spa/utils/string.h> +#include <spa/utils/json.h> +#include <spa/utils/ringbuffer.h> +#include <spa/param/latency-utils.h> +#include <spa/debug/types.h> + +#include <pipewire/impl.h> +#include <pipewire/extensions/profiler.h> + +/** \page page_module_example_filter PipeWire Module: Example Filter + * + * The example filter is a good starting point for writing a custom + * filter. We refer to the source code for more information. + * + * ## Module Options + * + * - `node.description`: a human readable name for the filter streams + * - `capture.props = {}`: properties to be passed to the input stream + * - `playback.props = {}`: properties to be passed to the output stream + * + * ## General options + * + * Options with well-known behavior. Most options can be added to the global + * configuration or the individual streams: + * + * - \ref PW_KEY_REMOTE_NAME + * - \ref PW_KEY_AUDIO_RATE + * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_POSITION + * - \ref PW_KEY_MEDIA_NAME + * - \ref PW_KEY_NODE_LATENCY + * - \ref PW_KEY_NODE_DESCRIPTION + * - \ref PW_KEY_NODE_GROUP + * - \ref PW_KEY_NODE_LINK_GROUP + * - \ref PW_KEY_NODE_VIRTUAL + * - \ref PW_KEY_NODE_NAME: See notes below. If not specified, defaults to + * 'filter-<pid>-<module-id>'. + * + * Stream only properties: + * + * - \ref PW_KEY_MEDIA_CLASS + * - \ref PW_KEY_NODE_NAME: if not given per stream, the global node.name will be + * prefixed with 'input.' and 'output.' to generate a capture and playback + * stream node.name respectively. + * + * ## Example configuration of a virtual source + * + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-example-filter + * args = { + * node.description = "Example Filter" + * capture.props = { + * audio.position = FL FR + * node.passive = true + * } + * playback.props = { + * node.name = "Example Filter" + * media.class = "Audio/Source" + * audio.position = FL FR + * } + * } + * } + * + *\endcode + * + *\code{.unparsed} + * pw-cli -m lm libpipewire-module-example-filter '{ audio.position=FL FR }' + *\endcode + * + */ + +#define NAME "example-filter" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +static const struct spa_dict_item module_props = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "Create example filter streams" }, + { PW_KEY_MODULE_USAGE, " ( remote.name=<remote> ) " + "( node.latency=<latency as fraction> ) " + "( node.description=<description of the nodes> ) " + "( audio.rate=<sample rate> ) " + "( audio.channels=<number of channels> ) " + "( audio.position=<channel map> ) " + "( capture.props=<properties> ) " + "( playback.props=<properties> ) " }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +#include <stdlib.h> +#include <signal.h> +#include <getopt.h> +#include <limits.h> +#include <math.h> + +#include <spa/pod/builder.h> +#include <spa/param/audio/format-utils.h> +#include <spa/param/audio/raw.h> + +#include <pipewire/pipewire.h> + +struct impl { + struct pw_context *context; + + struct pw_impl_module *module; + + struct spa_hook module_listener; + + struct pw_core *core; + struct spa_hook core_proxy_listener; + struct spa_hook core_listener; + + struct pw_properties *capture_props; + struct pw_stream *capture; + struct spa_hook capture_listener; + struct spa_audio_info_raw capture_info; + struct spa_latency_info capture_latency; + + struct pw_properties *playback_props; + struct pw_stream *playback; + struct spa_hook playback_listener; + struct spa_audio_info_raw playback_info; + struct spa_latency_info playback_latency; + + unsigned int do_disconnect:1; +}; + +static void capture_destroy(void *d) +{ + struct impl *impl = d; + spa_hook_remove(&impl->capture_listener); + impl->capture = NULL; +} + +static void capture_process(void *d) +{ + struct impl *impl = d; + pw_stream_trigger_process(impl->playback); +} + +static void playback_process(void *d) +{ + struct impl *impl = d; + struct pw_buffer *in, *out; + uint32_t i; + + in = NULL; + while (true) { + struct pw_buffer *t; + if ((t = pw_stream_dequeue_buffer(impl->capture)) == NULL) + break; + if (in) + pw_stream_queue_buffer(impl->capture, in); + in = t; + } + if (in == NULL) + pw_log_debug("%p: out of capture buffers: %m", impl); + + if ((out = pw_stream_dequeue_buffer(impl->playback)) == NULL) + pw_log_debug("%p: out of playback buffers: %m", impl); + + if (in != NULL && out != NULL) { + uint32_t outsize = UINT32_MAX; + int32_t stride = 0; + struct spa_data *d; + const void *srcin->buffer->n_datas; + void *dstout->buffer->n_datas; + + for (i = 0; i < in->buffer->n_datas; i++) { + uint32_t offs, size; + + d = &in->buffer->datasi; + offs = SPA_MIN(d->chunk->offset, d->maxsize); + size = SPA_MIN(d->chunk->size, d->maxsize - offs); + + srci = SPA_PTROFF(d->data, offs, void); + outsize = SPA_MIN(outsize, size); + stride = SPA_MAX(stride, d->chunk->stride); + } + for (i = 0; i < out->buffer->n_datas; i++) { + d = &out->buffer->datasi; + + outsize = SPA_MIN(outsize, d->maxsize); + dsti = d->data; + + if (i < in->buffer->n_datas) { + /* do filtering here, samples are a single + * channel float */ + memcpy(dsti, srci, outsize); + } else { + memset(dsti, 0, outsize); + } + d->chunk->offset = 0; + d->chunk->size = outsize; + d->chunk->stride = stride; + } + } + + if (in != NULL) + pw_stream_queue_buffer(impl->capture, in); + if (out != NULL) + pw_stream_queue_buffer(impl->playback, out); +} + +static void param_latency_changed(struct impl *impl, const struct spa_pod *param, + struct spa_latency_info *info, struct pw_stream *other) +{ + struct spa_latency_info latency; + uint8_t buffer1024; + struct spa_pod_builder b; + const struct spa_pod *params1; + + if (spa_latency_parse(param, &latency) < 0) + return; + + *info = latency; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + params0 = spa_latency_build(&b, SPA_PARAM_Latency, &latency); + pw_stream_update_params(other, params, 1); +} + +static void stream_state_changed(void *data, enum pw_stream_state old, + enum pw_stream_state state, const char *error) +{ + struct impl *impl = data; + switch (state) { + case PW_STREAM_STATE_PAUSED: + pw_stream_flush(impl->playback, false); + pw_stream_flush(impl->capture, false); + break; + case PW_STREAM_STATE_UNCONNECTED: + pw_log_info("module %p: unconnected", impl); + pw_impl_module_schedule_destroy(impl->module); + break; + case PW_STREAM_STATE_ERROR: + pw_log_info("module %p: error: %s", impl, error); + break; + default: + break; + } +} + +static void capture_param_changed(void *data, uint32_t id, const struct spa_pod *param) +{ + struct impl *impl = data; + + switch (id) { + case SPA_PARAM_Format: + { + struct spa_audio_info_raw info; + if (param == NULL) + return; + if (spa_format_audio_raw_parse(param, &info) < 0) + return; + if (info.rate == 0 || + info.channels == 0 || + info.channels > SPA_AUDIO_MAX_CHANNELS) + return; + break; + } + case SPA_PARAM_Latency: + param_latency_changed(impl, param, &impl->capture_latency, impl->playback); + break; + } +} + +static const struct pw_stream_events in_stream_events = { + PW_VERSION_STREAM_EVENTS, + .destroy = capture_destroy, + .process = capture_process, + .state_changed = stream_state_changed, + .param_changed = capture_param_changed, +}; + +static void playback_destroy(void *d) +{ + struct impl *impl = d; + spa_hook_remove(&impl->playback_listener); + impl->playback = NULL; +} + +static void playback_param_changed(void *data, uint32_t id, const struct spa_pod *param) +{ + struct impl *impl = data; + + switch (id) { + case SPA_PARAM_Latency: + param_latency_changed(impl, param, &impl->playback_latency, impl->capture); + break; + } +} +static const struct pw_stream_events out_stream_events = { + PW_VERSION_STREAM_EVENTS, + .destroy = playback_destroy, + .process = playback_process, + .state_changed = stream_state_changed, + .param_changed = playback_param_changed, +}; + +static int setup_streams(struct impl *impl) +{ + int res; + uint32_t n_params; + const struct spa_pod *params1; + uint8_t buffer1024; + struct spa_pod_builder b; + + impl->capture = pw_stream_new(impl->core, + "filter capture", impl->capture_props); + impl->capture_props = NULL; + if (impl->capture == NULL) + return -errno; + + pw_stream_add_listener(impl->capture, + &impl->capture_listener, + &in_stream_events, impl); + + impl->playback = pw_stream_new(impl->core, + "filter playback", impl->playback_props); + impl->playback_props = NULL; + if (impl->playback == NULL) + return -errno; + + pw_stream_add_listener(impl->playback, + &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->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_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->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_ASYNC, + params, n_params)) < 0) + return res; + + return 0; +} + +static void core_error(void *data, uint32_t id, int seq, int res, const char *message) +{ + struct impl *impl = data; + + 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); +} + +static const struct pw_core_events core_events = { + PW_VERSION_CORE_EVENTS, + .error = core_error, +}; + +static void core_destroy(void *d) +{ + struct impl *impl = d; + spa_hook_remove(&impl->core_listener); + impl->core = NULL; + pw_impl_module_schedule_destroy(impl->module); +} + +static const struct pw_proxy_events core_proxy_events = { + .destroy = core_destroy, +}; + +static void impl_destroy(struct impl *impl) +{ + /* deactivate both streams before destroying any of them */ + if (impl->capture) + pw_stream_set_active(impl->capture, false); + if (impl->playback) + pw_stream_set_active(impl->playback, false); + + if (impl->capture) + pw_stream_destroy(impl->capture); + if (impl->playback) + pw_stream_destroy(impl->playback); + + if (impl->core && impl->do_disconnect) + pw_core_disconnect(impl->core); + + pw_properties_free(impl->capture_props); + pw_properties_free(impl->playback_props); + free(impl); +} + +static void module_destroy(void *data) +{ + struct impl *impl = data; + spa_hook_remove(&impl->module_listener); + impl_destroy(impl); +} + +static const struct pw_impl_module_events module_events = { + PW_VERSION_IMPL_MODULE_EVENTS, + .destroy = module_destroy, +}; + +static uint32_t channel_from_name(const char *name) +{ + int i; + for (i = 0; spa_type_audio_channeli.name; i++) { + if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name))) + return spa_type_audio_channeli.type; + } + return SPA_AUDIO_CHANNEL_UNKNOWN; +} + +static void parse_position(struct spa_audio_info_raw *info, const char *val, size_t len) +{ + struct spa_json it2; + char v256; + + spa_json_init(&it0, val, len); + if (spa_json_enter_array(&it0, &it1) <= 0) + spa_json_init(&it1, val, len); + + info->channels = 0; + while (spa_json_get_string(&it1, v, sizeof(v)) > 0 && + info->channels < SPA_AUDIO_MAX_CHANNELS) { + info->positioninfo->channels++ = channel_from_name(v); + } +} + +static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +{ + const char *str; + + *info = SPA_AUDIO_INFO_RAW_INIT( + .format = SPA_AUDIO_FORMAT_F32P); + info->rate = pw_properties_get_int32(props, PW_KEY_AUDIO_RATE, 0); + info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, 0); + info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) + parse_position(info, str, strlen(str)); +} + +static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) +{ + const char *str; + if ((str = pw_properties_get(props, key)) != NULL) { + if (pw_properties_get(impl->capture_props, key) == NULL) + pw_properties_set(impl->capture_props, key, str); + if (pw_properties_get(impl->playback_props, key) == NULL) + pw_properties_set(impl->playback_props, key, str); + } +} + +SPA_EXPORT +int pipewire__module_init(struct pw_impl_module *module, const char *args) +{ + struct pw_context *context = pw_impl_module_get_context(module); + struct pw_properties *props; + struct impl *impl; + uint32_t id = pw_global_get_id(pw_impl_module_get_global(module)); + uint32_t pid = getpid(); + const char *str; + int res; + + PW_LOG_TOPIC_INIT(mod_topic); + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + return -errno; + + pw_log_debug("module %p: new %s", impl, args); + + if (args) + props = pw_properties_new_string(args); + else + props = pw_properties_new(NULL, NULL); + if (props == NULL) { + res = -errno; + pw_log_error( "can't create properties: %m"); + goto error; + } + + impl->capture_props = pw_properties_new(NULL, NULL); + impl->playback_props = pw_properties_new(NULL, NULL); + if (impl->capture_props == NULL || impl->playback_props == NULL) { + res = -errno; + pw_log_error( "can't create properties: %m"); + goto error; + } + + impl->module = module; + impl->context = context; + + if (pw_properties_get(props, PW_KEY_NODE_GROUP) == NULL) + pw_properties_setf(props, PW_KEY_NODE_GROUP, "filter-%u-%u", pid, id); + if (pw_properties_get(props, PW_KEY_NODE_LINK_GROUP) == NULL) + pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "filter-%u-%u", pid, id); + if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) + pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); + if (pw_properties_get(props, "resample.prefill") == NULL) + pw_properties_set(props, "resample.prefill", "true"); + + if ((str = pw_properties_get(props, "capture.props")) != NULL) + pw_properties_update_string(impl->capture_props, str, strlen(str)); + if ((str = pw_properties_get(props, "playback.props")) != NULL) + pw_properties_update_string(impl->playback_props, str, strlen(str)); + + copy_props(impl, props, PW_KEY_AUDIO_RATE); + copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_POSITION); + copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); + copy_props(impl, props, PW_KEY_NODE_GROUP); + copy_props(impl, props, PW_KEY_NODE_LINK_GROUP); + copy_props(impl, props, PW_KEY_NODE_LATENCY); + copy_props(impl, props, PW_KEY_NODE_VIRTUAL); + copy_props(impl, props, PW_KEY_MEDIA_NAME); + copy_props(impl, props, "resample.prefill"); + + if ((str = pw_properties_get(props, PW_KEY_NODE_NAME)) == NULL) { + pw_properties_setf(props, PW_KEY_NODE_NAME, + "filter-%u-%u", pid, id); + str = pw_properties_get(props, PW_KEY_NODE_NAME); + } + if (pw_properties_get(impl->capture_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->capture_props, PW_KEY_NODE_NAME, + "input.%s", str); + if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME, + "output.%s", str); + if (pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION) == NULL) + pw_properties_set(impl->capture_props, PW_KEY_NODE_DESCRIPTION, str); + if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL) + pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str); + + parse_audio_info(impl->capture_props, &impl->capture_info); + parse_audio_info(impl->playback_props, &impl->playback_info); + + if (!impl->capture_info.rate && !impl->playback_info.rate) { + if (pw_properties_get(impl->playback_props, "resample.disable") == NULL) + pw_properties_set(impl->playback_props, "resample.disable", "true"); + if (pw_properties_get(impl->capture_props, "resample.disable") == NULL) + pw_properties_set(impl->capture_props, "resample.disable", "true"); + } else if (impl->capture_info.rate && !impl->playback_info.rate) + impl->playback_info.rate = impl->capture_info.rate; + else if (impl->playback_info.rate && !impl->capture_info.rate) + impl->capture_info.rate = !impl->playback_info.rate; + else if (impl->capture_info.rate != impl->playback_info.rate) { + pw_log_warn("Both capture and playback rate are set, but" + " they are different. Using the highest of two. This behaviour" + " is deprecated, please use equal rates in the module config"); + impl->playback_info.rate = impl->capture_info.rate = + SPA_MAX(impl->playback_info.rate, impl->capture_info.rate); + } + + if (pw_properties_get(impl->capture_props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(impl->capture_props, PW_KEY_MEDIA_NAME, "%s input", + pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION)); + if (pw_properties_get(impl->playback_props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(impl->playback_props, PW_KEY_MEDIA_NAME, "%s output", + pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION)); + + impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); + if (impl->core == NULL) { + str = pw_properties_get(props, PW_KEY_REMOTE_NAME); + impl->core = pw_context_connect(impl->context, + pw_properties_new( + PW_KEY_REMOTE_NAME, str, + NULL), + 0); + impl->do_disconnect = true; + } + if (impl->core == NULL) { + res = -errno; + pw_log_error("can't connect: %m"); + goto error; + } + + pw_properties_free(props); + + pw_proxy_add_listener((struct pw_proxy*)impl->core, + &impl->core_proxy_listener, + &core_proxy_events, impl); + pw_core_add_listener(impl->core, + &impl->core_listener, + &core_events, impl); + + setup_streams(impl); + + pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); + + pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props)); + + return 0; + +error: + pw_properties_free(props); + impl_destroy(impl); + return res; +}
View file
pipewire-0.3.72.tar.gz/src/modules/module-ffado-driver.c -> pipewire-0.3.74.tar.gz/src/modules/module-ffado-driver.c
Changed
@@ -27,7 +27,6 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> -#include <pipewire/private.h> #include <pipewire/thread.h> #include <libffado/ffado.h> @@ -745,20 +744,6 @@ return NULL; } -static int -do_schedule_destroy(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct impl *impl = user_data; - pw_impl_module_schedule_destroy(impl->module); - return 0; -} - -void module_schedule_destroy(struct impl *impl) -{ - pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl); -} - static int open_ffado_device(struct impl *impl) { ffado_streaming_stream_type stream_type;
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -147,7 +147,7 @@ * * The mixer plugin has up to 8 input ports labeled "In 1" to "In 8" and each with * a gain control labeled "Gain 1" to "Gain 8". There is an output port labeled - * "Out". Unused input ports will be ignoded and not cause overhead. + * "Out". Unused input ports will be ignored and not cause overhead. * * ### Copy * @@ -518,9 +518,16 @@ #define MAX_HNDL 64 #define MAX_SAMPLES 8192 +#define DEFAULT_RATE 48000 + static float silence_dataMAX_SAMPLES; static float discard_dataMAX_SAMPLES; +struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support, + struct dsp_ops *dsp, const char *path, const char *config); +struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support, + struct dsp_ops *dsp, const char *path, const char *config); + struct plugin { struct spa_list link; int ref; @@ -531,6 +538,13 @@ struct spa_list descriptor_list; }; +struct plugin_func { + struct spa_list link; + char type256; + fc_plugin_load_func *func; + void *hndl; +}; + struct descriptor { struct spa_list link; int ref; @@ -627,6 +641,8 @@ uint32_t n_control; struct port **control_port; + + unsigned instantiated:1; }; struct impl { @@ -643,6 +659,7 @@ struct dsp_ops dsp; struct spa_list plugin_list; + struct spa_list plugin_func_list; struct pw_properties *capture_props; struct pw_stream *capture; @@ -654,6 +671,10 @@ struct spa_hook playback_listener; struct spa_audio_info_raw playback_info; + struct spa_audio_info_raw info; + + struct spa_io_position *position; + unsigned int do_disconnect:1; long unsigned rate; @@ -856,7 +877,7 @@ struct fc_port *p = &d->portsport->p; float def, min, max; char name512; - uint32_t rate = impl->rate ? impl->rate : 48000; + uint32_t rate = impl->rate ? impl->rate : DEFAULT_RATE; if (p->hint & FC_HINT_SAMPLE_RATE) { def = p->def * rate; @@ -1105,6 +1126,7 @@ { struct impl *impl = data; struct graph *graph = &impl->graph; + int res; switch (state) { case PW_STREAM_STATE_PAUSED: @@ -1119,6 +1141,40 @@ case PW_STREAM_STATE_ERROR: pw_log_info("module %p: error: %s", impl, error); break; + case PW_STREAM_STATE_STREAMING: + { + uint32_t target = impl->info.rate; + if (target == 0) + target = impl->position ? + impl->position->clock.target_rate.denom : DEFAULT_RATE; + if (target == 0) { + res = -EINVAL; + goto error; + } + if (impl->rate != target) { + impl->rate = target; + graph_cleanup(graph); + if ((res = graph_instantiate(graph)) < 0) + goto error; + } + break; + } + default: + break; + } + return; +error: + pw_stream_set_error(impl->capture, res, "can't start graph: %s", + spa_strerror(res)); +} + +static void io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + switch (id) { + case SPA_IO_Position: + impl->position = area; + break; default: break; } @@ -1132,22 +1188,19 @@ switch (id) { case SPA_PARAM_Format: + { + struct spa_audio_info_raw info; + spa_zero(info); if (param == NULL) { graph_cleanup(graph); + impl->rate = 0; } else { - struct spa_audio_info_raw info; - spa_zero(info); if ((res = spa_format_audio_raw_parse(param, &info)) < 0) goto error; - if (info.rate == 0) { - res = -EINVAL; - goto error; - } - impl->rate = info.rate; - if ((res = graph_instantiate(graph)) < 0) - goto error; } + impl->info = info; break; + } case SPA_PARAM_Props: if (param != NULL) param_props_changed(impl, param); @@ -1167,6 +1220,7 @@ PW_VERSION_STREAM_EVENTS, .destroy = capture_destroy, .process = capture_process, + .io_changed = io_changed, .state_changed = state_changed, .param_changed = param_changed }; @@ -1182,8 +1236,9 @@ PW_VERSION_STREAM_EVENTS, .destroy = playback_destroy, .process = playback_process, + .io_changed = io_changed, .state_changed = state_changed, - .param_changed = param_changed + .param_changed = param_changed, }; static int setup_streams(struct impl *impl) @@ -1255,7 +1310,8 @@ 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_ASYNC, params, n_params); spa_pod_dynamic_builder_clean(&b); @@ -1305,12 +1361,92 @@ free(hndl); } + +static struct plugin_func *add_plugin_func(struct impl *impl, const char *type, + fc_plugin_load_func *func, void *hndl) +{ + struct plugin_func *pl; + + pl = calloc(1, sizeof(*pl)); + if (pl == NULL) + return NULL; + + snprintf(pl->type, sizeof(pl->type), "%s", type); + pl->func = func; + pl->hndl = hndl; + spa_list_append(&impl->plugin_func_list, &pl->link); + return pl; +} + +static void free_plugin_func(struct plugin_func *pl) +{ + spa_list_remove(&pl->link); + if (pl->hndl) + dlclose(pl->hndl); + free(pl); +} + +static fc_plugin_load_func *find_plugin_func(struct impl *impl, const char *type) +{ + fc_plugin_load_func *func = NULL; + void *hndl = NULL; + int res; + struct plugin_func *pl; + char modulePATH_MAX; + const char *module_dir; + const char *state = NULL, *p; + size_t len; + + spa_list_for_each(pl, &impl->plugin_func_list, link) { + if (spa_streq(pl->type, type)) + return pl->func; + } + module_dir = getenv("PIPEWIRE_MODULE_DIR"); + if (module_dir == NULL) + module_dir = MODULEDIR; + pw_log_debug("moduledir set to: %s", module_dir); + + while ((p = pw_split_walk(module_dir, ":", &len, &state))) { + if ((res = spa_scnprintf(module, sizeof(module), + "%.*s/libpipewire-module-filter-chain-%s.so", + (int)len, p, type)) <= 0) + continue; + + hndl = dlopen(module, RTLD_NOW | RTLD_LOCAL); + if (hndl != NULL) + break; + + pw_log_debug("open plugin module %s failed: %s", module, dlerror()); + } + if (hndl == NULL) { + errno = ENOENT; + return NULL; + } + func = dlsym(hndl, FC_PLUGIN_LOAD_FUNC); + if (func != NULL) { + pw_log_info("opened plugin module %s", module); + pl = add_plugin_func(impl, type, func, hndl); + if (pl == NULL) + goto error_close; + } else { + errno = ENOSYS; + pw_log_error("%s is not a filter chain plugin: %m", module); + goto error_close; + } + return func; + +error_close: + dlclose(hndl); + return NULL; +} + static struct plugin *plugin_load(struct impl *impl, const char *type, const char *path) { struct fc_plugin *pl = NULL; struct plugin *hndl; const struct spa_support *support; uint32_t n_support; + fc_plugin_load_func *plugin_func; spa_list_for_each(hndl, &impl->plugin_list, link) { if (spa_streq(hndl->type, type) && @@ -1321,27 +1457,12 @@ } support = pw_context_get_support(impl->context, &n_support); - if (spa_streq(type, "builtin")) { - pl = load_builtin_plugin(support, n_support, &impl->dsp, path, NULL); - } - else if (spa_streq(type, "sofa")) { - pl = load_sofa_plugin(support, n_support, &impl->dsp, path, NULL); - } - else if (spa_streq(type, "ladspa")) { - pl = load_ladspa_plugin(support, n_support, &impl->dsp, path, NULL); - } - else if (spa_streq(type, "lv2")) { -#ifdef HAVE_LILV - pl = load_lv2_plugin(support, n_support, &impl->dsp, path, NULL); -#else - pw_log_error("filter-chain is compiled without lv2 support"); + plugin_func = find_plugin_func(impl, type); + if (plugin_func == NULL) { + pw_log_error("can't load plugin type '%s': %m", type); pl = NULL; - errno = ENOTSUP; -#endif } else { - pw_log_error("invalid plugin type '%s'", type); - pl = NULL; - errno = EINVAL; + pl = plugin_func(support, n_support, &impl->dsp, path, NULL); } if (pl == NULL) goto exit; @@ -1354,7 +1475,7 @@ snprintf(hndl->type, sizeof(hndl->type), "%s", type); snprintf(hndl->path, sizeof(hndl->path), "%s", path); - pw_log_info("successfully opened '%s'", path); + pw_log_info("successfully opened '%s':'%s'", type, path); hndl->plugin = pl; @@ -1560,7 +1681,7 @@ char output256 = ""; char input256 = ""; const char *val; - struct node *def_node; + struct node *def_in_node, *def_out_node; struct port *in_port, *out_port; struct link *link; @@ -1585,16 +1706,25 @@ else if (spa_json_next(json, &val) < 0) break; } - def_node = spa_list_first(&graph->node_list, struct node, link); - if ((out_port = find_port(def_node, output, FC_PORT_OUTPUT)) == NULL) { - pw_log_error("unknown output port %s", output); - return -ENOENT; + def_out_node = spa_list_first(&graph->node_list, struct node, link); + def_in_node = spa_list_last(&graph->node_list, struct node, link); + + out_port = find_port(def_out_node, output, FC_PORT_OUTPUT); + in_port = find_port(def_in_node, input, FC_PORT_INPUT); + + if (out_port == NULL && out_port == NULL) { + /* try control ports */ + out_port = find_port(def_out_node, output, FC_PORT_OUTPUT | FC_PORT_CONTROL); + in_port = find_port(def_in_node, input, FC_PORT_INPUT | FC_PORT_CONTROL); } - def_node = spa_list_last(&graph->node_list, struct node, link); - if ((in_port = find_port(def_node, input, FC_PORT_INPUT)) == NULL) { - pw_log_error("unknown input port %s", input); + if (in_port == NULL || out_port == NULL) { + if (out_port == NULL) + pw_log_error("unknown output port %s", output); + if (in_port == NULL) + pw_log_error("unknown input port %s", input); return -ENOENT; } + if (in_port->n_links > 0) { pw_log_info("Can't have more than 1 link to %s, use a mixer", input); return -ENOTSUP; @@ -1776,6 +1906,7 @@ for (i = 0; i < node->n_hndl; i++) { if (node->hndli == NULL) continue; + pw_log_info("cleanup %s %d", d->name, i); if (d->deactivate) d->deactivate(node->hndli); d->cleanup(node->hndli); @@ -1825,6 +1956,9 @@ static void graph_cleanup(struct graph *graph) { struct node *node; + if (!graph->instantiated) + return; + graph->instantiated = false; spa_list_for_each(node, &graph->node_list, link) node_cleanup(node); } @@ -1840,6 +1974,11 @@ uint32_t i, j; int res; + if (graph->instantiated) + return 0; + + graph->instantiated = true; + spa_list_for_each(node, &graph->node_list, link) { float *sd = silence_data, *dd = discard_data; @@ -1852,8 +1991,9 @@ for (i = 0; i < node->n_hndl; i++) { pw_log_info("instantiate %s %d rate:%lu", d->name, i, impl->rate); + errno = EINVAL; if ((node->hndli = d->instantiate(d, impl->rate, i, node->config)) == NULL) { - pw_log_error("cannot create plugin instance: %m"); + pw_log_error("cannot create plugin instance %d rate:%lu: %m", i, impl->rate); res = -errno; goto error; } @@ -1883,9 +2023,20 @@ for (j = 0; j < desc->n_control; j++) { port = &node->control_portj; d->connect_port(node->hndli, port->p, &port->control_data); + + spa_list_for_each(link, &port->link_list, input_link) { + struct port *peer = link->output; + pw_log_info("connect control port %s%d:%s %p", + node->name, i, d->portsport->p.name, + &peer->control_data); + d->connect_port(node->hndli, port->p, &peer->control_data); + } } for (j = 0; j < desc->n_notify; j++) { port = &node->notify_portj; + pw_log_info("connect notify port %s%d:%s %p", + node->name, i, d->portsport->p.name, + &port->control_data); d->connect_port(node->hndli, port->p, &port->control_data); } if (d->activate) @@ -2301,6 +2452,8 @@ static void impl_destroy(struct impl *impl) { + struct plugin_func *pl; + /* disconnect both streams before destroying any of them */ if (impl->capture) pw_stream_disconnect(impl->capture); @@ -2318,6 +2471,8 @@ pw_properties_free(impl->capture_props); pw_properties_free(impl->playback_props); graph_free(&impl->graph); + spa_list_consume(pl, &impl->plugin_func_list, link) + free_plugin_func(pl); free(impl); } @@ -2429,6 +2584,10 @@ impl->graph.impl = impl; spa_list_init(&impl->plugin_list); + spa_list_init(&impl->plugin_func_list); + + add_plugin_func(impl, "builtin", load_builtin_plugin, NULL); + add_plugin_func(impl, "ladspa", load_ladspa_plugin, NULL); support = pw_context_get_support(impl->context, &n_support);
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/builtin_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/builtin_plugin.c
Changed
@@ -10,6 +10,7 @@ #include <sndfile.h> #endif #include <unistd.h> +#include <limits.h> #include <spa/utils/json.h> #include <spa/utils/result.h>
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c
Changed
@@ -84,33 +84,27 @@ 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 x, y, x1, x2; 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; + x = ini; + y = b0 * x + x1; + x1 = b1 * x - a1 * y + x2; + x2 = b2 * x - a2 * y; 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.72.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/ladspa_plugin.c
Changed
@@ -6,6 +6,7 @@ #include <dlfcn.h> #include <math.h> +#include <limits.h> #include <spa/utils/defs.h> #include <spa/utils/list.h>
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/lv2_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/lv2_plugin.c
Changed
@@ -451,7 +451,8 @@ free(p); } -struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support, +SPA_EXPORT +struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support, struct dsp_ops *ops, const char *plugin_uri, const char *config) { struct context *c;
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/plugin.h -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/plugin.h
Changed
@@ -7,14 +7,8 @@ #include <stdint.h> #include <stddef.h> -#include <errno.h> -#include <stdio.h> -#include <limits.h> #include <spa/support/plugin.h> -#include <spa/utils/defs.h> -#include <spa/utils/list.h> -#include <spa/utils/string.h> #include "dsp-ops.h" @@ -83,13 +77,10 @@ desc->free(desc); } -struct fc_plugin *load_ladspa_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); -struct fc_plugin *load_lv2_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); -struct fc_plugin *load_builtin_plugin(const struct spa_support *support, uint32_t n_support, - struct dsp_ops *dsp, const char *path, const char *config); -struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support, +#define FC_PLUGIN_LOAD_FUNC "pipewire__filter_chain_plugin_load" + +typedef struct fc_plugin *(fc_plugin_load_func)(const struct spa_support *support, uint32_t n_support, struct dsp_ops *dsp, const char *path, const char *config); + #endif /* PLUGIN_H */
View file
pipewire-0.3.72.tar.gz/src/modules/module-filter-chain/sofa_plugin.c -> pipewire-0.3.74.tar.gz/src/modules/module-filter-chain/sofa_plugin.c
Changed
@@ -1,19 +1,20 @@ #include "config.h" +#include <limits.h> + #include <spa/utils/json.h> #include <spa/support/loop.h> #include <pipewire/log.h> + #include "plugin.h" #include "convolver.h" #include "dsp-ops.h" #include "pffft.h" -#ifdef HAVE_LIBMYSOFA #include <mysofa.h> #define MAX_SAMPLES 8192u -#endif static struct dsp_ops *dsp_ops; static struct spa_loop *data_loop; @@ -25,9 +26,7 @@ int n_samples, blocksize, tailsize; float *tmp2; -#ifdef HAVE_LIBMYSOFA struct MYSOFA_EASY *sofa; -#endif unsigned int interpolate:1; struct convolver *l_conv3; struct convolver *r_conv3; @@ -36,7 +35,6 @@ static void * spatializer_instantiate(const struct fc_descriptor * Descriptor, unsigned long SampleRate, int index, const char *config) { -#ifdef HAVE_LIBMYSOFA struct spatializer_impl *impl; struct spa_json it2; const char *val; @@ -115,14 +113,8 @@ mysofa_close_cached(impl->sofa); free(impl); return NULL; -#else - pw_log_error("libmysofa is required for spatializer, but disabled at compile time"); - errno = EINVAL; - return NULL; -#endif } -#ifdef HAVE_LIBMYSOFA static int do_switch(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) @@ -205,11 +197,9 @@ convolver_free(fd->item1); return 0; } -#endif static void spatializer_run(void * Instance, unsigned long SampleCount) { -#ifdef HAVE_LIBMYSOFA struct spatializer_impl *impl = Instance; if (impl->interpolate) { @@ -239,7 +229,6 @@ convolver_run(impl->l_conv0, impl->port2, impl->port0, SampleCount); convolver_run(impl->r_conv0, impl->port2, impl->port1, SampleCount); } -#endif } static void spatializer_connect_port(void * Instance, unsigned long Port, @@ -261,10 +250,8 @@ if (impl->r_convi) convolver_free(impl->r_convi); } -#ifdef HAVE_LIBMYSOFA if (impl->sofa) mysofa_close_cached(impl->sofa); -#endif free(impl->tmp0); free(impl->tmp1); @@ -273,10 +260,8 @@ static void spatializer_control_changed(void * Instance) { -#ifdef HAVE_LIBMYSOFA pw_log_info("control changed"); spatializer_reload(Instance); -#endif } static void spatializer_deactivate(void * Instance) @@ -361,7 +346,8 @@ .make_desc = sofa_make_desc }; -struct fc_plugin *load_sofa_plugin(const struct spa_support *support, uint32_t n_support, +SPA_EXPORT +struct fc_plugin *pipewire__filter_chain_plugin_load(const struct spa_support *support, uint32_t n_support, struct dsp_ops *dsp, const char *plugin, const char *config) { dsp_ops = dsp; @@ -372,4 +358,3 @@ return &builtin_plugin; } -
View file
pipewire-0.3.72.tar.gz/src/modules/module-jack-tunnel.c -> pipewire-0.3.74.tar.gz/src/modules/module-jack-tunnel.c
Changed
@@ -27,7 +27,6 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> -#include <pipewire/private.h> #include "module-jack-tunnel/weakjack.h" @@ -744,7 +743,7 @@ return 0; } -void module_schedule_destroy(struct impl *impl) +static void module_schedule_destroy(struct impl *impl) { pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl); }
View file
pipewire-0.3.72.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.74.tar.gz/src/modules/module-loopback.c
Changed
@@ -142,6 +142,8 @@ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; +#define DEFAULT_RATE 48000 + #include <stdlib.h> #include <signal.h> #include <getopt.h> @@ -180,7 +182,9 @@ unsigned int do_disconnect:1; unsigned int recalc_delay:1; - struct spa_audio_info_raw delay_info; + struct spa_io_position *position; + struct spa_audio_info_raw info; + uint32_t rate; float target_delay; struct spa_ringbuffer buffer; uint8_t *buffer_data; @@ -196,7 +200,7 @@ static void recalculate_delay(struct impl *impl) { - uint32_t target = impl->delay_info.rate * impl->target_delay, cdelay, pdelay; + uint32_t target = impl->rate * impl->target_delay, cdelay, pdelay; uint32_t delay, w; struct pw_time pwt; @@ -332,36 +336,14 @@ impl->recalc_delay = true; } -static void stream_state_changed(void *data, enum pw_stream_state old, - enum pw_stream_state state, const char *error) -{ - struct impl *impl = data; - switch (state) { - case PW_STREAM_STATE_PAUSED: - pw_stream_flush(impl->playback, false); - pw_stream_flush(impl->capture, false); - impl->recalc_delay = true; - break; - case PW_STREAM_STATE_UNCONNECTED: - pw_log_info("module %p: unconnected", impl); - pw_impl_module_schedule_destroy(impl->module); - break; - case PW_STREAM_STATE_ERROR: - pw_log_info("module %p: error: %s", impl, error); - break; - default: - break; - } -} - static void recalculate_buffer(struct impl *impl) { if (impl->target_delay > 0.0f) { - uint32_t delay = impl->delay_info.rate * impl->target_delay; + uint32_t delay = impl->rate * impl->target_delay; void *data; impl->buffer_size = (delay + (1u<<15)) * 4; - data = realloc(impl->buffer_data, impl->buffer_size * impl->delay_info.channels); + data = realloc(impl->buffer_data, impl->buffer_size * impl->info.channels); if (data == NULL) { pw_log_warn("can't allocate delay buffer, delay disabled: %m"); impl->buffer_size = 0; @@ -378,6 +360,40 @@ impl->recalc_delay = true; } +static void stream_state_changed(void *data, enum pw_stream_state old, + enum pw_stream_state state, const char *error) +{ + struct impl *impl = data; + switch (state) { + case PW_STREAM_STATE_PAUSED: + pw_stream_flush(impl->playback, false); + pw_stream_flush(impl->capture, false); + impl->recalc_delay = true; + break; + case PW_STREAM_STATE_UNCONNECTED: + pw_log_info("module %p: unconnected", impl); + pw_impl_module_schedule_destroy(impl->module); + break; + case PW_STREAM_STATE_ERROR: + pw_log_info("module %p: error: %s", impl, error); + break; + case PW_STREAM_STATE_STREAMING: + { + uint32_t target = impl->info.rate; + if (target == 0) + target = impl->position ? + impl->position->clock.target_rate.denom : DEFAULT_RATE; + if (impl->rate != target) { + impl->rate = target; + recalculate_buffer(impl); + } + break; + } + default: + break; + } +} + static void capture_param_changed(void *data, uint32_t id, const struct spa_pod *param) { struct impl *impl = data; @@ -386,17 +402,15 @@ case SPA_PARAM_Format: { struct spa_audio_info_raw info; - if (param == NULL) - return; - if (spa_format_audio_raw_parse(param, &info) < 0) - return; - if (info.rate == 0 || - info.channels == 0 || - info.channels > SPA_AUDIO_MAX_CHANNELS) - return; - - impl->delay_info = info; - recalculate_buffer(impl); + spa_zero(info); + if (param != NULL) { + if (spa_format_audio_raw_parse(param, &info) < 0 || + info.channels == 0 || + info.channels > SPA_AUDIO_MAX_CHANNELS) + return; + } + impl->rate = 0; + impl->info = info; break; } case SPA_PARAM_Latency: @@ -405,12 +419,25 @@ } } +static void io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + switch (id) { + case SPA_IO_Position: + impl->position = area; + break; + default: + break; + } +} + static const struct pw_stream_events in_stream_events = { PW_VERSION_STREAM_EVENTS, .destroy = capture_destroy, .process = capture_process, .state_changed = stream_state_changed, .param_changed = capture_param_changed, + .io_changed = io_changed, }; static void playback_destroy(void *d) @@ -436,6 +463,7 @@ .process = playback_process, .state_changed = stream_state_changed, .param_changed = playback_param_changed, + .io_changed = io_changed, }; static int setup_streams(struct impl *impl) @@ -490,7 +518,8 @@ 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_ASYNC, params, n_params)) < 0) return res;
View file
pipewire-0.3.72.tar.gz/src/modules/module-netjack2-driver.c -> pipewire-0.3.74.tar.gz/src/modules/module-netjack2-driver.c
Changed
@@ -31,7 +31,6 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> -#include <pipewire/private.h> #include "module-netjack2/packets.h" #include "module-netjack2/peer.c" @@ -186,7 +185,7 @@ struct impl { struct pw_context *context; struct pw_loop *main_loop; - struct pw_data_loop *data_loop; + struct pw_loop *data_loop; struct spa_system *system; #define MODE_SINK (1<<0) @@ -617,7 +616,7 @@ if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { pw_log_warn("error:%08x", mask); - pw_loop_update_io(impl->data_loop->loop, impl->socket, 0); + pw_loop_update_io(impl->data_loop, impl->socket, 0); return; } if (mask & SPA_IO_IN) { @@ -685,20 +684,6 @@ } } -static int -do_schedule_destroy(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct impl *impl = user_data; - pw_impl_module_schedule_destroy(impl->module); - return 0; -} - -void module_schedule_destroy(struct impl *impl) -{ - pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl); -} - static int parse_address(const char *address, uint16_t port, struct sockaddr_storage *addr, socklen_t *len) { @@ -903,7 +888,7 @@ send(impl->socket->fd, params, sizeof(*params), 0); impl->done = true; - pw_loop_update_io(impl->data_loop->loop, impl->socket, SPA_IO_IN); + pw_loop_update_io(impl->data_loop, impl->socket, SPA_IO_IN); return 0; connect_error: @@ -1027,7 +1012,7 @@ goto out; } - impl->socket = pw_loop_add_io(impl->data_loop->loop, fd, + impl->socket = pw_loop_add_io(impl->data_loop, fd, 0, false, on_data_io, impl); if (impl->socket == NULL) { res = -errno; @@ -1049,7 +1034,7 @@ impl->started = false; if (impl->socket) - pw_loop_update_io(impl->data_loop->loop, impl->socket, 0); + pw_loop_update_io(impl->data_loop, impl->socket, 0); pw_log_info("sending STOP_DRIVER"); nj2_session_params_hton(¶ms, &impl->peer.params); @@ -1071,7 +1056,7 @@ update_timer(impl, 0); if (impl->socket) { - pw_loop_destroy_source(impl->data_loop->loop, impl->socket); + pw_loop_destroy_source(impl->data_loop, impl->socket); impl->socket = NULL; } if (impl->setup_socket) { @@ -1228,6 +1213,7 @@ { struct pw_context *context = pw_impl_module_get_context(module); struct pw_properties *props = NULL; + struct pw_data_loop *data_loop; struct impl *impl; const char *str; int res; @@ -1250,7 +1236,8 @@ goto error; } impl->props = props; - impl->data_loop = pw_context_get_data_loop(context); + data_loop = pw_context_get_data_loop(context); + impl->data_loop = pw_data_loop_get_loop(data_loop); impl->sink.props = pw_properties_new(NULL, NULL); impl->source.props = pw_properties_new(NULL, NULL);
View file
pipewire-0.3.72.tar.gz/src/modules/module-netjack2-manager.c -> pipewire-0.3.74.tar.gz/src/modules/module-netjack2-manager.c
Changed
@@ -32,7 +32,6 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> -#include <pipewire/private.h> #include "module-netjack2/packets.h" @@ -224,7 +223,7 @@ struct impl { struct pw_context *context; struct pw_loop *main_loop; - struct pw_data_loop *data_loop; + struct pw_loop *data_loop; struct spa_system *system; #define MODE_SINK (1<<0) @@ -340,7 +339,7 @@ netjack2_send_data(&follower->peer, nframes, midi, n_midi, audio, n_audio); if (follower->socket) - pw_loop_update_io(s->impl->data_loop->loop, follower->socket, SPA_IO_IN); + pw_loop_update_io(s->impl->data_loop, follower->socket, SPA_IO_IN); } static void source_process(void *d, struct spa_io_position *position) @@ -373,7 +372,7 @@ pw_properties_free(follower->sink.props); if (follower->socket) - pw_loop_destroy_source(impl->data_loop->loop, follower->socket); + pw_loop_destroy_source(impl->data_loop, follower->socket); if (follower->setup_socket) pw_loop_destroy_source(impl->main_loop, follower->setup_socket); @@ -460,13 +459,13 @@ if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { pw_log_warn("error:%08x", mask); - pw_loop_destroy_source(impl->data_loop->loop, follower->socket); + pw_loop_destroy_source(impl->data_loop, follower->socket); follower->socket = NULL; pw_loop_invoke(impl->main_loop, do_stop_follower, 1, NULL, 0, false, follower); return; } if (mask & SPA_IO_IN) { - pw_loop_update_io(impl->data_loop->loop, follower->socket, 0); + pw_loop_update_io(impl->data_loop, follower->socket, 0); pw_filter_trigger_process(follower->source.filter); } @@ -730,21 +729,6 @@ return res; } - -static int -do_schedule_destroy(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct impl *impl = user_data; - pw_impl_module_schedule_destroy(impl->module); - return 0; -} - -void module_schedule_destroy(struct impl *impl) -{ - pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl); -} - static int parse_address(const char *address, uint16_t port, struct sockaddr_storage *addr, socklen_t *len) { @@ -1015,7 +999,7 @@ goto socket_failed; } - follower->socket = pw_loop_add_io(impl->data_loop->loop, fd, + follower->socket = pw_loop_add_io(impl->data_loop, fd, 0, false, on_data_io, follower); if (follower->socket == NULL) { res = -errno; @@ -1269,6 +1253,7 @@ { struct pw_context *context = pw_impl_module_get_context(module); struct pw_properties *props = NULL; + struct pw_data_loop *data_loop; struct impl *impl; const char *str; int res; @@ -1292,7 +1277,8 @@ goto error; } impl->props = props; - impl->data_loop = pw_context_get_data_loop(context); + data_loop = pw_context_get_data_loop(context); + impl->data_loop = pw_data_loop_get_loop(data_loop); impl->sink_props = pw_properties_new(NULL, NULL); impl->source_props = pw_properties_new(NULL, NULL);
View file
pipewire-0.3.72.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.74.tar.gz/src/modules/module-profiler.c
Changed
@@ -12,6 +12,7 @@ #include "config.h" +#include <spa/pod/builder.h> #include <spa/utils/result.h> #include <spa/utils/ringbuffer.h> #include <spa/param/profiler.h> @@ -74,6 +75,7 @@ struct pw_context *context; struct pw_properties *properties; + struct pw_loop *main_loop; struct pw_loop *data_loop; struct spa_hook context_listener; @@ -111,7 +113,7 @@ value.tv_nsec = 1; interval.tv_sec = DEFAULT_INTERVAL; interval.tv_nsec = 0; - pw_loop_update_timer(impl->context->main_loop, + pw_loop_update_timer(impl->main_loop, impl->flush_timeout, &value, &interval, false); impl->flushing = true; } @@ -127,7 +129,7 @@ value.tv_nsec = 0; interval.tv_sec = 0; interval.tv_nsec = 0; - pw_loop_update_timer(impl->context->main_loop, + pw_loop_update_timer(impl->main_loop, impl->flush_timeout, &value, &interval, false); impl->flushing = false; } @@ -348,7 +350,7 @@ pw_properties_free(impl->properties); - pw_loop_destroy_source(pw_context_get_main_loop(impl->context), impl->flush_timeout); + pw_loop_destroy_source(impl->main_loop, impl->flush_timeout); free(impl); } @@ -380,7 +382,6 @@ struct pw_context *context = pw_impl_module_get_context(module); struct pw_properties *props; struct impl *impl; - struct pw_loop *main_loop = pw_context_get_main_loop(context); static const char * const keys = { PW_KEY_OBJECT_SERIAL, NULL @@ -403,7 +404,8 @@ impl->context = context; impl->properties = props; - impl->data_loop = pw_context_get_data_loop(impl->context)->loop; + impl->main_loop = pw_context_get_main_loop(impl->context); + impl->data_loop = pw_data_loop_get_loop(pw_context_get_data_loop(impl->context)); spa_ringbuffer_init(&impl->buffer); @@ -416,11 +418,11 @@ free(impl); return -errno; } - pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", impl->global->id); + pw_properties_setf(impl->properties, PW_KEY_OBJECT_ID, "%d", pw_global_get_id(impl->global)); pw_properties_setf(impl->properties, PW_KEY_OBJECT_SERIAL, "%"PRIu64, pw_global_get_serial(impl->global)); - impl->flush_timeout = pw_loop_add_timer(main_loop, flush_timeout, impl); + impl->flush_timeout = pw_loop_add_timer(impl->main_loop, flush_timeout, impl); pw_global_update_keys(impl->global, &impl->properties->dict, keys);
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -23,6 +23,8 @@ #endif #include <spa/pod/iter.h> +#include <spa/pod/parser.h> +#include <spa/pod/builder.h> #include <spa/utils/result.h> #include <spa/utils/string.h> @@ -1465,6 +1467,7 @@ { struct pw_context *context = pw_impl_module_get_context(module); struct pw_protocol *this; + struct pw_impl_core *core = context->core; struct protocol_data *d; const struct pw_properties *props; int res; @@ -1472,8 +1475,10 @@ PW_LOG_TOPIC_INIT(mod_topic); PW_LOG_TOPIC_INIT(mod_topic_connection); - if (pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native) != NULL) - return 0; + if (pw_context_find_protocol(context, PW_TYPE_INFO_PROTOCOL_Native) != NULL) { + pw_log_error("protocol %s is already loaded", PW_TYPE_INFO_PROTOCOL_Native); + return -EEXIST; + } this = pw_protocol_new(context, PW_TYPE_INFO_PROTOCOL_Native, sizeof(struct protocol_data)); if (this == NULL) @@ -1494,10 +1499,10 @@ d->module = module; props = pw_context_get_properties(context); - d->local = create_server(this, context->core, &props->dict); + d->local = create_server(this, core, &props->dict); if (need_server(context, &props->dict)) { - if (impl_add_server(this, context->core, &props->dict) == NULL) { + if (impl_add_server(this, core, &props->dict) == NULL) { res = -errno; goto error_cleanup; }
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/defs.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/defs.h
Changed
@@ -27,3 +27,9 @@ return NULL; return pod; } + +struct protocol_compat_v2 { + /* v2 typemap */ + struct pw_map types; + unsigned int send_types:1; +};
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/protocol-footer.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/protocol-footer.c
Changed
@@ -89,7 +89,7 @@ end_footer(&fb); } -int demarshal_core_generation(void *object, struct spa_pod_parser *parser) +static int demarshal_core_generation(void *object, struct spa_pod_parser *parser) { struct pw_core *core = object; int64_t generation; @@ -106,7 +106,7 @@ return 0; } -int demarshal_client_generation(void *object, struct spa_pod_parser *parser) +static int demarshal_client_generation(void *object, struct spa_pod_parser *parser) { struct pw_impl_client *client = object; int64_t generation;
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/v0/protocol-native.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/v0/protocol-native.c
Changed
@@ -22,6 +22,7 @@ #include "interfaces.h" #include "typemap.h" +#include "../defs.h" #include "../connection.h" PW_LOG_TOPIC_EXTERN(mod_topic);
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-native/v0/typemap.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-native/v0/typemap.h
Changed
@@ -1,3 +1,13 @@ +enum spa_node0_event { + SPA_NODE0_EVENT_START = SPA_TYPE_VENDOR_PipeWire, + SPA_NODE0_EVENT_RequestClockUpdate, +}; + +enum spa_node0_command { + SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire, + SPA_NODE0_COMMAND_ClockUpdate, +}; + static const struct type_info { const char *type; const char *name;
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse.c
Changed
@@ -194,6 +194,32 @@ * VMs usually can't support the low latency settings that are possible on real * hardware. * + * ### Quirk options + * + *\code{.unparsed} + * pulse.fix.format = "S16LE" + *\endcode + * + * When a stream uses the FIX_FORMAT flag, fixate the format to this value. + * Normally the format would be fixed to the sink/source that the stream connects + * to. When an invalid format (null or "") is set, the FIX_FORMAT flag is ignored. + * + *\code{.unparsed} + * pulse.fix.rate = 48000 + *\endcode + * + * When a stream uses the FIX_RATE flag, fixate the sample rate to this value. + * Normally the rate would be fixed to the sink/source that the stream connects + * to. When a 0 rate is set, the FIX_RATE flag is ignored. + * + *\code{.unparsed} + * pulse.fix.position = " FL FR " + *\endcode + * + * When a stream uses the FIX_CHANNELS flag, fixate the channels to this value. + * Normally the channels would be fixed to the sink/source that the stream connects + * to. When an invalid position (null or "") is set, the FIX_CHANNELS flag is ignored. + * * ## Command execution * * As part of the server startup sequence, a set of commands can be executed.
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/cmd.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/cmd.c
Changed
@@ -4,6 +4,7 @@ #include <spa/utils/json.h> +#include <pipewire/cleanup.h> #include <pipewire/utils.h> #include "module.h" @@ -68,15 +69,14 @@ { struct impl *impl = user_data; struct spa_json it3; - char key512, *s; + char key512; int res = 0; - s = strndup(str, len); + spa_autofree char *s = strndup(str, len); spa_json_init(&it0, s, len); if (spa_json_enter_array(&it0, &it1) < 0) { pw_log_error("config file error: pulse.cmd is not an array"); - res = -EINVAL; - goto exit; + return -EINVAL; } while (spa_json_enter_object(&it1, &it2) > 0) { @@ -107,8 +107,7 @@ if (res < 0) break; } -exit: - free(s); + return res; }
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c
Changed
@@ -10,10 +10,14 @@ #include <stdlib.h> #include <string.h> +#include <spa/pod/builder.h> #include <spa/utils/defs.h> #include <spa/utils/dict.h> #include <spa/utils/string.h> #include <spa/utils/json.h> +#include <spa/param/audio/format.h> +#include <spa/param/props.h> + #include <pipewire/log.h> #include <pipewire/properties.h>
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/format.c
Changed
@@ -243,24 +243,34 @@ { const char *str; if (fix_ss->format != 0) { - if ((str = spa_dict_lookup(props, "pulse.fix.format")) != NULL) - ss->format = format_name2id(str); + if ((str = spa_dict_lookup(props, "pulse.fix.format")) != NULL) { + uint32_t val = format_name2id(str); + if (val != SPA_AUDIO_FORMAT_UNKNOWN) + ss->format = val; + } else ss->format = fix_ss->format; /* convert back and forth to convert potential planar to packed */ ss->format = format_pa2id(format_id2pa(ss->format)); } if (fix_ss->rate != 0) { - if ((str = spa_dict_lookup(props, "pulse.fix.rate")) != NULL) - ss->rate = atoi(str); + if ((str = spa_dict_lookup(props, "pulse.fix.rate")) != NULL) { + uint32_t val = atoi(str); + if (val != 0) + ss->rate = val; + } else ss->rate = fix_ss->rate; ss->rate = SPA_CLAMP(ss->rate, 0u, RATE_MAX); } if (fix_ss->channels != 0) { if ((str = spa_dict_lookup(props, "pulse.fix.position")) != NULL) { - channel_map_parse_position(str, map); - ss->channels = map->channels; + struct channel_map val; + channel_map_parse_position(str, &val); + if (val.channels > 0) { + ss->channels = val.channels; + *map = val; + } } else { ss->channels = fix_ss->channels; *map = *fix_map; @@ -519,6 +529,8 @@ if (ss != NULL) *ss = *def_ss; } else { + if (info.info.raw.rate == 0) + info.info.raw.rate = 48000; if (info.info.raw.format == 0 || info.info.raw.rate == 0 || info.info.raw.channels == 0 ||
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/format.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/format.h
Changed
@@ -214,8 +214,6 @@ const struct spa_pod *format_info_build_param(struct spa_pod_builder *b, uint32_t id, const struct format_info *info, uint32_t *rate); -int format_info_from_spec(struct format_info *info, const struct sample_spec *ss, - const struct channel_map *map); int format_info_to_spec(const struct format_info *info, struct sample_spec *ss, struct channel_map *map);
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/internal.h -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/internal.h
Changed
@@ -10,10 +10,11 @@ #include <stdbool.h> #include <stdint.h> +#include <spa/utils/result.h> #include <spa/utils/defs.h> +#include <spa/utils/ratelimit.h> #include <spa/utils/ringbuffer.h> -#include <pipewire/map.h> -#include <pipewire/private.h> +#include <pipewire/impl.h> #include "format.h" #include "server.h" @@ -52,7 +53,7 @@ struct pw_properties *props; void *dbus_name; - struct ratelimit rate_limit; + struct spa_ratelimit rate_limit; struct spa_hook_list hooks; struct spa_list servers;
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
@@ -11,6 +11,7 @@ #include <spa/utils/list.h> #include <spa/utils/hook.h> #include <spa/utils/string.h> +#include <pipewire/cleanup.h> #include <pipewire/log.h> #include <pipewire/map.h> #include <pipewire/properties.h> @@ -117,7 +118,8 @@ /** utils */ void module_args_add_props(struct pw_properties *props, const char *str) { - char *s = strdup(str), *p = s, *e, f; + spa_autofree char *s = strdup(str); + char *p = s, *e, f; const char *k, *v; const struct str_map *map; @@ -160,7 +162,6 @@ } pw_properties_set(props, k, v); } - free(s); } int module_args_to_audioinfo_keys(struct impl *impl, struct pw_properties *props,
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
@@ -56,8 +56,6 @@ struct spa_source *sinks_timeout; - struct spa_audio_info_raw info; - unsigned int sinks_pending; unsigned int load_emitted:1; unsigned int start_error:1; @@ -304,7 +302,6 @@ audioinfo_to_properties(&info, global_props); d->module = module; - d->info = info; d->sink_names = sink_names; d->sinks_pending = (sink_names == NULL) ? 0 : num_sinks; d->stream_props = stream_props;
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c
Changed
@@ -19,6 +19,8 @@ struct spa_hook mod_listener; struct pw_impl_module *mod; + + uint32_t latency_msec; }; static void module_destroy(void *data) @@ -37,10 +39,25 @@ static int module_raop_discover_load(struct module *module) { struct module_raop_discover_data *data = module->user_data; + FILE *f; + char *args; + size_t size; + + if ((f = open_memstream(&args, &size)) == NULL) + return -errno; + + fprintf(f, "{"); + if (data->latency_msec > 0) + fprintf(f, " raop.latency.ms = %u ", data->latency_msec); + fprintf(f, "}"); + fclose(f); data->mod = pw_context_load_module(module->impl->context, "libpipewire-module-raop-discover", - NULL, NULL); + args, NULL); + + free(args); + if (data->mod == NULL) return -errno; @@ -75,9 +92,12 @@ { PW_LOG_TOPIC_INIT(mod_topic); + struct pw_properties * const props = module->props; struct module_raop_discover_data * const data = module->user_data; data->module = module; + pw_properties_fetch_uint32(props, "latency_msec", &data->latency_msec); + return 0; }
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -28,6 +28,7 @@ #include <spa/utils/ringbuffer.h> #include <spa/utils/json.h> +#include <pipewire/cleanup.h> #include <pipewire/pipewire.h> #include <pipewire/extensions/metadata.h> @@ -1564,7 +1565,7 @@ int res; struct sample_spec ss, fix_ss; struct channel_map map, fix_map; - uint32_t sink_index, syncid, rate = 0; + uint32_t sink_index, syncid, ss_rate = 0, rate = 0; const char *sink_name; struct buffer_attr attr = { 0 }; bool corked = false, @@ -1712,7 +1713,7 @@ n_params++; n_valid_formats++; if (r > rate) - rate = r; + ss_rate = rate = r; } else { log_format_info(impl, SPA_LOG_LEVEL_WARN, &format); } @@ -1724,9 +1725,9 @@ struct sample_spec sfix = ss; struct channel_map mfix = map; - rate = ss.rate; - + ss_rate = ss.rate; sample_spec_fix(&sfix, &mfix, &fix_ss, &fix_map, &props->dict); + rate = sfix.rate; if (n_params < MAX_FORMATS && (paramsn_params = format_build_param(&b, @@ -1736,8 +1737,8 @@ n_valid_formats++; } else { pw_log_warn("%p: unsupported format:%s rate:%d channels:%u", - impl, format_id2name(ss.format), ss.rate, - ss.channels); + impl, format_id2name(sfix.format), sfix.rate, + sfix.channels); } } @@ -1763,7 +1764,7 @@ if (rate != 0) { struct spa_fraction lat; - fix_playback_buffer_attr(stream, &attr, rate, &lat); + fix_playback_buffer_attr(stream, &attr, ss_rate, &lat); pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate); pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", lat.num, lat.denom); @@ -1860,7 +1861,7 @@ struct pw_properties *props = NULL; uint8_t n_formats = 0; struct stream *stream = NULL; - uint32_t n_params = 0, n_valid_formats = 0, flags, id, rate = 0; + uint32_t n_params = 0, n_valid_formats = 0, flags, id, ss_rate = 0, rate = 0; const struct spa_pod *paramsMAX_FORMATS; uint8_t buffer4096; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); @@ -1966,7 +1967,7 @@ n_params++; n_valid_formats++; if (r > rate) - rate = r; + ss_rate = rate = r; } else { log_format_info(impl, SPA_LOG_LEVEL_WARN, &format); } @@ -1989,9 +1990,9 @@ struct sample_spec sfix = ss; struct channel_map mfix = map; - rate = ss.rate; - + ss_rate = ss.rate; sample_spec_fix(&sfix, &mfix, &fix_ss, &fix_map, &props->dict); + rate = sfix.rate; if (n_params < MAX_FORMATS && (paramsn_params = format_build_param(&b, @@ -2001,8 +2002,8 @@ n_valid_formats++; } else { pw_log_warn("%p: unsupported format:%s rate:%d channels:%u", - impl, format_id2name(ss.format), ss.rate, - ss.channels); + impl, format_id2name(sfix.format), sfix.rate, + sfix.channels); } } if (m->offset != m->length) @@ -2028,7 +2029,7 @@ if (rate != 0) { struct spa_fraction lat; - fix_record_buffer_attr(stream, &attr, rate, &lat); + fix_record_buffer_attr(stream, &attr, ss_rate, &lat); pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate); pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", lat.num, lat.denom); @@ -2516,12 +2517,12 @@ uint32_t sink_index, volume; struct sample *sample; const char *sink_name, *name; - struct pw_properties *props = NULL; + spa_autoptr(pw_properties) props = NULL; struct pw_manager_object *o; int res; if ((props = pw_properties_new(NULL, NULL)) == NULL) - goto error_errno; + return -errno; if ((res = message_get(m, TAG_U32, &sink_index, @@ -2529,13 +2530,13 @@ TAG_U32, &volume, TAG_STRING, &name, TAG_INVALID)) < 0) - goto error_proto; + return -EPROTO; if (client->version >= 13) { if ((res = message_get(m, TAG_PROPLIST, props, TAG_INVALID)) < 0) - goto error_proto; + return -EPROTO; } pw_log_info("%s %s tag:%u sink_index:%u sink_name:%s name:%s", @@ -2545,35 +2546,19 @@ pw_properties_update(props, &client->props->dict); if (sink_index != SPA_ID_INVALID && sink_name != NULL) - goto error_inval; + return -EINVAL; o = find_device(client, sink_index, sink_name, PW_DIRECTION_OUTPUT, NULL); if (o == NULL) - goto error_noent; + return -ENOENT; sample = find_sample(impl, SPA_ID_INVALID, name); if (sample == NULL) - goto error_noent; + return -ENOENT; pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%"PRIu64, o->serial); - return pending_sample_new(client, sample, props, tag); - -error_errno: - res = -errno; - goto error; -error_proto: - res = -EPROTO; - goto error; -error_inval: - res = -EINVAL; - goto error; -error_noent: - res = -ENOENT; - goto error; -error: - pw_properties_free(props); - return res; + return pending_sample_new(client, sample, spa_steal_ptr(props), tag); } static int do_remove_sample(struct client *client, uint32_t command, uint32_t tag, struct message *m) @@ -3184,11 +3169,8 @@ static int do_update_proplist(struct client *client, uint32_t command, uint32_t tag, struct message *m) { uint32_t channel, mode; - struct stream *stream; - struct pw_properties *props; - int res; - props = pw_properties_new(NULL, NULL); + spa_autoptr(pw_properties) props = pw_properties_new(NULL, NULL); if (props == NULL) return -errno; @@ -3196,7 +3178,7 @@ if (message_get(m, TAG_U32, &channel, TAG_INVALID) < 0) - goto error_protocol; + return -EPROTO; } else { channel = SPA_ID_INVALID; } @@ -3208,12 +3190,12 @@ TAG_U32, &mode, TAG_PROPLIST, props, TAG_INVALID) < 0) - goto error_protocol; + return -EPROTO; if (command != COMMAND_UPDATE_CLIENT_PROPLIST) { - stream = pw_map_lookup(&client->streams, channel); + struct stream *stream = pw_map_lookup(&client->streams, channel); if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD) - goto error_noentity; + return -ENOENT; pw_stream_update_properties(stream->stream, &props->dict); } else { @@ -3223,29 +3205,17 @@ pw_core_update_properties(client->core, &client->props->dict); } } - res = reply_simple_ack(client, tag); -exit: - pw_properties_free(props); - return res; -error_protocol: - res = -EPROTO; - goto exit; -error_noentity: - res = -ENOENT; - goto exit; + return reply_simple_ack(client, tag); } static int do_remove_proplist(struct client *client, uint32_t command, uint32_t tag, struct message *m) { uint32_t i, channel; - struct stream *stream; - struct pw_properties *props; struct spa_dict dict; struct spa_dict_item *items; - int res; - props = pw_properties_new(NULL, NULL); + spa_autoptr(pw_properties) props = pw_properties_new(NULL, NULL); if (props == NULL) return -errno; @@ -3253,7 +3223,7 @@ if (message_get(m, TAG_U32, &channel, TAG_INVALID) < 0) - goto error_protocol; + return -EPROTO; } else { channel = SPA_ID_INVALID; } @@ -3267,7 +3237,7 @@ if (message_get(m, TAG_STRING, &key, TAG_INVALID) < 0) - goto error_protocol; + return -EPROTO; if (key == NULL) break; pw_properties_set(props, key, key); @@ -3280,26 +3250,17 @@ itemsi.value = NULL; } - if (command != COMMAND_UPDATE_CLIENT_PROPLIST) { - stream = pw_map_lookup(&client->streams, channel); + if (command != COMMAND_REMOVE_CLIENT_PROPLIST) { + struct stream *stream = pw_map_lookup(&client->streams, channel); if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD) - goto error_noentity; + return -ENOENT; pw_stream_update_properties(stream->stream, &dict); } else { pw_core_update_properties(client->core, &dict); } - res = reply_simple_ack(client, tag); -exit: - pw_properties_free(props); - return res; -error_protocol: - res = -EPROTO; - goto exit; -error_noentity: - res = -ENOENT; - goto exit; + return reply_simple_ack(client, tag); } @@ -3529,10 +3490,11 @@ { struct pw_manager *manager = client->manager; struct pw_device_info *info = o->info; - const char *str, *drv_name; + const char *str, *drv_name, *card_name; uint32_t module_id = SPA_ID_INVALID, n_profiles, n; struct card_info card_info = CARD_INFO_INIT; struct profile_info *profile_info; + char name128; if (!pw_manager_object_is_card(o) || info == NULL || info->props == NULL) return -ENOENT; @@ -3544,9 +3506,17 @@ if (drv_name && spa_streq("bluez5", drv_name)) drv_name = "module-bluez5-device.c"; /* blueman needs this */ + card_name = spa_dict_lookup(info->props, PW_KEY_DEVICE_NAME); + if (card_name == NULL) + card_name = spa_dict_lookup(info->props, "api.alsa.card.name"); + if (card_name == NULL) { + snprintf(name, sizeof(name), "card_%u", o->index); + card_name = name; + } + message_put(m, TAG_U32, o->index, /* card index */ - TAG_STRING, spa_dict_lookup(info->props, PW_KEY_DEVICE_NAME), + TAG_STRING, card_name, TAG_U32, id_to_index(manager, module_id), TAG_STRING, drv_name, TAG_INVALID); @@ -3663,7 +3633,7 @@ const struct pw_manager_object *card) { struct pw_device_info *card_info = card ? card->info : NULL; - struct pw_properties *props = NULL; + spa_autoptr(pw_properties) props = NULL; if (card_info && card_info->props) { props = pw_properties_new_dict(sink_props); @@ -3673,9 +3643,8 @@ pw_properties_add(props, card_info->props); sink_props = &props->dict; } - message_put(m, TAG_PROPLIST, sink_props, TAG_INVALID); - pw_properties_free(props); + message_put(m, TAG_PROPLIST, sink_props, TAG_INVALID); return 0; } @@ -3873,7 +3842,7 @@ const struct pw_manager_object *card, const bool is_monitor) { struct pw_device_info *card_info = card ? card->info : NULL; - struct pw_properties *props = NULL; + spa_autoptr(pw_properties) props = NULL; if ((card_info && card_info->props) || is_monitor) { props = pw_properties_new_dict(source_props); @@ -3888,9 +3857,8 @@ source_props = &props->dict; } - message_put(m, TAG_PROPLIST, source_props, TAG_INVALID); - pw_properties_free(props); + message_put(m, TAG_PROPLIST, source_props, TAG_INVALID); return 0; } @@ -5131,12 +5099,9 @@ const char *object_path = NULL; const char *message = NULL; const char *params = NULL; - char *response = NULL; - char *path = NULL; struct message *reply; struct pw_manager_object *o; int len = 0; - int res; if (message_get(m, TAG_STRING, &object_path, @@ -5155,11 +5120,13 @@ len = strlen(object_path); if (len > 0 && object_pathlen - 1 == '/') --len; - path = strndup(object_path, len); + + spa_autofree char *path = strndup(object_path, len); if (path == NULL) return -ENOMEM; - res = -ENOENT; + spa_autofree char *response = NULL; + int res = -ENOENT; spa_list_for_each(o, &manager->object_list, link) { if (o->message_object_path && spa_streq(o->message_object_path, path)) { @@ -5171,7 +5138,6 @@ } } - free(path); if (res < 0) return res; @@ -5179,7 +5145,7 @@ reply = reply_new(client, tag); message_put(reply, TAG_STRING, response, TAG_INVALID); - free(response); + return client_queue_message(client, reply); }
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/reply.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/reply.c
Changed
@@ -12,6 +12,7 @@ #include "commands.h" #include "message.h" #include "log.h" +#include "reply.h" struct message *reply_new(const struct client *client, uint32_t tag) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -28,6 +28,7 @@ #include <spa/utils/defs.h> #include <spa/utils/json.h> #include <spa/utils/result.h> +#include <pipewire/cleanup.h> #include <pipewire/pipewire.h> #include "client.h" @@ -404,7 +405,7 @@ client_access = server->client_access; if (server->addr.ss_family == AF_UNIX) { - char *app_id = NULL, *devices = NULL; + spa_autofree char *app_id = NULL, *devices = NULL; #ifdef SO_PRIORITY val = 6; @@ -443,8 +444,6 @@ else pw_properties_set(client->props, PW_KEY_MEDIA_CATEGORY, NULL); } - free(devices); - free(app_id); } else if (server->addr.ss_family == AF_INET || server->addr.ss_family == AF_INET6) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
@@ -216,10 +216,11 @@ struct client *client = stream->client; struct impl *impl = client->impl; struct message *reply; + int missed; - if (ratelimit_test(&impl->rate_limit, stream->timestamp, SPA_LOG_LEVEL_INFO)) { - pw_log_info("%s: UNDERFLOW channel:%u offset:%" PRIi64, - client->name, stream->channel, offset); + if ((missed = spa_ratelimit_test(&impl->rate_limit, stream->timestamp)) >= 0) { + pw_log_info("%s: UNDERFLOW channel:%u offset:%" PRIi64" (%d missed)", + client->name, stream->channel, offset, missed); } reply = message_alloc(impl, -1, 0);
View file
pipewire-0.3.72.tar.gz/src/modules/module-pulse-tunnel.c -> pipewire-0.3.74.tar.gz/src/modules/module-pulse-tunnel.c
Changed
@@ -21,6 +21,7 @@ #include <spa/utils/json.h> #include <spa/utils/ringbuffer.h> #include <spa/utils/dll.h> +#include <spa/utils/ratelimit.h> #include <spa/debug/types.h> #include <spa/pod/builder.h> #include <spa/param/audio/format-utils.h> @@ -29,7 +30,6 @@ #include <pipewire/impl.h> #include <pipewire/i18n.h> -#include <pipewire/private.h> #include <pulse/pulseaudio.h> #include "module-protocol-pulse/defs.h" @@ -170,7 +170,7 @@ pa_stream *pa_stream; uint32_t pa_index; - struct ratelimit rate_limit; + struct spa_ratelimit rate_limit; uint32_t target_latency; uint32_t current_latency; @@ -506,7 +506,7 @@ return 0; } -void module_schedule_destroy(struct impl *impl) +static void module_schedule_destroy(struct impl *impl) { pw_loop_invoke(impl->main_loop, do_schedule_destroy, 1, NULL, 0, false, impl); } @@ -669,19 +669,22 @@ { struct impl *impl = userdata; struct timespec ts; + int missed; clock_gettime(CLOCK_MONOTONIC, &ts); - if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN)) - pw_log_warn("underflow"); + if ((missed = spa_ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts))) >= 0) + pw_log_warn("underflow (%d missed)", missed); impl->resync = true; } static void stream_overflow_cb(pa_stream *s, void *userdata) { struct impl *impl = userdata; struct timespec ts; + int missed; + clock_gettime(CLOCK_MONOTONIC, &ts); - if (ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts), SPA_LOG_LEVEL_WARN)) - pw_log_warn("overflow"); + if ((missed = spa_ratelimit_test(&impl->rate_limit, SPA_TIMESPEC_TO_NSEC(&ts))) >= 0) + pw_log_warn("overflow (%d missed)", missed); impl->resync = true; }
View file
pipewire-0.3.72.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.74.tar.gz/src/modules/module-raop-discover.c
Changed
@@ -41,6 +41,8 @@ * * Options specific to the behavior of this module * + * - `raop.latency.ms` = latency for all streams in microseconds. This + * can be overwritten in the stream rules. * - `stream.rules` = <rules>: match rules, use create-stream actions. See * \ref page_module_raop_sink for module properties. * @@ -50,6 +52,7 @@ * context.modules = * { name = libpipewire-raop-discover * args = { + * #raop.latency.ms = 1000 * stream.rules = * { matches = * { raop.ip = "~.*" @@ -410,6 +413,9 @@ avahi_free(value); } + if ((str = pw_properties_get(impl->properties, "raop.latency.ms")) != NULL) + pw_properties_set(props, "raop.latency.ms", str); + if ((str = pw_properties_get(impl->properties, "stream.rules")) == NULL) str = DEFAULT_CREATE_RULES; if (str != NULL) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.74.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -39,6 +39,7 @@ #include <spa/param/audio/raw.h> #include <spa/param/latency-utils.h> +#include <pipewire/cleanup.h> #include <pipewire/impl.h> #include <pipewire/i18n.h> @@ -317,7 +318,7 @@ pkt0 |= htonl(0x10000000); pkt1 = htonl(rtptime - latency); transmitted = ntp_now(); - pkt2 = htonl(transmitted >> 32); + pkt2 = htonl((transmitted >> 32) & 0x0000ffff); pkt3 = htonl(transmitted & 0xffffffff); pkt4 = htonl(rtptime); @@ -972,6 +973,7 @@ size_t len; uint64_t ntp; uint16_t control_port, timing_port; + int res; pw_log_info("reply %d", status); @@ -1003,9 +1005,9 @@ return 0; } - if (pw_getrandom(&impl->seq, sizeof(impl->seq), 0) < 0 || - pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0) < 0) { - pw_log_error("error generating random seq and rtptime: %m"); + if ((res = pw_getrandom(&impl->seq, sizeof(impl->seq), 0)) < 0 || + (res = pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0)) < 0) { + pw_log_error("error generating random seq and rtptime: %s", spa_strerror(res)); return 0; } @@ -1210,7 +1212,7 @@ char key512*2; char iv16*2; int res, frames, rsa_len, ip_version; - char *sdp; + spa_autofree char *sdp = NULL; char local_ip256; host = pw_properties_get(impl->props, "raop.ip"); @@ -1258,9 +1260,9 @@ break; case CRYPTO_RSA: - if (pw_getrandom(impl->key, sizeof(impl->key), 0) < 0 || - pw_getrandom(impl->iv, sizeof(impl->iv), 0) < 0) - return -errno; + if ((res = pw_getrandom(impl->key, sizeof(impl->key), 0)) < 0 || + (res = pw_getrandom(impl->iv, sizeof(impl->iv), 0)) < 0) + return res; rsa_len = rsa_encrypt(impl->key, 16, rsakey); if (rsa_len < 0) @@ -1288,10 +1290,8 @@ default: return -ENOTSUP; } - res = rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply); - free(sdp); - return res; + return rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply); } static int rtsp_auth_setup_reply(void *data, int status, const struct spa_dict *headers) @@ -1354,7 +1354,6 @@ static int rtsp_do_auth(struct impl *impl, const struct spa_dict *headers) { const char *str, *realm, *nonce; - char **tokens; int n_tokens; if ((str = spa_dict_lookup(headers, "WWW-Authenticate")) == NULL) @@ -1367,9 +1366,9 @@ pw_log_info("Auth: %s", str); - tokens = pw_split_strv(str, " ", INT_MAX, &n_tokens); + spa_auto(pw_strv) tokens = pw_split_strv(str, " ", INT_MAX, &n_tokens); if (tokens == NULL || tokens0 == NULL) - goto error; + return -EINVAL; impl->auth_method = strdup(tokens0); @@ -1377,20 +1376,13 @@ realm = find_attr(tokens, "realm"); nonce = find_attr(tokens, "nonce"); if (realm == NULL || nonce == NULL) - goto error; + return -EINVAL; impl->realm = strdup(realm); impl->nonce = strdup(nonce); } - pw_free_strv(tokens); - - rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply); - return 0; - -error: - pw_free_strv(tokens); - return -EINVAL; + return rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply); } static int rtsp_options_reply(void *data, int status, const struct spa_dict *headers) @@ -1420,14 +1412,15 @@ uint32_t sci2; uint8_t rac16; char sac16*4; + int res; pw_log_info("connected"); impl->connected = true; - if (pw_getrandom(sci, sizeof(sci), 0) < 0 || - pw_getrandom(rac, sizeof(rac), 0) < 0) { - pw_log_error("error generating random data: %m"); + if ((res = pw_getrandom(sci, sizeof(sci), 0)) < 0 || + (res = pw_getrandom(rac, sizeof(rac), 0)) < 0) { + pw_log_error("error generating random data: %s", spa_strerror(res)); return; } @@ -1533,6 +1526,7 @@ { const char *hostname, *port; uint32_t session_id; + int res; if (impl->connected) { if (!impl->ready) @@ -1545,8 +1539,8 @@ if (hostname == NULL || port == NULL) return -EINVAL; - if (pw_getrandom(&session_id, sizeof(session_id), 0) < 0) - return -errno; + if ((res = pw_getrandom(&session_id, sizeof(session_id), 0)) < 0) + return res; spa_scnprintf(impl->session_id, sizeof(impl->session_id), "%u", session_id);
View file
pipewire-0.3.72.tar.gz/src/modules/module-rt.c -> pipewire-0.3.74.tar.gz/src/modules/module-rt.c
Changed
@@ -63,7 +63,8 @@ * This requires `RLIMIT_RTPRIO` to be set to a value that's equal to this * module's `rt.prio` parameter or higher. Most distros will come with some * package that configures this for certain groups or users. If this is not set - * up and DBus is available, then this module will fall back to using RTKit. + * up and DBus is available, then this module will fall back to using the Portal + * Realtime DBus API or RTKit. * * ## Module Options * @@ -75,6 +76,9 @@ * consume without doing any blocking calls before the kernel kills * the thread. This is a safety measure to avoid lockups of the complete * system when some thread consumes 100%. + * - `rlimits.enabled`: enable the use of rtlimits, default true. + * - `rtportal.enabled`: enable the use of realtime portal, default true + * - `rtkit.enabled`: enable the use of rtkit, default true * The nice level is by default set to an invalid value so that clients don't * automatically have the nice level raised. @@ -91,6 +95,9 @@ * #rt.prio = 88 * #rt.time.soft = -1 * #rt.time.hard = -1 + * #rlimits.enabled = true + * #rtportal.enabled = true + * #rtkit.enabled = true * } * flags = ifexists nofail * } @@ -115,7 +122,7 @@ #define MAX_NICE_LEVEL 19 #define IS_VALID_NICE_LEVEL(l) ((l)>=MIN_NICE_LEVEL && (l)<=MAX_NICE_LEVEL) -#define DEFAULT_NICE_LEVEL 20 +#define DEFAULT_NICE_LEVEL 20 /* invalid value by default, see above */ #define DEFAULT_RT_PRIO_MIN 11 #define DEFAULT_RT_PRIO 88 #define DEFAULT_RT_TIME_SOFT -1 @@ -123,8 +130,11 @@ #define MODULE_USAGE "( nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL)"(don't change)> ) " \ "( rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO)"> ) " \ - "( rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)" ) " \ - "( rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)" ) " + "( rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"> ) " \ + "( rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"> ) " \ + "( rlimits.enabled=<default true> ) " \ + "( rtportal.enabled=<default true> ) " \ + "( rtkit.enabled=<default true> ) " static const struct spa_dict_item module_props = { { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, @@ -170,6 +180,10 @@ struct spa_hook module_listener; + unsigned rlimits_enabled:1; + unsigned rtportal_enabled:1; + unsigned rtkit_enabled:1; + #ifdef HAVE_DBUS bool use_rtkit; /* For D-Bus. These are const static. */ @@ -207,7 +221,7 @@ } #ifdef HAVE_DBUS -struct pw_rtkit_bus *pw_rtkit_bus_get(DBusBusType bus_type) +static struct pw_rtkit_bus *pw_rtkit_bus_get(DBusBusType bus_type) { struct pw_rtkit_bus *bus; DBusError error; @@ -240,17 +254,17 @@ return NULL; } -struct pw_rtkit_bus *pw_rtkit_bus_get_system(void) +static struct pw_rtkit_bus *pw_rtkit_bus_get_system(void) { return pw_rtkit_bus_get(DBUS_BUS_SYSTEM); } -struct pw_rtkit_bus *pw_rtkit_bus_get_session(void) +static struct pw_rtkit_bus *pw_rtkit_bus_get_session(void) { return pw_rtkit_bus_get(DBUS_BUS_SESSION); } -bool pw_rtkit_check_xdg_portal(struct pw_rtkit_bus *system_bus) +static bool pw_rtkit_check_xdg_portal(struct pw_rtkit_bus *system_bus) { if (!dbus_bus_name_has_owner(system_bus->bus, XDG_PORTAL_SERVICE_NAME, NULL)) { pw_log_info("Can't find %s. Is xdg-desktop-portal running?", XDG_PORTAL_SERVICE_NAME); @@ -260,7 +274,7 @@ return true; } -void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus) +static void pw_rtkit_bus_free(struct pw_rtkit_bus *system_bus) { dbus_connection_close(system_bus->bus); dbus_connection_unref(system_bus->bus); @@ -369,7 +383,7 @@ return ret; } -int pw_rtkit_get_max_realtime_priority(struct impl *impl) +static int pw_rtkit_get_max_realtime_priority(struct impl *impl) { long long retval; int err; @@ -378,7 +392,7 @@ return err < 0 ? err : retval; } -int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level) +static int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level) { long long retval; int err; @@ -389,7 +403,7 @@ return err; } -long long pw_rtkit_get_rttime_usec_max(struct impl *impl) +static long long pw_rtkit_get_rttime_usec_max(struct impl *impl) { long long retval; int err; @@ -398,7 +412,7 @@ return err < 0 ? err : retval; } -int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority) +static int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority) { DBusMessage *m = NULL, *r = NULL; dbus_uint64_t pid; @@ -458,7 +472,7 @@ return ret; } -int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level) +static int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level) { DBusMessage *m = NULL, *r = NULL; dbus_uint64_t pid; @@ -568,6 +582,9 @@ struct sched_param new_sched_params; int try = 0; + if (!impl->rlimits_enabled) + return false; + while (try++ < 2) { /* We could check `RLIMIT_RTPRIO`, but the BSDs generally don't have * that available, and there are also other ways to use realtime @@ -643,10 +660,15 @@ } res = pw_rtkit_make_high_priority(impl, 0, nice_level); } - else + else if (impl->rlimits_enabled) res = sched_set_nice(nice_level); + else + res = -ENOTSUP; #else - res = sched_set_nice(nice_level); + if (impl->rlimits_enabled) + res = sched_set_nice(nice_level); + else + res = -ENOTSUP; #endif if (res < 0) { @@ -993,6 +1015,9 @@ impl->rt_prio = pw_properties_get_int32(props, "rt.prio", DEFAULT_RT_PRIO); impl->rt_time_soft = pw_properties_get_int32(props, "rt.time.soft", DEFAULT_RT_TIME_SOFT); impl->rt_time_hard = pw_properties_get_int32(props, "rt.time.hard", DEFAULT_RT_TIME_HARD); + impl->rlimits_enabled = pw_properties_get_bool(props, "rlimits.enabled", true); + impl->rtportal_enabled = pw_properties_get_bool(props, "rtportal.enabled", true); + impl->rtkit_enabled = pw_properties_get_bool(props, "rtkit.enabled", true); bool can_use_rtkit = false, use_rtkit = false; @@ -1031,7 +1056,10 @@ impl->use_rtkit = use_rtkit; if (impl->use_rtkit) { /* Checking xdg-desktop-portal. It works fine in all situations. */ - impl->rtkit_bus = pw_rtkit_bus_get_session(); + if (impl->rtportal_enabled) + impl->rtkit_bus = pw_rtkit_bus_get_session(); + else + pw_log_info("Portal Realtime disabled"); if (impl->rtkit_bus != NULL) { if (pw_rtkit_check_xdg_portal(impl->rtkit_bus)) { impl->service_name = XDG_PORTAL_SERVICE_NAME; @@ -1045,7 +1073,11 @@ } /* Failed to get xdg-desktop-portal, try to use rtkit. */ if (impl->rtkit_bus == NULL) { - impl->rtkit_bus = pw_rtkit_bus_get_system(); + if (impl->rtkit_enabled) + impl->rtkit_bus = pw_rtkit_bus_get_system(); + else + pw_log_info("RTkit disabled"); + if (impl->rtkit_bus != NULL) { impl->service_name = RTKIT_SERVICE_NAME; impl->object_path = RTKIT_OBJECT_PATH;
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp-sap.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp-sap.c
Changed
@@ -28,7 +28,7 @@ #define ifr_ifindex ifr_index #endif -/** \page page_module_rtp_sap PipeWire Module: Announce and create RTP streams +/** \page page_module_rtp_sap PipeWire Module: SAP Announce and create RTP streams * * The `rtp-sap` module announces RTP streams that match the rules with the * announce-stream action. @@ -1489,7 +1489,7 @@ } } } - if ((res = parse_address(str, port, &impl->src_addr, &impl->src_len)) < 0) { + if ((res = parse_address(str, 0, &impl->src_addr, &impl->src_len)) < 0) { pw_log_error("invalid source.ip %s: %s", str, spa_strerror(res)); goto out; }
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp-source.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp-source.c
Changed
@@ -40,13 +40,19 @@ * The `rtp-source` module creates a PipeWire source that receives audio * and midi RTP packets. * + * This module is usually loaded from the \page page_module_rtp_sap so that the + * source.ip and source.port and format parameters matches that of the sender. + * * ## Module Options * * Options specific to the behavior of this module * * - `local.ifname = <str>`: interface name to use + * - `source.ip = <str>`: the source ip address, default 224.0.0.56 + * - `source.port = <int>`: the source port * - `node.always-process = <bool>`: true to receive even when not running * - `sess.latency.msec = <str>`: target network latency in milliseconds, default 100 + * - `sess.ignore-ssrc = <bool>`: ignore SSRC, default false * - `sess.media = <string>`: the media type audio|midi|opus, default audio * - `stream.props = {}`: properties to be passed to the stream * @@ -73,7 +79,10 @@ * { name = libpipewire-module-rtp-source * args = { * #local.ifname = eth0 + * #source.ip = 224.0.0.56 + * #source.port = 0 * sess.latency.msec = 100 + * #sess.ignore-ssrc = false * #node.always-process = false * #sess.media = "audio" * #audio.format = "S16BE" @@ -106,6 +115,7 @@ "( source.ip=<source IP address, default:"DEFAULT_SOURCE_IP"> ) " \ "source.port=<int, source port> " \ "( sess.latency.msec=<target network latency, default "SPA_STRINGIFY(DEFAULT_SESS_LATENCY)"> ) "\ + "( sess.ignore-ssrc=<to ignore SSRC, default false> ) "\ "( sess.media=<string, the media type audio|midi|opus, default audio> ) " \ "( audio.format=<format, default:"DEFAULT_FORMAT"> ) " \ "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ @@ -490,6 +500,7 @@ copy_props(impl, props, "sess.max-ptime"); copy_props(impl, props, "sess.latency.msec"); copy_props(impl, props, "sess.ts-direct"); + copy_props(impl, props, "sess.ignore-ssrc"); str = pw_properties_get(props, "local.ifname"); impl->ifname = str ? strdup(str) : NULL;
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp/audio.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/audio.c
Changed
@@ -117,7 +117,7 @@ if (impl->have_ssrc && impl->ssrc != hdr->ssrc) goto unexpected_ssrc; impl->ssrc = hdr->ssrc; - impl->have_ssrc = true; + impl->have_ssrc = !impl->ignore_ssrc; seq = ntohs(hdr->sequence_number); if (impl->have_seq && impl->seq != seq) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp/midi.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/midi.c
Changed
@@ -293,7 +293,7 @@ if (impl->have_ssrc && impl->ssrc != hdr->ssrc) goto unexpected_ssrc; impl->ssrc = hdr->ssrc; - impl->have_ssrc = true; + impl->have_ssrc = !impl->ignore_ssrc; seq = ntohs(hdr->sequence_number); if (impl->have_seq && impl->seq != seq) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp/opus.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/opus.c
Changed
@@ -124,7 +124,7 @@ if (impl->have_ssrc && impl->ssrc != hdr->ssrc) goto unexpected_ssrc; impl->ssrc = hdr->ssrc; - impl->have_ssrc = true; + impl->have_ssrc = !impl->ignore_ssrc; seq = ntohs(hdr->sequence_number); if (impl->have_seq && impl->seq != seq) {
View file
pipewire-0.3.72.tar.gz/src/modules/module-rtp/stream.c -> pipewire-0.3.74.tar.gz/src/modules/module-rtp/stream.c
Changed
@@ -56,6 +56,7 @@ uint32_t ssrc; uint16_t seq; unsigned have_ssrc:1; + unsigned ignore_ssrc:1; unsigned have_seq:1; uint32_t ts_offset; uint32_t psamples; @@ -363,6 +364,7 @@ if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(props, PW_KEY_NODE_NETWORK, "true"); + impl->ignore_ssrc = pw_properties_get_bool(props, "sess.ignore-ssrc", false); impl->direct_timestamp = pw_properties_get_bool(props, "sess.ts-direct", false); if (direction == PW_DIRECTION_INPUT) {
View file
pipewire-0.3.72.tar.gz/src/modules/spa/module-device.c -> pipewire-0.3.74.tar.gz/src/modules/spa/module-device.c
Changed
@@ -8,6 +8,7 @@ #include <getopt.h> #include <limits.h> +#include <pipewire/cleanup.h> #include <pipewire/impl.h> #include "spa-device.h" @@ -51,12 +52,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) { struct pw_properties *props = NULL; - char **argv = NULL; + spa_auto(pw_strv) argv = NULL; int n_tokens; struct pw_context *context = pw_impl_module_get_context(module); struct pw_impl_device *device; struct device_data *data; - int res; PW_LOG_TOPIC_INIT(mod_topic); @@ -69,10 +69,8 @@ if (n_tokens == 2) { props = pw_properties_new_string(argv1); - if (props == NULL) { - res = -errno; - goto error_exit_cleanup; - } + if (props == NULL) + return -errno; } device = pw_spa_device_load(context, @@ -80,12 +78,8 @@ 0, props, sizeof(struct device_data)); - if (device == NULL) { - res = -errno; - goto error_exit_cleanup; - } - - pw_free_strv(argv); + if (device == NULL) + return -errno; data = pw_spa_device_get_user_data(device); data->this = device; @@ -99,10 +93,6 @@ return 0; error_arguments: - res = -EINVAL; pw_log_error("usage: module-spa-device " MODULE_USAGE); - goto error_exit_cleanup; -error_exit_cleanup: - pw_free_strv(argv); - return res; + return -EINVAL; }
View file
pipewire-0.3.72.tar.gz/src/modules/spa/module-node.c -> pipewire-0.3.74.tar.gz/src/modules/spa/module-node.c
Changed
@@ -10,6 +10,7 @@ #include <getopt.h> #include <limits.h> +#include <pipewire/cleanup.h> #include <pipewire/impl.h> #include "spa-node.h" @@ -52,8 +53,8 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) { struct pw_properties *props = NULL; - char **argv = NULL; - int n_tokens, res; + spa_auto(pw_strv) argv = NULL; + int n_tokens; struct pw_context *context = pw_impl_module_get_context(module); struct pw_impl_node *node; struct node_data *data; @@ -69,10 +70,8 @@ if (n_tokens == 2) { props = pw_properties_new_string(argv1); - if (props == NULL) { - res = -errno; - goto error_exit_cleanup; - } + if (props == NULL) + return -errno; } node = pw_spa_node_load(context, @@ -81,12 +80,8 @@ props, sizeof(struct node_data)); - if (node == NULL) { - res = -errno; - goto error_exit_cleanup; - } - - pw_free_strv(argv); + if (node == NULL) + return -errno; data = pw_spa_node_get_user_data(node); data->this = node; @@ -101,10 +96,6 @@ return 0; error_arguments: - res = -EINVAL; pw_log_error("usage: module-spa-node " MODULE_USAGE); - goto error_exit_cleanup; -error_exit_cleanup: - pw_free_strv(argv); - return res; + return -EINVAL; }
View file
pipewire-0.3.74.tar.gz/src/pipewire/cleanup.h
Added
@@ -0,0 +1,21 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */ +/* SPDX-License-Identifier: MIT */ + +#ifndef PIPEWIRE_CLEANUP_H +#define PIPEWIRE_CLEANUP_H + +#include <spa/utils/cleanup.h> + +#include <pipewire/properties.h> +#include <pipewire/utils.h> + +SPA_DEFINE_AUTOPTR_CLEANUP(pw_properties, struct pw_properties, { + spa_clear_ptr(*thing, pw_properties_free); +}) + +SPA_DEFINE_AUTO_CLEANUP(pw_strv, char **, { + spa_clear_ptr(*thing, pw_free_strv); +}) + +#endif /* PIPEWIRE_CLEANUP_H */
View file
pipewire-0.3.72.tar.gz/src/pipewire/conf.c -> pipewire-0.3.74.tar.gz/src/pipewire/conf.c
Changed
@@ -28,6 +28,7 @@ #include <spa/utils/string.h> #include <spa/utils/json.h> +#include <pipewire/cleanup.h> #include <pipewire/impl.h> #include <pipewire/private.h> @@ -345,7 +346,8 @@ { char pathPATH_MAX; char *tmp_name; - int res, sfd, fd, count = 0; + spa_autoclose int sfd = -1; + int res, fd, count = 0; FILE *f; if ((sfd = open_write_dir(path, sizeof(path), prefix)) < 0) @@ -354,9 +356,9 @@ tmp_name = alloca(strlen(name)+5); sprintf(tmp_name, "%s.tmp", name); if ((fd = openat(sfd, tmp_name, O_CLOEXEC | O_CREAT | O_WRONLY | O_TRUNC, 0600)) < 0) { - pw_log_error("can't open file '%s': %m", tmp_name); res = -errno; - goto error; + pw_log_error("can't open file '%s': %m", tmp_name); + return res; } f = fdopen(fd, "w"); @@ -366,46 +368,43 @@ fclose(f); if (renameat(sfd, tmp_name, sfd, name) < 0) { - pw_log_error("can't rename temp file '%s': %m", tmp_name); res = -errno; - goto error; + pw_log_error("can't rename temp file '%s': %m", tmp_name); + return res; } - res = 0; + pw_log_info("%p: saved state '%s%s'", conf, path, name); -error: - close(sfd); - return res; + + return 0; } static int conf_load(const char *path, struct pw_properties *conf) { char *data; struct stat sbuf; - int fd, count; + int count; - if ((fd = open(path, O_CLOEXEC | O_RDONLY)) < 0) + spa_autoclose int fd = open(path, O_CLOEXEC | O_RDONLY); + if (fd < 0) goto error; if (fstat(fd, &sbuf) < 0) - goto error_close; + goto error; if (sbuf.st_size > 0) { if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED) - goto error_close; + goto error; count = pw_properties_update_string(conf, data, sbuf.st_size); munmap(data, sbuf.st_size); } else { count = 0; } - close(fd); pw_log_info("%p: loaded config '%s' with %d items", conf, path, count); return 0; -error_close: - close(fd); error: pw_log_warn("%p: error loading config '%s': %m", conf, path); return -errno; @@ -455,7 +454,7 @@ char pathPATH_MAX; char fnamePATH_MAX + 256; int i, res, level = 0; - struct pw_properties *override = NULL; + spa_autoptr(pw_properties) override = NULL; const char *dname; if (name == NULL) { @@ -510,7 +509,7 @@ } free(entries); } - pw_properties_free(override); + return 0; } @@ -660,15 +659,14 @@ struct data *d = user_data; struct pw_context *context = d->context; struct spa_json it4; - char key512, *s; + char key512; int res = 0; - s = strndup(str, len); + spa_autofree char *s = strndup(str, len); spa_json_init(&it0, s, len); if (spa_json_enter_array(&it0, &it1) < 0) { pw_log_error("config file error: context.modules is not an array"); - res = -EINVAL; - goto exit; + return -EINVAL; } while (spa_json_enter_object(&it1, &it2) > 0) { @@ -714,8 +712,7 @@ d->count++; } -exit: - free(s); + return res; } @@ -761,15 +758,14 @@ struct data *d = user_data; struct pw_context *context = d->context; struct spa_json it4; - char key512, *s; + char key512; int res = 0; - s = strndup(str, len); + spa_autofree char *s = strndup(str, len); spa_json_init(&it0, s, len); if (spa_json_enter_array(&it0, &it1) < 0) { pw_log_error("config file error: context.objects is not an array"); - res = -EINVAL; - goto exit; + return -EINVAL; } while (spa_json_enter_object(&it1, &it2) > 0) { @@ -815,8 +811,7 @@ break; d->count++; } -exit: - free(s); + return res; } @@ -880,15 +875,14 @@ struct data *d = user_data; struct pw_context *context = d->context; struct spa_json it4; - char key512, *s; + char key512; int res = 0; - s = strndup(str, len); + spa_autofree char *s = strndup(str, len); spa_json_init(&it0, s, len); if (spa_json_enter_array(&it0, &it1) < 0) { pw_log_error("config file error: context.exec is not an array"); - res = -EINVAL; - goto exit; + return -EINVAL; } while (spa_json_enter_object(&it1, &it2) > 0) { @@ -926,8 +920,7 @@ d->count++; } -exit: - free(s); + return res; }
View file
pipewire-0.3.72.tar.gz/src/pipewire/conf.h -> pipewire-0.3.74.tar.gz/src/pipewire/conf.h
Changed
@@ -2,6 +2,9 @@ /* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */ /* SPDX-License-Identifier: MIT */ +#ifndef PIPEWIRE_CONF_H +#define PIPEWIRE_CONF_H + #include <pipewire/context.h> /** \defgroup pw_conf Configuration @@ -40,3 +43,5 @@ /** * \} */ + +#endif /* PIPEWIRE_CONF_H */
View file
pipewire-0.3.72.tar.gz/src/pipewire/context.c -> pipewire-0.3.74.tar.gz/src/pipewire/context.c
Changed
@@ -560,6 +560,12 @@ } SPA_EXPORT +struct pw_mempool *pw_context_get_mempool(struct pw_context *context) +{ + return context->pool; +} + +SPA_EXPORT const struct pw_properties *pw_context_get_properties(struct pw_context *context) { return context->properties; @@ -1155,12 +1161,14 @@ * 8000 and 44100 192000 -> 44100 * 11025 and 44100 48000 -> 44100 * 44100 and 48000 176400 -> 48000 + * 144 and 44100 48000 88200 96000 -> 48000 */ spa_zero(best); /* Don't try to do excessive upsampling by limiting the max rate * for desired < default to default*2. For other rates allow - * a x3 upsample rate max */ - limit = rate < def ? def*2 : rate*3; + * a x3 upsample rate max. For values lower than half of the default, + * limit to the default. */ + limit = rate < def/2 ? def : rate < def ? def*2 : rate*3; for (i = 0; i < n_rates; i++) { if (infoi.rate >= rate && infoi.rate <= limit) update_nearest_gcd(&best, &infoi); @@ -1327,11 +1335,11 @@ if ((t->want_driver && t->active && t->runnable) || t->always_process) { driver = target; - driver->runnable = true; break; } } if (driver != NULL) { + driver->runnable = true; /* driver needed for this group */ move_to_driver(context, &collect, driver); } else {
View file
pipewire-0.3.72.tar.gz/src/pipewire/context.h -> pipewire-0.3.74.tar.gz/src/pipewire/context.h
Changed
@@ -122,6 +122,9 @@ /** Get the work queue from the context: Since 0.3.26 */ struct pw_work_queue *pw_context_get_work_queue(struct pw_context *context); +/** Get the memmory pool from the context: Since 0.3.74 */ +struct pw_mempool *pw_context_get_mempool(struct pw_context *context); + /** Iterate the globals of the context. The callback should return * 0 to fetch the next item, any other value stops the iteration and returns * the value. When all callbacks return 0, this function returns 0 when all
View file
pipewire-0.3.72.tar.gz/src/pipewire/core.c -> pipewire-0.3.74.tar.gz/src/pipewire/core.c
Changed
@@ -24,7 +24,7 @@ { struct pw_core *this = data; pw_log_debug("%p: object %u ping %u", this, id, seq); - pw_core_pong(this->core, id, seq); + pw_core_pong(this, id, seq); } static void core_event_done(void *data, uint32_t id, int seq) @@ -317,11 +317,9 @@ pw_properties_add(properties, &context->properties->dict); - p->proxy.core = p; p->context = context; p->properties = properties; p->pool = pw_mempool_new(NULL); - p->core = p; if (user_data_size > 0) p->user_data = SPA_PTROFF(p, sizeof(struct pw_core), void); p->proxy.user_data = p->user_data; @@ -344,7 +342,7 @@ if (p->conn == NULL) goto error_connection; - if ((res = pw_proxy_init(&p->proxy, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE)) < 0) + if ((res = pw_proxy_init(&p->proxy, p, PW_TYPE_INTERFACE_Core, PW_VERSION_CORE)) < 0) goto error_proxy; p->client = (struct pw_client*)pw_proxy_new(&p->proxy, @@ -478,6 +476,12 @@ SPA_EXPORT int pw_core_disconnect(struct pw_core *core) { + /* + * the `proxy` member must be the first because the whole pw_core object is + * freed via the free() call in pw_proxy_destroy() -> pw_proxy_unref() + */ + SPA_STATIC_ASSERT(offsetof(struct pw_core, proxy) == 0, "`proxy` member must be first"); + pw_log_debug("%p: disconnect", core); if (!core->removed) pw_proxy_remove(&core->proxy);
View file
pipewire-0.3.72.tar.gz/src/pipewire/filter.c -> pipewire-0.3.74.tar.gz/src/pipewire/filter.c
Changed
@@ -18,6 +18,7 @@ #include <spa/pod/dynamic.h> #include <spa/debug/types.h> +#include <pipewire/cleanup.h> #include "pipewire/pipewire.h" #include "pipewire/filter.h" #include "pipewire/private.h" @@ -1632,7 +1633,9 @@ impl->info = SPA_NODE_INFO_INIT(); impl->info.max_input_ports = UINT32_MAX; impl->info.max_output_ports = UINT32_MAX; - impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0; + impl->info.flags = SPA_NODE_FLAG_RT; + if (!impl->process_rt || SPA_FLAG_IS_SET(flags, PW_FILTER_FLAG_ASYNC)) + impl->info.flags |= SPA_NODE_FLAG_ASYNC; impl->info.props = &filter->properties->dict; impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); @@ -1896,8 +1899,8 @@ ensure_loop(impl->main_loop, return -EIO); if (res < 0) { + spa_autofree char *value = NULL; va_list args; - char *value; int r; va_start(args, error); @@ -1909,8 +1912,6 @@ if (filter->proxy) pw_proxy_error(filter->proxy, res, value); filter_set_state(filter, PW_FILTER_STATE_ERROR, res, value); - - free(value); } return res; }
View file
pipewire-0.3.72.tar.gz/src/pipewire/filter.h -> pipewire-0.3.74.tar.gz/src/pipewire/filter.h
Changed
@@ -109,6 +109,13 @@ * needs to be called. This can be used * when the filter depends on processing * of other filters. */ + PW_FILTER_FLAG_ASYNC = (1 << 5), /**< Buffers will not be dequeued/queued from + * the realtime process() function. This is + * assumed when RT_PROCESS is unset but can + * also be the case when the process() function + * does a trigger_process() that will then + * dequeue/queue a buffer from another process() + * function. since 0.3.73 */ }; enum pw_filter_port_flags {
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-client.c
Changed
@@ -572,6 +572,12 @@ } SPA_EXPORT +struct pw_mempool *pw_impl_client_get_mempool(struct pw_impl_client *client) +{ + return client->pool; +} + +SPA_EXPORT const struct pw_properties *pw_impl_client_get_properties(struct pw_impl_client *client) { return client->properties;
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-client.h -> pipewire-0.3.74.tar.gz/src/pipewire/impl-client.h
Changed
@@ -143,6 +143,9 @@ /** Get the global associated with this client */ struct pw_global *pw_impl_client_get_global(struct pw_impl_client *client); +/** Get the mempool associated with this client, Since 0.3.74 */ +struct pw_mempool *pw_impl_client_get_mempool(struct pw_impl_client *client); + /** listen to events from this client */ void pw_impl_client_add_listener(struct pw_impl_client *client, struct spa_hook *listener,
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-metadata.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-metadata.c
Changed
@@ -7,6 +7,7 @@ #include <spa/debug/types.h> #include <spa/utils/string.h> +#include <pipewire/cleanup.h> #include "pipewire/impl.h" #include "pipewire/private.h" @@ -576,32 +577,15 @@ uint32_t subject, const char *key, const char *type, const char *fmt, ...) { + spa_autofree char *value = NULL; va_list args; - int n = 0, res; - size_t size = 0; - char *p = NULL; - - va_start(args, fmt); - n = vsnprintf(p, size, fmt, args); - va_end(args); - if (n < 0) - return -errno; - - size = (size_t) n + 1; - p = malloc(size); - if (p == NULL) - return -errno; + int res; va_start(args, fmt); - n = vsnprintf(p, size, fmt, args); + res = vasprintf(&value, fmt, args); va_end(args); - - if (n < 0) { - free(p); + if (res < 0) return -errno; - } - res = pw_impl_metadata_set_property(metadata, subject, key, type, p); - free(p); - return res; + return pw_impl_metadata_set_property(metadata, subject, key, type, value); }
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-module.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-module.c
Changed
@@ -15,6 +15,7 @@ #include <spa/utils/string.h> +#include <pipewire/cleanup.h> #include "pipewire/impl.h" #include "pipewire/private.h" @@ -38,7 +39,6 @@ char *filename; struct dirent *entry; struct stat s; - DIR *dir; int res; filename = spa_aprintf("%s/%s.so", path, name); @@ -57,7 +57,7 @@ if (level <= 0) return NULL; - dir = opendir(path); + spa_autoptr(DIR) dir = opendir(path); if (dir == NULL) { res = -errno; pw_log_warn("could not open %s: %m", path); @@ -66,27 +66,22 @@ } while ((entry = readdir(dir))) { - char *newpath; - if (spa_streq(entry->d_name, ".") || spa_streq(entry->d_name, "..")) continue; - newpath = spa_aprintf("%s/%s", path, entry->d_name); + spa_autofree char *newpath = spa_aprintf("%s/%s", path, entry->d_name); if (newpath == NULL) break; - if (stat(newpath, &s) == 0 && S_ISDIR(s.st_mode)) + if (entry->d_type == DT_DIR || + (entry->d_type == DT_UNKNOWN && stat(newpath, &s) == 0 && S_ISDIR(s.st_mode))) { filename = find_module(newpath, name, level - 1); - - free(newpath); - - if (filename != NULL) - break; + if (filename) + return filename; + } } - closedir(dir); - - return filename; + return NULL; } static int
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-node.c
Changed
@@ -901,8 +901,8 @@ pw_impl_node_emit_driver_changed(node, old, driver); - pw_impl_node_emit_peer_added(driver, node); pw_impl_node_emit_peer_removed(old, node); + pw_impl_node_emit_peer_added(driver, node); return 0; } @@ -1095,22 +1095,27 @@ struct pw_node_activation *na = driver->rt.target.activation; struct spa_io_clock *cl = &na->position.clock; enum spa_log_level level = SPA_LOG_LEVEL_DEBUG; + int missed; - if (ratelimit_test(&driver->rt.rate_limit, nsec, SPA_LOG_LEVEL_DEBUG)) + if ((missed = spa_ratelimit_test(&driver->rt.rate_limit, nsec)) >= 0) level = SPA_LOG_LEVEL_INFO; spa_list_for_each(t, &driver->rt.target_list, link) { struct pw_node_activation *a = t->activation; struct pw_node_activation_state *state = &a->state0; + if (t->id == driver->info.id) + continue; + if (a->status == PW_NODE_ACTIVATION_TRIGGERED || a->status == PW_NODE_ACTIVATION_AWAKE) { update_xrun_stats(a, nsec / 1000, 0); - pw_log(level, "(%s-%u) client too slow! rate:%u/%u pos:%"PRIu64" status:%s", + pw_log(level, "(%s-%u) client too slow! rate:%u/%u pos:%"PRIu64" status:%s (%u missed)", t->name, t->id, (uint32_t)(cl->rate.num * cl->duration), cl->rate.denom, - cl->position, str_status(a->status)); + cl->position, str_status(a->status), + missed); } pw_log_debug("(%s-%u) state:%p pending:%d/%d s:%"PRIu64" a:%"PRIu64" f:%"PRIu64 " waiting:%"PRIu64" process:%"PRIu64" status:%s sync:%d", @@ -1878,10 +1883,11 @@ struct pw_node_activation *da = this->rt.driver_target.activation; struct spa_system *data_system = this->data_system; uint64_t nsec = get_time_ns(data_system); + int missed; update_xrun_stats(a, trigger, delay); - if (ratelimit_test(&this->rt.rate_limit, nsec, SPA_LOG_LEVEL_INFO)) { + if ((missed = spa_ratelimit_test(&this->rt.rate_limit, nsec)) >= 0) { struct spa_fraction rate; if (da) { struct spa_io_clock *cl = &da->position.clock; @@ -1891,10 +1897,11 @@ rate = SPA_FRACTION(0,0); } pw_log_info("(%s-%d) XRun! rate:%u/%u count:%u time:%"PRIu64 - " delay:%"PRIu64" max:%"PRIu64, + " delay:%"PRIu64" max:%"PRIu64" (%d missed)", this->name, this->info.id, rate.num, rate.denom, a->xrun_count, - trigger, delay, a->max_delay); + trigger, delay, a->max_delay, + missed); } pw_context_driver_emit_xrun(this->context, this); @@ -1980,6 +1987,7 @@ /* remove ourself as a follower from the driver node */ spa_list_remove(&node->follower_link); + pw_impl_node_emit_peer_removed(node->driver_node, node); remove_segment_owner(node->driver_node, node->info.id); spa_list_consume(follower, &node->follower_list, follower_link) {
View file
pipewire-0.3.72.tar.gz/src/pipewire/impl-port.c -> pipewire-0.3.74.tar.gz/src/pipewire/impl-port.c
Changed
@@ -298,9 +298,9 @@ spa_list_append(&port->mix_list, &mix->link); port->n_mix++; - pw_log_debug("%p: init mix n_mix:%d %d.%d io:%p: (%s)", port, + pw_log_debug("%p: init mix n_mix:%d %d.%d id:%d peer:%d io:%p: (%s)", port, port->n_mix, port->port_id, mix->port.port_id, - mix->io, spa_strerror(res)); + mix->id, mix->peer_id, mix->io, spa_strerror(res)); if (port->n_mix == 1) { pw_log_debug("%p: setting port io", port); @@ -329,6 +329,9 @@ spa_list_remove(&mix->link); port->n_mix--; + pw_log_debug("%p: release mix %d %d.%d", port, + port->n_mix, port->port_id, mix->port.port_id); + res = pw_impl_port_call_release_mix(port, mix); if (port->destroying) @@ -338,9 +341,6 @@ res != -ENOTSUP) pw_log_warn("can't remove mix port %d: %s", port_id, spa_strerror(res)); - pw_log_debug("%p: release mix %d %d.%d", port, - port->n_mix, port->port_id, mix->port.port_id); - if (port->n_mix == 0) { pw_log_debug("%p: clearing port io", port); spa_node_port_set_io(node->node,
View file
pipewire-0.3.72.tar.gz/src/pipewire/log.h -> pipewire-0.3.74.tar.gz/src/pipewire/log.h
Changed
@@ -96,7 +96,7 @@ */ #define PW_LOG_TOPIC_STATIC(var, topic) \ static struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \ - static struct spa_log_topic *(var) = &(var##__LINE__) + static struct spa_log_topic *var = &(var##__LINE__) /** * Declare a static log topic named \a var. @@ -111,7 +111,7 @@ */ #define PW_LOG_TOPIC(var, topic) \ struct spa_log_topic var##__LINE__ = SPA_LOG_TOPIC(0, topic); \ - struct spa_log_topic *(var) = &(var##__LINE__) + struct spa_log_topic *var = &(var##__LINE__) #define PW_LOG_TOPIC_INIT(var) \ spa_log_topic_init(pw_log_get(), var);
View file
pipewire-0.3.72.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.74.tar.gz/src/pipewire/pipewire.c
Changed
@@ -25,8 +25,10 @@ #include <spa/support/cpu.h> #include <spa/support/i18n.h> +#include <pipewire/cleanup.h> #include "pipewire.h" #include "private.h" +#include "i18n.h" #define MAX_SUPPORT 32 @@ -497,9 +499,7 @@ parse_pw_debug_env(void) { const char *str; - char **tokens; int n_tokens; - size_t slen; char json1024 = {0}; char *pos = json; char *end = pos + sizeof(json) - 1; @@ -507,7 +507,7 @@ str = getenv("PIPEWIRE_DEBUG"); - if (!str || (slen = strlen(str)) == 0) + if (!str || !*str) return NULL; /* String format is PIPEWIRE_DEBUG=<glob>:<level>,..., @@ -516,17 +516,16 @@ */ pos += spa_scnprintf(pos, end - pos, " { conn.* = %d },", SPA_LOG_LEVEL_NONE); - tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens); + spa_auto(pw_strv) tokens = pw_split_strv(str, ",", INT_MAX, &n_tokens); if (n_tokens > 0) { int i; for (i = 0; i < n_tokens; i++) { int n_tok; - char **tok; - char *pattern; + char *tok2; - tok = pw_split_strv(tokensi, ":", 2, &n_tok); + n_tok = pw_split_ip(tokensi, ":", SPA_N_ELEMENTS(tok), tok); if (n_tok == 2 && parse_log_level(tok1, &lvl)) { - pattern = tok0; + char *pattern = tok0; pos += spa_scnprintf(pos, end - pos, "{ %s = %d },", pattern, lvl); } else if (n_tok == 1 && parse_log_level(tok0, &lvl)) { @@ -535,11 +534,9 @@ pw_log_warn("Ignoring invalid format in PIPEWIRE_DEBUG: '%s'", tokensi); } - - pw_free_strv(tok); } } - pw_free_strv(tokens); + pos += spa_scnprintf(pos, end - pos, ""); return strdup(json); }
View file
pipewire-0.3.72.tar.gz/src/pipewire/private.h -> pipewire-0.3.74.tar.gz/src/pipewire/private.h
Changed
@@ -17,6 +17,7 @@ #include <spa/support/plugin.h> #include <spa/pod/builder.h> #include <spa/param/latency-utils.h> +#include <spa/utils/ratelimit.h> #include <spa/utils/result.h> #include <spa/utils/type-info.h> @@ -53,29 +54,6 @@ uint32_t clock_force_quantum; /* force a quantum */ }; -struct ratelimit { - uint64_t interval; - uint64_t begin; - unsigned burst; - unsigned n_printed, n_missed; -}; - -static inline bool ratelimit_test(struct ratelimit *r, uint64_t now, enum spa_log_level level) -{ - if (r->begin + r->interval < now) { - if (r->n_missed) - pw_log(level, "%u events suppressed", r->n_missed); - r->begin = now; - r->n_printed = 0; - r->n_missed = 0; - } else if (r->n_printed >= r->burst) { - r->n_missed++; - return false; - } - r->n_printed++; - return true; -} - #define MAX_PARAMS 32 struct pw_param { @@ -203,22 +181,6 @@ #define pw_impl_client_emit_resource_removed(o,r) pw_impl_client_emit(o, resource_removed, 0, r) #define pw_impl_client_emit_busy_changed(o,b) pw_impl_client_emit(o, busy_changed, 0, b) -enum spa_node0_event { - SPA_NODE0_EVENT_START = SPA_TYPE_VENDOR_PipeWire, - SPA_NODE0_EVENT_RequestClockUpdate, -}; - -enum spa_node0_command { - SPA_NODE0_COMMAND_START = SPA_TYPE_VENDOR_PipeWire, - SPA_NODE0_COMMAND_ClockUpdate, -}; - -struct protocol_compat_v2 { - /* v2 typemap */ - struct pw_map types; - unsigned int send_types:1; -}; - #define pw_impl_core_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, struct pw_impl_core_events, m, v, ##__VA_ARGS__) #define pw_impl_core_emit_destroy(s) pw_impl_core_emit(s, destroy, 0) @@ -801,7 +763,7 @@ driver */ struct spa_list driver_link; /* our link in driver */ - struct ratelimit rate_limit; + struct spa_ratelimit rate_limit; } rt; struct spa_fraction target_rate; uint64_t target_quantum; @@ -1066,7 +1028,6 @@ struct pw_properties *properties; /**< extra properties */ struct pw_mempool *pool; /**< memory pool */ - struct pw_core *core; /**< proxy for the core object */ struct spa_hook core_listener; struct spa_hook proxy_core_listener; @@ -1229,9 +1190,7 @@ struct spa_node *node, enum spa_direction direction, uint32_t port_id, uint32_t id, int err, const char *debug, ...); -const struct pw_export_type *pw_context_find_export_type(struct pw_context *context, const char *type); - -int pw_proxy_init(struct pw_proxy *proxy, const char *type, uint32_t version); +int pw_proxy_init(struct pw_proxy *proxy, struct pw_core *core, const char *type, uint32_t version); void pw_proxy_remove(struct pw_proxy *proxy); @@ -1356,7 +1315,7 @@ void pw_log_init(void); void pw_log_deinit(void); -void pw_random_init(); +void pw_random_init(void); void pw_settings_init(struct pw_context *context); int pw_settings_expose(struct pw_context *context);
View file
pipewire-0.3.72.tar.gz/src/pipewire/proxy.c -> pipewire-0.3.74.tar.gz/src/pipewire/proxy.c
Changed
@@ -21,10 +21,11 @@ }; /** \endcond */ -int pw_proxy_init(struct pw_proxy *proxy, const char *type, uint32_t version) +int pw_proxy_init(struct pw_proxy *proxy, struct pw_core *core, const char *type, uint32_t version) { int res; + proxy->core = core; proxy->refcount = 1; proxy->type = type; proxy->version = version; @@ -81,9 +82,8 @@ return NULL; this = &impl->this; - this->core = factory->core; - if ((res = pw_proxy_init(this, type, version)) < 0) + if ((res = pw_proxy_init(this, factory->core, type, version)) < 0) goto error_init; if (user_data_size > 0) @@ -160,12 +160,6 @@ } SPA_EXPORT -struct pw_core *pw_proxy_get_core(struct pw_proxy *proxy) -{ - return proxy->core; -} - -SPA_EXPORT struct pw_protocol *pw_proxy_get_protocol(struct pw_proxy *proxy) { if (proxy->core == NULL || proxy->core->conn == NULL)
View file
pipewire-0.3.72.tar.gz/src/pipewire/stream.c -> pipewire-0.3.74.tar.gz/src/pipewire/stream.c
Changed
@@ -21,6 +21,7 @@ #define PW_ENABLE_DEPRECATED +#include <pipewire/cleanup.h> #include "pipewire/pipewire.h" #include "pipewire/stream.h" #include "pipewire/private.h" @@ -446,7 +447,8 @@ struct stream *impl = user_data; struct pw_stream *stream = &impl->this; pw_log_trace_fp("%p: do process", stream); - pw_stream_emit_process(stream); + if (!impl->disconnecting) + pw_stream_emit_process(stream); return 0; } @@ -1957,7 +1959,7 @@ impl->info.flags = SPA_NODE_FLAG_RT; /* if the callback was not marked RT_PROCESS, we will offload * the process callback in the main thread and we are ASYNC */ - if (!impl->process_rt) + if (!impl->process_rt || SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_ASYNC)) impl->info.flags |= SPA_NODE_FLAG_ASYNC; impl->info.props = &stream->properties->dict; impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); @@ -2164,8 +2166,8 @@ ensure_loop(impl->main_loop, return -EIO); if (res < 0) { + spa_autofree char *value = NULL; va_list args; - char *value; int r; va_start(args, error); @@ -2177,8 +2179,6 @@ if (stream->proxy) pw_proxy_error(stream->proxy, res, value); stream_set_state(stream, PW_STREAM_STATE_ERROR, res, value); - - free(value); } return res; }
View file
pipewire-0.3.72.tar.gz/src/pipewire/stream.h -> pipewire-0.3.74.tar.gz/src/pipewire/stream.h
Changed
@@ -378,6 +378,13 @@ * needs to be called. This can be used * when the output of the stream depends * on input from other streams. */ + PW_STREAM_FLAG_ASYNC = (1 << 10), /**< Buffers will not be dequeued/queued from + * the realtime process() function. This is + * assumed when RT_PROCESS is unset but can + * also be the case when the process() function + * does a trigger_process() that will then + * dequeue/queue a buffer from another process() + * function. since 0.3.73 */ }; /** Create a new unconneced \ref pw_stream
View file
pipewire-0.3.72.tar.gz/src/pipewire/thread.c -> pipewire-0.3.74.tar.gz/src/pipewire/thread.c
Changed
@@ -12,8 +12,8 @@ #include <spa/utils/list.h> #include <pipewire/log.h> - -#include "thread.h" +#include <pipewire/private.h> +#include <pipewire/thread.h> #define CHECK(expression,label) \ do { \
View file
pipewire-0.3.72.tar.gz/src/pipewire/utils.c -> pipewire-0.3.74.tar.gz/src/pipewire/utils.c
Changed
@@ -16,6 +16,7 @@ #include <pipewire/array.h> #include <pipewire/log.h> #include <pipewire/utils.h> +#include <pipewire/private.h> /** Split a string based on delimiters * \param str a string to split @@ -157,21 +158,25 @@ static inline ssize_t make_random(void *buf, size_t buflen, unsigned int flags) { ssize_t bytes; - int read_errno; #ifdef HAVE_GETRANDOM bytes = getrandom(buf, buflen, flags); - if (!(bytes == -1 && errno == ENOSYS)) + if (bytes < 0) + bytes = -errno; + if (bytes != -ENOSYS) return bytes; #endif int fd = open("/dev/urandom", O_CLOEXEC); if (fd < 0) - return -1; + return -errno; + bytes = read(fd, buf, buflen); - read_errno = errno; + if (bytes < 0) + bytes = -errno; + close(fd); - errno = read_errno; + return bytes; } @@ -189,9 +194,9 @@ ssize_t res; do { res = make_random(buf, buflen, flags); - } while ((res == -1) && (errno == EINTR)); - if (res == -1) - return -errno; + } while (res == -EINTR); + if (res < 0) + return res; if ((size_t)res != buflen) return -ENODATA; return res; @@ -227,7 +232,7 @@ } } -void pw_random_init() +void pw_random_init(void) { unsigned int seed; if (pw_getrandom(&seed, sizeof(seed), 0) < 0) {
View file
pipewire-0.3.72.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.74.tar.gz/src/tools/pw-cat.c
Changed
@@ -26,6 +26,7 @@ #include <spa/utils/json.h> #include <spa/debug/types.h> +#include <pipewire/cleanup.h> #include <pipewire/pipewire.h> #include <pipewire/i18n.h> #include <pipewire/extensions/metadata.h> @@ -603,7 +604,6 @@ static int parse_channelmap(const char *channel_map, struct channelmap *map) { int i, nch; - char **ch; SPA_FOR_EACH_ELEMENT_VAR(maps, m) { if (spa_streq(m->name, channel_map)) { @@ -614,7 +614,7 @@ } } - ch = pw_split_strv(channel_map, ",", SPA_AUDIO_MAX_CHANNELS, &nch); + spa_auto(pw_strv) ch = pw_split_strv(channel_map, ",", SPA_AUDIO_MAX_CHANNELS, &nch); if (ch == NULL) return -1; @@ -623,7 +623,7 @@ int c = find_channel(chi); map->channelsi = c; } - pw_free_strv(ch); + return 0; } @@ -1245,7 +1245,8 @@ *s == '\0') continue; - pw_properties_set(data->props, tablec, s); + if (pw_properties_get(data->props, tablec) == NULL) + pw_properties_set(data->props, tablec, s); } spa_zero(sfi); @@ -1257,13 +1258,15 @@ spa_zero(fi); fi.format = sfi.format; if (sf_command(data->file, SFC_GET_FORMAT_INFO, &fi, sizeof(fi)) == 0 && fi.name) - pw_properties_set(data->props, PW_KEY_MEDIA_FORMAT, fi.name); + if (pw_properties_get(data->props, PW_KEY_MEDIA_FORMAT) == NULL) + pw_properties_set(data->props, PW_KEY_MEDIA_FORMAT, fi.name); s = pw_properties_get(data->props, PW_KEY_MEDIA_TITLE); t = pw_properties_get(data->props, PW_KEY_MEDIA_ARTIST); if (s && t) - pw_properties_setf(data->props, PW_KEY_MEDIA_NAME, - "'%s' / '%s'", s, t); + if (pw_properties_get(data->props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(data->props, PW_KEY_MEDIA_NAME, + "'%s' / '%s'", s, t); return 0; } @@ -1494,10 +1497,10 @@ const char *s; unsigned int nom = 0; - if (data->quality >= 0) + if (data->quality >= 0 && pw_properties_get(data->props, "resample.quality") == NULL) pw_properties_setf(data->props, "resample.quality", "%d", data->quality); - if (data->rate) + if (data->rate && pw_properties_get(data->props, PW_KEY_NODE_RATE) == NULL) pw_properties_setf(data->props, PW_KEY_NODE_RATE, "1/%u", data->rate); data->latency_unit = unit_none; @@ -1551,7 +1554,7 @@ if (data->verbose) printf("rate:%d latency:%u (%.3fs)\n", data->rate, nom, data->rate ? (double)nom/data->rate : 0.0f); - if (nom) + if (nom && pw_properties_get(data->props, PW_KEY_NODE_LATENCY) == NULL) pw_properties_setf(data->props, PW_KEY_NODE_LATENCY, "%u/%u", nom, data->rate); return 0; @@ -1785,12 +1788,18 @@ } data.filename = argvoptind++; - pw_properties_set(data.props, PW_KEY_MEDIA_TYPE, data.media_type); - pw_properties_set(data.props, PW_KEY_MEDIA_CATEGORY, data.media_category); - pw_properties_set(data.props, PW_KEY_MEDIA_ROLE, data.media_role); - pw_properties_set(data.props, PW_KEY_MEDIA_FILENAME, data.filename); - pw_properties_set(data.props, PW_KEY_MEDIA_NAME, data.filename); - pw_properties_set(data.props, PW_KEY_TARGET_OBJECT, data.target); + if (pw_properties_get(data.props, PW_KEY_MEDIA_TYPE) == NULL) + pw_properties_set(data.props, PW_KEY_MEDIA_TYPE, data.media_type); + if (pw_properties_get(data.props, PW_KEY_MEDIA_CATEGORY) == NULL) + pw_properties_set(data.props, PW_KEY_MEDIA_CATEGORY, data.media_category); + if (pw_properties_get(data.props, PW_KEY_MEDIA_ROLE) == NULL) + pw_properties_set(data.props, PW_KEY_MEDIA_ROLE, data.media_role); + if (pw_properties_get(data.props, PW_KEY_MEDIA_FILENAME) == NULL) + pw_properties_set(data.props, PW_KEY_MEDIA_FILENAME, data.filename); + if (pw_properties_get(data.props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_set(data.props, PW_KEY_MEDIA_NAME, data.filename); + if (pw_properties_get(data.props, PW_KEY_TARGET_OBJECT) == NULL) + pw_properties_set(data.props, PW_KEY_TARGET_OBJECT, data.target); /* make a main loop. If you already have another main loop, you can add * the fd of this pipewire mainloop to it. */
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
.