Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 35
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sun Oct 8 16:26:36 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.81 + +------------------------------------------------------------------- Fri Sep 22 17:21:32 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.80
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.80 +Version: 0.3.81 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.80.tar.gz/.gitlab-ci.yml -> pipewire-0.3.81.tar.gz/.gitlab-ci.yml
Changed
@@ -458,8 +458,15 @@ extends: - .build_on_fedora stage: analysis + variables: + MESON_OPTIONS: >- + -Dpipewire-v4l2=enabled + -Dpipewire-jack=enabled script: - - shellcheck $(git grep -l "#\!/.*bin/.*sh") + - echo "Configuring with meson options $MESON_OPTIONS" + - meson setup "$BUILD_DIR" --prefix="$PREFIX" $MESON_OPTIONS + - shellcheck $(git ls-files '*.sh') + - shellcheck $(grep -rl "#\!/.*bin/.*sh" "$BUILD_DIR") spellcheck: extends:
View file
pipewire-0.3.80.tar.gz/NEWS -> pipewire-0.3.81.tar.gz/NEWS
Changed
@@ -1,3 +1,88 @@ +# PipeWire 0.3.81 (2023-10-06) + +This is the first 1.0 release candidate that is API and ABI compatible +with previous 0.3.x releases. + +## Highlights + - jackdbus support is now enabled by default. + - IRQ based scheduling in ALSA was improved and enabled by default for + Pro-Audio profile. It will also link the pcms together to get lower + latency. This now matches what JACK does and gives equal latency to + PipeWire for Pro-Audio profiles. + - Support both old and new versions of webrtc-audio-processing to make + the transition easier. + - Forced quantum changes by nodes or metadata will now also force a + suspend and resume of the graph, like the rate changes to make sure all + nodes adapt to the new quantum. This is important for Pro-Audio nodes + that need to reconfigure the hardware to a new period in IRQ based + scheduling. + - Fix a regression in regex parsing. + - Many bugfixes and improvements. + + +## PipeWire + - jackdbus is by default enabled now. The idea is that when jackdbus is + installed, the real libjack.so is in the path and we can become a + real JACK client. + - Forces quantum changes by nodes or metadata will now also force a + suspend and resume in the graph, like the rate changes to make sure all + nodes adapt to the new quantum. This is important for Pro-Audio nodes + that need to reconfigure the hardware to a new period. + - The stream now has an EARLY_PROCESS option that can be used to implement + custum buffer fill levels. (#3480) + - Fix a regression in regex parsing. (#3528) + - Fix a bug in position reporting in the driver node. (#3189) (#3544) + - Destroying a link will now recalculate the graph correctly. + - Fix the rate comparison for finding the best rate in the graph. + - Use malloc_trim() when available to release memory. (#1840) + +## Tools + - pw-cat now supports DFF DSD files. + - pw-cli avoid some NULL derefs in some cases. + +## Modules + - The RAOP sink has seen some cleanups and improvements. It will now ask + for feedback every 2 seconds to keep some devices alive. + - A bug in filter-chain was fixed where it would fail to apply the gain + when mixing just one source. + - The filter-chain can now pass the stream volume to a control in the + filter-chain graph. (#3434) + - Improve volume handling in RAOP sink. + +## Pulse-server + - Some cleanup in the pending_stream handling. + - Fix a regression in the event emission code where it failed to emit + a changed event when a node was linked. (#3522) + - Lower the realtime priority of pulseaudio clients. + - Set pulse.module.id on the echo-cancel streams. (#3541) + +## SPA + - Support both old and new versions of webrtc-audio-processing to make + the transition easier. + - The ALSA driver now does the sync of all followers directly from the + wakeup event. This results in more stable rate matching. + - IRQ based scheduling in ALSA was improved and enabled by default for + Pro-Audio profile. It will also link the pcms together to get lower + latency. This now matches what JACK does and gives equal latency to + PipeWire for Pro-Audio profiles. + - GNU/Hurd support was added. + - Some improvements to passthrough handling. + +## Bluetooth + - Improvements to the codec handling when PipeWire is used as Audio + Gateway. + - Adapt to new Bluez API for BAP devices. + +## JACK + - When the jack library is set in the default library path, avoid using + LD_LIBRARY_PATH because this can cause confusion. + - Handle clearing the latency on a port. + - jack_property now always manages to actually change the metadata because + it waits for a roundtrip before exiting. + +Older versions: + + # PipeWire 0.3.80 (2023-09-14) This is a bugfix release that is API and ABI compatible with previous @@ -63,9 +148,6 @@ - The mixer io areas are updated and handled safely now to avoid crashes. (#3506) -Older versions: - - # PipeWire 0.3.79 (2023-08-29) This is a quick bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.80.tar.gz/doc/input-filter-h.sh -> pipewire-0.3.81.tar.gz/doc/input-filter-h.sh
Changed
@@ -11,6 +11,7 @@ # Add \ingroup commands for the file, for each \addgroup in it BASEFILE=$(echo "$FILENAME" | sed -e 's@.*src/pipewire/@pipewire/@; s@.*spa/include/spa/@spa/@; s@.*src/test/@test/@;') +# shellcheck disable=SC2028 # \file is not an escape sequence echo "/** \file" echo "\`$BASEFILE\`" sed -n -e '/.*\\addtogroup a-zA-Z0-9_.*/ { s/.*addtogroup /\\ingroup /; p; }' < "$FILENAME" | sort | uniq
View file
pipewire-0.3.80.tar.gz/meson.build -> pipewire-0.3.81.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.80', + version : '0.3.81', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -23,15 +23,15 @@ spaversion = '0.2' apiversion = '0.3' soversion = 0 -libversion = '@0@.@1@.0'.format(soversion, pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int()) +libversion_minor = pipewire_version_major.to_int() * 1000 + pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int() +libversion = '@0@.@1@.0'.format(soversion, libversion_minor) # LADI/jack # 3, for PipeWire being the third JACK implementation, after JACK1 and jackdmp/JACK2) jack_version_major = 3 -jack_version_minor = pipewire_version_minor.to_int() * 100 + pipewire_version_micro.to_int() +jack_version_minor = libversion_minor # libjackserver version has 0 for major (for compatibility with other implementations), -# 3 for minor, and "100*pipewire_version_minor + pipewire_version_micro" -# as micro version (the minor libpipewire soversion number) +# 3 for minor, and "1000*major + 100*minor + micro" as micro version (the minor libpipewire soversion number) libjackversion = '@0@.@1@.@2@'.format(soversion, jack_version_major, jack_version_minor) pipewire_name = 'pipewire-@0@'.format(apiversion) @@ -377,9 +377,17 @@ webrtc_dep = dependency('webrtc-audio-processing-1', version : '>= 1.2' , - required : get_option('echo-cancel-webrtc')) -summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') -cdata.set('HAVE_WEBRTC', webrtc_dep.found()) + required : false) +cdata.set('HAVE_WEBRTC1', webrtc_dep.found()) +if webrtc_dep.found() + summary({'WebRTC Echo Canceling >= 1.2': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') +else + webrtc_dep = dependency('webrtc-audio-processing', + version : '>= 0.2', '< 1.0', + required : get_option('echo-cancel-webrtc')) + cdata.set('HAVE_WEBRTC', webrtc_dep.found()) + summary({'WebRTC Echo Canceling < 1.0': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') +endif # On FreeBSD and MidnightBSD, epoll-shim library is required for eventfd() and timerfd() epoll_shim_dep = (host_machine.system() == 'freebsd' or host_machine.system() == 'midnightbsd' @@ -427,6 +435,7 @@ 'reallocarray', '#include <stdlib.h>', '-D_GNU_SOURCE', , 'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', , 'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep, + 'malloc_trim', '#include <malloc.h>', , , foreach f : check_functions
View file
pipewire-0.3.80.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.81.tar.gz/pipewire-jack/src/meson.build
Changed
@@ -21,12 +21,19 @@ if libjack_path == '' libjack_path = modules_install_dir / 'jack' libjack_path_dlopen = modules_install_dir_dlopen / 'jack' + libjack_path_enable = '' +elif libjack_path == get_option('libdir') or libjack_path == pipewire_libdir + libjack_path = pipewire_libdir + libjack_path_dlopen = libjack_path + libjack_path_enable = '#' else libjack_path_dlopen = libjack_path + libjack_path_enable = '' endif tools_config = configuration_data() tools_config.set('LIBJACK_PATH', libjack_path_dlopen) +tools_config.set('LIBJACK_PATH_ENABLE', libjack_path_enable) configure_file(input : 'pw-jack.in', output : 'pw-jack',
View file
pipewire-0.3.80.tar.gz/pipewire-jack/src/metadata.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/metadata.c
Changed
@@ -230,7 +230,7 @@ pw_log_info("set id:%u (%"PRIu64") '%s' to '%s@%s'", o->id, subject, key, value, type); if (update_property(c, subject, key, type, value)) pw_metadata_set_property(c->metadata->proxy, o->id, key, type, value); - res = 0; + res = do_sync(c); done: pw_thread_loop_unlock(c->context.loop); @@ -340,7 +340,7 @@ pw_log_info("remove id:%u (%"PRIu64") '%s'", id, subject, key); pw_metadata_set_property(c->metadata->proxy, id, key, NULL, NULL); - res = 0; + res = do_sync(c); done: pw_thread_loop_unlock(c->context.loop); @@ -365,7 +365,7 @@ pw_log_info("remove id:%u (%"PRIu64")", id, subject); pw_metadata_set_property(c->metadata->proxy, id, NULL, NULL, NULL); - res = 0; + res = do_sync(c); done: pw_thread_loop_unlock(c->context.loop); @@ -375,15 +375,17 @@ SPA_EXPORT int jack_remove_all_properties (jack_client_t* client) { + int res; struct client *c = (struct client *) client; spa_return_val_if_fail(c != NULL, -EINVAL); pw_thread_loop_lock(c->context.loop); pw_metadata_clear(c->metadata->proxy); + res = do_sync(c); pw_thread_loop_unlock(c->context.loop); - return 0; + return res; } SPA_EXPORT
View file
pipewire-0.3.80.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -2441,9 +2441,11 @@ int res; if (param == NULL) - return 0; - if ((res = spa_latency_parse(param, &info)) < 0) + info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(p->direction)); + else if ((res = spa_latency_parse(param, &info)) < 0) return res; + if (info.direction == p->direction) + return 0; current = &p->object->port.latencyinfo.direction; if (spa_latency_info_compare(current, &info) == 0) @@ -2457,8 +2459,6 @@ info.min_rate, info.max_rate, info.min_ns, info.max_ns); - if (info.direction == p->direction) - return 0; if (info.direction == SPA_DIRECTION_INPUT) mode = JackPlaybackLatency;
View file
pipewire-0.3.80.tar.gz/pipewire-jack/src/pw-jack.in -> pipewire-0.3.81.tar.gz/pipewire-jack/src/pw-jack.in
Changed
@@ -52,7 +52,9 @@ fi export PIPEWIRE_QUANTUM fi -LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}" -export LD_LIBRARY_PATH + +# shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell +@LIBJACK_PATH_ENABLE@LD_LIBRARY_PATH='@LIBJACK_PATH@'"${LD_LIBRARY_PATH+":$LD_LIBRARY_PATH"}" +@LIBJACK_PATH_ENABLE@export LD_LIBRARY_PATH exec "$@"
View file
pipewire-0.3.80.tar.gz/pipewire-v4l2/src/pw-v4l2.in -> pipewire-0.3.81.tar.gz/pipewire-v4l2/src/pw-v4l2.in
Changed
@@ -37,6 +37,7 @@ if "$PW_UNINSTALLED" = 1 ; then PW_V4L2_LD_PRELOAD="$PW_BUILDDIR"'/pipewire-v4l2/src/libpw-v4l2.so' else + # shellcheck disable=SC2016 # ${LIB} is interpreted by ld.so, not the shell PW_V4L2_LD_PRELOAD='@LIBV4L2_PATH@/libpw-v4l2.so' fi
View file
pipewire-0.3.80.tar.gz/spa/examples/adapter-control.c -> pipewire-0.3.81.tar.gz/spa/examples/adapter-control.c
Changed
@@ -906,9 +906,9 @@ printf("got error %d\n", res); } -static char *getscale(uint32_t scale) +static const char *getscale(uint32_t scale) { - char *scale_s = NULL; + const char *scale_s = NULL; if (scale == SPA_AUDIO_VOLUME_RAMP_LINEAR) scale_s = LINEAR;
View file
pipewire-0.3.80.tar.gz/spa/include/spa/debug/log.h -> pipewire-0.3.81.tar.gz/spa/include/spa/debug/log.h
Changed
@@ -15,6 +15,10 @@ #include <spa/utils/defs.h> #include <spa/support/log.h> #include <spa/debug/context.h> +#include <spa/debug/dict.h> +#include <spa/debug/format.h> +#include <spa/debug/mem.h> +#include <spa/debug/pod.h> /** * \addtogroup spa_debug
View file
pipewire-0.3.80.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-0.3.81.tar.gz/spa/include/spa/utils/cleanup.h
Changed
@@ -35,15 +35,16 @@ #define spa_exchange(var, new_value) \ __extension__ ({ \ - __typeof__(var) _old_value = (var); \ - (var) = (new_value); \ + __typeof__(var) *_ptr = &(var); \ + __typeof__(var) _old_value = *_ptr; \ + *_ptr = (new_value); \ _old_value; \ }) -#if __GNUC__ > 10 || defined(__clang__) +#if __GNUC__ >= 10 || defined(__clang__) #define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL)) #else -#define spa_steal_ptr(ptr) ((__typeof__(ptr)) spa_exchange((ptr), NULL)) +#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL) #endif #define spa_steal_fd(fd) spa_exchange((fd), -1) @@ -52,16 +53,6 @@ #include <stdlib.h> - -#if __GNUC__ > 10 || defined(__clang__) -#define spa_clear_ptr(ptr, destructor) \ -__extension__ ({ \ - __typeof__(*(ptr)) *_old_value = spa_steal_ptr(ptr); \ - if (_old_value) \ - destructor(_old_value); \ - (void) 0; \ -}) -#else #define spa_clear_ptr(ptr, destructor) \ __extension__ ({ \ __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \ @@ -69,7 +60,6 @@ destructor(_old_value); \ (void) 0; \ }) -#endif static inline void _spa_autofree_cleanup_func(void *p) {
View file
pipewire-0.3.80.tar.gz/spa/plugins/aec/aec-webrtc.cpp -> pipewire-0.3.81.tar.gz/spa/plugins/aec/aec-webrtc.cpp
Changed
@@ -3,6 +3,8 @@ /* SPDX-FileCopyrightText: Copyright © 2021 Arun Raghavan <arun@asymptotic.io> */ /* SPDX-License-Identifier: MIT */ +#include "config.h" + #include <memory> #include <utility> @@ -13,7 +15,13 @@ #include <spa/utils/json.h> #include <spa/support/plugin.h> +#ifdef HAVE_WEBRTC +#include <webrtc/modules/audio_processing/include/audio_processing.h> +#include <webrtc/modules/interface/module_common_types.h> +#include <webrtc/system_wrappers/include/trace.h> +#else #include <modules/audio_processing/include/audio_processing.h> +#endif struct impl_data { struct spa_handle handle; @@ -39,6 +47,54 @@ return default_value; } +#ifdef HAVE_WEBRTC +/* f0 f1 f2 */ +static int parse_point(struct spa_json *it, float (&f)3) +{ + struct spa_json arr; + int i, res; + + if (spa_json_enter_array(it, &arr) <= 0) + return -EINVAL; + + for (i = 0; i < 3; i++) { + if ((res = spa_json_get_float(&arr, &fi)) <= 0) + return -EINVAL; + } + return 0; +} + +/* point1 point2 ... */ +static int parse_mic_geometry(struct impl_data *impl, const char *mic_geometry, + std::vector<webrtc::Point>& geometry) +{ + int res; + size_t i; + struct spa_json it2; + + spa_json_init(&it0, mic_geometry, strlen(mic_geometry)); + if (spa_json_enter_array(&it0, &it1) <= 0) { + spa_log_error(impl->log, "Error: webrtc.mic-geometry expects an array"); + return -EINVAL; + } + + for (i = 0; i < geometry.size(); i++) { + float f3; + + if ((res = parse_point(&it1, f)) < 0) { + spa_log_error(impl->log, "Error: can't parse webrtc.mic-geometry points: %d", res); + return res; + } + + spa_log_info(impl->log, "mic %zd position: (%g %g %g)", i, f0, f1, f2); + geometryi.c0 = f0; + geometryi.c1 = f1; + geometryi.c2 = f2; + } + return 0; +} +#endif + static int webrtc_init2(void *object, const struct spa_dict *args, struct spa_audio_info_raw *rec_info, struct spa_audio_info_raw *out_info, struct spa_audio_info_raw *play_info) @@ -48,9 +104,18 @@ bool high_pass_filter = webrtc_get_spa_bool(args, "webrtc.high_pass_filter", true); bool noise_suppression = webrtc_get_spa_bool(args, "webrtc.noise_suppression", true); - bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true); bool voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true); - +#ifdef HAVE_WEBRTC + bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true); + bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true); + // Disable experimental flags by default + bool experimental_agc = webrtc_get_spa_bool(args, "webrtc.experimental_agc", false); + bool experimental_ns = webrtc_get_spa_bool(args, "webrtc.experimental_ns", false); + + bool beamforming = webrtc_get_spa_bool(args, "webrtc.beamforming", false); +#else + bool transient_suppression = webrtc_get_spa_bool(args, "webrtc.transient_suppression", true); +#endif // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech, // result in very poor performance, disable by default bool gain_control = webrtc_get_spa_bool(args, "webrtc.gain_control", false); @@ -59,6 +124,51 @@ // This filter will modify playback buffer (when calling ProcessReverseStream), but now // playback buffer modifications are discarded. +#ifdef HAVE_WEBRTC + webrtc::Config config; + config.Set<webrtc::ExtendedFilter>(new webrtc::ExtendedFilter(extended_filter)); + config.Set<webrtc::DelayAgnostic>(new webrtc::DelayAgnostic(delay_agnostic)); + config.Set<webrtc::ExperimentalAgc>(new webrtc::ExperimentalAgc(experimental_agc)); + config.Set<webrtc::ExperimentalNs>(new webrtc::ExperimentalNs(experimental_ns)); + + if (beamforming) { + std::vector<webrtc::Point> geometry(rec_info->channels); + const char *mic_geometry, *target_direction; + + /* The beamformer gives a single mono channel */ + out_info->channels = 1; + out_info->position0 = SPA_AUDIO_CHANNEL_MONO; + + if ((mic_geometry = spa_dict_lookup(args, "webrtc.mic-geometry")) == NULL) { + spa_log_error(impl->log, "Error: webrtc.beamforming requires webrtc.mic-geometry"); + return -EINVAL; + } + + if ((res = parse_mic_geometry(impl, mic_geometry, geometry)) < 0) + return res; + + if ((target_direction = spa_dict_lookup(args, "webrtc.target-direction")) != NULL) { + webrtc::SphericalPointf direction(0.0f, 0.0f, 0.0f); + struct spa_json it; + float f3; + + spa_json_init(&it, target_direction, strlen(target_direction)); + if (parse_point(&it, f) < 0) { + spa_log_error(impl->log, "Error: can't parse target-direction %s", + target_direction); + return -EINVAL; + } + + direction.s0 = f0; + direction.s1 = f1; + direction.s2 = f2; + + config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry, direction)); + } else { + config.Set<webrtc::Beamforming>(new webrtc::Beamforming(true, geometry)); + } + } +#else webrtc::AudioProcessing::Config config; config.echo_canceller.enabled = true; // FIXME: Example code enables both gain controllers, but that seems sus @@ -73,6 +183,7 @@ // FIXME: expose pre/postamp gain config.transient_suppression.enabled = transient_suppression; config.voice_detection.enabled = voice_detection; +#endif webrtc::ProcessingConfig pconfig = {{ webrtc::StreamConfig(rec_info->rate, rec_info->channels, false), /* input stream */ @@ -81,15 +192,35 @@ webrtc::StreamConfig(play_info->rate, play_info->channels, false), /* reverse output stream */ }}; +#ifdef HAVE_WEBRTC + auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config)); +#else auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessingBuilder().Create()); apm->ApplyConfig(config); +#endif if ((res = apm->Initialize(pconfig)) != webrtc::AudioProcessing::kNoError) { spa_log_error(impl->log, "Error initialising webrtc audio processing module: %d", res); return -EINVAL; } +#ifdef HAVE_WEBRTC + apm->high_pass_filter()->Enable(high_pass_filter); + // Always disable drift compensation since PipeWire will already do + // drift compensation on all sinks and sources linked to this echo-canceler + apm->echo_cancellation()->enable_drift_compensation(false); + apm->echo_cancellation()->Enable(true); + // TODO: wire up supression levels to args + apm->echo_cancellation()->set_suppression_level(webrtc::EchoCancellation::kHighSuppression); + apm->noise_suppression()->set_level(webrtc::NoiseSuppression::kHigh); + apm->noise_suppression()->Enable(noise_suppression); + apm->voice_detection()->Enable(voice_detection); + // TODO: wire up AGC parameters to args + apm->gain_control()->set_analog_level_limits(0, 255); + apm->gain_control()->set_mode(webrtc::GainControl::kAdaptiveDigital); + apm->gain_control()->Enable(gain_control); +#endif impl->apm = std::move(apm); impl->rec_info = *rec_info; impl->out_info = *out_info;
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -388,6 +388,8 @@ pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm); pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index); pa_proplist_setf(m->output_proplist, "device.profile.pro", "true"); + pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index); + pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index); pa_alsa_close(&m->output_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX); @@ -419,6 +421,8 @@ pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm); pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index); pa_proplist_setf(m->input_proplist, "device.profile.pro", "true"); + pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index); + pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index); pa_alsa_close(&m->input_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-compress-offload-sink.c
Changed
@@ -843,12 +843,12 @@ nextptr = device + 3; for (value_index = 0; ; ++value_index) { - char *value_label; + const char *value_label; switch (value_index) { case 0: value_label = "card"; break; case 1: value_label = "device"; break; - default: assert(false); + default: spa_assert_not_reached(); } errno = 0;
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -252,9 +252,13 @@ switch (id) { case SPA_IO_Clock: + if (size > 0 && size < sizeof(struct spa_io_clock)) + return -EINVAL; this->clock = data; break; case SPA_IO_Position: + if (size > 0 && size < sizeof(struct spa_io_position)) + return -EINVAL; this->position = data; break; default:
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -235,6 +235,8 @@ this->clock = data; break; case SPA_IO_Position: + if (size > 0 && size < sizeof(struct spa_io_position)) + return -EINVAL; this->position = data; break; default:
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -17,6 +17,7 @@ #include "alsa-pcm.h" static struct spa_list cards = SPA_LIST_INIT(&cards); +static struct spa_list states = SPA_LIST_INIT(&states); static struct card *find_card(uint32_t index) { @@ -501,6 +502,9 @@ int err; const char *str; + spa_list_init(&state->followers); + spa_list_init(&state->rt.followers); + snd_config_update_free_global(); if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL) @@ -508,6 +512,7 @@ state->multi_rate = true; state->htimestamp = false; + state->disable_tsched = state->is_pro; for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; const char *s = info->itemsi.value; @@ -547,6 +552,8 @@ } CHECK(snd_output_stdio_attach(&state->output, state->log_file, 0), "attach failed"); + spa_list_append(&states, &state->link); + state->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; state->rate_limit.burst = 1; @@ -557,6 +564,7 @@ { int err; + spa_list_remove(&state->link); release_card(state->card); state->card = NULL; @@ -584,7 +592,7 @@ err = snd_ctl_open(&state->ctl, device_name, SND_CTL_NONBLOCK); if (err < 0) { spa_log_info(state->log, "%s could not find ctl device: %s", - state->props.device, snd_strerror(err)); + device_name, snd_strerror(err)); state->ctl = NULL; goto error; } @@ -599,7 +607,7 @@ err = snd_ctl_elem_read(state->ctl, state->pitch_elem); if (err < 0) { spa_log_debug(state->log, "%s: did not find ctl %s: %s", - state->props.device, elem_name, snd_strerror(err)); + device_name, elem_name, snd_strerror(err)); snd_ctl_elem_value_free(state->pitch_elem); state->pitch_elem = NULL; @@ -613,13 +621,34 @@ CHECK(snd_ctl_elem_write(state->ctl, state->pitch_elem), "snd_ctl_elem_write"); state->last_rate = 1.0; - spa_log_info(state->log, "%s: found ctl %s", state->props.device, elem_name); + spa_log_info(state->log, "%s: found ctl %s", device_name, elem_name); err = 0; error: snd_lib_error_set_handler(NULL); return err; } +static int do_link(struct state *driver, struct state *state) +{ + int res; + snd_pcm_status_t *status; + + snd_pcm_status_alloca(&status); + snd_pcm_status(driver->hndl, status); + snd_pcm_status_dump(status, state->output); + snd_pcm_status(state->hndl, status); + snd_pcm_status_dump(status, state->output); + fflush(state->log_file); + + res = snd_pcm_link(driver->hndl, state->hndl); + if (res >= 0 || res == -EALREADY) + state->linked = true; + + spa_log_info(state->log, "%p: linked to driver %p: %u (%s)", + state, driver, state->linked, snd_strerror(res)); + return 0; +} + int spa_alsa_open(struct state *state, const char *params) { int err; @@ -632,6 +661,8 @@ spa_scnprintf(device_name, sizeof(device_name), "%s%s%s", state->card->ucm_prefix ? state->card->ucm_prefix : "", props->device, params ? params : ""); + spa_scnprintf(state->name, sizeof(state->name), "%s%s", + props->device, state->stream == SND_PCM_STREAM_CAPTURE ? "c" : "p"); spa_log_info(state->log, "%p: ALSA device open '%s' %s", state, device_name, state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback"); @@ -655,9 +686,6 @@ * these are initialised in spa_alsa_start() */ } - if (state->clock) - spa_scnprintf(state->clock->name, sizeof(state->clock->name), - "%s", state->clock_name); state->opened = true; state->sample_count = 0; state->sample_time = 0; @@ -667,12 +695,32 @@ return 0; error_exit_close: - spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->props.device, + spa_log_info(state->log, "%p: Device '%s' closing: %s", state, state->name, spa_strerror(err)); snd_pcm_close(state->hndl); return err; } +static void try_unlink(struct state *state) +{ + struct state *follower; + + if (state->driver != NULL && state->linked) { + snd_pcm_unlink(state->hndl); + spa_log_info(state->log, "%p: unlinked from driver %p", + state, state->driver); + state->linked = false; + } + spa_list_for_each(follower, &state->followers, driver_link) { + if (follower->opened && follower->linked) { + snd_pcm_unlink(follower->hndl); + spa_log_info(state->log, "%p: follower unlinked from driver %p", + follower, state); + follower->linked = false; + } + } +} + int spa_alsa_close(struct state *state) { int err = 0; @@ -680,11 +728,13 @@ if (!state->opened) return 0; + try_unlink(state); + spa_alsa_pause(state); - spa_log_info(state->log, "%p: Device '%s' closing", state, state->props.device); + spa_log_info(state->log, "%p: Device '%s' closing", state, state->name); if ((err = snd_pcm_close(state->hndl)) < 0) - spa_log_warn(state->log, "%s: close failed: %s", state->props.device, + spa_log_warn(state->log, "%s: close failed: %s", state->name, snd_strerror(err)); if (!state->disable_tsched) @@ -697,6 +747,7 @@ state->have_format = false; state->opened = false; + state->linked = false; if (state->pitch_elem) { snd_ctl_elem_value_free(state->pitch_elem); @@ -1094,7 +1145,7 @@ CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &rchannels), "set_channels"); if (state->default_channels != rchannels) { spa_log_warn(state->log, "%s: Channels doesn't match (requested %u, got %u)", - state->props.device, state->default_channels, rchannels); + state->name, state->default_channels, rchannels); } } if (state->default_rate != 0) { @@ -1102,7 +1153,7 @@ CHECK(snd_pcm_hw_params_set_rate_near(hndl, params, &rrate, 0), "set_rate_near"); if (state->default_rate != rrate) { spa_log_warn(state->log, "%s: Rate doesn't match (requested %u, got %u)", - state->props.device, state->default_rate, rrate); + state->name, state->default_rate, rrate); } } @@ -1164,7 +1215,7 @@ } } spa_log_warn(state->log, "%s: no format found (def:%d) formats:%s", - state->props.device, state->default_format, buf); + state->name, state->default_format, buf); for (i = 0, offs = 0; i <= SND_PCM_ACCESS_LAST; i++) {
View file
pipewire-0.3.80.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -82,6 +82,15 @@ uint32_t rate; }; +struct rt_state { + struct spa_list followers; + struct state *driver; + struct spa_list driver_link; + + unsigned int sources_added:1; + unsigned int following:1; +}; + struct state { struct spa_handle handle; struct spa_node node; @@ -97,6 +106,7 @@ struct card *card; snd_pcm_stream_t stream; snd_output_t *output; + char name64; struct spa_hook_list hooks; struct spa_callbacks callbacks; @@ -111,7 +121,9 @@ struct spa_param_info paramsN_NODE_PARAMS; struct props props; - bool opened; + unsigned int opened:1; + unsigned int prepared:1; + unsigned int started:1; snd_pcm_t *hndl; bool have_format; @@ -127,9 +139,9 @@ uint32_t allowed_ratesMAX_RATES; uint32_t n_allowed_rates; struct channel_map default_pos; - unsigned int disable_mmap; - unsigned int disable_batch; - unsigned int disable_tsched; + unsigned int disable_mmap:1; + unsigned int disable_batch:1; + unsigned int disable_tsched:1; char clock_name64; uint32_t quantum_limit; @@ -141,9 +153,9 @@ size_t frame_size; size_t frame_scale; int blocks; - uint32_t rate_denom; uint32_t delay; uint32_t read_size; + uint32_t max_read; uint64_t port_info_all; struct spa_port_info port_info; @@ -169,7 +181,6 @@ size_t ready_offset; - bool started; /* Either a single source for tsched, or a set of pollfds from ALSA */ struct spa_source sourceMAX_POLL; int timerfd; @@ -183,7 +194,9 @@ uint32_t max_delay; uint32_t htimestamp_error; - uint32_t duration; + struct spa_fraction driver_rate; + uint32_t driver_duration; + unsigned int alsa_started:1; unsigned int alsa_sync:1; unsigned int alsa_sync_warning:1; @@ -200,6 +213,8 @@ unsigned int multi_rate:1; unsigned int htimestamp:1; unsigned int is_pro:1; + unsigned int sources_added:1; + unsigned int linked:1; uint64_t iec958_codecs; @@ -222,6 +237,14 @@ snd_ctl_t *ctl; snd_ctl_elem_value_t *pitch_elem; double last_rate; + + struct spa_list link; + + struct spa_list followers; + struct state *driver; + struct spa_list driver_link; + + struct rt_state rt; }; struct spa_pod *spa_alsa_enum_propinfo(struct state *state, @@ -240,6 +263,7 @@ int spa_alsa_clear(struct state *state); int spa_alsa_open(struct state *state, const char *params); +int spa_alsa_prepare(struct state *state); int spa_alsa_start(struct state *state); int spa_alsa_reassign_follower(struct state *state); int spa_alsa_pause(struct state *state);
View file
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -373,9 +373,6 @@ struct spa_data *datas; uint64_t follower_flags, conv_flags; - if (this->target == this->follower) - return 0; - spa_log_debug(this->log, "%p: n_buffers:%d", this, this->n_buffers); if (this->n_buffers > 0) @@ -516,10 +513,9 @@ this->have_format = format != NULL; if (format == NULL) { this->n_buffers = 0; - } else { + } else if (this->target != this->follower) { res = negotiate_buffers(this); } - return res; } @@ -555,7 +551,7 @@ struct spa_latency_info latency; int res; - spa_log_info(this->log, "%p: %d:%d", this, direction, port_id); + spa_log_debug(this->log, "%p: %d:%d", this, direction, port_id); if (this->target == this->follower) return 0; @@ -625,7 +621,7 @@ int res = 0; struct spa_hook l; - spa_log_info(this->log, "%p: passthrough mode %d", this, passthrough); + spa_log_debug(this->log, "%p: passthrough mode %d", this, passthrough); if (this->passthrough != passthrough) { if (passthrough) { @@ -846,9 +842,6 @@ struct spa_pod_builder b = { 0 }; int res; - if (this->target == this->follower) - return 0; - spa_log_debug(this->log, "%p: have_format:%d", this, this->have_format); if (this->have_format) @@ -920,12 +913,12 @@ switch (SPA_NODE_COMMAND_ID(command)) { case SPA_NODE_COMMAND_Start: spa_log_debug(this->log, "%p: starting %d", this, this->started); - if (this->started) - return 0; - if ((res = negotiate_format(this)) < 0) - return res; - if ((res = negotiate_buffers(this)) < 0) - return res; + if (this->target != this->follower) { + if (this->started) + return 0; + if ((res = negotiate_format(this)) < 0) + return res; + } this->ready = true; this->warned = false; break; @@ -1043,7 +1036,7 @@ uint32_t i; int res; - spa_log_info(this->log, "%p: convert port info %s %p %08"PRIx64, this, + spa_log_debug(this->log, "%p: convert port info %s %p %08"PRIx64, this, this->direction == SPA_DIRECTION_INPUT ? "Input" : "Output", info, info->change_mask);
View file
pipewire-0.3.80.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -370,8 +370,9 @@ } spa_list_init(&port->queue); - spa_log_info(this->log, "%p: add port %d:%d position:%s %d %d %d", - this, direction, port_id, port->position, is_dsp, is_monitor, is_control); + spa_log_debug(this->log, "%p: add port %d:%d position:%s %d %d %d", + this, direction, port_id, port->position, is_dsp, + is_monitor, is_control); emit_port_info(this, port, true); return 0; @@ -1266,8 +1267,9 @@ (info == NULL || memcmp(&dir->format, info, sizeof(*info)) == 0)) return 0; - spa_log_info(this->log, "%p: port config direction:%d monitor:%d control:%d mode:%d %d", this, - direction, monitor, control, mode, dir->n_ports); + spa_log_debug(this->log, "%p: port config direction:%d monitor:%d " + "control:%d mode:%d %d", this, direction, monitor, + control, mode, dir->n_ports); for (i = 0; i < dir->n_ports; i++) { spa_node_emit_port_info(&this->hooks, direction, i, NULL); @@ -2443,6 +2445,53 @@ SPA_FLAG_CLEAR(b->flags, BUFFER_FLAG_QUEUED); } +static void free_tmp(struct impl *this) +{ + uint32_t i; + + spa_log_debug(this->log, "free tmp %d", this->empty_size); + + free(this->empty); + this->empty = NULL; + this->empty_size = 0; + free(this->scratch); + this->scratch = NULL; + free(this->tmp0); + this->tmp0 = NULL; + free(this->tmp1); + this->tmp1 = NULL; + for (i = 0; i < MAX_PORTS; i++) { + this->tmp_datas0i = NULL; + this->tmp_datas1i = NULL; + } +} + +static int ensure_tmp(struct impl *this, uint32_t maxsize) +{ + if (maxsize > this->empty_size) { + float *empty, *scratch, *tmp2; + + spa_log_debug(this->log, "resize tmp %d -> %d", this->empty_size, maxsize); + + if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL) + this->empty = empty; + if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL) + this->scratch = scratch; + if ((tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL) + this->tmp0 = tmp0; + if ((tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS)) != NULL) + this->tmp1 = tmp1; + + if (empty == NULL || scratch == NULL || tmp0 == NULL || tmp1 == NULL) { + free_tmp(this); + return -ENOMEM; + } + memset(this->empty, 0, maxsize + MAX_ALIGN); + this->empty_size = maxsize; + } + return 0; +} + static int impl_node_port_use_buffers(void *object, enum spa_direction direction, @@ -2454,6 +2503,7 @@ struct impl *this = object; struct port *port; uint32_t i, j, maxsize; + int res; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -2510,17 +2560,9 @@ if (direction == SPA_DIRECTION_OUTPUT) queue_buffer(this, port, i); } - if (maxsize > this->empty_size) { - this->empty = realloc(this->empty, maxsize + MAX_ALIGN); - this->scratch = realloc(this->scratch, maxsize + MAX_ALIGN); - this->tmp0 = realloc(this->tmp0, (maxsize + MAX_ALIGN) * MAX_PORTS); - this->tmp1 = realloc(this->tmp1, (maxsize + MAX_ALIGN) * MAX_PORTS); - if (this->empty == NULL || this->scratch == NULL || - this->tmp0 == NULL || this->tmp1 == NULL) - return -errno; - memset(this->empty, 0, maxsize + MAX_ALIGN); - this->empty_size = maxsize; - } + if ((res = ensure_tmp(this, maxsize)) < 0) + return res; + port->n_buffers = n_buffers; return 0; @@ -3248,10 +3290,7 @@ free_dir(&this->dirSPA_DIRECTION_INPUT); free_dir(&this->dirSPA_DIRECTION_OUTPUT); - free(this->empty); - free(this->scratch); - free(this->tmp0); - free(this->tmp1); + free_tmp(this); if (this->resample.free) resample_free(&this->resample);
View file
pipewire-0.3.80.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -920,6 +920,12 @@ this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); spa_log_topic_init(this->log, log_topic); + this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); + if (this->data_loop == NULL) { + spa_log_error(this->log, "a data loop is needed"); + return -EINVAL; + } + this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu);
View file
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/a2dp-codec-opus.c
Changed
@@ -443,7 +443,7 @@ OPUS_05_SET_LOCATION(caps->bidi, props->bidi_location); break; default: - spa_assert(false); + spa_assert_not_reached(); }; return 0;
View file
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -1915,11 +1915,12 @@ .destroy = sco_destroy_cb, }; -static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device) +static struct rfcomm *device_find_rfcomm(struct impl *backend, struct spa_bt_device *device, + enum spa_bt_profile profile) { struct rfcomm *rfcomm; spa_list_for_each(rfcomm, &backend->rfcomm_list, link) { - if (rfcomm->device == device) + if (rfcomm->device == device && (rfcomm->profile & profile)) return rfcomm; } return NULL; @@ -1931,8 +1932,8 @@ struct impl *backend = data; struct rfcomm *rfcomm; - rfcomm = device_find_rfcomm(backend, device); - if (rfcomm == NULL || rfcomm->profile != SPA_BT_PROFILE_HFP_HF) + rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF); + if (rfcomm == NULL) return -ENOTSUP; if (codec == HFP_AUDIO_CODEC_CVSD) @@ -2097,10 +2098,12 @@ int res; res = backend_native_supports_codec(data, device, codec); - if (res <= 0) + if (res < 0) + return res; + else if (!res) return -EINVAL; - rfcomm = device_find_rfcomm(backend, device); + rfcomm = device_find_rfcomm(backend, device, SPA_BT_PROFILE_HFP_HF); if (rfcomm == NULL) return -ENOTSUP; @@ -2399,7 +2402,7 @@ DBusMessageIter it4; dbus_bool_t autoconnect; dbus_uint16_t version, chan, features; - char *str; + const char *str; if (!(backend->enabled_profiles & spa_bt_profile_from_uuid(uuid))) return -ECANCELED;
View file
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bap-codec-caps.h -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bap-codec-caps.h
Changed
@@ -97,14 +97,17 @@ }; struct bap_endpoint_qos { - uint8_t framing; - uint8_t phy; - uint8_t retransmission; - uint16_t latency; - uint32_t delay_min; - uint32_t delay_max; - uint32_t preferred_delay_min; - uint32_t preferred_delay_max; + uint8_t framing; + uint8_t phy; + uint8_t retransmission; + uint16_t latency; + uint32_t delay_min; + uint32_t delay_max; + uint32_t preferred_delay_min; + uint32_t preferred_delay_max; + uint32_t locations; + uint16_t supported_context; + uint16_t context; }; struct bap_codec_qos { @@ -118,4 +121,12 @@ uint8_t target_latency; }; +struct bap_codec_qos_full { + uint8_t cig; + uint8_t cis; + uint8_t big; + uint8_t bis; + struct bap_codec_qos qos; +}; + #endif
View file
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -627,6 +627,242 @@ static void append_basic_array_variant_dict_entry(DBusMessageIter *dict, const char* key, const char* variant_type_str, const char* array_type_str, int array_type_int, void* data, int data_size); static struct spa_bt_remote_endpoint *remote_endpoint_find(struct spa_bt_monitor *monitor, const char *path); +static bool check_iter_signature(DBusMessageIter *it, const char *sig) +{ + char *v; + bool res; + v = dbus_message_iter_get_signature(it); + res = spa_streq(v, sig); + dbus_free(v); + return res; +} + +static void parse_codec_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter, struct bap_codec_qos_full *qos) +{ + DBusMessageIter dict_iter = *iter; + + memset(qos, 0, sizeof(*qos)); + qos->cig = 0xff; + qos->cis = 0xff; + qos->big = 0xff; + qos->bis = 0xff; + + if (!check_iter_signature(&dict_iter, "{sv}")) { + spa_log_warn(monitor->log, "Invalid BAP QoS in DBus"); + return; + } + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + DBusMessageIter it2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict_iter, &it0); + dbus_message_iter_get_basic(&it0, &key); + dbus_message_iter_next(&it0); + dbus_message_iter_recurse(&it0, &it1); + + type = dbus_message_iter_get_arg_type(&it1); + + if (type == DBUS_TYPE_BYTE) { + uint8_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value); + + if (spa_streq(key, "PHY")) + qos->qos.phy = value; + else if (spa_streq(key, "Retransmissions")) + qos->qos.retransmission = value; + else if (spa_streq(key, "CIG")) + qos->cig = value; + else if (spa_streq(key, "CIS")) + qos->cis = value; + else if (spa_streq(key, "BIG")) + qos->big = value; + else if (spa_streq(key, "BIS")) + qos->bis = value; + else if (spa_streq(key, "TargetLatency")) + qos->qos.target_latency = value; + else if (spa_streq(key, "Framing")) + qos->qos.framing = value; + } + else if (type == DBUS_TYPE_UINT16) { + dbus_uint16_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value); + + if (spa_streq(key, "SDU")) + qos->qos.sdu = value; + else if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency")) + qos->qos.latency = value; + } + else if (type == DBUS_TYPE_UINT32) { + dbus_uint32_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "qos: %s=%d", key, (int)value); + + if (spa_streq(key, "Interval")) + qos->qos.interval = value; + else if (spa_streq(key, "PresentationDelay")) + qos->qos.delay = value; + } + + dbus_message_iter_next(&dict_iter); + } +} + +static void parse_endpoint_qos(struct spa_bt_monitor *monitor, DBusMessageIter *iter, + struct bap_endpoint_qos *qos) +{ + DBusMessageIter dict_iter = *iter; + + if (!check_iter_signature(&dict_iter, "{sv}")) { + spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus"); + return; + } + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + DBusMessageIter it2; + const char *key; + int type; + + dbus_message_iter_recurse(&dict_iter, &it0); + dbus_message_iter_get_basic(&it0, &key); + dbus_message_iter_next(&it0); + dbus_message_iter_recurse(&it0, &it1); + + type = dbus_message_iter_get_arg_type(&it1); + + if (type == DBUS_TYPE_BYTE) { + uint8_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value); + + if (spa_streq(key, "Framing")) + qos->framing = value; + else if (spa_streq(key, "PHY")) + qos->phy = value; + else if (spa_streq(key, "Retransmissions")) + qos->retransmission = value; + } else if (type == DBUS_TYPE_UINT16) { + dbus_uint16_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value); + + if (spa_streq(key, "Latency") || spa_streq(key, "MaximumLatency")) + qos->latency = value; + else if (spa_streq(key, "Context")) + qos->context = value; + else if (spa_streq(key, "SupportedContext")) + qos->supported_context = value; + } else if (type == DBUS_TYPE_UINT32) { + dbus_uint32_t value; + + dbus_message_iter_get_basic(&it1, &value); + spa_log_debug(monitor->log, "ep qos: %s=%d", key, (int)value); + + if (spa_streq(key, "MinimumDelay")) + qos->delay_min = value; + else if (spa_streq(key, "MaximumDelay")) + qos->delay_max = value; + else if (spa_streq(key, "PreferredMinimumDelay")) + qos->preferred_delay_min = value; + else if (spa_streq(key, "PreferredMaximumDelay")) + qos->preferred_delay_max = value; + else if (spa_streq(key, "Locations") || spa_streq(key, "Location")) + qos->locations = value; + } + + dbus_message_iter_next(&dict_iter); + } +} + +static int parse_endpoint_props(struct spa_bt_monitor *monitor, DBusMessageIter *iter, + uint8_t capsA2DP_MAX_CAPS_SIZE, int *caps_size, const char **endpoint_path, + struct bap_endpoint_qos *qos) +{ + DBusMessageIter dict_iter = *iter; + const char *key = NULL; + int type = 0; + + memset(caps, 0, A2DP_MAX_CAPS_SIZE); + *endpoint_path = NULL; + memset(qos, 0, sizeof(*qos)); + + if (!check_iter_signature(&dict_iter, "{sv}")) { + spa_log_warn(monitor->log, "Invalid BAP Endpoint QoS in DBus"); + return -EINVAL; + } + + while (dbus_message_iter_get_arg_type(&dict_iter) != DBUS_TYPE_INVALID) { + DBusMessageIter it3; + + dbus_message_iter_recurse(&dict_iter, &it0); + dbus_message_iter_get_basic(&it0, &key); + dbus_message_iter_next(&it0); + dbus_message_iter_recurse(&it0, &it1); + + type = dbus_message_iter_get_arg_type(&it1); + + if (spa_streq(key, "Capabilities")) { + uint8_t *buf; + + if (type != DBUS_TYPE_ARRAY) + goto bad_property; + + dbus_message_iter_recurse(&it1, &it2); + type = dbus_message_iter_get_arg_type(&it2); + if (type != DBUS_TYPE_BYTE) + goto bad_property; + + dbus_message_iter_get_fixed_array(&it2, &buf, caps_size); + if (*caps_size > A2DP_MAX_CAPS_SIZE) { + spa_log_error(monitor->log, "%s size:%d too large", key, (int)*caps_size);
View file
pipewire-0.3.80.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.81.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -1608,7 +1608,17 @@ name = "audio-gateway"; desc = _("Audio Gateway (A2DP Source & HSP/HFP AG)"); } - priority = 256; + + /* + * If the remote is A2DP sink and HF, we likely should prioritize being + * A2DP sender, not gateway. This can occur in PW<->PW if RFCOMM gets + * connected both as AG and HF. + */ + if ((device->connected_profiles & SPA_BT_PROFILE_A2DP_SINK) && + (device->connected_profiles & SPA_BT_PROFILE_HEADSET_HEAD_UNIT)) + priority = 15; + else + priority = 256; break; } case DEVICE_PROFILE_A2DP:
View file
pipewire-0.3.80.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/loop.c
Changed
@@ -16,6 +16,7 @@ #include <spa/support/plugin.h> #include <spa/utils/list.h> #include <spa/utils/names.h> +#include <spa/utils/ratelimit.h> #include <spa/utils/result.h> #include <spa/utils/type.h> #include <spa/utils/ringbuffer.h> @@ -64,6 +65,7 @@ struct spa_source *wakeup; int ack_fd; + struct spa_ratelimit rate_limit; struct spa_ringbuffer buffer; uint8_t *buffer_data; @@ -94,6 +96,13 @@ }; /** \endcond */ +static inline uint64_t get_time_ns(struct spa_system *system) +{ + struct timespec ts; + spa_system_clock_gettime(system, CLOCK_MONOTONIC, &ts); + return SPA_TIMESPEC_TO_NSEC(&ts); +} + static int loop_add_source(void *object, struct spa_source *source) { struct impl *impl = object; @@ -267,8 +276,12 @@ item->item_size = SPA_ROUND_UP_N(l0 + size, ITEM_ALIGN); } if (avail < item->item_size) { - spa_log_warn(impl->log, "%p: queue full %d, need %zd", impl, avail, - item->item_size); + int suppressed; + uint64_t nsec = get_time_ns(impl->system); + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, nsec)) >= 0) { + spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)", + impl, avail, item->item_size, suppressed); + } return -EPIPE; } if (data && size > 0) @@ -1004,6 +1017,8 @@ res = -EINVAL; goto error_exit; } + impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; + impl->rate_limit.burst = 1; if ((res = spa_system_pollfd_create(impl->system, SPA_FD_CLOEXEC)) < 0) { spa_log_error(impl->log, "%p: can't create pollfd: %s",
View file
pipewire-0.3.80.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.81.tar.gz/spa/plugins/support/node-driver.c
Changed
@@ -95,14 +95,18 @@ #ifdef CLOCK_MONOTONIC_RAW { "monotonic-raw", CLOCK_MONOTONIC_RAW }, #endif +#ifdef CLOCK_BOOTTIME { "boottime", CLOCK_BOOTTIME }, +#endif }; static bool clock_for_timerfd(clockid_t id) { return id == CLOCK_REALTIME || - id == CLOCK_MONOTONIC || - id == CLOCK_BOOTTIME; +#ifdef CLOCK_BOOTTIME + id == CLOCK_BOOTTIME || +#endif + id == CLOCK_MONOTONIC; } static clockid_t clock_name_to_id(const char *name)
View file
pipewire-0.3.80.tar.gz/spa/tests/stress-ringbuffer.c -> pipewire-0.3.81.tar.gz/spa/tests/stress-ringbuffer.c
Changed
@@ -11,10 +11,11 @@ #define ARRAY_SIZE 63 #define MAX_VALUE 0x10000 -#if defined(__FreeBSD__) || defined(__MidnightBSD__) +#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined (__GNU__) #include <sys/param.h> #if (__FreeBSD_version >= 1400000 && __FreeBSD_version < 1400043) \ - || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__) + || (__FreeBSD_version < 1300523) || defined(__MidnightBSD__) \ + || defined (__GNU__) static int sched_getcpu(void) { return -1; }; #endif #endif
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/demonic.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/demonic.conf
Changed
@@ -4,8 +4,9 @@ # ~/.config/pipewire/filter-chain.conf.d/ # context.modules = - { name = libpipewire-module-filter-chain - args = { + { name = libpipewire-module-filter-chain + flags = nofail + args = { #audio.format = F32 #audio.rate = 48000 audio.channels = 2
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-dolby-surround.conf
Changed
@@ -5,6 +5,7 @@ # context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Dolby Surround Sink" media.name = "Dolby Surround Sink"
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-matrix-spatialiser.conf
Changed
@@ -8,6 +8,7 @@ context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Matrix Spatialiser" media.name = "Matrix Spatialiser"
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-5.1-kemar.conf
Changed
@@ -3,8 +3,11 @@ # Copy this file into a conf.d/ directory such as # ~/.config/pipewire/filter-chain.conf.d/ # +# Adjust the paths to the convolver files to match your system +# context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Virtual Surround Sink" media.name = "Virtual Surround Sink"
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/sink-virtual-surround-7.1-hesuvi.conf
Changed
@@ -3,8 +3,11 @@ # Copy this file into a conf.d/ directory such as # ~/.config/pipewire/filter-chain.conf.d/ # +# Adjust the paths to the convolver files to match your system +# context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Virtual Surround Sink" media.name = "Virtual Surround Sink"
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/source-rnnoise.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/source-rnnoise.conf
Changed
@@ -3,8 +3,11 @@ # Copy this file into a conf.d/ directory such as # ~/.config/pipewire/filter-chain.conf.d/ # +# Adjust the paths to the rnnoise plugin to match your system +# context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Noise Canceling source" media.name = "Noise Canceling source" @@ -13,7 +16,13 @@ { type = ladspa name = rnnoise - plugin = librnnoise_ladspa + # The path to the plugin. The suffix .so is appended to + # this string and then the file is then located in the directories + # listed in the environment variable LADSPA_PATH or + # /usr/lib64/ladspa, /usr/lib/ladspa or the system library directory + # as a fallback. + # You might want to use an absolute path here to avoid problems. + plugin = "librnnoise_ladspa" label = noise_suppressor_stereo control = { "VAD Threshold (%)" 50.0
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-7.1.conf
Changed
@@ -3,8 +3,11 @@ # Copy this file into a conf.d/ directory such as # ~/.config/pipewire/filter-chain.conf.d/ # +# Adjust the paths to the sofa file to match your system. +# context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "Spatial Sink" media.name = "Spatial Sink"
View file
pipewire-0.3.80.tar.gz/src/daemon/filter-chain/spatializer-single.conf -> pipewire-0.3.81.tar.gz/src/daemon/filter-chain/spatializer-single.conf
Changed
@@ -4,8 +4,11 @@ # Copy this file into a conf.d/ directory such as # ~/.config/pipewire/filter-chain.conf.d/ # +# Adjust the paths to the sofa files to match your system +# context.modules = { name = libpipewire-module-filter-chain + flags = nofail args = { node.description = "3D Sink" media.name = "3D Sink"
View file
pipewire-0.3.80.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -28,6 +28,7 @@ args = { nice.level = -11 #rt.prio = 88 + rt.prio = 65 #rt.time.soft = -1 #rt.time.hard = -1 }
View file
pipewire-0.3.80.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.81.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -50,6 +50,8 @@ # enables autoloading of access module, when disabled an alternative # access module needs to be loaded. module.access = true + # enables autoloading of module-jackdbus-detect + module.jackdbus-detect = true } context.spa-libs = { @@ -179,6 +181,29 @@ flags = ifexists nofail condition = { module.x11.bell = true } } + { name = libpipewire-module-jackdbus-detect + args { + #jack.library = libjack.so.0 + #jack.server = null + #jack.client-name = PipeWire + #jack.connect = true + #tunnel.mode = duplex # source|sink|duplex + source.props = { + #audio.channels = 2 + #midi.ports = 1 + #audio.position = FL FR + # extra sink properties + } + sink.props = { + #audio.channels = 2 + #midi.ports = 1 + #audio.position = FL FR + # extra sink properties + } + } + flags = ifexists nofail + condition = { module.jackdbus-detect = true } + } context.objects =
View file
pipewire-0.3.80.tar.gz/src/modules/module-access.c -> pipewire-0.3.81.tar.gz/src/modules/module-access.c
Changed
@@ -143,7 +143,7 @@ * (in the current namespace). */ -#if defined(__linux__) +#if defined(__linux__) || defined(__GNU__) spa_scnprintf(path, sizeof(path), "/proc/%u/exe", pid); #elif defined(__FreeBSD__) || defined(__MidnightBSD__) spa_scnprintf(path, sizeof(path), "/proc/%u/file", pid);
View file
pipewire-0.3.80.tar.gz/src/modules/module-ffado-driver.c -> pipewire-0.3.81.tar.gz/src/modules/module-ffado-driver.c
Changed
@@ -39,7 +39,7 @@ * ## Module Options * * - `driver.mode`: the driver mode, sink|source|duplex, default duplex - * - `ffado.devices`: array of devices to open, default hw:0 + * - `ffado.devices`: array of devices to open, default "hw:0" * - `ffado.period-size`: period size,default 1024 * - `ffado.period-num`: period number,default 3 * - `ffado.sample-rate`: sample-rate, default 48000 @@ -71,7 +71,7 @@ * { name = libpipewire-module-ffado-driver * args = { * #driver.mode = duplex - * #ffado.devices = hw:0 + * #ffado.devices = "hw:0" * #ffado.period-size = 1024 * #ffado.period-num = 3 * #ffado.sample-rate = 48000 @@ -100,7 +100,7 @@ #define MAX_PORTS 128 -#define DEFAULT_DEVICES " hw:0 " +#define DEFAULT_DEVICES " \"hw:0\" " #define DEFAULT_PERIOD_SIZE 1024 #define DEFAULT_PERIOD_NUM 3 #define DEFAULT_SAMPLE_RATE 48000 @@ -113,7 +113,7 @@ #define MODULE_USAGE "( remote.name=<remote> ) " \ "( driver.mode=<sink|source|duplex> ) " \ - "( ffado.devices=<devices array size, default hw:0> ) " \ + "( ffado.devices=<devices array size, default \"hw:0\"> ) " \ "( ffado.period-size=<period size, default 1024> ) " \ "( ffado.period-num=<period num, default 3> ) " \ "( ffado.sample-rate=<sampe rate, default 48000> ) " \
View file
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -82,6 +82,12 @@ * * inputs = <portname> ... * outputs = <portname> ... + * capture.volumes = + * { control = <portname> min = <value> max = <value> scale = <scale> } ... + * + * playback.volumes = + * { control = <portname> min = <value> max = <value> scale = <scale> } ... + * * } *\endcode * @@ -137,6 +143,20 @@ * graph will then be duplicated as many times to match the number of input/output * channels of the streams. * + * ### Volumes + * + * Normally the volume of the sink/source is handled by the stream software volume. + * With the capture.volumes and playback.volumes properties this can be handled + * by a control port in the graph instead. + * + * The min and max values (defaults 0.0 and 1.0) respectively can be used to scale + * and translate the volume min and max values. + * + * Normally the control values are linear and it is assumed that the plugin does not + * perform any scaling to the values. This can be changed with the scale property. By + * default this is linear but it can be set to cubic when the control applies a + * cubic transformation. + * * ## Builtin filters * * There are some useful builtin filters available. You select them with the label @@ -576,7 +596,7 @@ uint32_t n_links; uint32_t external; - float control_data; + float control_dataMAX_HNDL; float *audio_dataMAX_HNDL; }; @@ -625,6 +645,20 @@ void **hndl; }; +struct volume { + bool mute; + uint32_t n_volumes; + float volumesSPA_AUDIO_MAX_CHANNELS; + + uint32_t n_ports; + struct port *portsSPA_AUDIO_MAX_CHANNELS; + float minSPA_AUDIO_MAX_CHANNELS; + float maxSPA_AUDIO_MAX_CHANNELS; +#define SCALE_LINEAR 0 +#define SCALE_CUBIC 1 + int scaleSPA_AUDIO_MAX_CHANNELS; +}; + struct graph { struct impl *impl; @@ -643,6 +677,9 @@ uint32_t n_control; struct port **control_port; + struct volume capture_volume; + struct volume playback_volume; + unsigned instantiated:1; }; @@ -962,35 +999,48 @@ spa_pod_builder_string(b, name); if (p->hint & FC_HINT_BOOLEAN) { - spa_pod_builder_bool(b, port->control_data <= 0.0f ? false : true); + spa_pod_builder_bool(b, port->control_data0 <= 0.0f ? false : true); } else if (p->hint & FC_HINT_INTEGER) { - spa_pod_builder_int(b, port->control_data); + spa_pod_builder_int(b, port->control_data0); } else { - spa_pod_builder_float(b, port->control_data); + spa_pod_builder_float(b, port->control_data0); } } spa_pod_builder_pop(b, &f1); return spa_pod_builder_pop(b, &f0); } +static int port_set_control_value(struct port *port, float *value, uint32_t id) +{ + struct node *node = port->node; + struct descriptor *desc = node->desc; + float old; + + old = port->control_dataid; + port->control_dataid = value ? *value : desc->default_controlport->idx; + pw_log_info("control %d %d ('%s') from %f to %f", port->idx, id, + desc->desc->portsport->p.name, old, port->control_dataid); + node->control_changed = old != port->control_dataid; + return node->control_changed ? 1 : 0; +} + static int set_control_value(struct node *node, const char *name, float *value) { - struct descriptor *desc; struct port *port; - float old; + int count = 0; + uint32_t i, n_hndl; port = find_port(node, name, FC_PORT_INPUT | FC_PORT_CONTROL); if (port == NULL) return -ENOENT; - node = port->node; - desc = node->desc; + /* if we don't have any instances yet, set the first control value, we will + * copy to other instances later */ + n_hndl = SPA_MAX(1u, port->node->n_hndl); + for (i = 0; i < n_hndl; i++) + count += port_set_control_value(port, value, i); - old = port->control_data; - port->control_data = value ? *value : desc->default_controlport->idx; - pw_log_info("control %d ('%s') from %f to %f", port->idx, name, old, port->control_data); - node->control_changed = old != port->control_data; - return node->control_changed ? 1 : 0; + return count; } static int parse_params(struct graph *graph, const struct spa_pod *pod) @@ -1082,17 +1132,115 @@ spa_pod_dynamic_builder_clean(&b); } -static void param_props_changed(struct impl *impl, const struct spa_pod *param) +static int sync_volume(struct graph *graph, struct volume *vol) +{ + uint32_t i; + int res = 0; + + if (vol->n_ports == 0) + return 0; + for (i = 0; i < vol->n_volumes; i++) { + uint32_t n_port = i % vol->n_ports, n_hndl; + struct port *p = vol->portsn_port; + float v = vol->mute ? 0.0f : vol->volumesi; + switch (vol->scalen_port) { + case SCALE_CUBIC: + v = cbrt(v); + break; + } + v = v * (vol->maxn_port - vol->minn_port) + vol->minn_port; + + n_hndl = SPA_MAX(1u, p->node->n_hndl); + res += port_set_control_value(p, &v, i % n_hndl); + } + return res; +} + +static void param_props_changed(struct impl *impl, const struct spa_pod *param, + bool capture) { struct spa_pod_object *obj = (struct spa_pod_object *) param; + struct spa_pod_frame f1; const struct spa_pod_prop *prop; struct graph *graph = &impl->graph; int changed = 0; + char buf1024; + struct spa_pod_dynamic_builder b; + struct volume *vol = capture ? &graph->capture_volume : + &graph->playback_volume; + bool do_volume = false; + + spa_pod_dynamic_builder_init(&b, buf, sizeof(buf), 1024); + spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); SPA_POD_OBJECT_FOREACH(obj, prop) { - if (prop->key == SPA_PROP_params) + switch (prop->key) { + case SPA_PROP_params: changed += parse_params(graph, &prop->value); + spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop)); + break; + case SPA_PROP_mute: + { + bool mute; + if (spa_pod_get_bool(&prop->value, &mute) == 0) { + if (vol->mute != mute) { + vol->mute = mute; + do_volume = true; + } + } + spa_pod_builder_raw_padded(&b.b, prop, SPA_POD_PROP_SIZE(prop)); + break; + }
View file
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-c.c
Changed
@@ -63,9 +63,6 @@ uint32_t i; if (n_src == 0) { dsp_clear_c(ops, dst, n_samples); - } else if (n_src == 1) { - if (dst != src0) - dsp_copy_c(ops, dst, src0, n_samples); } else { if (gain0 == 1.0f) dsp_copy_c(ops, dst, src0, n_samples);
View file
pipewire-0.3.80.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c -> pipewire-0.3.81.tar.gz/src/modules/module-filter-chain/dsp-ops-sse.c
Changed
@@ -19,7 +19,7 @@ { if (n_src == 0) { memset(dst, 0, n_samples * sizeof(float)); - } else if (n_src == 1) { + } else if (n_src == 1 && gain0 == 1.0f) { if (dst != src0) spa_memcpy(dst, src0, n_samples * sizeof(float)); } else {
View file
pipewire-0.3.80.tar.gz/src/modules/module-pipe-tunnel.c -> pipewire-0.3.81.tar.gz/src/modules/module-pipe-tunnel.c
Changed
@@ -8,6 +8,7 @@ #include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/uio.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h>
View file
pipewire-0.3.80.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.81.tar.gz/src/modules/module-profiler.c
Changed
@@ -269,7 +269,7 @@ n->count++; } -static struct pw_impl_node_rt_events node_rt_events = { +static const struct pw_impl_node_rt_events node_rt_events = { PW_VERSION_IMPL_NODE_RT_EVENTS, .complete = context_do_profile, .incomplete = context_do_profile,
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
@@ -46,7 +46,6 @@ spa_list_init(&client->out_messages); spa_list_init(&client->operations); spa_list_init(&client->pending_samples); - spa_list_init(&client->pending_streams); spa_hook_list_init(&client->listener_list); spa_list_append(&server->clients, &client->link);
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/client.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/client.h
Changed
@@ -74,8 +74,6 @@ struct spa_list pending_samples; - struct spa_list pending_streams; - unsigned int disconnect:1; unsigned int new_msg_since_last_flush:1; unsigned int authenticated:1;
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/manager.c
Changed
@@ -440,6 +440,10 @@ case SPA_PARAM_PropInfo: case SPA_PARAM_Format: case SPA_PARAM_EnumFormat: + /* also emit changed for the Latency param because the stream might + * now be linked. FIXME, we should check if a new link is made for + * a stream and only emit a changed event in that case. */ + case SPA_PARAM_Latency: changed++; break; default:
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
@@ -52,6 +52,11 @@ char *args; size_t size; + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->source_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->sink_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); + if ((f = open_memstream(&args, &size)) == NULL) return -errno;
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -832,42 +832,43 @@ } if (spa_streq(o->type, PW_TYPE_INTERFACE_Link)) { - struct stream *s, *t; struct pw_manager_object *peer = NULL; union pw_map_item *item; pw_array_for_each(item, &client->streams.items) { struct stream *s = item->data; const char *peer_name; - if (pw_map_item_is_free(item) || s->pending) + if (pw_map_item_is_free(item)) continue; - if (s->peer_index == SPA_ID_INVALID) + + if (!s->pending && s->peer_index == SPA_ID_INVALID) continue; peer = find_peer_for_link(manager, o, s->id, s->direction); - if (peer == NULL || peer->props == NULL || - peer->index == s->peer_index) + if (peer == NULL) continue; - s->peer_index = peer->index; - - peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME); - if (peer_name && s->direction == PW_DIRECTION_INPUT && - pw_manager_object_is_monitor(peer)) { - int len = strlen(peer_name) + 10; - char *tmp = alloca(len); - snprintf(tmp, len, "%s.monitor", peer_name); - peer_name = tmp; - } - if (peer_name != NULL) - stream_send_moved(s, peer->index, peer_name); - } - spa_list_for_each_safe(s, t, &client->pending_streams, link) { - peer = find_peer_for_link(manager, o, s->id, s->direction); - if (peer) { + if (s->pending) { reply_create_stream(s, peer); - spa_list_remove(&s->link); s->pending = false; + } else { + if (s->peer_index == peer->index) + continue; + if (peer->props == NULL) + continue; + + s->peer_index = peer->index; + + peer_name = pw_properties_get(peer->props, PW_KEY_NODE_NAME); + if (peer_name && s->direction == PW_DIRECTION_INPUT && + pw_manager_object_is_monitor(peer)) { + int len = strlen(peer_name) + 10; + char *tmp = alloca(len); + snprintf(tmp, len, "%s.monitor", peer_name); + peer_name = tmp; + } + if (peer_name != NULL) + stream_send_moved(s, peer->index, peer_name); } } } @@ -1244,7 +1245,6 @@ if (peer) { reply_create_stream(stream, peer); } else { - spa_list_append(&stream->client->pending_streams, &stream->link); stream->pending = true; } } @@ -5483,9 +5483,23 @@ const char *str; int res = 0; + debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn); + impl = calloc(1, sizeof(*impl) + user_data_size); if (impl == NULL) - goto error_exit; + goto error_free_props; + + impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; + impl->rate_limit.burst = 1; + spa_hook_list_init(&impl->hooks); + spa_list_init(&impl->servers); + pw_map_init(&impl->samples, 16, 16); + pw_map_init(&impl->modules, 16, 16); + spa_list_init(&impl->cleanup_clients); + spa_list_init(&impl->free_messages); + + impl->loop = pw_context_get_main_loop(context); + impl->work_queue = pw_context_get_work_queue(context); if (props == NULL) props = pw_properties_new(NULL, NULL); @@ -5503,25 +5517,6 @@ pw_properties_set(props, "vm.overrides", NULL); } - load_defaults(&impl->defs, props); - - debug_messages = pw_log_topic_enabled(SPA_LOG_LEVEL_INFO, pulse_conn); - - impl->context = context; - impl->loop = pw_context_get_main_loop(context); - impl->props = props; - - impl->work_queue = pw_context_get_work_queue(context); - - spa_hook_list_init(&impl->hooks); - spa_list_init(&impl->servers); - impl->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; - impl->rate_limit.burst = 1; - pw_map_init(&impl->samples, 16, 16); - pw_map_init(&impl->modules, 16, 16); - spa_list_init(&impl->cleanup_clients); - spa_list_init(&impl->free_messages); - str = pw_properties_get(props, "server.address"); if (str == NULL) { pw_properties_setf(props, "server.address", @@ -5544,8 +5539,6 @@ pw_log_warn("%p: can't create pid file: %s", impl, spa_strerror(res)); } - pw_context_add_listener(context, &impl->context_listener, - &context_events, impl); #ifdef HAVE_DBUS str = pw_properties_get(props, "server.dbus-name"); @@ -5554,14 +5547,22 @@ if (strlen(str) > 0) impl->dbus_name = dbus_request_name(context, str); #endif + + load_defaults(&impl->defs, props); + impl->props = spa_steal_ptr(props); + + pw_context_add_listener(context, &impl->context_listener, + &context_events, impl); + impl->context = context; + cmd_run(impl); return (struct pw_protocol_pulse *) impl; error_free: - free(impl); + impl_free(impl); -error_exit: +error_free_props: pw_properties_free(props); if (res < 0)
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
@@ -103,9 +103,6 @@ pw_log_debug("client %p: stream %p channel:%d", client, stream, stream->channel); - if (stream->pending) - spa_list_remove(&stream->link); - if (stream->drain_tag) reply_error(client, -1, stream->drain_tag, -ENOENT);
View file
pipewire-0.3.80.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
@@ -34,7 +34,6 @@ }; struct stream { - struct spa_list link; uint32_t create_tag; uint32_t channel; /* index in map */ uint32_t id; /* id of global */
View file
pipewire-0.3.80.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -44,6 +44,7 @@ #include <pipewire/i18n.h> #include "module-raop/rtsp-client.h" +#include "module-rtp/rtp.h" /** \page page_module_raop_sink PipeWire Module: AirPlay Sink * @@ -137,8 +138,8 @@ #endif #define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH) -#define DEFAULT_USER_AGENT "iTunes/11.0.4 (Windows; N)" -#define DEFAULT_USER_NAME "iTunes" +#define DEFAULT_USER_NAME "PipeWire" +#define RAOP_AUTH_USER_NAME "iTunes" #define MAX_PORT_RETRY 128 @@ -147,9 +148,9 @@ #define DEFAULT_CHANNELS 2 #define DEFAULT_POSITION " FL FR " -#define VOLUME_MAX 0.0 -#define VOLUME_DEF -30.0 -#define VOLUME_MIN -144.0 +#define VOLUME_MAX 0.0 +#define VOLUME_MIN -30.0 +#define VOLUME_MUTE -144.0 #define MODULE_USAGE "( raop.ip=<ip address of host> ) " \ "( raop.port=<remote port> ) " \ @@ -228,13 +229,14 @@ unsigned int do_disconnect:1; - uint8_t keyAES_CHUNK_SIZE; /* Key for aes-cbc */ - uint8_t ivAES_CHUNK_SIZE; /* Initialization vector for cbc */ + uint8_t aes_keyAES_CHUNK_SIZE; /* Key for aes-cbc */ + uint8_t aes_ivAES_CHUNK_SIZE; /* Initialization vector for cbc */ EVP_CIPHER_CTX *ctx; uint16_t control_port; int control_fd; struct spa_source *control_source; + struct spa_source *feedback_timer; uint16_t timing_port; int timing_fd; @@ -247,7 +249,7 @@ uint32_t block_size; uint32_t latency; - uint16_t seq; + uint16_t seq, cseq; uint32_t rtptime; uint32_t ssrc; uint32_t sync; @@ -287,7 +289,7 @@ static int aes_encrypt(struct impl *impl, uint8_t *data, int len) { int i = len & ~0xf, clen = i; - EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->key, impl->iv); + EVP_EncryptInit(impl->ctx, EVP_aes_128_cbc(), impl->aes_key, impl->aes_iv); EVP_EncryptUpdate(impl->ctx, data, &clen, data, i); return i; } @@ -308,46 +310,104 @@ static int send_udp_sync_packet(struct impl *impl, struct sockaddr *dest_addr, socklen_t addrlen) { - uint32_t pkt5; + uint32_t out3; uint32_t rtptime = impl->rtptime; uint32_t latency = impl->latency; uint64_t transmitted; + struct rtp_header header; + struct iovec iov2; + struct msghdr msg; + int res; - pkt0 = htonl(0x80d40007); + spa_zero(header); + header.v = 2; if (impl->first) - pkt0 |= htonl(0x10000000); - pkt1 = htonl(rtptime - latency); + header.x = 1; + header.m = 1; + header.pt = 84; + header.sequence_number = htons(impl->cseq); + header.timestamp = htonl(rtptime - latency); + + iov0.iov_base = &header; + iov0.iov_len = 8; + transmitted = ntp_now(); - pkt2 = htonl(transmitted >> 32); - pkt3 = htonl(transmitted & 0xffffffff); - pkt4 = htonl(rtptime); + out0 = htonl(transmitted >> 32); + out1 = htonl(transmitted & 0xffffffff); + out2 = htonl(rtptime); + + iov1.iov_base = out; + iov1.iov_len = sizeof(out); + + msg.msg_name = dest_addr; + msg.msg_namelen = addrlen; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + res = sendmsg(impl->control_fd, &msg, MSG_NOSIGNAL); + if (res < 0) { + res = -errno; + pw_log_warn("error sending control packet: %d", res); + } + + impl->cseq = (impl->cseq + 1) & 0xffff; - pw_log_debug("sync: first:%d latency:%u now:%"PRIx64" rtptime:%u", - impl->first, latency, transmitted, rtptime); + pw_log_debug("raop control sync: cseq:%d first:%d latency:%u now:%"PRIx64" rtptime:%u", + impl->cseq, impl->first, latency, transmitted, rtptime); - return sendto(impl->control_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen); + return res; } static int send_udp_timing_packet(struct impl *impl, uint64_t remote, uint64_t received, struct sockaddr *dest_addr, socklen_t addrlen) { - uint32_t pkt8; + uint32_t out6; uint64_t transmitted; + struct rtp_header header; + struct iovec iov2; + struct msghdr msg; + int res; - pkt0 = htonl(0x80d30007); - pkt1 = 0x00000000; - pkt2 = htonl(remote >> 32); - pkt3 = htonl(remote & 0xffffffff); - pkt4 = htonl(received >> 32); - pkt5 = htonl(received & 0xffffffff); - transmitted = ntp_now(); - pkt6 = htonl(transmitted >> 32); - pkt7 = htonl(transmitted & 0xffffffff); + spa_zero(header); + header.v = 2; + header.pt = 83; + header.m = 1; + + iov0.iov_base = &header; + iov0.iov_len = 8; + + out0 = htonl(remote >> 32); + out1 = htonl(remote & 0xffffffff); - pw_log_debug("sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64, + out2 = htonl(received >> 32); + out3 = htonl(received & 0xffffffff); + transmitted = ntp_now(); + out4 = htonl(transmitted >> 32); + out5 = htonl(transmitted & 0xffffffff); + + iov1.iov_base = out; + iov1.iov_len = sizeof(out); + + msg.msg_name = dest_addr; + msg.msg_namelen = addrlen; + msg.msg_iov = iov; + msg.msg_iovlen = 2; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + res = sendmsg(impl->timing_fd, &msg, MSG_NOSIGNAL); + if (res < 0) { + res = -errno; + pw_log_warn("error sending timing packet: %d", res); + } + pw_log_debug("raop timing sync: remote:%"PRIx64" received:%"PRIx64" transmitted:%"PRIx64, remote, received, transmitted); - return sendto(impl->timing_fd, pkt, sizeof(pkt), 0, dest_addr, addrlen); + return res; } static int write_codec_pcm(void *dst, void *frames, uint32_t n_frames) @@ -382,8 +442,11 @@ static int flush_to_udp_packet(struct impl *impl) { - const size_t max = 12 + 8 + impl->block_size; - uint32_t pktmax, len, n_frames;
View file
pipewire-0.3.80.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.81.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
@@ -21,12 +21,12 @@ struct message { struct spa_list link; - void *data; size_t len; size_t offset; uint32_t cseq; int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content); void *user_data; + unsigned char data; }; enum client_recv_state { @@ -598,7 +598,6 @@ fclose(f); - msg->data = SPA_PTROFF(msg, sizeof(*msg), void); msg->len = len - sizeof(*msg); msg->offset = 0; msg->reply = reply;
View file
pipewire-0.3.80.tar.gz/src/modules/module-rt.c -> pipewire-0.3.81.tar.gz/src/modules/module-rt.c
Changed
@@ -35,6 +35,9 @@ #if defined(__FreeBSD__) || defined(__MidnightBSD__) #include <sys/thr.h> #endif +#if defined(__GNU__) +#include <mach.h> +#endif #include <fcntl.h> #include <unistd.h> #include <pthread.h> @@ -221,6 +224,9 @@ long pid; thr_self(&pid); return (pid_t)pid; +#elif defined(__GNU__) + mach_port_t thread = mach_thread_self(); + return (pid_t)thread; #else #error "No gettid impl" #endif
View file
pipewire-0.3.80.tar.gz/src/modules/module-rtp-session.c -> pipewire-0.3.81.tar.gz/src/modules/module-rtp-session.c
Changed
@@ -1335,7 +1335,8 @@ if (spa_streq(service_name, "_pipewire-audio._udp")) { uint32_t mask = 0; for (l = txt; l && compatible; l = l->next) { - char *key, *value, *k = NULL; + const char *k = NULL; + char *key, *value; if (avahi_string_list_get_pair(l, &key, &value, NULL) != 0) break;
View file
pipewire-0.3.80.tar.gz/src/pipewire/conf.c -> pipewire-0.3.81.tar.gz/src/pipewire/conf.c
Changed
@@ -18,7 +18,7 @@ #ifdef HAVE_PWD_H #include <pwd.h> #endif -#if defined(__FreeBSD__) || defined(__MidnightBSD__) +#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__) #ifndef O_PATH #define O_PATH 0 #endif @@ -599,10 +599,11 @@ char key256, val1024; const char *str, *value; int match = 0, fail = 0; - int len, skip = 0; + int len; while (spa_json_get_string(&it0, key, sizeof(key)) > 0) { bool success = false; + int skip = 0; if ((len = spa_json_next(&it0, &value)) <= 0) break;
View file
pipewire-0.3.80.tar.gz/src/pipewire/context.c -> pipewire-0.3.81.tar.gz/src/pipewire/context.c
Changed
@@ -1306,9 +1306,10 @@ struct spa_fraction latency = SPA_FRACTION(0, 0); struct spa_fraction max_latency = SPA_FRACTION(0, 0); struct spa_fraction rate = SPA_FRACTION(0, 0); - uint32_t quantum, target_rate, current_rate; + uint32_t target_quantum, target_rate, current_rate, current_quantum; uint64_t quantum_stamp = 0, rate_stamp = 0; - bool force_rate, force_quantum, restore_rate = false; + bool force_rate, force_quantum, restore_rate = false, restore_quantum = false; + bool do_reconfigure = false, was_target_pending; const uint32_t *node_rates; uint32_t node_n_rates, node_def_rate; uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum; @@ -1364,10 +1365,10 @@ fraction_compare(&s->max_latency, &max_latency) < 0)) max_latency = s->max_latency; - /* largest rate */ + /* largest rate, which is in fact the smallest fraction */ if (rate.denom == 0 || (s->rate.denom > 0 && - fraction_compare(&s->rate, &rate) > 0)) + fraction_compare(&s->rate, &rate) < 0)) rate = s->rate; if (s->active) @@ -1386,6 +1387,12 @@ pw_log_info("(%s-%u) restore rate", n->name, n->info.id); restore_rate = true; } + if (n->forced_quantum && !force_quantum && n->runnable) { + /* A node that was forced to a quantum but is no longer being + * forced can restore its quantum */ + pw_log_info("(%s-%u) restore quantum", n->name, n->info.id); + restore_quantum = true; + } if (force_quantum) lock_quantum = false; @@ -1416,8 +1423,9 @@ rate.denom, target_rate); } + was_target_pending = n->target_pending; + if (target_rate != current_rate) { - bool do_reconfigure = false; /* we doing a rate switch */ pw_log_info("(%s-%u) state:%s new rate:%u/(%u)->%u", n->name, n->info.id, @@ -1427,23 +1435,17 @@ if (force_rate) { if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD) - do_reconfigure = !n->target_pending; + do_reconfigure |= !was_target_pending; } else { if (n->info.state >= PW_NODE_STATE_SUSPENDED) - do_reconfigure = !n->target_pending; + do_reconfigure |= !was_target_pending; } - if (do_reconfigure) - reconfigure_driver(context, n); - /* we're setting the pending rate. This will become the new * current rate in the next iteration of the graph. */ n->target_rate = SPA_FRACTION(1, target_rate); - n->target_pending = true; n->forced_rate = force_rate; + n->target_pending = true; current_rate = target_rate; - /* we might be suspended now and the links need to be prepared again */ - if (do_reconfigure) - goto again; } if (node_rate_quantum != 0 && current_rate != node_rate_quantum) { @@ -1460,26 +1462,42 @@ node_max_quantum = tmp; } - quantum = node_def_quantum; - if (latency.denom != 0) - quantum = (latency.num * current_rate / latency.denom); - quantum = SPA_CLAMP(quantum, node_min_quantum, node_max_quantum); - quantum = SPA_MIN(quantum, lim_quantum); - - if (settings->clock_power_of_two_quantum) - quantum = flp2(quantum); + current_quantum = n->target_quantum; + if (!restore_quantum && + (lock_quantum || n->reconfigure || !running || + (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE)))) + target_quantum = current_quantum; + else { + target_quantum = node_def_quantum; + if (latency.denom != 0) + target_quantum = (latency.num * current_rate / latency.denom); + target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum); + target_quantum = SPA_MIN(target_quantum, lim_quantum); + + if (settings->clock_power_of_two_quantum) + target_quantum = flp2(target_quantum); + } - if (running && quantum != n->target_quantum && !lock_quantum) { + if (target_quantum != current_quantum) { pw_log_info("(%s-%u) new quantum:%"PRIu64"->%u", n->name, n->info.id, n->target_quantum, - quantum); + target_quantum); /* this is the new pending quantum */ - n->target_quantum = quantum; + n->target_quantum = target_quantum; + n->forced_quantum = force_quantum; n->target_pending = true; + + if (force_quantum) + do_reconfigure |= !was_target_pending; } if (n->target_pending) { + if (do_reconfigure) { + reconfigure_driver(context, n); + /* we might be suspended now and the links need to be prepared again */ + goto again; + } /* we have a pending change. We place the new values in the * pending fields so that they are picked up by the driver in * the next cycle */ @@ -1501,8 +1519,10 @@ n->target_rate = n->rt.position->clock.target_rate; } - pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u '%s'", - context, n, running, n->runnable, quantum, n->name); + pw_log_debug("%p: driver %p running:%d runnable:%d quantum:%u rate:%u (%"PRIu64"/%u)'%s'", + context, n, running, n->runnable, target_quantum, target_rate, + n->rt.position->clock.target_duration, + n->rt.position->clock.target_rate.denom, n->name); /* first change the node states of the followers to the new target */ spa_list_for_each(s, &n->follower_list, follower_link) {
View file
pipewire-0.3.80.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-link.c
Changed
@@ -1545,6 +1545,7 @@ void pw_impl_link_destroy(struct pw_impl_link *link) { struct impl *impl = SPA_CONTAINER_OF(link, struct impl, this); + bool was_prepared = link->prepared; pw_log_debug("%p: destroy", impl); pw_log_info("(%s) destroy", link->name); @@ -1570,7 +1571,7 @@ pw_global_destroy(link->global); } - if (link->prepared) + if (was_prepared) pw_context_recalc_graph(link->context, "link destroy"); pw_log_debug("%p: free", impl);
View file
pipewire-0.3.80.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.81.tar.gz/src/pipewire/impl-node.c
Changed
@@ -8,6 +8,7 @@ #include <unistd.h> #include <errno.h> #include <time.h> +#include <malloc.h> #include <spa/support/system.h> #include <spa/pod/parser.h> @@ -1321,6 +1322,7 @@ this->target_rate = SPA_FRACTION(1, rate); this->target_quantum = quantum; + this->elapsed = 0; pos->clock.rate = pos->clock.target_rate = this->target_rate; pos->clock.duration = pos->clock.target_duration = this->target_quantum; @@ -1744,8 +1746,10 @@ if (all_ready) a->position.state = SPA_IO_POSITION_STATE_RUNNING; } - if (SPA_LIKELY(a->position.state != SPA_IO_POSITION_STATE_RUNNING)) - a->position.offset += a->position.clock.duration; + if (SPA_LIKELY(a->position.state == SPA_IO_POSITION_STATE_RUNNING)) + node->elapsed += a->position.clock.duration; + + a->position.offset = a->position.clock.position - node->elapsed; } /* Called from the data-loop and it is the starting point for driver nodes. @@ -2103,6 +2107,11 @@ spa_system_close(node->data_system, node->source.fd); free(impl); + +#ifdef HAVE_MALLOC_TRIM + int res = malloc_trim(0); + pw_log_debug("malloc_trim(): %d", res); +#endif } SPA_EXPORT
View file
pipewire-0.3.80.tar.gz/src/pipewire/mem.c -> pipewire-0.3.81.tar.gz/src/pipewire/mem.c
Changed
@@ -25,7 +25,8 @@ PW_LOG_TOPIC_EXTERN(log_mem); #define PW_LOG_TOPIC_DEFAULT log_mem -#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(HAVE_MEMFD_CREATE) +#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__) \ + && !defined(HAVE_MEMFD_CREATE) /* * No glibc wrappers exist for memfd_create(2), so provide our own. * @@ -42,7 +43,7 @@ #define HAVE_MEMFD_CREATE 1 #endif -#if defined(__FreeBSD__) || defined(__MidnightBSD__) +#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__) #define MAP_LOCKED 0 #endif
View file
pipewire-0.3.80.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.81.tar.gz/src/pipewire/pipewire.c
Changed
@@ -7,7 +7,7 @@ #include <unistd.h> #include <limits.h> #include <stdio.h> -#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) +#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__) #include <sys/prctl.h> #endif #include <pwd.h> @@ -720,7 +720,7 @@ static char namePATH_MAX; spa_memzero(name, sizeof(name)); -#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__) +#if defined(__linux__) || defined(__FreeBSD_kernel__) || defined(__MidnightBSD_kernel__) || defined(__GNU__) { if (readlink("/proc/self/exe", name, sizeof(name)-1) > 0) { prgname = strrchr(name, '/') + 1; @@ -738,7 +738,7 @@ } } #endif -#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) +#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) && !defined(__GNU__) { if (prctl(PR_GET_NAME, (unsigned long) name, 0, 0, 0) == 0) { prgname = name;
View file
pipewire-0.3.80.tar.gz/src/pipewire/private.h -> pipewire-0.3.81.tar.gz/src/pipewire/private.h
Changed
@@ -22,7 +22,7 @@ #include <spa/utils/result.h> #include <spa/utils/type-info.h> -#if defined(__FreeBSD__) || defined(__MidnightBSD__) +#if defined(__FreeBSD__) || defined(__MidnightBSD__) || defined(__GNU__) struct ucred { }; #endif @@ -673,6 +673,7 @@ unsigned int suspend_on_idle:1; unsigned int reconfigure:1; unsigned int forced_rate:1; + unsigned int forced_quantum:1; unsigned int trigger:1; /**< has the TRIGGER property and needs an extra * trigger to start processing. */ unsigned int can_suspend:1; @@ -731,6 +732,7 @@ uint64_t target_quantum; uint64_t driver_start; + uint64_t elapsed; /* elapsed time in playing */ void *user_data; /**< extra user data */ };
View file
pipewire-0.3.80.tar.gz/src/pipewire/stream.c -> pipewire-0.3.81.tar.gz/src/pipewire/stream.c
Changed
@@ -157,6 +157,7 @@ unsigned int driving:1; unsigned int using_trigger:1; unsigned int trigger:1; + unsigned int early_process:1; int in_set_param; int in_emit_param_changed; }; @@ -1103,7 +1104,7 @@ * rate matching node (audioconvert) has been scheduled to * update the values. */ ask_more = !impl->process_rt && impl->rate_match == NULL && - queue_is_empty(impl, &impl->queued) && + (impl->early_process || queue_is_empty(impl, &impl->queued)) && !queue_is_empty(impl, &impl->dequeued); pw_log_trace_fp("%p: pop %d %p ask_more:%u %p", stream, b->id, io, ask_more, impl->rate_match); @@ -1121,7 +1122,7 @@ } } else { ask_more = !impl->process_rt && - queue_is_empty(impl, &impl->queued) && + (impl->early_process || queue_is_empty(impl, &impl->queued)) && !queue_is_empty(impl, &impl->dequeued); } @@ -1912,6 +1913,7 @@ impl->node_methods.process = impl_node_process_output; impl->process_rt = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_RT_PROCESS); + impl->early_process = SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_EARLY_PROCESS); impl->impl_node.iface = SPA_INTERFACE_INIT( SPA_TYPE_INTERFACE_Node,
View file
pipewire-0.3.80.tar.gz/src/pipewire/stream.h -> pipewire-0.3.81.tar.gz/src/pipewire/stream.h
Changed
@@ -394,6 +394,11 @@ * does a trigger_process() that will then * dequeue/queue a buffer from another process() * function. since 0.3.73 */ + PW_STREAM_FLAG_EARLY_PROCESS = (1 << 11), /**< Call process as soon as there is a buffer + * to dequeue. This is only relevant for + * playback and when not using RT_PROCESS. It + * can be used to keep the maximum number of + * buffers queued. Since 0.3.81 */ }; /** Create a new unconneced \ref pw_stream
View file
pipewire-0.3.80.tar.gz/src/pipewire/thread.c -> pipewire-0.3.81.tar.gz/src/pipewire/thread.c
Changed
@@ -53,6 +53,9 @@ } #endif #endif +#if defined(__GNU__) +int pthread_setname_np(pthread_t thread, const char *name) { return 0; } +#endif static struct spa_thread *impl_create(void *object, const struct spa_dict *props,
View file
pipewire-0.3.80.tar.gz/src/pipewire/utils.h -> pipewire-0.3.81.tar.gz/src/pipewire/utils.h
Changed
@@ -15,6 +15,7 @@ #ifndef _POSIX_C_SOURCE # include <sys/mount.h> #endif +#include <errno.h> #ifndef ENODATA #define ENODATA 9919
View file
pipewire-0.3.81.tar.gz/src/tools/dfffile.c
Added
@@ -0,0 +1,313 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#include <errno.h> +#include <sys/mman.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <math.h> + +#include <spa/utils/string.h> +#include <spa/debug/mem.h> + +#include "dfffile.h" + +struct dff_file { + uint8_t *data; + size_t size; + + int mode; + int fd; + + struct dff_file_info info; + + uint8_t *p; + size_t offset; +}; + +struct dff_chunk { + uint32_t id; + uint64_t size; + void *data; +}; + +#define FOURCC(a,b,c,d) (d | (c << 8) | (b << 16) | (a << 24)) + +static inline uint16_t parse_be16(const uint8_t *in) +{ + return (in0 << 8) | in1; +} +static inline uint32_t parse_be32(const uint8_t *in) +{ + return FOURCC(in0, in1, in2, in3); +} + +static inline uint64_t parse_be64(const uint8_t *in) +{ + uint64_t res = in7; + res |= ((uint64_t)in6) << 8; + res |= ((uint64_t)in5) << 16; + res |= ((uint64_t)in4) << 24; + res |= ((uint64_t)in3) << 32; + res |= ((uint64_t)in2) << 40; + res |= ((uint64_t)in1) << 48; + res |= ((uint64_t)in0) << 56; + return res; +} + +static inline int f_avail(struct dff_file *f) +{ + if (f->p < f->data + f->size) + return f->size + f->data - f->p; + return 0; +} + +static int read_chunk(struct dff_file *f, struct dff_chunk *c) +{ + if (f_avail(f) < 12) + return -ENOSPC; + + c->id = parse_be32(f->p); /* id of this chunk */ + c->size = parse_be64(f->p + 4); /* size of this chunk */ + f->p += 12; + c->data = f->p; + return 0; +} + +static int skip_chunk(struct dff_file *f, const struct dff_chunk *c) +{ + f->p = SPA_PTROFF(c->data, c->size, uint8_t); + return 0; +} + +static int read_PROP(struct dff_file *f, struct dff_chunk *prop) +{ + struct dff_chunk c1; + int res; + + if (f_avail(f) < 4 || + memcmp(prop->data, "SND ", 4) != 0) + return -EINVAL; + f->p += 4; + + while (f->p < SPA_PTROFF(prop->data, prop->size, uint8_t)) { + if ((res = read_chunk(f, &c0)) < 0) + return res; + + switch (c0.id) { + case FOURCC('F', 'S', ' ', ' '): + f->info.rate = parse_be32(f->p); + break; + case FOURCC('C', 'H', 'N', 'L'): + f->info.channels = parse_be16(f->p); + switch (f->info.channels) { + case 2: + f->info.channel_type = 2; + break; + case 5: + f->info.channel_type = 6; + break; + case 6: + f->info.channel_type = 7; + break; + } + break; + case FOURCC('C', 'M', 'P', 'R'): + { + uint32_t cmpr = parse_be32(f->p); + if (cmpr != FOURCC('D', 'S', 'D', ' ')) + return -ENOTSUP; + break; + } + case FOURCC('A', 'B', 'S', 'S'): + break; + case FOURCC('L', 'S', 'C', 'O'): + break; + default: + break; + } + skip_chunk(f, &c0); + } + return 0; +} + +static int read_FRM8(struct dff_file *f) +{ + struct dff_chunk c2; + int res; + bool found_dsd = false; + + if ((res = read_chunk(f, &c0)) < 0) + return res; + if (c0.id != FOURCC('F','R','M','8')) + return -EINVAL; + if (f_avail(f) < 4 || + memcmp(c0.data, "DSD ", 4) != 0) + return -EINVAL; + f->p += 4; + + while (true) { + if ((res = read_chunk(f, &c1)) < 0) + return res; + + switch (c1.id) { + case FOURCC('F', 'V', 'E', 'R'): + break; + case FOURCC('P', 'R', 'O', 'P'): + read_PROP(f, &c1); + break; + case FOURCC('D', 'S', 'D', ' '): + { + f->info.length = c1.size; + f->info.samples = c1.size / f->info.channels; + f->info.lsb = 0; + f->info.blocksize = 1; + found_dsd = true; + break; + } + default: + break; + } + if (found_dsd) + break; + + skip_chunk(f, &c1); + } + return 0; +} + +static int open_read(struct dff_file *f, const char *filename, struct dff_file_info *info) +{ + int res; + struct stat st; + + if ((f->fd = open(filename, O_RDONLY)) < 0) { + res = -errno; + goto exit; + } + if (fstat(f->fd, &st) < 0) { + res = -errno; + goto exit_close; + } + f->size = st.st_size; + + f->data = mmap(NULL, f->size, PROT_READ, MAP_SHARED, f->fd, 0); + if (f->data == MAP_FAILED) { + res = -errno; + goto exit_close;
View file
pipewire-0.3.81.tar.gz/src/tools/dfffile.h
Added
@@ -0,0 +1,31 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#include <stdio.h> + +#include <spa/utils/defs.h> + +struct dff_file; + +struct dff_file_info { + uint32_t channel_type; + uint32_t channels; + uint32_t rate; + bool lsb; + uint64_t samples; + uint64_t length; + uint32_t blocksize; +}; + +struct dff_layout { + int32_t interleave; + uint32_t channels; + bool lsb; +}; + +struct dff_file * dff_file_open(const char *filename, const char *mode, struct dff_file_info *info); + +ssize_t dff_file_read(struct dff_file *f, void *data, size_t samples, const struct dff_layout *layout); + +int dff_file_close(struct dff_file *f);
View file
pipewire-0.3.80.tar.gz/src/tools/meson.build -> pipewire-0.3.81.tar.gz/src/tools/meson.build
Changed
@@ -47,6 +47,7 @@ pwcat_sources = 'pw-cat.c', 'midifile.c', + 'dfffile.c', 'dsffile.c',
View file
pipewire-0.3.80.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cat.c
Changed
@@ -41,6 +41,7 @@ #endif #include "midifile.h" +#include "dfffile.h" #include "dsffile.h" #define DEFAULT_MEDIA_TYPE "Audio" @@ -143,6 +144,11 @@ struct dsf_file_info info; struct dsf_layout layout; } dsf; + struct { + struct dff_file *file; + struct dff_file_info info; + struct dff_layout layout; + } dff; #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION struct { @@ -798,6 +804,10 @@ data->dsf.layout.channels = info.info.dsd.channels; data->dsf.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb; + data->dff.layout.interleave = info.info.dsd.interleave, + data->dff.layout.channels = info.info.dsd.channels; + data->dff.layout.lsb = info.info.dsd.bitorder == SPA_PARAM_BITORDER_lsb; + data->stride = data->dsf.layout.channels * SPA_ABS(data->dsf.layout.interleave); if (data->verbose) { @@ -1164,26 +1174,46 @@ return dsf_file_read(d->dsf.file, src, n_frames, &d->dsf.layout); } -static int setup_dsffile(struct data *data) +static int dff_play(struct data *d, void *src, unsigned int n_frames, bool *null_frame) +{ + return dff_file_read(d->dff.file, src, n_frames, &d->dff.layout); +} + +static int setup_dsdfile(struct data *data) { if (data->mode == mode_record) return -ENOTSUP; data->dsf.file = dsf_file_open(data->filename, "r", &data->dsf.info); if (data->dsf.file == NULL) { - fprintf(stderr, "dsffile: can't read dsf file '%s': %m\n", data->filename); - return -errno; + data->dff.file = dff_file_open(data->filename, "r", &data->dff.info); + if (data->dff.file == NULL) { + fprintf(stderr, "dsdfile: can't read dsd file '%s': %m\n", data->filename); + return -errno; + } } - if (data->verbose) - printf("dsffile: opened file \"%s\" channels:%d rate:%d samples:%"PRIu64" bitorder:%s\n", + if (data->dsf.file != NULL) { + if (data->verbose) + printf("dsffile: opened file \"%s\" channels:%d rate:%d " + "samples:%"PRIu64" bitorder:%s\n", data->filename, data->dsf.info.channels, data->dsf.info.rate, data->dsf.info.samples, data->dsf.info.lsb ? "lsb" : "msb"); - data->fill = dsf_play; + data->fill = dsf_play; + } else { + if (data->verbose) + printf("dfffile: opened file \"%s\" channels:%d rate:%d " + "samples:%"PRIu64" bitorder:%s\n", + data->filename, + data->dff.info.channels, data->dff.info.rate, + data->dff.info.samples, + data->dff.info.lsb ? "lsb" : "msb"); + data->fill = dff_play; + } return 0; } @@ -1839,7 +1869,7 @@ ret = setup_midifile(&data); break; case TYPE_DSD: - ret = setup_dsffile(&data); + ret = setup_dsdfile(&data); break; #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION case TYPE_ENCODED: @@ -1918,13 +1948,21 @@ case TYPE_DSD: { struct spa_audio_info_dsd info; + uint32_t channel_type; spa_zero(info); - info.channels = data.dsf.info.channels; - info.rate = data.dsf.info.rate / 8; + if (data.dsf.file != NULL) { + info.channels = data.dsf.info.channels; + info.rate = data.dsf.info.rate / 8; + channel_type = data.dsf.info.channel_type; + } else { + info.channels = data.dff.info.channels; + info.rate = data.dff.info.rate / 8; + channel_type = data.dff.info.channel_type; + } SPA_FOR_EACH_ELEMENT_VAR(dsd_layouts, i) { - if (i->type != data.dsf.info.channel_type) + if (i->type != channel_type) continue; info.channels = i->info.n_channels; memcpy(info.position, i->info.position, @@ -2020,6 +2058,10 @@ sf_close(data.file); if (data.midi.file) midi_file_close(data.midi.file); + if (data.dsf.file) + dsf_file_close(data.dsf.file); + if (data.dff.file) + dff_file_close(data.dff.file); #ifdef HAVE_PW_CAT_FFMPEG_INTEGRATION if (data.encoded.packet) av_packet_free(&data.encoded.packet);
View file
pipewire-0.3.80.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.81.tar.gz/src/tools/pw-cli.c
Changed
@@ -348,6 +348,10 @@ bool ret; global = calloc(1, sizeof(struct global)); + if (global == NULL) { + fprintf(stderr, "Allocation failed: %m"); + return; + } global->rd = rd; global->id = id; global->permissions = permissions; @@ -615,6 +619,8 @@ struct pw_core_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\tcookie: %u\n", info->cookie); printf("\tuser-name: \"%s\"\n", info->user_name); printf("\thost-name: \"%s\"\n", info->host_name); @@ -629,6 +635,8 @@ struct pw_module_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\tname: \"%s\"\n", info->name); printf("\tfilename: \"%s\"\n", info->filename); printf("\targs: \"%s\"\n", info->args); @@ -641,6 +649,8 @@ struct pw_node_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), info->n_input_ports, info->max_input_ports); printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), @@ -661,6 +671,8 @@ struct pw_port_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); print_properties(info->props, MARK_CHANGE(PW_PORT_CHANGE_MASK_PROPS), true); print_params(info->params, info->n_params, MARK_CHANGE(PW_PORT_CHANGE_MASK_PARAMS), true); @@ -672,6 +684,8 @@ struct pw_factory_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\tname: \"%s\"\n", info->name); printf("\tobject-type: %s/%d\n", info->type, info->version); print_properties(info->props, MARK_CHANGE(PW_FACTORY_CHANGE_MASK_PROPS), true); @@ -683,6 +697,8 @@ struct pw_client_info *info = pd->info; info_global(pd); + if (info == NULL) + return; print_properties(info->props, MARK_CHANGE(PW_CLIENT_CHANGE_MASK_PROPS), true); info->change_mask = 0; } @@ -692,6 +708,8 @@ struct pw_link_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\toutput-node-id: %u\n", info->output_node_id); printf("\toutput-port-id: %u\n", info->output_port_id); printf("\tinput-node-id: %u\n", info->input_node_id); @@ -717,6 +735,8 @@ struct pw_device_info *info = pd->info; info_global(pd); + if (info == NULL) + return; print_properties(info->props, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PROPS), true); print_params(info->params, info->n_params, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PARAMS), true); info->change_mask = 0; @@ -727,6 +747,8 @@ struct pw_session_info *info = pd->info; info_global(pd); + if (info == NULL) + return; print_properties(info->props, MARK_CHANGE(0), true); print_params(info->params, info->n_params, MARK_CHANGE(1), true); info->change_mask = 0; @@ -738,6 +760,8 @@ const char *direction; info_global(pd); + if (info == NULL) + return; printf("\tname: %s\n", info->name); printf("\tmedia-class: %s\n", info->media_class); switch(info->direction) { @@ -765,6 +789,8 @@ struct pw_endpoint_stream_info *info = pd->info; info_global(pd); + if (info == NULL) + return; printf("\tid: %u\n", info->id); printf("\tendpoint-id: %u\n", info->endpoint_id); printf("\tname: %s\n", info->name); @@ -987,25 +1013,25 @@ struct remote_data *rd = pd->rd; struct pw_session_info *info = pd->info; - if (!info) { + if (info == NULL) info = pd->info = calloc(1, sizeof(*info)); + if (info != NULL) { info->id = update->id; + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) { + info->n_params = update->n_params; + free(info->params); + info->params = malloc(info->n_params * sizeof(struct spa_param_info)); + memcpy(info->params, update->params, + info->n_params * sizeof(struct spa_param_info)); + } + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { + pw_properties_free ((struct pw_properties *)info->props); + info->props = + (struct spa_dict *) pw_properties_new_dict (update->props); + } } - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) { - info->n_params = update->n_params; - free(info->params); - info->params = malloc(info->n_params * sizeof(struct spa_param_info)); - memcpy(info->params, update->params, - info->n_params * sizeof(struct spa_param_info)); - } - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { - pw_properties_free ((struct pw_properties *)info->props); - info->props = - (struct spa_dict *) pw_properties_new_dict (update->props); - } - if (pd->global == NULL) - pd->global = pw_map_lookup(&rd->globals, info->id); + pd->global = pw_map_lookup(&rd->globals, update->id); if (pd->global && pd->global->info_pending) { info_session(pd); pd->global->info_pending = false; @@ -1034,33 +1060,34 @@ struct remote_data *rd = pd->rd; struct pw_endpoint_info *info = pd->info; - if (!info) { + if (info == NULL) info = pd->info = calloc(1, sizeof(*info)); + if (info != NULL) { info->id = update->id; info->name = update->name ? strdup(update->name) : NULL; info->media_class = update->media_class ? strdup(update->media_class) : NULL; info->direction = update->direction; info->flags = update->flags; - } - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS) - info->n_streams = update->n_streams; - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION) - info->session_id = update->session_id; - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) { - info->n_params = update->n_params; - free(info->params); - info->params = malloc(info->n_params * sizeof(struct spa_param_info)); - memcpy(info->params, update->params, - info->n_params * sizeof(struct spa_param_info)); - } - if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { - pw_properties_free ((struct pw_properties *)info->props); - info->props = - (struct spa_dict *) pw_properties_new_dict (update->props); - } + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_STREAMS) + info->n_streams = update->n_streams; + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_SESSION) + info->session_id = update->session_id; + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PARAMS) { + info->n_params = update->n_params; + free(info->params); + info->params = malloc(info->n_params * sizeof(struct spa_param_info)); + memcpy(info->params, update->params, + info->n_params * sizeof(struct spa_param_info)); + } + if (update->change_mask & PW_ENDPOINT_CHANGE_MASK_PROPS) { + pw_properties_free ((struct pw_properties *)info->props); + info->props = + (struct spa_dict *) pw_properties_new_dict (update->props); + } + } if (pd->global == NULL)
View file
pipewire-0.3.80.tar.gz/src/tools/pw-link.c -> pipewire-0.3.81.tar.gz/src/tools/pw-link.c
Changed
@@ -197,7 +197,9 @@ static void print_port(struct data *data, const char *prefix, struct object *n, struct object *p, bool verbose) { - char buffer1024, id64 = "", *prefix2 = ""; + char buffer1024, id64 = ""; + const char *prefix2 = ""; + if (data->opt_id) { snprintf(id, sizeof(id), "%4d ", p->id); prefix2 = " ";
View file
pipewire-0.3.80.tar.gz/test/pwtest.c -> pipewire-0.3.81.tar.gz/test/pwtest.c
Changed
@@ -1207,7 +1207,7 @@ time_t t = time(NULL); struct tm *tm = localtime(&t); char *dir; - char *tmpdir = getenv("TMPDIR"); + const char *tmpdir = getenv("TMPDIR"); char pathPATH_MAX; FILE *fp;
View file
pipewire-0.3.80.tar.gz/test/test-logger.c -> pipewire-0.3.81.tar.gz/test/test-logger.c
Changed
@@ -232,7 +232,7 @@ enum spa_log_level level = pwtest_get_iteration(current_test); enum spa_log_level default_level = pw_log_level; struct spa_log *default_logger = pw_log_get(); - char *lvl = NULL; + const char *lvl = NULL; char *oldenv = getenv("PIPEWIRE_DEBUG"); if (oldenv) @@ -276,7 +276,7 @@ struct spa_log *default_logger = pw_log_get(); char *oldenv = getenv("PIPEWIRE_DEBUG"); char lvlstr32; - char *lvl = "X"; + const char *lvl = "X"; if (oldenv) oldenv = strdup(oldenv);
View file
pipewire-0.3.80.tar.gz/test/test-spa-json.c -> pipewire-0.3.81.tar.gz/test/test-spa-json.c
Changed
@@ -166,7 +166,7 @@ return PWTEST_PASS; } -static void test_array(char *str, char **vals) +static void test_array(const char *str, const char * const vals) { struct spa_json it2; char val256; @@ -183,12 +183,12 @@ PWTEST(json_array) { - test_array("FL,FR", (char *){ "FL", "FR", NULL }); - test_array(" FL , FR ", (char *){ "FL", "FR", NULL }); - test_array(" FL , FR ", (char *){ "FL", "FR", NULL }); - test_array("FL FR", (char *){ "FL", "FR", NULL }); - test_array("FL FR", (char *){ "FL", "FR", NULL }); - test_array(" FL FR ", (char *){ "FL", "FR", NULL }); + test_array("FL,FR", (const char *){ "FL", "FR", NULL }); + test_array(" FL , FR ", (const char *){ "FL", "FR", NULL }); + test_array(" FL , FR ", (const char *){ "FL", "FR", NULL }); + test_array("FL FR", (const char *){ "FL", "FR", NULL }); + test_array("FL FR", (const char *){ "FL", "FR", NULL }); + test_array(" FL FR ", (const char *){ "FL", "FR", NULL }); return PWTEST_PASS; }
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.