Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 4
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,14 @@ ------------------------------------------------------------------- +Fri Feb 18 14:59:46 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.47 + +------------------------------------------------------------------- +Thu Feb 17 13:55:01 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.46 + +------------------------------------------------------------------- Fri Feb 4 06:41:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.45
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.45 +Version: 0.3.47 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.45.tar.gz/pipewire-jack/src/match-rules.c
Deleted
@@ -1,141 +0,0 @@ -/* PipeWire - * - * Copyright © 2021 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <string.h> -#include <stdio.h> -#include <errno.h> -#include <math.h> -#include <time.h> -#include <regex.h> - -#include "config.h" - -#include <spa/utils/json.h> -#include <spa/utils/string.h> - -#include <pipewire/pipewire.h> - -static bool find_match(struct spa_json *arr, const struct spa_dict *props) -{ - struct spa_json it[1]; - - while (spa_json_enter_object(arr, &it[0]) > 0) { - char key[256], val[1024]; - const char *str, *value; - int match = 0, fail = 0; - int len; - - while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { - bool success = false; - - if ((len = spa_json_next(&it[0], &value)) <= 0) - break; - - str = spa_dict_lookup(props, key); - - if (spa_json_is_null(value, len)) { - success = str == NULL; - } else { - if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) - continue; - value = val; - len = strlen(val); - } - if (str != NULL) { - if (value[0] == '~') { - regex_t preg; - if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { - if (regexec(&preg, str, 0, NULL, 0) == 0) - success = true; - regfree(&preg); - } - } else if (strncmp(str, value, len) == 0 && - strlen(str) == (size_t)len) { - success = true; - } - } - if (success) { - match++; - pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value); - } - else - fail++; - } - if (match > 0 && fail == 0) - return true; - } - return false; -} - -int pw_jack_match_rules(const char *rules, size_t size, const struct spa_dict *props, - int (*matched) (void *data, const char *action, const char *val, size_t len), - void *data) -{ - const char *val; - struct spa_json it[4], actions; - int count = 0; - - spa_json_init(&it[0], rules, size); - if (spa_json_enter_array(&it[0], &it[1]) < 0) - return 0; - - while (spa_json_enter_object(&it[1], &it[2]) > 0) { - char key[64]; - bool have_match = false, have_actions = false; - - while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) { - if (spa_streq(key, "matches")) { - if (spa_json_enter_array(&it[2], &it[3]) < 0) - break; - - have_match = find_match(&it[3], props); - } - else if (spa_streq(key, "actions")) { - if (spa_json_enter_object(&it[2], &actions) > 0) - have_actions = true; - } - else if (spa_json_next(&it[2], &val) <= 0) - break; - } - if (!have_match || !have_actions) - continue; - - while (spa_json_get_string(&actions, key, sizeof(key)) > 0) { - int res, len; - pw_log_debug("action %s", key); - - if ((len = spa_json_next(&actions, &val)) <= 0) - break; - - if (spa_json_is_container(val, len)) - len = spa_json_container_len(&actions, val, len); - - if ((res = matched(data, key, val, len)) < 0) - return res; - - count += res; - } - } - return count; -}
View file
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel
Deleted
-(directory)
View file
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/aec-null.c
Deleted
@@ -1,64 +0,0 @@ -/* PipeWire - * - * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "echo-cancel.h" - -struct impl { - uint32_t channels; -}; - -static void *null_create(const struct pw_properties *args, const struct spa_audio_info_raw *info) -{ - struct impl *impl; - impl = calloc(1, sizeof(struct impl)); - impl->channels = info->channels; - return impl; -} - -static void null_destroy(void *ec) -{ - free(ec); -} - -static int null_run(void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples) -{ - struct impl *impl = ec; - uint32_t i; - for (i = 0; i < impl->channels; i++) - memcpy(out[i], rec[i], n_samples * sizeof(float)); - return 0; -} - -static const struct echo_cancel_info echo_cancel_null_impl = { - .name = "null", - .info = SPA_DICT_INIT(NULL, 0), - .latency = NULL, - - .create = null_create, - .destroy = null_destroy, - - .run = null_run, -}; - -const struct echo_cancel_info *echo_cancel_null = &echo_cancel_null_impl;
View file
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/aec-webrtc.cpp
Deleted
@@ -1,163 +0,0 @@ -/* PipeWire - * - * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> - * © 2021 Arun Raghavan <arun@asymptotic.io> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <memory> -#include <utility> - -#include "echo-cancel.h" - -#include <pipewire/pipewire.h> - -#include <webrtc/modules/audio_processing/include/audio_processing.h> -#include <webrtc/modules/interface/module_common_types.h> -#include <webrtc/system_wrappers/include/trace.h> - -struct impl { - std::unique_ptr<webrtc::AudioProcessing> apm; - spa_audio_info_raw info; - std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer; - - impl(std::unique_ptr<webrtc::AudioProcessing> apm, const spa_audio_info_raw& info) - : apm(std::move(apm)), - info(info), - play_buffer(std::make_unique<float *[]>(info.channels)), - rec_buffer(std::make_unique<float *[]>(info.channels)), - out_buffer(std::make_unique<float *[]>(info.channels)) - { } -}; - -static void *webrtc_create(const struct pw_properties *args, const spa_audio_info_raw *info) -{ - bool extended_filter = pw_properties_get_bool(args, "webrtc.extended_filter", true); - bool delay_agnostic = pw_properties_get_bool(args, "webrtc.delay_agnostic", true); - bool high_pass_filter = pw_properties_get_bool(args, "webrtc.high_pass_filter", true); - bool noise_suppression = pw_properties_get_bool(args, "webrtc.noise_suppression", true); - bool voice_detection = pw_properties_get_bool(args, "webrtc.voice_detection", true); - - // Note: AGC seems to mess up with Agnostic Delay Detection, especially with speech, - // result in very poor performance, disable by default - bool gain_control = pw_properties_get_bool(args, "webrtc.gain_control", false); - - // Disable experimental flags by default - bool experimental_agc = pw_properties_get_bool(args, "webrtc.experimental_agc", false); - bool experimental_ns = pw_properties_get_bool(args, "webrtc.experimental_ns", false); - - // FIXME: Intelligibility enhancer is not currently supported - // This filter will modify playback buffer (when calling ProcessReverseStream), but now - // playback buffer modifications are discarded. - - 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)); - - webrtc::ProcessingConfig pconfig = {{ - webrtc::StreamConfig(info->rate, info->channels, false), /* input stream */ - webrtc::StreamConfig(info->rate, info->channels, false), /* output stream */ - webrtc::StreamConfig(info->rate, info->channels, false), /* reverse input stream */ - webrtc::StreamConfig(info->rate, info->channels, false), /* reverse output stream */ - }}; - - auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config)); - if (apm->Initialize(pconfig) != webrtc::AudioProcessing::kNoError) { - pw_log_error("Error initialising webrtc audio processing module"); - return nullptr; - } - - apm->high_pass_filter()->Enable(high_pass_filter); - // Always disable drift compensation since it requires drift sampling - 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); - - return new impl(std::move(apm), *info); -} - -static void webrtc_destroy(void *ec) -{ - auto impl = static_cast<struct impl *>(ec); - - delete impl; -} - -static int webrtc_run(void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples) -{ - auto impl = static_cast<struct impl *>(ec); - webrtc::StreamConfig config = - webrtc::StreamConfig(impl->info.rate, impl->info.channels, false); - unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10; - - if (n_samples * 1000 / impl->info.rate % 10 != 0) { - pw_log_error("Buffers must be multiples of 10ms in length (currently %u samples)", n_samples); - return -1; - } - - for (size_t i = 0; i < num_blocks; i ++) { - for (size_t j = 0; j < impl->info.channels; j++) { - impl->play_buffer[j] = const_cast<float *>(play[j]) + config.num_frames() * i; - impl->rec_buffer[j] = const_cast<float *>(rec[j]) + config.num_frames() * i; - impl->out_buffer[j] = out[j] + config.num_frames() * i; - } - /* FIXME: ProcessReverseStream may change the playback buffer, in which - * case we should use that, if we ever expose the intelligibility - * enhancer */ - if (impl->apm->ProcessReverseStream(impl->play_buffer.get(), config, config, impl->play_buffer.get()) != - webrtc::AudioProcessing::kNoError) { - pw_log_error("Processing reverse stream failed"); - } - - // Extra delay introduced by multiple frames - impl->apm->set_stream_delay_ms((num_blocks - 1) * 10); - - if (impl->apm->ProcessStream(impl->rec_buffer.get(), config, config, impl->out_buffer.get()) != - webrtc::AudioProcessing::kNoError) { - pw_log_error("Processing stream failed"); - } - } - - return 0; -} - -static const struct echo_cancel_info echo_cancel_webrtc_impl = { - .name = "webrtc", - .info = SPA_DICT_INIT(NULL, 0), - .latency = "480/48000", - - .create = webrtc_create, - .destroy = webrtc_destroy, - - .run = webrtc_run, -}; - -const struct echo_cancel_info *echo_cancel_webrtc = &echo_cancel_webrtc_impl;
View file
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel/echo-cancel.h
Deleted
@@ -1,50 +0,0 @@ -/* PipeWire - * - * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include "config.h" - -#include <spa/utils/dict.h> -#include <spa/param/audio/raw.h> - -#include <pipewire/properties.h> - -struct echo_cancel_info { - const char *name; - const struct spa_dict info; - const char *latency; - - void *(*create) (const struct pw_properties *args, const struct spa_audio_info_raw *info); - void (*destroy) (void *ec); - - int (*run) (void *ec, const float *rec[], const float *play[], float *out[], uint32_t n_samples); -}; - -#define echo_cancel_create(i,...) (i)->create(__VA_ARGS__) -#define echo_cancel_destroy(i,...) (i)->destroy(__VA_ARGS__) -#define echo_cancel_run(i,...) (i)->run(__VA_ARGS__) - -#ifdef HAVE_WEBRTC -extern const struct echo_cancel_info *echo_cancel_webrtc; -#endif -extern const struct echo_cancel_info *echo_cancel_null;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/media-roles.c
Deleted
@@ -1,40 +0,0 @@ -/* PipeWire - * - * Copyright © 2020 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include <stddef.h> - -#include "media-roles.h" - -const struct str_map media_role_map[] = { - { "Movie", "video", }, - { "Music", "music", }, - { "Game", "game", }, - { "Notification", "event", }, - { "Communication", "phone", }, - { "Movie", "animation", }, - { "Production", "production", }, - { "Accessibility", "a11y", }, - { "Test", "test", }, - { NULL, NULL }, -};
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/media-roles.h
Deleted
@@ -1,50 +0,0 @@ -/* PipeWire - * - * Copyright © 2020 Wim Taymans - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifndef PULSE_SERVER_MEDIA_ROLES_H -#define PULSE_SERVER_MEDIA_ROLES_H - -#include <stddef.h> - -#include <spa/utils/string.h> - -struct str_map { - const char *pw_str; - const char *pa_str; - const struct str_map *child; -}; - -extern const struct str_map media_role_map[]; - -static inline const struct str_map *str_map_find(const struct str_map *map, const char *pw, const char *pa) -{ - size_t i; - for (i = 0; map[i].pw_str; i++) - if ((pw && spa_streq(map[i].pw_str, pw)) || - (pa && spa_streq(map[i].pa_str, pa))) - return &map[i]; - return NULL; -} - -#endif /* PULSE_SERVER_MEDIA_ROLES_H */
View file
pipewire-0.3.45.tar.gz/.gitlab-ci.yml -> pipewire-0.3.47.tar.gz/.gitlab-ci.yml
Changed
@@ -25,7 +25,7 @@ .fedora: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2022-01-28.0' + FDO_DISTRIBUTION_TAG: '2022-02-16.0' FDO_DISTRIBUTION_VERSION: '35' FDO_DISTRIBUTION_PACKAGES: >- alsa-lib-devel @@ -142,7 +142,7 @@ FDO_DISTRIBUTION_EXEC: >- mkdir -p /opt ; cd /opt ; - curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/linux64 + curl -o /tmp/cov-analysis-linux64.tgz https://scan.coverity.com/download/cxx/linux64 --form project=$COVERITY_SCAN_PROJECT_NAME --form token=$COVERITY_SCAN_TOKEN ; tar xf /tmp/cov-analysis-linux64.tgz ; mv cov-analysis-linux64-* coverity ;
View file
pipewire-0.3.45.tar.gz/NEWS -> pipewire-0.3.47.tar.gz/NEWS
Changed
@@ -1,3 +1,110 @@ +# PipeWire 0.3.47 (2022-02-18) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +This is a quick emergency release to fix some severe +problems with the previous release. + +## Highlights + - Fixes a bug in pulse-server that caused cached notifications + to play multiple times. (#2142) + - Removed check and warnings to catch leaked listeners on the + proxy. This might access invalid memory and cause infinite + loops in older wireplumber. + +Older versions: + +# PipeWire 0.3.46 (2022-02-17) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a critical bug in pipewire-pulse buffer size handling that made some + apps (MuseScore, ... ) stutter. + - Fix a critical bug where devices would not show when the kernel was + compiled without VERBOSE_PROCSFS. + - JACK clients will now use lock-quantum by default. This makes sure that + all dynamic quantum changes are disabled while a JACK app is running. + The only way to force a quantum chance is through a JACK app or with + the metadata. + - Almost all limits on number of ports, clients and nodes are removed. + - A Dummy fallback sink is now automatically created when there are no + other sinks. This avoids stalling browsers. + - Sound sharing with Zoom should work better. A new WirePlumber release + might be required. + - Many more fixes and improvements. + + +## PipeWire + - Update docs with new config overrides. + - The rule matching logic was moved to config and code is now shared with + pulse-server and JACK. + - Add new Romanian translation. + - When a quantum is forced with metadata, any node that asked to lock-quantum + is ignored so that the quantum change can happen. + - Fix a bug where a mixer was removed twice, leading to potential memory + corruption. + - The port limits on nodes and filters are now removed. Some code was + simplified. + - Fix a potential leak because listeners where removed while they could be + emitted. + - Improve context.exec and avoid zombie processes. + +## Modules + - The RAOP module now has a default latency of 2 seconds, like PulseAudio. + - The echo-cancel module now uses the plugin loader to load the backends. + This makes it possible to add custom, out of tree, echo cancel plugins. + +## Tools + - Improve help of pw-link. + - Output to stdout and error to stderr. Use setlinebuf for stdout to improve + piping between apps. (#2110) + +## SPA + - Improve removing sources when dispatching. Also improve performance now + that a destroy loop can be removed. (#2114) + - Fix an fd leak in the logger when logging to a file. + - Improve loop enter/leave checks and support recursive loops. + +## pulse-server + - Clamp various buffer attributes to the max length. Fixes some issues + with various applications. (#2100) + - Module properties are now remapped correctly from their pulseaudio variant + to the PipeWire ones. + - Fix module index in introspect. Use the right index when loaded from our + internal modules. (#2101) + - Improve argument parsing and node.description. (#2086) + - The sink-index should now be filled in correctly when playing a sample. + (#2129) + - module-always-sink is now implemented and loaded by default. (#1838) + - Add support for loading some modules only once. + - Module load and unload now does extra sync to make it appear synchronous, + like in PulseAudio. This improves sounds sharing in Zoom. + +## ALSA + - Fix critial bug where alsa devices would not show when the kernel was + compiled without VERBOSE_PROCFS. + - Some corner cases were fixed in the ALSA timing code. When the capture node + is follower, it will now not try to read too much data and xrun but it will + instead produce a cycle of silence. + - Various fixes and improvements to make ALSA devices resync to the driver + more quickly and accurately. + +## JACK + - Add an option to name the defauld device as `system` to improve + compatibility with some applications, + - Use lock-quantum by default. This makes sure that all dynamic quantum + changes are disabled while a JACK app is running. The only way to force + a quantum chance is through a JACK app or with the metadata. + - It is now possible to do IPC calls from the data thread. Note that this + is a very bad idea but required for compatibility with JACK2. + +## GStreamer + - GStreamer sink will now set a default channelmap to make it possible to + remap to the channel layout of the device. + # PipeWire 0.3.45 (2022-02-03) This is a bugfix release that is API and ABI compatible with previous @@ -62,9 +169,6 @@ switch quantum and ensure it can't change for the lifetime of the JACK app. (#2079) -Older versions: - - # PipeWire 0.3.44 (2022-01-27) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.45.tar.gz/doc/pipewire-daemon.dox -> pipewire-0.3.47.tar.gz/doc/pipewire-daemon.dox
Changed
@@ -62,8 +62,18 @@ - `$sysconfdir/pipewire/pipewire.conf` (usually `/etc/pipewire/pipewire.conf`) - `$datadir/pipewire/pipewire.conf` (usually `/usr/share/pipewire/pipewire.conf`) -The first configuration file found is loaded, the PipeWire daemon does not -currently combine configuration files. +The first configuration file found is loaded as the base configuration. + +Next, configuration sections are collected in the directories in this +order: + +- `$datadir/pipewire/pipewire.conf.d/` (usually `/usr/share/pipewire/pipewire.conf.d/`) +- `$sysconfdir/pipewire/pipewire.conf.d/` (usually `/etc/pipewire/pipewire.conf.d/`) +- `$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/` (usually `$HOME/.config/pipewire/pipewire.conf.d/`) + +They are applied to the global configuration file. Properties are overwritten +and array elements are appended. This makes it possible to make small custom customizations +or additions to the main configuration file. The environment variables `PIPEWIRE_CONFIG_DIR`, `PIPEWIRE_CONFIG_PREFIX` and `PIPEWIRE_CONFIG_NAME` can be used to specify an alternative config
View file
pipewire-0.3.45.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.47.tar.gz/doc/pipewire-modules.dox
Changed
@@ -59,6 +59,7 @@ - \subpage page_module_echo_cancel - \subpage page_module_example_sink - \subpage page_module_example_source +- \subpage page_module_fallback_sink - \subpage page_module_filter_chain - \subpage page_module_link_factory - \subpage page_module_loopback
View file
pipewire-0.3.45.tar.gz/man/meson.build -> pipewire-0.3.47.tar.gz/man/meson.build
Changed
@@ -19,7 +19,7 @@ 'pw-profiler.1.rst.in', ] -if not get_option('pipewire-jack').disabled() +if get_option('pipewire-jack').allowed() manpages += 'pw-jack.1.rst.in' endif
View file
pipewire-0.3.45.tar.gz/man/pipewire.conf.5.rst.in -> pipewire-0.3.47.tar.gz/man/pipewire.conf.5.rst.in
Changed
@@ -19,13 +19,19 @@ *@PIPEWIRE_CONFDATADIR@/pipewire.conf* +*@PIPEWIRE_CONFDATADIR@/pipewire.conf.d/* + +*@PIPEWIRE_CONFIG_DIR@/pipewire.conf.d/* + +*$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/* + DESCRIPTION =========== PipeWire is a service that facilitates sharing of multimedia content between devices and applications. -On startup, the daemon reads a configuration file to configure +On startup, the daemon reads a main configuration file to configure itself. It executes a series of commands listed in the config file. @@ -34,6 +40,13 @@ and ``PIPEWIRE_CONFIG_NAME`` can be used to specify an alternative config directory, subdirectory and file respectively. +Next to the configuration file can be a directory with the same name as +the file with a ``.d/`` suffix. All directories in the SYNOPSIS_ directory +search paths are traversed in the listed order and the contents of the +``*.conf`` files inside them are appended to the main configuration file +as overrides. Object sections are merged and array sections are appended. + + CONFIGURATION FILE FORMAT ========================= @@ -51,6 +64,17 @@ name = [ { k = v1 } { k = v2 } ] # an array of dictionaries + +The configuration files can be expressed in full JSON syntax but for ease +of use, a relaxed format may be used where: + + * ``:`` to delimit keys and values can be substuted by ``=`` or a space. + * ``"`` around keys and string can be omited as long as no special characters + are used in the strings. + * ``,`` to separate objects can be replaced with a whitespace character. + * ``#`` can be used to start a comment until the line end + + CONFIGURATION FILE SECTIONS ===========================
View file
pipewire-0.3.45.tar.gz/meson.build -> pipewire-0.3.47.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', ['c' ], - version : '0.3.45', + version : '0.3.47', license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ], meson_version : '>= 0.59.0', default_options : [ 'warning_level=3', @@ -202,8 +202,6 @@ cdata.set_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir) cdata.set_quoted('PLUGINDIR', spa_plugindir) cdata.set_quoted('SPADATADIR', spa_datadir) -# FIXME: --with-memory-alignment],[8,N,malloc,pagesize (default is 32)]) option -cdata.set('MEMORY_ALIGNMENT_MALLOC', 1) cdata.set_quoted('PA_ALSA_PATHS_DIR', alsadatadir / 'paths') cdata.set_quoted('PA_ALSA_PROFILE_SETS_DIR', alsadatadir / 'profile-sets') @@ -211,95 +209,38 @@ cdata.set('WORDS_BIGENDIAN', 1) endif -check_headers = [['dlfcn.h','HAVE_DLFCN_H'], - ['inttypes.h', 'HAVE_INTTYPES_H'], - ['memory.h', 'HAVE_MEMORY_H'], - ['poll.h', 'HAVE_POLL_H'], - ['stddef.h', 'HAVE_STDDEF_H'], - ['stdint.h', 'HAVE_STDINT_H'], - ['stdio_ext.h', 'HAVE_STDIO_EXT_H'], - ['strings.h', 'HAVE_STRINGS_H'], - ['string.h', 'HAVE_STRING_H'], +check_headers = [ ['sys/mount.h', 'HAVE_SYS_MOUNT_H'], ['sys/param.h', 'HAVE_SYS_PARAM_H'], - ['sys/poll.h', 'HAVE_SYS_POLL_H'], - ['sys/prctl.h', 'HAVE_SYS_PRCTL_H'], ['sys/random.h', 'HAVE_SYS_RANDOM_H'], - ['sys/socket.h', 'HAVE_SYS_SOCKET_H'], - ['sys/stat.h', 'HAVE_SYS_STAT_H'], - ['sys/times.h', 'HAVE_SYS_TIMES_H'], - ['sys/time.h', 'HAVE_SYS_TIME_H'], - ['sys/types.h', 'HAVE_SYS_TYPES_H'], - ['sys/utsname.h', 'HAVE_SYS_UTSNAME_H'], ['sys/vfs.h', 'HAVE_SYS_VFS_H'], - ['sys/wait.h', 'HAVE_SYS_WAIT_H'], ['pwd.h', 'HAVE_PWD_H'], - ['ucontext.h', 'HAVE_UCONTEXT_H'], - ['unistd.h', 'HAVE_UNISTD_H'], ] foreach h : check_headers - if cc.has_header(h.get(0)) - cdata.set(h.get(1), 1) - endif + cdata.set(h.get(1), cc.has_header(h.get(0))) endforeach -if cc.has_function('poll', prefix : '#include<poll.h>') - cdata.set('HAVE_POLL', 1) -endif -if cc.has_function('pselect', prefix : '#include<sys/select.h>') - cdata.set('HAVE_PSELECT', 1) -endif -cdata.set('HAVE_MMAP', 1) - -if cc.has_function('posix_memalign', prefix : '#include<stdlib.h>') - cdata.set('HAVE_POSIX_MEMALIGN', 1) -endif -if cc.has_function('getpagesize', prefix : '#include<unistd.h>') - cdata.set('HAVE_GETPAGESIZE', 1) -endif -if cc.has_function('gettid', prefix : '#include<unistd.h>', args: [ '-D_GNU_SOURCE' ]) - cdata.set('HAVE_GETTID', 1) -endif -if cc.has_function('clock_gettime', prefix : '#include <time.h>') - cdata.set('HAVE_CLOCK_GETTIME', 1) -endif - -if cc.has_type('ptrdiff_t', prefix : '#include <stddef.h>') - cdata.set('HAVE_PTRDIFF_T', 1) -endif - -if cc.has_header_symbol('string.h', 'strndupa', args : [ '-D_GNU_SOURCE' ]) - cdata.set('HAVE_STRNDUPA', 1) -endif - -if cc.has_function('mkstemp', prefix : '#include <stdlib.h>') - cdata.set('HAVE_MKSTEMP', 1) -endif - -if cc.has_function('memfd_create', prefix : '#include <sys/mman.h>', args : [ '-D_GNU_SOURCE' ]) - cdata.set('HAVE_MEMFD_CREATE', 1) -endif - -if cc.has_function('getrandom', prefix : '#include <stddef.h>\n#include <sys/random.h>', args : [ '-D_GNU_SOURCE' ]) - cdata.set('HAVE_GETRANDOM', 1) -endif +check_functions = [ + ['gettid', '#include <unistd.h>', ['-D_GNU_SOURCE']], + ['memfd_create', '#include <sys/mman.h>', ['-D_GNU_SOURCE']], + ['getrandom', '#include <stddef.h>\n#include <sys/random.h>', ['-D_GNU_SOURCE']], + ['sigabbrev_np', '#include <string.h>', ['-D_GNU_SOURCE']], +] -if cc.has_function('sigabbrev_np', prefix : '#include <string.h>', args : [ '-D_GNU_SOURCE' ]) - cdata.set('HAVE_SIGABBREV_NP', 1) -endif +foreach f : check_functions + cdata.set('HAVE_' + f.get(0).to_upper(), + cc.has_function(f.get(0), prefix: f.get(1), args: f.get(2))) +endforeach -if cc.get_define('SYS_pidfd_open', prefix : '#include <sys/syscall.h>') != '' - cdata.set('HAVE_PIDFD_OPEN', 1) -endif +cdata.set('HAVE_PIDFD_OPEN', + cc.get_define('SYS_pidfd_open', prefix: '#include <sys/syscall.h>') != '') systemd = dependency('systemd', required: get_option('systemd')) systemd_dep = dependency('libsystemd',required: get_option('systemd')) summary({'systemd conf data': systemd.found()}, bool_yn: true) summary({'libsystemd': systemd_dep.found()}, bool_yn: true) -if systemd.found() and systemd_dep.found() - cdata.set('HAVE_SYSTEMD', 1) -endif +cdata.set('HAVE_SYSTEMD', systemd.found() and systemd_dep.found()) configinc = include_directories('.') includes_inc = include_directories('include') @@ -326,9 +267,7 @@ pthread_lib = dependency('threads') dbus_dep = dependency('dbus-1', required : get_option('dbus')) summary({'dbus (Bluetooth, rt, portal, pw-reserve)': dbus_dep.found()}, bool_yn: true, section: 'Misc dependencies') -if dbus_dep.found() - cdata.set('HAVE_DBUS', 1) -endif +cdata.set('HAVE_DBUS', dbus_dep.found()) sdl_dep = dependency('sdl2', required : get_option('sdl2')) summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies') drm_dep = dependency('libdrm', required : false) @@ -342,9 +281,7 @@ ncurses_dep = dependency('ncursesw', required : false) sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile')) summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain') -if sndfile_dep.found() - cdata.set('HAVE_SNDFILE', 1) -endif +cdata.set('HAVE_SNDFILE', sndfile_dep.found()) pulseaudio_dep = dependency('libpulse', required : get_option('libpulse')) summary({'libpulse': pulseaudio_dep.found()}, bool_yn: true, section: 'Streaming between daemons') avahi_dep = dependency('avahi-client', required : get_option('avahi')) @@ -361,14 +298,10 @@ libusb_dep = dependency('libusb-1.0', required : get_option('libusb')) summary({'libusb (Bluetooth quirks)': libusb_dep.found()}, bool_yn: true, section: 'Backend') -if libusb_dep.found() - cdata.set('HAVE_LIBUSB', 1) -endif +cdata.set('HAVE_LIBUSB', libusb_dep.found()) cap_lib = dependency('libcap', required : false) -if cap_lib.found() - cdata.set('HAVE_LIBCAP', 1) -endif +cdata.set('HAVE_LIBCAP', cap_lib.found()) gst_option = get_option('gstreamer') gst_deps_def = { @@ -403,18 +336,13 @@ gst_dp_found = gst_dep.length() > 0 summary({'gstreamer-device-provider': gst_dp_found}, bool_yn: true, section: 'Backend') -if not get_option('gstreamer-device-provider').disabled() - cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', 1) -endif +cdata.set('HAVE_GSTREAMER_DEVICE_PROVIDER', get_option('gstreamer-device-provider').allowed()) webrtc_dep = dependency('webrtc-audio-processing', version : ['>= 0.2', '< 1.0'], required : get_option('echo-cancel-webrtc')) summary({'WebRTC Echo Canceling': webrtc_dep.found()}, bool_yn: true, section: 'Misc dependencies') - -if webrtc_dep.found() - cdata.set('HAVE_WEBRTC', 1) -endif +cdata.set('HAVE_WEBRTC', webrtc_dep.found()) # On FreeBSD, epoll-shim library is required for eventfd() and timerfd() epoll_shim_dep = (build_machine.system() == 'freebsd' @@ -450,35 +378,33 @@ lilv_lib = dependency('lilv-0', required: get_option('lv2')) summary({'lilv (for lv2 plugins)': lilv_lib.found()}, bool_yn: true) -if lilv_lib.found() - cdata.set('HAVE_LILV', 1) -endif +cdata.set('HAVE_LILV', lilv_lib.found()) installed_tests_metadir = pipewire_datadir / 'installed-tests' / pipewire_name installed_tests_execdir = pipewire_libexecdir / 'installed-tests' / pipewire_name -installed_tests_enabled = not get_option('installed_tests').disabled() +installed_tests_enabled = get_option('installed_tests').allowed() installed_tests_template = files('template.test.in') -if not get_option('tests').disabled() +if get_option('tests').allowed() gstack = find_program('gstack', required : false) - cdata.set10('HAVE_GSTACK', gstack.found()) + cdata.set('HAVE_GSTACK', gstack.found()) endif subdir('po') subdir('spa') subdir('src') -if not get_option('tests').disabled() +if get_option('tests').allowed() subdir('test') endif configure_file(output : 'config.h', configuration : cdata) -if not get_option('pipewire-jack').disabled() +if get_option('pipewire-jack').allowed() subdir('pipewire-jack') endif -if not get_option('pipewire-v4l2').disabled() +if get_option('pipewire-v4l2').allowed() subdir('pipewire-v4l2') endif @@ -489,7 +415,7 @@ endif generate_manpages = false -if not get_option('man').disabled() +if get_option('man').allowed() rst2man = find_program('rst2man', required: false) if not rst2man.found() rst2man = find_program('rst2man.py', required: get_option('man'))
View file
pipewire-0.3.45.tar.gz/pipewire-jack/src/meson.build -> pipewire-0.3.47.tar.gz/pipewire-jack/src/meson.build
Changed
@@ -1,7 +1,6 @@ pipewire_jack_sources = [ 'export.c', 'pipewire-jack.c', - 'match-rules.c', 'ringbuffer.c', 'uuid.c', ]
View file
pipewire-0.3.45.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.47.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -64,15 +64,13 @@ #define JACK_CLIENT_NAME_SIZE 128 #define JACK_PORT_NAME_SIZE 256 -#define JACK_PORT_MAX 4096 #define JACK_PORT_TYPE_SIZE 32 -#define CONNECTION_NUM_FOR_PORT 1024 #define MONITOR_EXT " Monitor" +#define MAX_MIDI_MIX 1024 #define MAX_BUFFER_FRAMES 8192 #define MAX_ALIGN 16 -#define MAX_PORTS 1024 #define MAX_BUFFERS 2 #define MAX_BUFFER_DATAS 1u @@ -380,6 +378,7 @@ } rt; pthread_mutex_t rt_lock; + unsigned int rt_locked:1; unsigned int started:1; unsigned int active:1; @@ -396,6 +395,7 @@ unsigned int filter_name:1; unsigned int freewheeling:1; unsigned int locked_process:1; + unsigned int default_as_system:1; int self_connect_mode; int rt_max; @@ -808,7 +808,9 @@ int res = 0; \ if (c->callback) { \ if (pthread_mutex_trylock(&c->rt_lock) == 0) { \ + c->rt_locked = true; \ res = c->callback(__VA_ARGS__); \ + c->rt_locked = false; \ pthread_mutex_unlock(&c->rt_lock); \ } \ } \ @@ -859,6 +861,8 @@ static int do_sync(struct client *client) { + bool in_data_thread = pw_data_loop_in_thread(client->loop); + if (pw_thread_loop_in_thread(client->context.loop)) { pw_log_warn("sync requested from callback"); return 0; @@ -869,8 +873,14 @@ client->pending_sync = pw_proxy_sync((struct pw_proxy*)client->core, client->pending_sync); while (true) { + if (in_data_thread && client->rt_locked) + pthread_mutex_unlock(&client->rt_lock); + pw_thread_loop_wait(client->context.loop); + if (in_data_thread && client->rt_locked) + pthread_mutex_lock(&client->rt_lock); + if (client->error) return client->last_res; @@ -891,6 +901,7 @@ struct client *client = data; client->node = NULL; spa_hook_remove(&client->proxy_listener); + spa_hook_remove(&client->node_listener); } static void on_node_bound(void *data, uint32_t global_id) @@ -3087,7 +3098,8 @@ } -static int execute_match(void *data, const char *action, const char *val, int len) +static int execute_match(void *data, const char *location, const char *action, + const char *val, size_t len) { struct client *client = data; if (spa_streq(action, "update-props")) @@ -3095,19 +3107,6 @@ return 1; } -static int apply_jack_rules(void *data, const char *location, const char *section, - const char *str, size_t len) -{ - struct client *client = data; - const struct pw_properties *p = - pw_context_get_properties(client->context.context); - - if (p != NULL) - pw_jack_match_rules(str, len, &p->dict, execute_match, client); - - return 0; -} - SPA_EXPORT jack_client_t * jack_client_open (const char *client_name, jack_options_t options, @@ -3171,15 +3170,15 @@ if ((str = getenv("PIPEWIRE_PROPS")) != NULL) pw_properties_update_string(client->props, str, strlen(str)); - - pw_context_conf_section_for_each(client->context.context, "jack.rules", - apply_jack_rules, client); + pw_context_conf_section_match_rules(client->context.context, "jack.rules", + &client->props->dict, execute_match, client); client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true); client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false); client->short_name = pw_properties_get_bool(client->props, "jack.short-name", false); client->filter_name = pw_properties_get_bool(client->props, "jack.filter-name", false); client->locked_process = pw_properties_get_bool(client->props, "jack.locked-process", true); + client->default_as_system = pw_properties_get_bool(client->props, "jack.default-as-system", false); client->self_connect_mode = SELF_CONNECT_ALLOW; if ((str = pw_properties_get(client->props, "jack.self-connect-mode")) != NULL) { @@ -3221,8 +3220,8 @@ spa_list_init(&client->mix); spa_list_init(&client->free_mix); - pw_map_init(&client->ports[SPA_DIRECTION_INPUT], MAX_PORTS, 32); - pw_map_init(&client->ports[SPA_DIRECTION_OUTPUT], MAX_PORTS, 32); + pw_map_init(&client->ports[SPA_DIRECTION_INPUT], 32, 32); + pw_map_init(&client->ports[SPA_DIRECTION_OUTPUT], 32, 32); spa_list_init(&client->free_ports); pw_thread_loop_start(client->context.loop); @@ -3278,6 +3277,8 @@ pw_properties_set(client->props, PW_KEY_MEDIA_ROLE, "DSP"); if (pw_properties_get(client->props, PW_KEY_NODE_ALWAYS_PROCESS) == NULL) pw_properties_set(client->props, PW_KEY_NODE_ALWAYS_PROCESS, "true"); + if (pw_properties_get(client->props, PW_KEY_NODE_LOCK_QUANTUM) == NULL) + pw_properties_set(client->props, PW_KEY_NODE_LOCK_QUANTUM, "true"); pw_properties_set(client->props, PW_KEY_NODE_TRANSPORT_SYNC, "true"); client->node = pw_core_create_object(client->core, @@ -3295,8 +3296,8 @@ &client->proxy_listener, &node_proxy_events, client); client->info = SPA_NODE_INFO_INIT(); - client->info.max_input_ports = MAX_PORTS; - client->info.max_output_ports = MAX_PORTS; + client->info.max_input_ports = UINT32_MAX; + client->info.max_output_ports = UINT32_MAX; client->info.change_mask = SPA_NODE_CHANGE_MASK_FLAGS | SPA_NODE_CHANGE_MASK_PROPS; client->info.flags = SPA_NODE_FLAG_RT; @@ -3383,11 +3384,14 @@ pw_thread_loop_stop(c->context.loop); - if (c->registry) + if (c->registry) { + spa_hook_remove(&c->registry_listener); pw_proxy_destroy((struct pw_proxy*)c->registry); + } if (c->metadata && c->metadata->proxy) { pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy); } + spa_hook_remove(&c->core_listener); pw_core_disconnect(c->core); pw_context_destroy(c->context.context); @@ -3996,15 +4000,12 @@ int jack_set_buffer_size (jack_client_t *client, jack_nframes_t nframes) { struct client *c = (struct client *) client; - char latency[128]; spa_return_val_if_fail(c != NULL, -EINVAL); - snprintf(latency, sizeof(latency), "%d/%d", nframes, jack_get_sample_rate(client)); - pw_log_info("%p: buffer-size %s", client, latency); + pw_log_info("%p: buffer-size %u", client, nframes); pw_thread_loop_lock(c->context.loop); - pw_properties_set(c->props, PW_KEY_NODE_LATENCY, latency); pw_properties_setf(c->props, PW_KEY_NODE_FORCE_QUANTUM, "%u", nframes); c->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS; @@ -4334,7 +4335,7 @@ { struct mix *mix; void *ptr = p->emptyptr; - struct spa_pod_sequence *seq[CONNECTION_NUM_FOR_PORT]; + struct spa_pod_sequence *seq[MAX_MIDI_MIX]; uint32_t n_seq = 0; jack_midi_clear_buffer(ptr); @@ -4358,6 +4359,8 @@ continue; seq[n_seq++] = pod; + if (n_seq == MAX_MIDI_MIX) + break; } convert_to_midi(seq, n_seq, ptr); @@ -4439,12 +4442,23 @@ return jack_port_uuid_generate(o->serial); } +static const char *port_name(struct object *o) +{ + const char *name; + struct client *c = o->client; + if (c->default_as_system && is_port_default(c, o)) + name = o->port.system; + else + name = o->port.name; + return name; +} + SPA_EXPORT const char * jack_port_name (const jack_port_t *port) { struct object *o = (struct object *) port; spa_return_val_if_fail(o != NULL, NULL); - return o->port.name; + return port_name(o); } SPA_EXPORT @@ -4452,7 +4466,7 @@ { struct object *o = (struct object *) port; spa_return_val_if_fail(o != NULL, NULL); - return strchr(o->port.name, ':') + 1; + return strchr(port_name(o), ':') + 1; } SPA_EXPORT @@ -4583,11 +4597,12 @@ struct object *p, *l; const char **res; int count = 0; + struct pw_array tmp; spa_return_val_if_fail(c != NULL, NULL); spa_return_val_if_fail(o != NULL, NULL); - res = malloc(sizeof(char*) * (CONNECTION_NUM_FOR_PORT + 1)); + pw_array_init(&tmp, sizeof(void*) * 32); pthread_mutex_lock(&c->context.lock); spa_list_for_each(l, &c->context.objects, link) { @@ -4603,18 +4618,18 @@ if (p == NULL) continue; - res[count++] = p->port.name; - if (count == CONNECTION_NUM_FOR_PORT) - break; + pw_array_add_ptr(&tmp, (void*)port_name(p)); + count++; } pthread_mutex_unlock(&c->context.lock); if (count == 0) { - free(res); + pw_array_clear(&tmp); res = NULL; - } else - res[count] = NULL; - + } else { + pw_array_add_ptr(&tmp, NULL); + res = tmp.data; + } return res; } @@ -5340,7 +5355,7 @@ struct client *c = (struct client *) client; const char **res; struct object *o; - struct object *tmp[JACK_PORT_MAX]; + struct pw_array tmp; const char *str; uint32_t i, count, id; int r; @@ -5370,14 +5385,14 @@ port_name_pattern, type_name_pattern, flags); pthread_mutex_lock(&c->context.lock); + pw_array_init(&tmp, sizeof(void*) * 32); count = 0; + spa_list_for_each(o, &c->context.objects, link) { if (o->type != INTERFACE_Port || o->removed) continue; pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c, o->port.type_id, o->port.flags, o->port.name); - if (count == JACK_PORT_MAX) - break; if (o->port.type_id > TYPE_ID_VIDEO) continue; if (!SPA_FLAG_IS_SET(o->port.flags, flags)) @@ -5398,21 +5413,22 @@ 0, NULL, 0) == REG_NOMATCH) continue; } - pw_log_debug("%p: port \"%s\" prio:%d matches (%d)", c, o->port.name, o->port.priority, count); - tmp[count++] = o; + + pw_array_add_ptr(&tmp, o); + count++; } pthread_mutex_unlock(&c->context.lock); if (count > 0) { - qsort(tmp, count, sizeof(struct object *), port_compare_func); - - res = malloc(sizeof(char*) * (count + 1)); + qsort(tmp.data, count, sizeof(struct object *), port_compare_func); + pw_array_add_ptr(&tmp, NULL); + res = tmp.data; for (i = 0; i < count; i++) - res[i] = tmp[i]->port.name; - res[count] = NULL; + res[i] = port_name((struct object*)res[i]); } else { + pw_array_clear(&tmp); res = NULL; }
View file
pipewire-0.3.45.tar.gz/po/LINGUAS -> pipewire-0.3.47.tar.gz/po/LINGUAS
Changed
@@ -36,6 +36,7 @@ pl pt_BR pt +ro ru sk sr@latin
View file
pipewire-0.3.45.tar.gz/po/POTFILES.in -> pipewire-0.3.47.tar.gz/po/POTFILES.in
Changed
@@ -2,6 +2,7 @@ src/daemon/pipewire.desktop.in src/modules/module-protocol-pulse/modules/module-tunnel-sink.c src/modules/module-protocol-pulse/modules/module-tunnel-source.c +src/modules/module-fallback-sink.c src/modules/module-pulse-tunnel.c src/modules/module-zeroconf-discover.c src/tools/pw-cat.c
View file
pipewire-0.3.47.tar.gz/po/ro.po
Added
@@ -0,0 +1,679 @@ +# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER +# This file is distributed under the same license as the pipewire package. +# +# Sergiu Bivol <sergiu@cip.md>, 2022. +msgid "" +msgstr "" +"Project-Id-Version: pipewire\n" +"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/issues/" +"new\n" +"POT-Creation-Date: 2021-11-17 15:06+0100\n" +"PO-Revision-Date: 2022-02-05 12:06+0000\n" +"Last-Translator: Sergiu Bivol <sergiu@cip.md>\n" +"Language-Team: Romanian\n" +"Language: ro\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=3; plural=n==1 ? 0 : (n==0 || (n%100 > 0 && n%100 <" +" 20)) ? 1 : 2;\n" +"X-Generator: Lokalize 21.12.2\n" + +#: src/daemon/pipewire.c:45 +#, c-format +msgid "" +"%s [options]\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -c, --config Load config (Default %s)\n" +msgstr "" +"%s [opțiuni]\n" +" -h, --help Arată acest ajutor\n" +" --version Arată versiunea\n" +" -c, --config Încarcă configurare (implicit %s)\n" + +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:185 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:185 +#, c-format +msgid "Tunnel to %s/%s" +msgstr "Tunelează spre %s/%s" + +#: src/modules/module-pulse-tunnel.c:536 +#, c-format +msgid "Tunnel for %s@%s" +msgstr "Tunelează pentru %s@%s" + +#: src/modules/module-zeroconf-discover.c:332 +msgid "Unknown device" +msgstr "Dispozitiv necunoscut" + +#: src/modules/module-zeroconf-discover.c:344 +#, c-format +msgid "%s on %s@%s" +msgstr "%s pe %s@%s" + +#: src/modules/module-zeroconf-discover.c:348 +#, c-format +msgid "%s on %s" +msgstr "%s pe %s" + +#: src/tools/pw-cat.c:1058 +#, c-format +msgid "" +"%s [options] <file>\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -v, --verbose Enable verbose operations\n" +"\n" +msgstr "" +"%s [opțiuni] <fișier>\n" +" -h, --help Arată acest ajutor\n" +" --version Arată versiunea\n" +" -v, --verbose Activează operații verboase\n" +"\n" + +#: src/tools/pw-cat.c:1065 +#, c-format +msgid "" +" -R, --remote Remote daemon name\n" +" --media-type Set media type (default %s)\n" +" --media-category Set media category (default %s)\n" +" --media-role Set media role (default %s)\n" +" --target Set node target (default %s)\n" +" 0 means don't link\n" +" --latency Set node latency (default %s)\n" +" Xunit (unit = s, ms, us, ns)\n" +" or direct samples (256)\n" +" the rate is the one of the source " +"file\n" +" --list-targets List available targets for --target\n" +"\n" +msgstr "" +" -R, --remote Denumirea demonului distant\n" +" --media-type Stabilește tipul mediului (implicit " +"%s)\n" +" --media-category Stabilește categoria mediului" +" (implicit %s)\n" +" --media-role Stabilește rolul mediului (implicit " +"%s)\n" +" --target Stabilește ținta nodului (implicit " +"%s)\n" +" 0 înseamnă „nu lega”\n" +" --latency Stabilește latența nodului (implicit " +"%s)\n" +" Xunit (unitate = s, ms, us, ns)\n" +" sau mostre directe (256)\n" +" rata este cea a fișierului sursă\n" +" --list-targets Enumeră țintele disponibile pentru" +" --target\n" +"\n" + +#: src/tools/pw-cat.c:1083 +#, c-format +msgid "" +" --rate Sample rate (req. for rec) (default " +"%u)\n" +" --channels Number of channels (req. for rec) " +"(default %u)\n" +" --channel-map Channel map\n" +" one of: \"stereo\", " +"\"surround-51\",... or\n" +" comma separated list of channel " +"names: eg. \"FL,FR\"\n" +" --format Sample format %s (req. for rec) " +"(default %s)\n" +" --volume Stream volume 0-1.0 (default %.3f)\n" +" -q --quality Resampler quality (0 - 15) (default " +"%d)\n" +"\n" +msgstr "" +" --rate Rată de eșantionare (nec. pt." +" înregistrare) (implicit %u)\n" +" --channels Număr de canale (nec. pt." +" înregistrare) (implicit %u)\n" +" --channel-map Hartă canale\n" +" una dintre: \"stereo\"," +" \"surround-51\",... sau listă\n" +" separată prin virgulă cu denumiri" +" de canale: de ex. \"FL,FR\"\n" +" --format Format de eșantionare %s (nec. pt." +" înregistrare) (implicit %s)\n" +" --volume Volum flux 0-1.0 (implicit %.3f)\n" +" -q --quality Calitate de re-eșantionare (0 - 15)" +" (implicit %d)\n" +"\n" + +#: src/tools/pw-cat.c:1100 +msgid "" +" -p, --playback Playback mode\n" +" -r, --record Recording mode\n" +" -m, --midi Midi mode\n" +" -d, --dsd DSD mode\n" +"\n" +msgstr "" +" -p, --playback Regim de redare\n" +" -r, --record Regim de înregistrare\n" +" -m, --midi Regim MIDI\n" +" -d, --dsd regim DSD\n" +"\n" + +#: src/tools/pw-cli.c:3018 +#, c-format +msgid "" +"%s [options] [command]\n" +" -h, --help Show this help\n" +" --version Show version\n" +" -d, --daemon Start as daemon (Default false)\n" +" -r, --remote Remote daemon name\n" +"\n" +msgstr "" +"%s [opțiuni] [comandă]\n" +" -h, --help Arată acest ajutor\n" +" --version Arată versiunea\n" +" -d, --daemon Pornește ca demon (implicit fals)\n" +" -r, --remote Denumire demon distant\n" +"\n" + +#: spa/plugins/alsa/acp/acp.c:321 +msgid "Pro Audio" +msgstr "Pro Audio" + +#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1145 +msgid "Off" +msgstr "Oprit" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2652 +msgid "Input" +msgstr "Intrare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2653 +msgid "Docking Station Input" +msgstr "Intrare stație de andocare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2654 +msgid "Docking Station Microphone" +msgstr "Microfon stație de andocare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2655 +msgid "Docking Station Line In" +msgstr "Linie de intrare stație de andocare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2656 +#: spa/plugins/alsa/acp/alsa-mixer.c:2747 +msgid "Line In" +msgstr "Linie de intrare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2657 +#: spa/plugins/alsa/acp/alsa-mixer.c:2741 +#: spa/plugins/bluez5/bluez5-device.c:1302 +msgid "Microphone" +msgstr "Microfon" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2658 +#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +msgid "Front Microphone" +msgstr "Microfon frontal" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2659 +#: spa/plugins/alsa/acp/alsa-mixer.c:2743 +msgid "Rear Microphone" +msgstr "Microfon spate" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2660 +msgid "External Microphone" +msgstr "Microfon extern" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2661 +#: spa/plugins/alsa/acp/alsa-mixer.c:2745 +msgid "Internal Microphone" +msgstr "Microfon intern" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2662 +#: spa/plugins/alsa/acp/alsa-mixer.c:2748 +msgid "Radio" +msgstr "Radio" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2663 +#: spa/plugins/alsa/acp/alsa-mixer.c:2749 +msgid "Video" +msgstr "Video" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2664 +msgid "Automatic Gain Control" +msgstr "Control automat al nivelului de intrare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2665 +msgid "No Automatic Gain Control" +msgstr "Fără control automat al nivelului de intrare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2666 +msgid "Boost" +msgstr "Stimulare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2667 +msgid "No Boost" +msgstr "Fără stimulare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2668 +msgid "Amplifier" +msgstr "Amplificator" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2669 +msgid "No Amplifier" +msgstr "Fără amplificator" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2670 +msgid "Bass Boost" +msgstr "Stimulare bas" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2671 +msgid "No Bass Boost" +msgstr "Fără stimulare bas" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2672 +#: spa/plugins/bluez5/bluez5-device.c:1307 +msgid "Speaker" +msgstr "Difuzor" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2673 +#: spa/plugins/alsa/acp/alsa-mixer.c:2751 +msgid "Headphones" +msgstr "Căști" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2740 +msgid "Analog Input" +msgstr "Intrare analogică" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2744 +msgid "Dock Microphone" +msgstr "Microfon andocare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2746 +msgid "Headset Microphone" +msgstr "Microfon căști" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2750 +msgid "Analog Output" +msgstr "Ieșire analogică" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2752 +msgid "Headphones 2" +msgstr "Căști 2" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2753 +msgid "Headphones Mono Output" +msgstr "Ieșire mono căști" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2754 +msgid "Line Out" +msgstr "Linie de ieșire" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2755 +msgid "Analog Mono Output" +msgstr "Ieșire mono analogic" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2756 +msgid "Speakers" +msgstr "Difuzoare" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2757 +msgid "HDMI / DisplayPort" +msgstr "HDMI / DisplayPort" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2758 +msgid "Digital Output (S/PDIF)" +msgstr "Ieșire digitală (S/PDIF)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2759 +msgid "Digital Input (S/PDIF)" +msgstr "Intrare digitală (S/PDIF)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2760 +msgid "Multichannel Input" +msgstr "Intrare multicanal" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2761 +msgid "Multichannel Output" +msgstr "Ieșire multicanal" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2762 +msgid "Game Output" +msgstr "Ieșire joc" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2763 +#: spa/plugins/alsa/acp/alsa-mixer.c:2764 +msgid "Chat Output" +msgstr "Ieșire discuție" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2765 +msgid "Chat Input" +msgstr "Intrare discuție" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2766 +msgid "Virtual Surround 7.1" +msgstr "surround virtual 7.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4471 +msgid "Analog Mono" +msgstr "mono analogic" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4472 +msgid "Analog Mono (Left)" +msgstr "mono analogic (stânga)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4473 +msgid "Analog Mono (Right)" +msgstr "mono analogic (dreapta)" + +#. Note: Not translated to "Analog Stereo Input", because the source +#. * name gets "Input" appended to it automatically, so adding "Input" +#. * here would lead to the source name to become "Analog Stereo Input +#. * Input". The same logic applies to analog-stereo-output, +#. * multichannel-input and multichannel-output. +#: spa/plugins/alsa/acp/alsa-mixer.c:4474 +#: spa/plugins/alsa/acp/alsa-mixer.c:4482 +#: spa/plugins/alsa/acp/alsa-mixer.c:4483 +msgid "Analog Stereo" +msgstr "stereo analogic" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4475 +msgid "Mono" +msgstr "Mono" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4476 +msgid "Stereo" +msgstr "Stereo" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4484 +#: spa/plugins/alsa/acp/alsa-mixer.c:4642 +#: spa/plugins/bluez5/bluez5-device.c:1292 +msgid "Headset" +msgstr "Set cu cască" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4485 +#: spa/plugins/alsa/acp/alsa-mixer.c:4643 +msgid "Speakerphone" +msgstr "Difuzor" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4486 +#: spa/plugins/alsa/acp/alsa-mixer.c:4487 +msgid "Multichannel" +msgstr "multicanal" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4488 +msgid "Analog Surround 2.1" +msgstr "surround analogic 2.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4489 +msgid "Analog Surround 3.0" +msgstr "surround analogic 3.0" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4490 +msgid "Analog Surround 3.1" +msgstr "surround analogic 3.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4491 +msgid "Analog Surround 4.0" +msgstr "surround analogic 4.0" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4492 +msgid "Analog Surround 4.1" +msgstr "surround analogic 4.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4493 +msgid "Analog Surround 5.0" +msgstr "surround analogic 5.0" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4494 +msgid "Analog Surround 5.1" +msgstr "surround analogic 5.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4495 +msgid "Analog Surround 6.0" +msgstr "surround analogic 6.0" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4496 +msgid "Analog Surround 6.1" +msgstr "surround analogic 6.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4497 +msgid "Analog Surround 7.0" +msgstr "surround analogic 7.0" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4498 +msgid "Analog Surround 7.1" +msgstr "surround analogic 7.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4499 +msgid "Digital Stereo (IEC958)" +msgstr "stereo digital (IEC958)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4500 +msgid "Digital Surround 4.0 (IEC958/AC3)" +msgstr "surround digital 4.0 (IEC958/AC3)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4501 +msgid "Digital Surround 5.1 (IEC958/AC3)" +msgstr "surround digital 5.1 (IEC958/AC3)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4502 +msgid "Digital Surround 5.1 (IEC958/DTS)" +msgstr "surround digital 5.1 (IEC958/DTS)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4503 +msgid "Digital Stereo (HDMI)" +msgstr "stereo digital (HDMI)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4504 +msgid "Digital Surround 5.1 (HDMI)" +msgstr "surround digital 5.1 (HDMI)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4505 +msgid "Chat" +msgstr "Discuție" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4506 +msgid "Game" +msgstr "joc" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4640 +msgid "Analog Mono Duplex" +msgstr "Duplex mono analogic" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4641 +msgid "Analog Stereo Duplex" +msgstr "Duplex stereo analogic" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4644 +msgid "Digital Stereo Duplex (IEC958)" +msgstr "Duplex stereo digital (IEC958)" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4645 +msgid "Multichannel Duplex" +msgstr "Duplex multicanal" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4646 +msgid "Stereo Duplex" +msgstr "Duplex stereo" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4647 +msgid "Mono Chat + 7.1 Surround" +msgstr "Discuție mono + Surround 7.1" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4750 +#, c-format +msgid "%s Output" +msgstr "Ieșire %s" + +#: spa/plugins/alsa/acp/alsa-mixer.c:4757 +#, c-format +msgid "%s Input" +msgstr "Intrare %s" + +#: spa/plugins/alsa/acp/alsa-util.c:1173 +#: spa/plugins/alsa/acp/alsa-util.c:1267 +#, c-format +msgid "" +"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " +"ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgid_plural "" +"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu " +"ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgstr[0] "" +"snd_pcm_avail() a întors o valoare excepțional de mare: %lu octet (%lu ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[1] "" +"snd_pcm_avail() a întors o valoare excepțional de mare: %lu octeți (%lu ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[2] "" +"snd_pcm_avail() a întors o valoare excepțional de mare: %lu de octeți (%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." + +#: spa/plugins/alsa/acp/alsa-util.c:1239 +#, c-format +msgid "" +"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" +"%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgid_plural "" +"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s" +"%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgstr[0] "" +"snd_pcm_delay() a întors o valoare excepțional de mare: %li octet (%s%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[1] "" +"snd_pcm_delay() a întors o valoare excepțional de mare: %li octeți (%s%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[2] "" +"snd_pcm_delay() a întors o valoare excepțional de mare: %li de octeți (%s%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." + +#: spa/plugins/alsa/acp/alsa-util.c:1286 +#, c-format +msgid "" +"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail " +"%lu.\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgstr "" +"snd_pcm_avail_delay() a întors valori stranii: întârzierea %lu e mai mică" +" decât disponibilul %lu.\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." + +#: spa/plugins/alsa/acp/alsa-util.c:1329 +#, c-format +msgid "" +"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte " +"(%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgid_plural "" +"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes " +"(%lu ms).\n" +"Most likely this is a bug in the ALSA driver '%s'. Please report this issue " +"to the ALSA developers." +msgstr[0] "" +"snd_pcm_mmap_begin() a întors o valoare excepțional de mare: %lu octet (%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[1] "" +"snd_pcm_mmap_begin() a întors o valoare excepțional de mare: %lu octeți (%lu" +" ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." +msgstr[2] "" +"snd_pcm_mmap_begin() a întors o valoare excepțional de mare: %lu de octeți (" +"%lu ms).\n" +"Cel mai probabil, acesta e un defect în driver-ul ALSA „%s”. Raportați" +" această problemă dezvoltatorilor ALSA." + +#: spa/plugins/alsa/acp/channelmap.h:464 +msgid "(invalid)" +msgstr "(nevalid)" + +#: spa/plugins/alsa/acp/compat.c:189 +msgid "Built-in Audio" +msgstr "Audio încorporat" + +#: spa/plugins/alsa/acp/compat.c:194 +msgid "Modem" +msgstr "Modem" + +#: spa/plugins/bluez5/bluez5-device.c:1155 +msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" +msgstr "Poartă de acces audio (sursă A2DP și HSP/HFP AG)" + +#: spa/plugins/bluez5/bluez5-device.c:1178 +#, c-format +msgid "High Fidelity Playback (A2DP Sink, codec %s)" +msgstr "Redare de fidelitate înaltă (chiuvetă A2DP, codec %s)" + +#: spa/plugins/bluez5/bluez5-device.c:1181 +#, c-format +msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" +msgstr "Duplex de fidelitate înaltă (sursă/chiuvetă A2DP, codec %s)" + +#: spa/plugins/bluez5/bluez5-device.c:1188 +msgid "High Fidelity Playback (A2DP Sink)" +msgstr "Redare de fidelitate înaltă (chiuvetă A2DP)" + +#: spa/plugins/bluez5/bluez5-device.c:1190 +msgid "High Fidelity Duplex (A2DP Source/Sink)" +msgstr "Duplex de fidelitate înaltă (sursă/chiuvetă A2DP)" + +#: spa/plugins/bluez5/bluez5-device.c:1217 +#, c-format +msgid "Headset Head Unit (HSP/HFP, codec %s)" +msgstr "Bază pentru set cu cască (HSP/HFP, codec %s)" + +#: spa/plugins/bluez5/bluez5-device.c:1221 +msgid "Headset Head Unit (HSP/HFP)" +msgstr "Bază pentru set cu cască (HSP/HFP)" + +#: spa/plugins/bluez5/bluez5-device.c:1297 +msgid "Handsfree" +msgstr "Mâini libere" + +#: spa/plugins/bluez5/bluez5-device.c:1312 +msgid "Headphone" +msgstr "Cască" + +#: spa/plugins/bluez5/bluez5-device.c:1317 +msgid "Portable" +msgstr "Portabil" + +#: spa/plugins/bluez5/bluez5-device.c:1322 +msgid "Car" +msgstr "Mașină" + +#: spa/plugins/bluez5/bluez5-device.c:1327 +msgid "HiFi" +msgstr "HiFi" + +#: spa/plugins/bluez5/bluez5-device.c:1332 +msgid "Phone" +msgstr "Telefon" + +#: spa/plugins/bluez5/bluez5-device.c:1338 +msgid "Bluetooth" +msgstr "Bluetooth"
View file
pipewire-0.3.45.tar.gz/po/sv.po -> pipewire-0.3.47.tar.gz/po/sv.po
Changed
@@ -1,9 +1,9 @@ # Swedish translation for pipewire. -# Copyright © 2008-2021 Free Software Foundation, Inc. +# Copyright © 2008-2022 Free Software Foundation, Inc. # This file is distributed under the same license as the pipewire package. # Daniel Nylander <po@danielnylander.se>, 2008, 2012. # Josef Andersson <josef.andersson@fripost.org>, 2014, 2017. -# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021. +# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022. # # Termer: # input/output: ingång/utgång (det handlar om ljud) @@ -19,8 +19,8 @@ "Project-Id-Version: pipewire\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" "issues\n" -"POT-Creation-Date: 2021-09-21 15:31+0000\n" -"PO-Revision-Date: 2021-09-21 21:51+0200\n" +"POT-Creation-Date: 2022-02-13 15:33+0000\n" +"PO-Revision-Date: 2022-02-14 22:57+0100\n" "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -28,7 +28,7 @@ "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Poedit 3.0\n" +"X-Generator: Poedit 3.0.1\n" #: src/daemon/pipewire.c:45 #, c-format @@ -51,43 +51,36 @@ msgid "Start the PipeWire Media System" msgstr "Starta mediasystemet PipeWire" -#: src/examples/media-session/alsa-monitor.c:656 -#: spa/plugins/alsa/acp/compat.c:189 -msgid "Built-in Audio" -msgstr "Inbyggt ljud" - -#: src/examples/media-session/alsa-monitor.c:660 -#: spa/plugins/alsa/acp/compat.c:194 -msgid "Modem" -msgstr "Modem" - -#: src/examples/media-session/alsa-monitor.c:669 -#: src/modules/module-zeroconf-discover.c:296 -msgid "Unknown device" -msgstr "Okänd enhet" - -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:173 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:173 +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:188 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:188 #, c-format msgid "Tunnel to %s/%s" msgstr "Tunnel till %s/%s" -#: src/modules/module-pulse-tunnel.c:534 +#: src/modules/module-fallback-sink.c:51 +msgid "Dummy Output" +msgstr "Attrapputgång" + +#: src/modules/module-pulse-tunnel.c:536 #, c-format msgid "Tunnel for %s@%s" msgstr "Tunnel för %s@%s" -#: src/modules/module-zeroconf-discover.c:308 +#: src/modules/module-zeroconf-discover.c:332 +msgid "Unknown device" +msgstr "Okänd enhet" + +#: src/modules/module-zeroconf-discover.c:344 #, c-format msgid "%s on %s@%s" msgstr "%s på %s@%s" -#: src/modules/module-zeroconf-discover.c:312 +#: src/modules/module-zeroconf-discover.c:348 #, c-format msgid "%s on %s" msgstr "%s på %s" -#: src/tools/pw-cat.c:1055 +#: src/tools/pw-cat.c:1075 #, c-format msgid "" "%s [options] <file>\n" @@ -102,7 +95,7 @@ " -v, --verbose Aktivera utförliga operationer\n" "\n" -#: src/tools/pw-cat.c:1062 +#: src/tools/pw-cat.c:1082 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -132,7 +125,7 @@ " --list-targets Lista tillgängliga mål för --target\n" "\n" -#: src/tools/pw-cat.c:1080 +#: src/tools/pw-cat.c:1100 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -167,7 +160,7 @@ "%d)\n" "\n" -#: src/tools/pw-cat.c:1097 +#: src/tools/pw-cat.c:1117 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -181,7 +174,7 @@ " -d, --dsd DSD-läge\n" "\n" -#: src/tools/pw-cli.c:2954 +#: src/tools/pw-cli.c:3050 #, c-format msgid "" "%s [options] [command]\n" @@ -198,12 +191,12 @@ " -r, --remote Fjärrdemonnamn\n" "\n" -#: spa/plugins/alsa/acp/acp.c:310 +#: spa/plugins/alsa/acp/acp.c:321 msgid "Pro Audio" msgstr "Professionellt ljud" -#: spa/plugins/alsa/acp/acp.c:433 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1135 +#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1159 msgid "Off" msgstr "Av" @@ -230,7 +223,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1292 +#: spa/plugins/bluez5/bluez5-device.c:1328 msgid "Microphone" msgstr "Mikrofon" @@ -296,7 +289,7 @@ msgstr "Ingen basökning" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1297 +#: spa/plugins/bluez5/bluez5-device.c:1333 msgid "Speaker" msgstr "Högtalare" @@ -411,7 +404,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:4484 #: spa/plugins/alsa/acp/alsa-mixer.c:4642 -#: spa/plugins/bluez5/bluez5-device.c:1282 +#: spa/plugins/bluez5/bluez5-device.c:1318 msgid "Headset" msgstr "Headset" @@ -561,13 +554,13 @@ #: spa/plugins/alsa/acp/alsa-util.c:1239 #, c-format msgid "" -"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" -"%lu ms).\n" +"snd_pcm_delay() returned a value that is exceptionally large: %li byte " +"(%s%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." msgid_plural "" -"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s" -"%lu ms).\n" +"snd_pcm_delay() returned a value that is exceptionally large: %li bytes " +"(%s%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." msgstr[0] "" @@ -617,65 +610,73 @@ "Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera " "problemet till ALSA-utvecklarna." -#: spa/plugins/alsa/acp/channelmap.h:466 +#: spa/plugins/alsa/acp/channelmap.h:464 msgid "(invalid)" msgstr "(ogiltig)" -#: spa/plugins/bluez5/bluez5-device.c:1145 +#: spa/plugins/alsa/acp/compat.c:189 +msgid "Built-in Audio" +msgstr "Inbyggt ljud" + +#: spa/plugins/alsa/acp/compat.c:194 +msgid "Modem" +msgstr "Modem" + +#: spa/plugins/bluez5/bluez5-device.c:1170 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)" -#: spa/plugins/bluez5/bluez5-device.c:1168 +#: spa/plugins/bluez5/bluez5-device.c:1195 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1171 +#: spa/plugins/bluez5/bluez5-device.c:1198 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1178 +#: spa/plugins/bluez5/bluez5-device.c:1206 msgid "High Fidelity Playback (A2DP Sink)" msgstr "High fidelity-uppspelning (A2DP-utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1180 +#: spa/plugins/bluez5/bluez5-device.c:1208 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "High fidelity duplex (A2DP-källa/utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1207 +#: spa/plugins/bluez5/bluez5-device.c:1236 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1211 +#: spa/plugins/bluez5/bluez5-device.c:1241 msgid "Headset Head Unit (HSP/HFP)" msgstr "Headset-huvudenhet (HSP/HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1287 +#: spa/plugins/bluez5/bluez5-device.c:1323 msgid "Handsfree" msgstr "Handsfree" -#: spa/plugins/bluez5/bluez5-device.c:1302 +#: spa/plugins/bluez5/bluez5-device.c:1338 msgid "Headphone" msgstr "Hörlurar" -#: spa/plugins/bluez5/bluez5-device.c:1307 +#: spa/plugins/bluez5/bluez5-device.c:1343 msgid "Portable" msgstr "Bärbar" -#: spa/plugins/bluez5/bluez5-device.c:1312 +#: spa/plugins/bluez5/bluez5-device.c:1348 msgid "Car" msgstr "Bil" -#: spa/plugins/bluez5/bluez5-device.c:1317 +#: spa/plugins/bluez5/bluez5-device.c:1353 msgid "HiFi" msgstr "HiFi" -#: spa/plugins/bluez5/bluez5-device.c:1322 +#: spa/plugins/bluez5/bluez5-device.c:1358 msgid "Phone" msgstr "Telefon" -#: spa/plugins/bluez5/bluez5-device.c:1328 +#: spa/plugins/bluez5/bluez5-device.c:1364 msgid "Bluetooth" msgstr "Bluetooth"
View file
pipewire-0.3.45.tar.gz/spa/include/meson.build -> pipewire-0.3.47.tar.gz/spa/include/meson.build
Changed
@@ -3,6 +3,7 @@ 'control', 'debug', 'graph', + 'interfaces', 'monitor', 'node', 'param',
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/buffer.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/buffer.h
Changed
@@ -38,14 +38,11 @@ * \{ */ +#include <spa/debug/log.h> #include <spa/debug/mem.h> #include <spa/debug/types.h> #include <spa/buffer/type-info.h> -#ifndef spa_debug -#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -#endif - static inline int spa_debug_buffer(int indent, const struct spa_buffer *buffer) { uint32_t i;
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/dict.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/dict.h
Changed
@@ -34,12 +34,9 @@ * \{ */ +#include <spa/debug/log.h> #include <spa/utils/dict.h> -#ifndef spa_debug -#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -#endif - static inline int spa_debug_dict(int indent, const struct spa_dict *dict) { const struct spa_dict_item *item;
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/format.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/format.h
Changed
@@ -35,6 +35,7 @@ */ #include <spa/pod/parser.h> +#include <spa/debug/log.h> #include <spa/debug/types.h> #include <spa/param/type-info.h> #include <spa/param/format-utils.h> @@ -45,7 +46,7 @@ { switch (type) { case SPA_TYPE_Bool: - fprintf(stderr, "%s", *(int32_t *) body ? "true" : "false"); + spa_debugn("%s", *(int32_t *) body ? "true" : "false"); break; case SPA_TYPE_Id: { @@ -55,41 +56,41 @@ snprintf(tmp, sizeof(tmp), "%d", *(int32_t*)body); str = tmp; } - fprintf(stderr, "%s", str); + spa_debugn("%s", str); break; } case SPA_TYPE_Int: - fprintf(stderr, "%d", *(int32_t *) body); + spa_debugn("%d", *(int32_t *) body); break; case SPA_TYPE_Long: - fprintf(stderr, "%" PRIi64, *(int64_t *) body); + spa_debugn("%" PRIi64, *(int64_t *) body); break; case SPA_TYPE_Float: - fprintf(stderr, "%f", *(float *) body); + spa_debugn("%f", *(float *) body); break; case SPA_TYPE_Double: - fprintf(stderr, "%g", *(double *) body); + spa_debugn("%g", *(double *) body); break; case SPA_TYPE_String: - fprintf(stderr, "%s", (char *) body); + spa_debugn("%s", (char *) body); break; case SPA_TYPE_Rectangle: { struct spa_rectangle *r = (struct spa_rectangle *)body; - fprintf(stderr, "%" PRIu32 "x%" PRIu32, r->width, r->height); + spa_debugn("%" PRIu32 "x%" PRIu32, r->width, r->height); break; } case SPA_TYPE_Fraction: { struct spa_fraction *f = (struct spa_fraction *)body; - fprintf(stderr, "%" PRIu32 "/%" PRIu32, f->num, f->denom); + spa_debugn("%" PRIu32 "/%" PRIu32, f->num, f->denom); break; } case SPA_TYPE_Bitmap: - fprintf(stderr, "Bitmap"); + spa_debugn("Bitmap"); break; case SPA_TYPE_Bytes: - fprintf(stderr, "Bytes"); + spa_debugn("Bytes"); break; case SPA_TYPE_Array: { @@ -97,17 +98,17 @@ struct spa_pod_array_body *b = (struct spa_pod_array_body *)body; int i = 0; info = info && info->values ? info->values : info; - fprintf(stderr, "< "); + spa_debugn("< "); SPA_POD_ARRAY_BODY_FOREACH(b, size, p) { if (i++ > 0) - fprintf(stderr, ", "); + spa_debugn(", "); spa_debug_format_value(info, b->child.type, p, b->child.size); } - fprintf(stderr, " >"); + spa_debugn(" >"); break; } default: - fprintf(stderr, "INVALID type %d", type); + spa_debugn("INVALID type %d", type); break; } return 0; @@ -133,7 +134,7 @@ media_type = spa_debug_type_find_name(spa_type_media_type, mtype); media_subtype = spa_debug_type_find_name(spa_type_media_subtype, mstype); - fprintf(stderr, "%*s %s/%s\n", indent, "", + spa_debug("%*s %s/%s", indent, "", media_type ? spa_debug_type_short_name(media_type) : "unknown", media_subtype ? spa_debug_type_short_name(media_subtype) : "unknown"); @@ -160,7 +161,7 @@ ti = spa_debug_type_find(info, prop->key); key = ti ? ti->name : NULL; - fprintf(stderr, "%*s %16s : (%s) ", indent, "", + spa_debugn("%*s %16s : (%s) ", indent, "", key ? spa_debug_type_short_name(key) : "unknown", spa_debug_type_short_name(spa_types[type].name)); @@ -185,17 +186,17 @@ break; } - fprintf(stderr, "%s", ssep); + spa_debugn("%s", ssep); for (i = 1; i < n_vals; i++) { vals = SPA_PTROFF(vals, size, void); if (i > 1) - fprintf(stderr, "%s", sep); + spa_debugn("%s", sep); spa_debug_format_value(ti ? ti->values : NULL, type, vals, size); } - fprintf(stderr, "%s", esep); + spa_debugn("%s", esep); } - fprintf(stderr, "\n"); + spa_debugn("\n"); } return 0; }
View file
pipewire-0.3.47.tar.gz/spa/include/spa/debug/log.h
Added
@@ -0,0 +1,53 @@ +/* Simple Plugin API + * + * Copyright © 2022 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef SPA_DEBUG_LOG_H +#define SPA_DEBUG_LOG_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdio.h> +/** + * \addtogroup spa_debug + * \{ + */ + +#ifndef spa_debug +#define spa_debug(fmt,...) ({ printf(fmt"\n", ## __VA_ARGS__); }) +#endif +#ifndef spa_debugn +#define spa_debugn(fmt,...) ({ printf(fmt, ## __VA_ARGS__); }) +#endif + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_DEBUG_LOGH */
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/mem.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/mem.h
Changed
@@ -29,16 +29,14 @@ extern "C" { #endif +#include <inttypes.h> + /** * \addtogroup spa_debug * \{ */ -#include <spa/utils/dict.h> - -#ifndef spa_debug -#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -#endif +#include <spa/debug/log.h> static inline int spa_debug_mem(int indent, const void *data, size_t size) {
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/node.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/node.h
Changed
@@ -35,12 +35,9 @@ */ #include <spa/node/node.h> +#include <spa/debug/log.h> #include <spa/debug/dict.h> -#ifndef spa_debug -#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -#endif - static inline int spa_debug_port_info(int indent, const struct spa_port_info *info) { spa_debug("%*s" "struct spa_port_info %p:", indent, "", info);
View file
pipewire-0.3.45.tar.gz/spa/include/spa/debug/pod.h -> pipewire-0.3.47.tar.gz/spa/include/spa/debug/pod.h
Changed
@@ -34,15 +34,12 @@ * \{ */ +#include <spa/debug/log.h> #include <spa/debug/mem.h> #include <spa/debug/types.h> #include <spa/pod/pod.h> #include <spa/pod/iter.h> -#ifndef spa_debug -#define spa_debug(...) ({ fprintf(stderr, __VA_ARGS__);fputc('\n', stderr); }) -#endif - static inline int spa_debug_pod_value(int indent, const struct spa_type_info *info, uint32_t type, void *body, uint32_t size)
View file
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces
Added
+(directory)
View file
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces/audio
Added
+(directory)
View file
pipewire-0.3.47.tar.gz/spa/include/spa/interfaces/audio/aec.h
Added
@@ -0,0 +1,95 @@ +/* PipeWire + * + * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + + +#include <spa/utils/dict.h> +#include <spa/utils/hook.h> +#include <spa/param/audio/raw.h> + +#ifndef SPA_AUDIO_AEC_H +#define SPA_AUDIO_AEC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPA_TYPE_INTERFACE_AUDIO_AEC SPA_TYPE_INFO_INTERFACE_BASE "Audio:AEC" + +#define SPA_VERSION_AUDIO_AEC 0 +struct spa_audio_aec { + struct spa_interface iface; + const char *name; + const struct spa_dict *info; + const char *latency; +}; + +struct spa_audio_aec_info { +#define SPA_AUDIO_AEC_CHANGE_MASK_PROPS (1u<<0) + uint64_t change_mask; + + const struct spa_dict *props; +}; + +struct spa_audio_aec_events { +#define SPA_VERSION_AUDIO_AEC_EVENTS 0 + uint32_t version; /**< version of this structure */ + + /** Emitted when info changes */ + void (*info) (void *data, const struct spa_audio_aec_info *info); +}; + +struct spa_audio_aec_methods { +#define SPA_VERSION_AUDIO_AEC_METHODS 0 + uint32_t version; + + int (*add_listener) (void *object, + struct spa_hook *listener, + const struct spa_audio_aec_events *events, + void *data); + + int (*init) (void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info); + int (*run) (void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples); + int (*set_props) (void *data, const struct spa_dict *args); +}; + +#define spa_audio_aec_method(o,method,version,...) \ +({ \ + int _res = -ENOTSUP; \ + struct spa_audio_aec *_o = o; \ + spa_interface_call_res(&_o->iface, \ + struct spa_audio_aec_methods, _res, \ + method, version, ##__VA_ARGS__); \ + _res; \ +}) + +#define spa_audio_aec_add_listener(o,...) spa_audio_aec_method(o, add_listener, 0, __VA_ARGS__) +#define spa_audio_aec_init(o,...) spa_audio_aec_method(o, init, 0, __VA_ARGS__) +#define spa_audio_aec_run(o,...) spa_audio_aec_method(o, run, 0, __VA_ARGS__) +#define spa_audio_aec_set_props(o,...) spa_audio_aec_method(o, set_props, 0, __VA_ARGS__) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_AUDIO_AEC_H */
View file
pipewire-0.3.45.tar.gz/spa/include/spa/support/loop.h -> pipewire-0.3.47.tar.gz/spa/include/spa/support/loop.h
Changed
@@ -66,6 +66,8 @@ int fd; uint32_t mask; uint32_t rmask; + /* private data for the loop implementer */ + void *priv; }; typedef int (*spa_invoke_func_t) (struct spa_loop *loop,
View file
pipewire-0.3.45.tar.gz/spa/include/spa/utils/defs.h -> pipewire-0.3.47.tar.gz/spa/include/spa/utils/defs.h
Changed
@@ -228,6 +228,9 @@ #define SPA_RESTRICT #endif +#define SPA_ROUND_DOWN(num,value) ((num) - ((num) % (value))) +#define SPA_ROUND_UP(num,value) ((((num) + (value) - 1) / (value)) * (value)) + #define SPA_ROUND_DOWN_N(num,align) ((num) & ~((align) - 1)) #define SPA_ROUND_UP_N(num,align) SPA_ROUND_DOWN_N((num) + ((align) - 1),align)
View file
pipewire-0.3.45.tar.gz/spa/include/spa/utils/names.h -> pipewire-0.3.47.tar.gz/spa/include/spa/utils/names.h
Changed
@@ -82,6 +82,8 @@ #define SPA_NAME_AUDIO_ADAPT "audio.adapt" /**< combination of a node and an * audio.convert. Does clock slaving */ +#define SPA_NAME_AEC "audio.aec" /**< Echo canceling */ + /** video processing */ #define SPA_NAME_VIDEO_PROCESS_FORMAT "video.process.format" /**< processes raw video from one format * to another */
View file
pipewire-0.3.45.tar.gz/spa/meson.build -> pipewire-0.3.47.tar.gz/spa/meson.build
Changed
@@ -31,7 +31,7 @@ subdir('include') -if not get_option('spa-plugins').disabled() +if get_option('spa-plugins').allowed() udevrulesdir = get_option('udevrulesdir') if udevrulesdir == '' # absolute path, otherwise meson prepends the prefix @@ -74,6 +74,6 @@ subdir('tools') subdir('tests') -if not get_option('examples').disabled() +if get_option('examples').allowed() subdir('examples') endif
View file
pipewire-0.3.47.tar.gz/spa/plugins/aec
Added
+(directory)
View file
pipewire-0.3.47.tar.gz/spa/plugins/aec/aec-null.c
Added
@@ -0,0 +1,179 @@ +/* PipeWire + * + * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <spa/interfaces/audio/aec.h> +#include <spa/support/log.h> +#include <spa/utils/string.h> +#include <spa/utils/names.h> +#include <spa/support/plugin.h> + +struct impl { + struct spa_handle handle; + struct spa_audio_aec aec; + struct spa_log *log; + + struct spa_hook_list hooks_list; + + uint32_t channels; +}; + +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.aec.null"); +#undef SPA_LOG_TOPIC_DEFAULT +#define SPA_LOG_TOPIC_DEFAULT &log_topic + +static int null_init(void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info) +{ + struct impl *impl = data; + impl->channels = info->channels; + return 0; +} + +static int null_run(void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples) +{ + struct impl *impl = data; + uint32_t i; + for (i = 0; i < impl->channels; i++) + memcpy(out[i], rec[i], n_samples * sizeof(float)); + return 0; +} + +static struct spa_audio_aec_methods impl_aec = { + .init = null_init, + .run = null_run, +}; + +static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface) +{ + struct impl *impl; + + spa_return_val_if_fail(handle != NULL, -EINVAL); + spa_return_val_if_fail(interface != NULL, -EINVAL); + + impl = (struct impl *) handle; + + if (spa_streq(type, SPA_TYPE_INTERFACE_AUDIO_AEC)) + *interface = &impl->aec; + else + return -ENOENT; + + return 0; +} + +static int impl_clear(struct spa_handle *handle) +{ + spa_return_val_if_fail(handle != NULL, -EINVAL); + + return 0; +} + +static size_t +impl_get_size(const struct spa_handle_factory *factory, + const struct spa_dict *params) +{ + return sizeof(struct impl); +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + struct impl *impl; + + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(handle != NULL, -EINVAL); + + handle->get_interface = impl_get_interface; + handle->clear = impl_clear; + + impl = (struct impl *) handle; + + impl->aec.iface = SPA_INTERFACE_INIT( + SPA_TYPE_INTERFACE_AUDIO_AEC, + SPA_VERSION_AUDIO_AEC, + &impl_aec, impl); + impl->aec.name = "null"; + impl->aec.info = NULL; + impl->aec.latency = NULL; + + impl->log = (struct spa_log*)spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); + spa_log_topic_init(impl->log, &log_topic); + + spa_hook_list_init(&impl->hooks_list); + + return 0; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE_INTERFACE_AUDIO_AEC,}, +}; + +static int +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t *index) +{ + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(info != NULL, -EINVAL); + spa_return_val_if_fail(index != NULL, -EINVAL); + + switch (*index) { + case 0: + *info = &impl_interfaces[*index]; + break; + default: + return 0; + } + (*index)++; + return 1; +} + +const struct spa_handle_factory spa_aec_exaudio_factory = { + SPA_VERSION_HANDLE_FACTORY, + SPA_NAME_AEC, + NULL, + impl_get_size, + impl_init, + impl_enum_interface_info, +}; + + +SPA_EXPORT +int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index) +{ + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(index != NULL, -EINVAL); + + switch (*index) { + case 0: + *factory = &spa_aec_exaudio_factory; + break; + default: + return 0; + } + (*index)++; + return 1; +}
View file
pipewire-0.3.47.tar.gz/spa/plugins/aec/aec-webrtc.cpp
Added
@@ -0,0 +1,278 @@ +/* PipeWire + * + * Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> + * © 2021 Arun Raghavan <arun@asymptotic.io> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <memory> +#include <utility> + +#include <spa/interfaces/audio/aec.h> +#include <spa/support/log.h> +#include <spa/utils/string.h> +#include <spa/utils/names.h> +#include <spa/support/plugin.h> + +#include <webrtc/modules/audio_processing/include/audio_processing.h> +#include <webrtc/modules/interface/module_common_types.h> +#include <webrtc/system_wrappers/include/trace.h> + +struct impl_data { + struct spa_handle handle; + struct spa_audio_aec aec; + + struct spa_log *log; + std::unique_ptr<webrtc::AudioProcessing> apm; + spa_audio_info_raw info; + std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer; +}; + +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.eac.webrtc"); +#undef SPA_LOG_TOPIC_DEFAULT +#define SPA_LOG_TOPIC_DEFAULT &log_topic + +static bool webrtc_get_spa_bool(const struct spa_dict *args, const char *key, bool default_value) { + const char *str_val; + bool value = default_value; + str_val = spa_dict_lookup(args, key); + if (str_val != NULL) + value =spa_atob(str_val); + + return value; +} + +static int webrtc_init(void *data, const struct spa_dict *args, const struct spa_audio_info_raw *info) +{ + auto impl = reinterpret_cast<struct impl_data*>(data); + + bool extended_filter = webrtc_get_spa_bool(args, "webrtc.extended_filter", true); + bool delay_agnostic = webrtc_get_spa_bool(args, "webrtc.delay_agnostic", true); + 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 voice_detection = webrtc_get_spa_bool(args, "webrtc.voice_detection", true); + + // 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); + + // 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); + + // FIXME: Intelligibility enhancer is not currently supported + // This filter will modify playback buffer (when calling ProcessReverseStream), but now + // playback buffer modifications are discarded. + + 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)); + + webrtc::ProcessingConfig pconfig = {{ + webrtc::StreamConfig(info->rate, info->channels, false), /* input stream */ + webrtc::StreamConfig(info->rate, info->channels, false), /* output stream */ + webrtc::StreamConfig(info->rate, info->channels, false), /* reverse input stream */ + webrtc::StreamConfig(info->rate, info->channels, false), /* reverse output stream */ + }}; + + auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config)); + if (apm->Initialize(pconfig) != webrtc::AudioProcessing::kNoError) { + spa_log_error(impl->log, "Error initialising webrtc audio processing module"); + return -1; + } + + apm->high_pass_filter()->Enable(high_pass_filter); + // Always disable drift compensation since it requires drift sampling + 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); + impl->apm = std::move(apm); + impl->info = *info; + impl->play_buffer = std::make_unique<float *[]>(info->channels); + impl->rec_buffer = std::make_unique<float *[]>(info->channels); + impl->out_buffer = std::make_unique<float *[]>(info->channels); + return 0; +} + +static int webrtc_run(void *data, const float *rec[], const float *play[], float *out[], uint32_t n_samples) +{ + auto impl = reinterpret_cast<struct impl_data*>(data); + webrtc::StreamConfig config = + webrtc::StreamConfig(impl->info.rate, impl->info.channels, false); + unsigned int num_blocks = n_samples * 1000 / impl->info.rate / 10; + + if (n_samples * 1000 / impl->info.rate % 10 != 0) { + spa_log_error(impl->log, "Buffers must be multiples of 10ms in length (currently %u samples)", n_samples); + return -1; + } + + for (size_t i = 0; i < num_blocks; i ++) { + for (size_t j = 0; j < impl->info.channels; j++) { + impl->play_buffer[j] = const_cast<float *>(play[j]) + config.num_frames() * i; + impl->rec_buffer[j] = const_cast<float *>(rec[j]) + config.num_frames() * i; + impl->out_buffer[j] = out[j] + config.num_frames() * i; + } + /* FIXME: ProcessReverseStream may change the playback buffer, in which + * case we should use that, if we ever expose the intelligibility + * enhancer */ + if (impl->apm->ProcessReverseStream(impl->play_buffer.get(), config, config, impl->play_buffer.get()) != + webrtc::AudioProcessing::kNoError) { + spa_log_error(impl->log, "Processing reverse stream failed"); + } + + // Extra delay introduced by multiple frames + impl->apm->set_stream_delay_ms((num_blocks - 1) * 10); + + if (impl->apm->ProcessStream(impl->rec_buffer.get(), config, config, impl->out_buffer.get()) != + webrtc::AudioProcessing::kNoError) { + spa_log_error(impl->log, "Processing stream failed"); + } + } + + return 0; +} + +static struct spa_audio_aec_methods impl_aec = { + SPA_VERSION_AUDIO_AEC_METHODS, + .add_listener = NULL, + .init = webrtc_init, + .run = webrtc_run, +}; + +static int impl_get_interface(struct spa_handle *handle, const char *type, void **interface) +{ + auto impl = reinterpret_cast<struct impl_data*>(handle); + + spa_return_val_if_fail(handle != NULL, -EINVAL); + spa_return_val_if_fail(interface != NULL, -EINVAL); + + if (spa_streq(type, SPA_TYPE_INTERFACE_AUDIO_AEC)) + *interface = &impl->aec; + else + return -ENOENT; + + return 0; +} + +static int impl_clear(struct spa_handle *handle) +{ + spa_return_val_if_fail(handle != NULL, -EINVAL); + auto impl = reinterpret_cast<struct impl_data*>(handle); + impl->~impl_data(); + return 0; +} + +static size_t +impl_get_size(const struct spa_handle_factory *factory, + const struct spa_dict *params) +{ + return sizeof(struct impl_data); +} + +static int +impl_init(const struct spa_handle_factory *factory, + struct spa_handle *handle, + const struct spa_dict *info, + const struct spa_support *support, + uint32_t n_support) +{ + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(handle != NULL, -EINVAL); + + auto impl = new (handle) impl_data(); + + impl->handle.get_interface = impl_get_interface; + impl->handle.clear = impl_clear; + + impl->aec.iface = SPA_INTERFACE_INIT( + SPA_TYPE_INTERFACE_AUDIO_AEC, + SPA_VERSION_AUDIO_AEC, + &impl_aec, impl); + impl->aec.name = "webrtc", + impl->aec.info = NULL; + impl->aec.latency = "480/48000", + + impl->log = (struct spa_log*)spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); + spa_log_topic_init(impl->log, &log_topic); + + return 0; +} + +static const struct spa_interface_info impl_interfaces[] = { + {SPA_TYPE_INTERFACE_AUDIO_AEC,}, +}; + +static int +impl_enum_interface_info(const struct spa_handle_factory *factory, + const struct spa_interface_info **info, + uint32_t *index) +{ + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(info != NULL, -EINVAL); + spa_return_val_if_fail(index != NULL, -EINVAL); + + switch (*index) { + case 0: + *info = &impl_interfaces[*index]; + break; + default: + return 0; + } + (*index)++; + return 1; +} + +const struct spa_handle_factory spa_aec_exaudio_factory = { + SPA_VERSION_HANDLE_FACTORY, + SPA_NAME_AEC, + NULL, + impl_get_size, + impl_init, + impl_enum_interface_info, +}; + + +SPA_EXPORT +int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index) +{ + spa_return_val_if_fail(factory != NULL, -EINVAL); + spa_return_val_if_fail(index != NULL, -EINVAL); + + switch (*index) { + case 0: + *factory = &spa_aec_exaudio_factory; + break; + default: + return 0; + } + (*index)++; + return 1; +}
View file
pipewire-0.3.47.tar.gz/spa/plugins/aec/meson.build
Added
@@ -0,0 +1,16 @@ +aec_null = shared_library('spa-aec-null', + [ 'aec-null.c' ], + include_directories : [ configinc ], + dependencies : [ spa_dep ], + install : true, + install_dir : spa_plugindir / 'aec') + +if webrtc_dep.found() + aec_webrtc = shared_library('spa-aec-webrtc', + [ 'aec-webrtc.cpp' ], + include_directories : [ configinc ], + dependencies : [ spa_dep, webrtc_dep ], + install : true, + install_dir : spa_plugindir / 'aec') +endif +
View file
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -1516,8 +1516,10 @@ /* get the current params */ CHECK(snd_pcm_sw_params_current(hndl, params), "sw_params_current"); - CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE), "sw_params_set_tstamp_mode"); - + CHECK(snd_pcm_sw_params_set_tstamp_mode(hndl, params, SND_PCM_TSTAMP_ENABLE), + "sw_params_set_tstamp_mode"); + CHECK(snd_pcm_sw_params_set_tstamp_type(hndl, params, SND_PCM_TSTAMP_TYPE_MONOTONIC), + "sw_params_set_tstamp_type"); #if 0 snd_pcm_uframes_t boundary; CHECK(snd_pcm_sw_params_get_boundary(params, &boundary), "get_boundary"); @@ -1644,6 +1646,9 @@ case SND_PCM_STATE_SUSPENDED: spa_log_info(state->log, "%s: recover from state %s", state->props.device, snd_pcm_state_name(st)); + res = snd_pcm_resume(state->hndl); + if (res >= 0) + return res; err = -ESTRPIPE; break; default: @@ -1668,10 +1673,10 @@ return do_start(state); } -static int get_status(struct state *state, snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target) +static int get_avail(struct state *state, uint64_t current_time) { - snd_pcm_sframes_t avail; int res; + snd_pcm_sframes_t avail; if (SPA_UNLIKELY((avail = snd_pcm_avail(state->hndl)) < 0)) { if ((res = alsa_recover(state, avail)) < 0) @@ -1684,6 +1689,48 @@ } else { state->alsa_recovering = false; } + return avail; +} + +#if 0 +static int get_avail_htimestamp(struct state *state, uint64_t current_time) +{ + int res; + snd_pcm_uframes_t avail; + snd_htimestamp_t tstamp; + uint64_t then; + + if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) { + if ((res = alsa_recover(state, avail)) < 0) + return res; + if ((res = snd_pcm_htimestamp(state->hndl, &avail, &tstamp)) < 0) { + spa_log_warn(state->log, "%s: snd_pcm_htimestamp error: %s", + state->props.device, snd_strerror(res)); + avail = state->threshold * 2; + } + } else { + state->alsa_recovering = false; + } + + if ((then = SPA_TIMESPEC_TO_NSEC(&tstamp)) != 0) { + if (then < current_time) + avail += (current_time - then) * state->rate / SPA_NSEC_PER_SEC; + else + avail -= (then - current_time) * state->rate / SPA_NSEC_PER_SEC; + } + return SPA_MIN(avail, state->buffer_frames); +} +#endif + +static int get_status(struct state *state, uint64_t current_time, + snd_pcm_uframes_t *delay, snd_pcm_uframes_t *target) +{ + int avail; + + if ((avail = get_avail(state, current_time)) < 0) + return avail; + + avail = SPA_MIN(avail, (int)state->buffer_frames); *target = state->threshold + state->headroom; @@ -1704,7 +1751,7 @@ return 0; } -static int update_time(struct state *state, uint64_t nsec, snd_pcm_sframes_t delay, +static int update_time(struct state *state, uint64_t current_time, snd_pcm_sframes_t delay, snd_pcm_sframes_t target, bool follower) { double err, corr; @@ -1717,8 +1764,8 @@ if (SPA_UNLIKELY(state->dll.bw == 0.0)) { spa_dll_set_bw(&state->dll, SPA_DLL_BW_MAX, state->threshold, state->rate); - state->next_time = nsec; - state->base_time = nsec; + state->next_time = current_time; + state->base_time = current_time; } diff = (int32_t) (state->last_threshold - state->threshold); @@ -1727,9 +1774,20 @@ spa_log_trace(state->log, "%p: follower:%d quantum change %d -> %d (%d) %f", state, follower, state->last_threshold, state->threshold, diff, err); state->last_threshold = state->threshold; + state->alsa_sync = true; } - err = SPA_CLAMP(err, -state->max_error, state->max_error); - corr = spa_dll_update(&state->dll, err); + if (err > state->max_error) { + err = state->max_error; + state->alsa_sync = true; + } else if (err < -state->max_error) { + err = -state->max_error; + state->alsa_sync = true; + } + + if (!follower || state->matching) + corr = spa_dll_update(&state->dll, err); + else + corr = 1.0; if (diff < 0) state->next_time += diff / corr * 1e9 / state->rate; @@ -1737,11 +1795,11 @@ if (SPA_UNLIKELY((state->next_time - state->base_time) > BW_PERIOD)) { state->base_time = state->next_time; - spa_log_debug(state->log, "%p: follower:%d match:%d rate:%f " - "bw:%f thr:%u del:%ld target:%ld err:%f", - state, follower, state->matching, corr, state->dll.bw, - state->threshold, delay, target, - err); + spa_log_debug(state->log, "%s: follower:%d match:%d rate:%f " + "bw:%f thr:%u del:%ld target:%ld err:%f max:%f", + state->props.device, follower, state->matching, + corr, state->dll.bw, state->threshold, delay, target, + err, state->max_error); } if (state->rate_match) { @@ -1756,7 +1814,7 @@ state->next_time += state->threshold / corr * 1e9 / state->rate; if (SPA_LIKELY(!follower && state->clock)) { - state->clock->nsec = nsec; + state->clock->nsec = current_time; state->clock->position += state->duration; state->clock->duration = state->duration; state->clock->delay = delay + state->delay; @@ -1765,7 +1823,7 @@ } spa_log_trace_fp(state->log, "%p: follower:%d %"PRIu64" %f %ld %f %f %u", - state, follower, nsec, corr, delay, err, state->threshold * corr, + state, follower, current_time, corr, delay, err, state->threshold * corr, state->threshold); return 0; @@ -1804,6 +1862,7 @@ state->rate_denom = state->position->clock.rate.denom; state->threshold = (state->duration * state->rate + state->rate_denom-1) / state->rate_denom; state->resample = ((uint32_t)state->rate != state->rate_denom) || state->matching; + state->alsa_sync = true; } } @@ -1811,45 +1870,42 @@ { snd_pcm_t *hndl = state->hndl; const snd_pcm_channel_area_t *my_areas; - snd_pcm_uframes_t written, frames, offset, off, to_write, total_written; + snd_pcm_uframes_t written, frames, offset, off, to_write, total_written, max_write; snd_pcm_sframes_t commitres; int res = 0; check_position_config(state); + max_write = state->buffer_frames; + if (state->following && state->alsa_started) { - uint64_t nsec; + uint64_t current_time; snd_pcm_uframes_t delay, target; - if (SPA_UNLIKELY((res = get_status(state, &delay, &target)) < 0)) + current_time = state->position->clock.nsec; + + if (SPA_UNLIKELY((res = get_status(state, current_time, &delay, &target)) < 0)) return res; - if (SPA_UNLIKELY(!state->alsa_recovering && delay > target + state->threshold)) { + if (SPA_UNLIKELY(state->alsa_sync)) { spa_log_warn(state->log, "%s: follower delay:%ld target:%ld thr:%u, resync", state->props.device, delay, target, state->threshold); - spa_dll_init(&state->dll); - state->alsa_sync = true; - } - if (SPA_UNLIKELY(state->alsa_sync)) { if (delay > target) snd_pcm_rewind(state->hndl, delay - target); - else - snd_pcm_forward(state->hndl, target - delay); - + else if (delay < target) + spa_alsa_silence(state, target - delay); delay = target; state->alsa_sync = false; } - - nsec = state->position->clock.nsec; - if (SPA_UNLIKELY((res = update_time(state, nsec, delay, target, true)) < 0)) + if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, true)) < 0)) return res; } total_written = 0; again: - frames = state->buffer_frames; - if (state->use_mmap) { + frames = max_write; + if (state->use_mmap && frames > 0) { if (SPA_UNLIKELY((res = snd_pcm_mmap_begin(hndl, &my_areas, &offset, &frames)) < 0)) { spa_log_error(state->log, "%s: snd_pcm_mmap_begin error: %s", state->props.device, snd_strerror(res)); @@ -1939,14 +1995,13 @@ state, offset, written, state->sample_count); total_written += written; - if (state->use_mmap) { + if (state->use_mmap && written > 0) { if (SPA_UNLIKELY((commitres = snd_pcm_mmap_commit(hndl, offset, written)) < 0)) { spa_log_error(state->log, "%s: snd_pcm_mmap_commit error: %s", state->props.device, snd_strerror(commitres)); if (commitres != -EPIPE && commitres != -ESTRPIPE) return res; } - if (commitres > 0 && written != (snd_pcm_uframes_t) commitres) { spa_log_warn(state->log, "%s: mmap_commit wrote %ld instead of %ld", state->props.device, commitres, written); @@ -2048,62 +2103,47 @@ int spa_alsa_read(struct state *state) { snd_pcm_t *hndl = state->hndl; - snd_pcm_uframes_t total_read = 0, to_read; + snd_pcm_uframes_t total_read = 0, to_read, max_read; const snd_pcm_channel_area_t *my_areas; snd_pcm_uframes_t read, frames, offset; snd_pcm_sframes_t commitres; int res = 0; - if (state->position) { - check_position_config(state); + check_position_config(state); - if (!state->following) { - uint64_t position; - - position = state->position->clock.position; - if (state->last_position && state->last_position + state->last_duration != position) { - state->alsa_sync = true; - spa_log_info(state->log, "%s: discont, resync %"PRIu64" %"PRIu64" %d", - state->props.device, state->last_position, - position, state->last_duration); - } - state->last_position = position; - state->last_duration = state->duration; - } - } + max_read = state->buffer_frames; if (state->following && state->alsa_started) { - uint64_t nsec; - snd_pcm_uframes_t delay, target; + uint64_t current_time; + snd_pcm_uframes_t avail, delay, target; uint32_t threshold = state->threshold; - if ((res = get_status(state, &delay, &target)) < 0) + current_time = state->position->clock.nsec; + + if ((res = get_status(state, current_time, &delay, &target)) < 0) return res; - if (!state->alsa_recovering && (delay < target / 2 || delay > target * 2)) { - spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync", - state->props.device, delay, target, threshold); - spa_dll_init(&state->dll); - state->alsa_sync = true; - } + avail = delay; + if (state->alsa_sync) { - spa_log_warn(state->log, "%s: follower resync delay:%ld target:%ld thr:%u", + spa_log_warn(state->log, "%s: follower delay:%lu target:%lu thr:%u, resync", state->props.device, delay, target, threshold); if (delay < target) - snd_pcm_rewind(state->hndl, target - delay); + max_read = target - delay; else if (delay > target) snd_pcm_forward(state->hndl, delay - target); - delay = target; state->alsa_sync = false; } - nsec = state->position->clock.nsec; - if ((res = update_time(state, nsec, delay, target, true)) < 0) + if ((res = update_time(state, current_time, delay, target, true)) < 0) return res; + + if (avail < state->read_size) + max_read = 0; } - frames = state->read_size; + frames = SPA_MIN(max_read, state->read_size); if (state->use_mmap) { to_read = state->buffer_frames; @@ -2119,20 +2159,24 @@ offset = 0; } - read = push_frames(state, my_areas, offset, frames); - - total_read += read; + if (frames > 0) { + read = push_frames(state, my_areas, offset, frames); + total_read += read; + } else { + spa_alsa_skip(state); + total_read += state->read_size; + read = 0; + } - if (state->use_mmap) { + if (state->use_mmap && read > 0) { spa_log_trace_fp(state->log, "%p: commit offs:%ld read:%ld count:%"PRIi64, state, offset, read, state->sample_count); if ((commitres = snd_pcm_mmap_commit(hndl, offset, read)) < 0) { - spa_log_error(state->log, "%s: snd_pcm_mmap_commit error: %s", - state->props.device, snd_strerror(commitres)); + spa_log_error(state->log, "%s: snd_pcm_mmap_commit error %lu %lu: %s", + state->props.device, frames, read, snd_strerror(commitres)); if (commitres != -EPIPE && commitres != -ESTRPIPE) return res; } - if (commitres > 0 && read != (snd_pcm_uframes_t) commitres) { spa_log_warn(state->log, "%s: mmap_commit read %ld instead of %ld", state->props.device, commitres, read); @@ -2178,7 +2222,7 @@ } -static int handle_play(struct state *state, uint64_t nsec, +static int handle_play(struct state *state, uint64_t current_time, snd_pcm_uframes_t delay, snd_pcm_uframes_t target) { int res; @@ -2187,11 +2231,11 @@ spa_log_trace(state->log, "%p: early wakeup %lu %lu", state, delay, target); if (delay > target * 3) delay = target * 3; - state->next_time = nsec + (delay - target) * SPA_NSEC_PER_SEC / state->rate; + state->next_time = current_time + (delay - target) * SPA_NSEC_PER_SEC / state->rate; return -EAGAIN; } - if (SPA_UNLIKELY((res = update_time(state, nsec, delay, target, false)) < 0)) + if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, false)) < 0)) return res; if (spa_list_is_empty(&state->ready)) { @@ -2209,7 +2253,7 @@ return res; } -static int handle_capture(struct state *state, uint64_t nsec, +static int handle_capture(struct state *state, uint64_t current_time, snd_pcm_uframes_t delay, snd_pcm_uframes_t target) { int res; @@ -2217,12 +2261,12 @@ if (SPA_UNLIKELY(delay < target)) { spa_log_trace(state->log, "%p: early wakeup %ld %ld", state, delay, target); - state->next_time = nsec + (target - delay) * SPA_NSEC_PER_SEC / + state->next_time = current_time + (target - delay) * SPA_NSEC_PER_SEC / state->rate; return -EAGAIN; } - if (SPA_UNLIKELY(res = update_time(state, nsec, delay, target, false)) < 0) + if (SPA_UNLIKELY(res = update_time(state, current_time, delay, target, false)) < 0) return res; if ((res = spa_alsa_read(state)) < 0) @@ -2255,17 +2299,20 @@ { struct state *state = source->data; snd_pcm_uframes_t delay, target; - uint64_t expire; + uint64_t expire, current_time; if (SPA_UNLIKELY(state->started && spa_system_timerfd_read(state->data_system, state->timerfd, &expire) < 0)) spa_log_warn(state->log, "%p: error reading timerfd: %m", state); check_position_config(state); - if (SPA_UNLIKELY(get_status(state, &delay, &target) < 0)) - return; + current_time = state->next_time; - state->current_time = state->next_time; + if (SPA_UNLIKELY(get_status(state, current_time, &delay, &target) < 0)) { + spa_log_error(state->log, "get_status error"); + state->next_time += state->threshold * 1e9 / state->rate; + goto done; + } #ifndef FASTPATH if (SPA_UNLIKELY(spa_log_level_enabled(state->log, SPA_LOG_LEVEL_TRACE))) { @@ -2275,16 +2322,24 @@ return; nsec = SPA_TIMESPEC_TO_NSEC(&now); spa_log_trace_fp(state->log, "%p: timeout %lu %lu %"PRIu64" %"PRIu64" %"PRIi64 - " %d %"PRIi64, state, delay, target, nsec, state->current_time, - nsec - state->current_time, state->threshold, state->sample_count); + " %d %"PRIi64, state, delay, target, nsec, nsec, + nsec - current_time, state->threshold, state->sample_count); } #endif if (state->stream == SND_PCM_STREAM_PLAYBACK) - handle_play(state, state->current_time, delay, target); + handle_play(state, current_time, delay, target); else - handle_capture(state, state->current_time, delay, target); + handle_capture(state, current_time, delay, target); +done: + if (state->next_time > current_time + SPA_NSEC_PER_SEC || + current_time > state->next_time + SPA_NSEC_PER_SEC) { + spa_log_error(state->log, "%s: impossible timeout %lu %lu %"PRIu64" %"PRIu64" %"PRIi64 + " %d %"PRIi64, state->props.device, delay, target, current_time, state->next_time, + state->next_time - current_time, state->threshold, state->sample_count); + state->next_time = current_time + state->threshold * 1e9 / state->rate; + } set_timeout(state, state->next_time); }
View file
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -189,8 +189,6 @@ uint32_t start_delay; uint32_t duration; - uint32_t last_duration; - uint64_t last_position; unsigned int alsa_started:1; unsigned int alsa_sync:1; unsigned int alsa_recovering:1; @@ -210,7 +208,6 @@ int64_t sample_count; int64_t sample_time; - uint64_t current_time; uint64_t next_time; uint64_t base_time;
View file
pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/alsa-udev.c
Changed
@@ -246,6 +246,60 @@ *d = 0; } +static int check_device_pcm_class(const char *devname) +{ + FILE *f; + char path[PATH_MAX]; + char buf[16]; + size_t sz; + + /* Check device class */ + spa_scnprintf(path, sizeof(path), "/sys/class/sound/%s/pcm_class", + devname); + f = fopen(path, "r"); + if (f == NULL) + return -errno; + sz = fread(buf, 1, sizeof(buf) - 1, f); + buf[sz] = '\0'; + fclose(f); + return spa_strstartswith(buf, "modem") ? -ENXIO : 0; +} + +static int get_num_pcm_devices(unsigned int card_id) +{ + char prefix[32]; + DIR *snd = NULL; + struct dirent *entry; + int num_dev = 0; + int res; + + /* Check if card has PCM devices, without opening them */ + + spa_scnprintf(prefix, sizeof(prefix), "pcmC%uD", card_id); + + if ((snd = opendir("/dev/snd")) == NULL) + return -errno; + + while ((errno = 0, entry = readdir(snd)) != NULL) { + if (!(entry->d_type == DT_CHR && + spa_strstartswith(entry->d_name, prefix))) + continue; + + res = check_device_pcm_class(entry->d_name); + if (res != -ENXIO) { + /* count device also if sysfs status file not accessible */ + ++num_dev; + } + } + if (errno != 0) + res = -errno; + else + res = num_dev; + + closedir(snd); + return res; +} + static int check_device_available(struct impl *this, struct device *device, int *num_pcm) { char path[PATH_MAX]; @@ -256,13 +310,27 @@ struct dirent *entry, *entry_pcm; int res; + res = get_num_pcm_devices(device->id); + if (res < 0) { + spa_log_error(this->log, "Error finding PCM devices for ALSA card %u: %s", + (unsigned int)device->id, spa_strerror(res)); + return res; + } + *num_pcm = res; + + spa_log_debug(this->log, "card %u has %d pcm device(s)", (unsigned int)device->id, *num_pcm); + /* * Check if some pcm devices of the card are busy. Check it via /proc, as we * don't want to actually open any devices using alsa-lib (generates uncontrolled * number of inotify events), or replicate its subdevice logic. + * + * The /proc/asound directory might not exist if kernel is compiled with + * CONFIG_SND_PROCFS=n, and the pcmXX directories may be missing if compiled + * with CONFIG_SND_VERBOSE_PROCFS=n. In those cases, the busy check always succeeds. */ - *num_pcm = 0; + res = 0; spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id); @@ -274,16 +342,9 @@ spa_strstartswith(entry->d_name, "pcm"))) continue; - /* Check device class */ - spa_scnprintf(path, sizeof(path), "/sys/class/sound/pcmC%uD%s/pcm_class", + spa_scnprintf(path, sizeof(path), "pcmC%uD%s", (unsigned int)device->id, entry->d_name+3); - f = fopen(path, "r"); - if (f == NULL) - goto done; - sz = fread(buf, 1, sizeof(buf) - 1, f); - buf[sz] = '\0'; - fclose(f); - if (spa_strstartswith(buf, "modem")) + if (check_device_pcm_class(path) < 0) continue; /* Check busy status */ @@ -310,7 +371,7 @@ if (!spa_strstartswith(buf, "closed")) { spa_log_debug(this->log, "card %u pcm device %s busy", (unsigned int)device->id, entry->d_name); - errno = EBUSY; + res = -EBUSY; goto done; } spa_log_debug(this->log, "card %u pcm device %s free", @@ -319,8 +380,6 @@ if (errno != 0) goto done; - ++*num_pcm; - closedir(pcm); pcm = NULL; } @@ -328,7 +387,10 @@ goto done; done: - res = -errno; + if (errno != 0) { + spa_log_info(this->log, "card %u: failed to find busy status (%s)", + (unsigned int)device->id, spa_strerror(-errno)); + } if (card) closedir(card); if (pcm) @@ -352,15 +414,16 @@ * device->emitted to true. alsalib functions can be used after that. */ + snprintf(path, sizeof(path), "hw:%u", id); + if ((res = check_device_available(this, device, &pcm)) < 0) return res; if (pcm == 0) { spa_log_debug(this->log, "no pcm devices for %s", path); device->ignored = true; - return 0; + return -ENODEV; } - snprintf(path, sizeof(path), "hw:%u", id); spa_log_debug(this->log, "emitting card %s", path); device->emitted = true;
View file
pipewire-0.3.45.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf
Changed
@@ -16,12 +16,14 @@ ; Texas Instruments PCM2902 ; ; This is a generic chip used in multiple products, including at least -; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and -; some unbranded "usb mini microphone". +; Behringer U-Phoria UMC22, Behringer U-Phoria UM2, Behringer Xenyx 302USB, +; Intopic Jazz-UB700 and some unbranded "usb mini microphone". ; ; Behringer UMC22 has stereo input (representing two physical mono inputs), ; others have mono input. ; +; (Behringer UMC22 and UM2 are "the same device" with different controls) +; ; Some devices have a mic input path, but at least Behringer Xenyx 302USB ; doesn't have any input mixer controls. ;
View file
pipewire-0.3.45.tar.gz/spa/plugins/alsa/test-timer.c -> pipewire-0.3.47.tar.gz/spa/plugins/alsa/test-timer.c
Changed
@@ -45,10 +45,12 @@ unsigned int rate; unsigned int channels; snd_pcm_uframes_t period; + snd_pcm_uframes_t buffer_frames; snd_pcm_t *hndl; int timerfd; + double max_error; float accumulator; uint64_t next_time; @@ -103,15 +105,36 @@ static int on_timer_wakeup(struct state *state) { - snd_pcm_sframes_t avail, delay; + snd_pcm_sframes_t delay; double error, corr; - - /* check the delay in the device */ - CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay"); +#if 1 + snd_pcm_sframes_t avail; + CHECK(snd_pcm_avail_delay(state->hndl, &avail, &delay), "delay"); +#else + snd_pcm_uframes_t avail; + snd_htimestamp_t tstamp; + uint64_t then; + + CHECK(snd_pcm_htimestamp(state->hndl, &avail, &tstamp), "htimestamp"); + delay = state->buffer_frames - avail; + + then = TIMESPEC_TO_NSEC(&tstamp); + if (then != 0) { + if (then < state->next_time) { + delay -= (state->next_time - then) * state->rate / NSEC_PER_SEC; + } else { + delay += (then - state->next_time) * state->rate / NSEC_PER_SEC; + } + } +#endif /* calculate the error, we want to have exactly 1 period of * samples remaining in the device when we wakeup. */ error = (double)delay - (double)state->period; + if (error > state->max_error) + error = state->max_error; + else if (error < -state->max_error) + error = -state->max_error; /* update the dll with the error, this gives a rate correction */ corr = spa_dll_update(&state->dll, error); @@ -124,12 +147,6 @@ if (state->next_time - state->prev_time > BW_PERIOD) { state->prev_time = state->next_time; - - /* reduce bandwidth and show some stats */ - if (state->dll.bw > SPA_DLL_BW_MIN) - spa_dll_set_bw(&state->dll, state->dll.bw / 2.0, - state->period, state->rate); - fprintf(stdout, "corr:%f error:%f bw:%f\n", corr, error, state->dll.bw); } @@ -144,6 +161,7 @@ struct state state = { 0, }; const char *device = DEFAULT_DEVICE; snd_pcm_hw_params_t *hparams; + snd_pcm_sw_params_t *sparams; struct timespec now; CHECK(snd_pcm_open(&state.hndl, device, SND_PCM_STREAM_PLAYBACK, 0), "open %s failed", device); @@ -165,12 +183,25 @@ &state.rate, 0), "set rate"); CHECK(snd_pcm_hw_params(state.hndl, hparams), "hw_params"); + CHECK(snd_pcm_hw_params_get_buffer_size(hparams, &state.buffer_frames), "get_buffer_size_max"); + fprintf(stdout, "opened format:%s rate:%u channels:%u\n", snd_pcm_format_name(SND_PCM_FORMAT_S32_LE), state.rate, state.channels); + snd_pcm_sw_params_alloca(&sparams); +#if 0 + CHECK(snd_pcm_sw_params_current(state.hndl, sparams), "sw_params_current"); + CHECK(snd_pcm_sw_params_set_tstamp_mode(state.hndl, sparams, SND_PCM_TSTAMP_ENABLE), + "sw_params_set_tstamp_type"); + CHECK(snd_pcm_sw_params_set_tstamp_type(state.hndl, sparams, SND_PCM_TSTAMP_TYPE_MONOTONIC), + "sw_params_set_tstamp_type"); + CHECK(snd_pcm_sw_params(state.hndl, sparams), "sw_params"); +#endif + spa_dll_init(&state.dll); spa_dll_set_bw(&state.dll, SPA_DLL_BW_MAX, state.period, state.rate); + state.max_error = 256.0; if ((state.timerfd = timerfd_create(CLOCK_MONOTONIC, 0)) < 0) perror("timerfd");
View file
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -594,7 +594,7 @@ /* Check if USB ALT6 is really available on the device */ if (device->adapter->bus_type == BUS_TYPE_USB && !msbc_alt1_ok && msbc_ok) { -#if HAVE_LIBUSB +#ifdef HAVE_LIBUSB if (device->adapter->source_id == SOURCE_ID_USB) { msbc_ok = check_usb_altsetting_6(backend, device->adapter->vendor_id, device->adapter->product_id);
View file
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -425,12 +425,6 @@ } } -static inline void add_dict(struct spa_pod_builder *builder, const char *key, const char *val) -{ - spa_pod_builder_string(builder, key); - spa_pod_builder_string(builder, val); -} - static int a2dp_codec_to_endpoint(const struct a2dp_codec *codec, const char * endpoint, char** object_path)
View file
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/bluez5/meson.build
Changed
@@ -5,24 +5,14 @@ endif endforeach -if not get_option('bluez5-backend-hsp-native').disabled() - cdata.set('HAVE_BLUEZ_5_BACKEND_HSP_NATIVE', 1) - cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', 1) -endif -if not get_option('bluez5-backend-hfp-native').disabled() - cdata.set('HAVE_BLUEZ_5_BACKEND_HFP_NATIVE', 1) - cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', 1) -endif -if not get_option('bluez5-backend-ofono').disabled() - cdata.set('HAVE_BLUEZ_5_BACKEND_OFONO', 1) -endif -if not get_option('bluez5-backend-hsphfpd').disabled() - cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', 1) -endif - -if dependency('bluez', version: '< 6', required: false).found() - cdata.set('HAVE_BLUEZ_5_HCI', 1) -endif +cdata.set('HAVE_BLUEZ_5_BACKEND_NATIVE', + get_option('bluez5-backend-hsp-native').allowed() or + get_option('bluez5-backend-hfp-native').allowed()) +cdata.set('HAVE_BLUEZ_5_BACKEND_HSP_NATIVE', get_option('bluez5-backend-hsp-native').allowed()) +cdata.set('HAVE_BLUEZ_5_BACKEND_HFP_NATIVE', get_option('bluez5-backend-hfp-native').allowed()) +cdata.set('HAVE_BLUEZ_5_BACKEND_OFONO', get_option('bluez5-backend-ofono').allowed()) +cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', get_option('bluez5-backend-hsphfpd').allowed()) +cdata.set('HAVE_BLUEZ_5_HCI', dependency('bluez', version: '< 6', required: false).found()) bluez5_sources = [ 'plugin.c', @@ -44,18 +34,18 @@ install_data(bluez5_data, install_dir : spa_datadir / 'bluez5') -if not get_option('bluez5-backend-hsp-native').disabled() or not get_option('bluez5-backend-hfp-native').disabled() +if get_option('bluez5-backend-hsp-native').allowed() or get_option('bluez5-backend-hfp-native').allowed() if libusb_dep.found() bluez5_deps += libusb_dep endif bluez5_sources += ['backend-native.c'] endif -if not get_option('bluez5-backend-ofono').disabled() +if get_option('bluez5-backend-ofono').allowed() bluez5_sources += ['backend-ofono.c'] endif -if not get_option('bluez5-backend-hsphfpd').disabled() +if get_option('bluez5-backend-hsphfpd').allowed() bluez5_sources += ['backend-hsphfpd.c'] endif
View file
pipewire-0.3.45.tar.gz/spa/plugins/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/meson.build
Changed
@@ -1,16 +1,16 @@ if alsa_dep.found() subdir('alsa') endif -if not get_option('audioconvert').disabled() +if get_option('audioconvert').allowed() subdir('audioconvert') endif -if not get_option('audiomixer').disabled() +if get_option('audiomixer').allowed() subdir('audiomixer') endif -if not get_option('control').disabled() +if get_option('control').allowed() subdir('control') endif -if not get_option('audiotestsrc').disabled() +if get_option('audiotestsrc').allowed() subdir('audiotestsrc') endif if bluez_dep.found() @@ -22,19 +22,19 @@ if jack_dep.found() subdir('jack') endif -if not get_option('support').disabled() +if get_option('support').allowed() subdir('support') endif -if not get_option('test').disabled() +if get_option('test').allowed() subdir('test') endif -if not get_option('videoconvert').disabled() +if get_option('videoconvert').allowed() subdir('videoconvert') endif -if not get_option('videotestsrc').disabled() +if get_option('videotestsrc').allowed() subdir('videotestsrc') endif -if not get_option('volume').disabled() +if get_option('volume').allowed() subdir('volume') endif if vulkan_headers @@ -51,3 +51,5 @@ if libcamera_dep.found() subdir('libcamera') endif + +subdir('aec') \ No newline at end of file
View file
pipewire-0.3.45.tar.gz/spa/plugins/support/logger.c -> pipewire-0.3.47.tar.gz/spa/plugins/support/logger.c
Changed
@@ -57,6 +57,7 @@ struct spa_log log; FILE *file; + bool close_file; struct spa_system *system; struct spa_source source; @@ -285,6 +286,9 @@ support_log_free_patterns(&this->patterns); + if (this->close_file && this->file != NULL) + fclose(this->file); + if (this->have_source) { spa_loop_remove_source(this->source.loop, &this->source); spa_system_close(this->system, this->source.fd); @@ -356,6 +360,8 @@ this->file = fopen(str, "w"); if (this->file == NULL) fprintf(stderr, "Warning: failed to open file %s: (%m)", str); + else + this->close_file = true; } if ((str = spa_dict_lookup(info, SPA_KEY_LOG_PATTERNS)) != NULL) support_log_parse_patterns(&this->patterns, str);
View file
pipewire-0.3.45.tar.gz/spa/plugins/support/loop.c -> pipewire-0.3.47.tar.gz/spa/plugins/support/loop.c
Changed
@@ -48,6 +48,7 @@ #define MAX_ALIGN 8 #define ITEM_ALIGN 8 #define DATAS_SIZE (4096*8) +#define MAX_EP 32 /** \cond */ @@ -74,11 +75,11 @@ struct spa_system *system; struct spa_list source_list; - struct spa_list destroy_list; struct spa_hook_list hooks_list; int poll_fd; pthread_t thread; + int enter_count; struct spa_source *wakeup; int ack_fd; @@ -113,6 +114,7 @@ { struct impl *impl = object; source->loop = &impl->loop; + source->priv = NULL; return spa_system_pollfd_add(impl->system, impl->poll_fd, source->fd, source->mask, source); } @@ -125,6 +127,12 @@ static int loop_remove_source(void *object, struct spa_source *source) { struct impl *impl = object; + struct spa_poll_event *e; + if ((e = source->priv)) { + /* active in an iteration of the loop, remove it from there */ + e->data = NULL; + source->priv = NULL; + } source->loop = NULL; return spa_system_pollfd_del(impl->system, impl->poll_fd, source->fd); } @@ -289,35 +297,43 @@ static void loop_enter(void *object) { struct impl *impl = object; - impl->thread = pthread_self(); + pthread_t thread_id = pthread_self(); + + if (impl->enter_count == 0) { + spa_return_if_fail(impl->thread == 0); + impl->thread = thread_id; + impl->enter_count = 1; + } else { + spa_return_if_fail(impl->enter_count > 0); + spa_return_if_fail(impl->thread == thread_id); + impl->enter_count++; + } spa_log_trace(impl->log, "%p: enter %lu", impl, impl->thread); } static void loop_leave(void *object) { struct impl *impl = object; + pthread_t thread_id = pthread_self(); + + spa_return_if_fail(impl->enter_count > 0); + spa_return_if_fail(impl->thread == thread_id); + spa_log_trace(impl->log, "%p: leave %lu", impl, impl->thread); - impl->thread = 0; -} -static inline void process_destroy(struct impl *impl) -{ - struct source_impl *source, *tmp; - spa_list_for_each_safe(source, tmp, &impl->destroy_list, link) - free(source); - spa_list_init(&impl->destroy_list); + if (--impl->enter_count == 0) + impl->thread = 0; } static int loop_iterate(void *object, int timeout) { struct impl *impl = object; - struct spa_loop *loop = &impl->loop; - struct spa_poll_event ep[32]; + struct spa_poll_event ep[MAX_EP], *e; int i, nfds; spa_loop_control_hook_before(&impl->hooks_list); - nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, SPA_N_ELEMENTS(ep), timeout); + nfds = spa_system_pollfd_wait(impl->system, impl->poll_fd, ep, MAX_EP, timeout); spa_loop_control_hook_after(&impl->hooks_list); @@ -330,15 +346,19 @@ for (i = 0; i < nfds; i++) { struct spa_source *s = ep[i].data; s->rmask = ep[i].events; + /* already active in another iteration of the loop, + * remove it from that iteration */ + if (SPA_UNLIKELY(e = s->priv)) + e->data = NULL; + s->priv = &ep[i]; } for (i = 0; i < nfds; i++) { struct spa_source *s = ep[i].data; - if (SPA_LIKELY(s->rmask && s->fd != -1 && s->loop == loop)) + if (SPA_LIKELY(s && s->rmask)) { + s->priv = NULL; s->func(s); + } } - if (SPA_UNLIKELY(!spa_list_is_empty(&impl->destroy_list))) - process_destroy(impl); - return nfds; } @@ -692,7 +712,7 @@ spa_system_close(impl->impl->system, source->fd); source->fd = -1; } - spa_list_insert(&impl->impl->destroy_list, &impl->link); + free(source); } static const struct spa_loop_methods impl_loop = { @@ -756,11 +776,13 @@ impl = (struct impl *) handle; + if (impl->enter_count != 0) + spa_log_warn(impl->log, "%p: loop is entered %d times", + impl, impl->enter_count); + spa_list_consume(source, &impl->source_list, link) loop_destroy_source(impl, &source->source); - process_destroy(impl); - spa_system_close(impl->system, impl->ack_fd); spa_system_close(impl->system, impl->poll_fd); @@ -822,7 +844,6 @@ impl->poll_fd = res; spa_list_init(&impl->source_list); - spa_list_init(&impl->destroy_list); spa_hook_list_init(&impl->hooks_list); impl->buffer_data = SPA_PTR_ALIGN(impl->buffer_mem, MAX_ALIGN, uint8_t);
View file
pipewire-0.3.45.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.47.tar.gz/spa/plugins/support/meson.build
Changed
@@ -23,7 +23,7 @@ install_dir : spa_plugindir / 'support') spa_support_dep = declare_dependency(link_with: spa_support_lib) -if not get_option('evl').disabled() +if get_option('evl').allowed() evl_inc = include_directories('/usr/evl/include') evl_lib = cc.find_library('evl', dirs: ['/usr/evl/lib/'],
View file
pipewire-0.3.45.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -2,6 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/client-rt.conf.d/ for system-wide changes or in +# ~/.config/pipewire/client-rt.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system.
View file
pipewire-0.3.45.tar.gz/src/daemon/client.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/client.conf.in
Changed
@@ -2,7 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. - +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/client.conf.d/ for system-wide changes or in +# ~/.config/pipewire/client.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system. #mem.warn-mlock = false
View file
pipewire-0.3.45.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/jack.conf.in
Changed
@@ -2,6 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/jack.conf.d/ for system-wide changes or in +# ~/.config/pipewire/jack.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system. @@ -60,7 +65,10 @@ # global properties for all jack clients jack.properties = { #node.latency = 1024/48000 - #node.lock-quantum = false + #node.rate = 1/48000 + #node.quantum = 1024/48000 + #node.lock-quantum = true + #node.force-quantum = 0 #jack.show-monitor = true #jack.merge-monitor = false #jack.short-name = false @@ -73,6 +81,7 @@ # ignore-all: Ignore all self connect requests #jack.self-connect-mode = allow #jack.locked-process = true + #jack.default-as-system = false } # client specific properties
View file
pipewire-0.3.45.tar.gz/src/daemon/minimal.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/minimal.conf.in
Changed
@@ -2,6 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/minimal.conf.d/ for system-wide changes or in +# ~/.config/pipewire/minimal.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system.
View file
pipewire-0.3.45.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -2,6 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/pipewire-pulse.conf.d/ for system-wide changes or in +# ~/.config/pipewire/pipewire-pulse.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system. @@ -67,6 +72,7 @@ # Extra modules can be loaded here. Setup in default.pa can be moved here context.exec = [ + { path = "pactl" args = "load-module module-always-sink" } #{ path = "pactl" args = "load-module module-switch-on-connect" } #{ path = "/usr/bin/sh" args = "~/.config/pipewire/default.pw" } ]
View file
pipewire-0.3.45.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.47.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -2,6 +2,11 @@ # # Copy and edit this file in @PIPEWIRE_CONFIG_DIR@ for system-wide changes # or in ~/.config/pipewire for local changes. +# +# It is also possible to place a file with an updated section in +# @PIPEWIRE_CONFIG_DIR@/pipewire.conf.d/ for system-wide changes or in +# ~/.config/pipewire/pipewire.conf.d/ for local changes. +# context.properties = { ## Configure properties in the system. @@ -24,7 +29,7 @@ #default.clock.rate = 48000 #default.clock.allowed-rates = [ 48000 ] #default.clock.quantum = 1024 - #default.clock.min-quantum = 32 + default.clock.min-quantum = 16 #default.clock.max-quantum = 2048 #default.clock.quantum-limit = 8192 #default.video.width = 640
View file
pipewire-0.3.45.tar.gz/src/daemon/systemd/meson.build -> pipewire-0.3.47.tar.gz/src/daemon/systemd/meson.build
Changed
@@ -1,6 +1,6 @@ -if not get_option('systemd-system-service').disabled() +if get_option('systemd-system-service').allowed() subdir('system') endif -if not get_option('systemd-user-service').disabled() +if get_option('systemd-user-service').allowed() subdir('user') endif
View file
pipewire-0.3.45.tar.gz/src/gst/gstpipewire.c -> pipewire-0.3.47.tar.gz/src/gst/gstpipewire.c
Changed
@@ -51,7 +51,7 @@ gst_element_register (plugin, "pipewiresink", GST_RANK_NONE, GST_TYPE_PIPEWIRE_SINK); -#if HAVE_GSTREAMER_DEVICE_PROVIDER +#ifdef HAVE_GSTREAMER_DEVICE_PROVIDER if (!gst_device_provider_register (plugin, "pipewiredeviceprovider", GST_RANK_PRIMARY + 1, GST_TYPE_PIPEWIRE_DEVICE_PROVIDER)) return FALSE;
View file
pipewire-0.3.45.tar.gz/src/gst/gstpipewireformat.c -> pipewire-0.3.47.tar.gz/src/gst/gstpipewireformat.c
Changed
@@ -445,6 +445,44 @@ return TRUE; } +static void +set_default_channels (struct spa_pod_builder *b, uint32_t channels) +{ + uint32_t position[SPA_AUDIO_MAX_CHANNELS] = {0}; + gboolean ok = TRUE; + + switch (channels) { + case 8: + position[6] = SPA_AUDIO_CHANNEL_SL; + position[7] = SPA_AUDIO_CHANNEL_SR; + SPA_FALLTHROUGH + case 6: + position[5] = SPA_AUDIO_CHANNEL_LFE; + SPA_FALLTHROUGH + case 5: + position[4] = SPA_AUDIO_CHANNEL_FC; + SPA_FALLTHROUGH + case 4: + position[2] = SPA_AUDIO_CHANNEL_RL; + position[3] = SPA_AUDIO_CHANNEL_RR; + SPA_FALLTHROUGH + case 2: + position[0] = SPA_AUDIO_CHANNEL_FL; + position[1] = SPA_AUDIO_CHANNEL_FR; + break; + case 1: + position[0] = SPA_AUDIO_CHANNEL_MONO; + break; + default: + ok = FALSE; + break; + } + + if (ok) + spa_pod_builder_add (b, SPA_FORMAT_AUDIO_position, + SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position), 0); +} + static gboolean handle_audio_fields (ConvertData *d) { @@ -538,8 +576,10 @@ } if (i > 0) { choice = spa_pod_builder_pop(&d->b, &f); - if (i == 1) + if (i == 1) { choice->body.type = SPA_CHOICE_None; + set_default_channels (&d->b, v); + } } } return TRUE;
View file
pipewire-0.3.45.tar.gz/src/gst/meson.build -> pipewire-0.3.47.tar.gz/src/gst/meson.build
Changed
@@ -8,7 +8,7 @@ 'gstpipewiresrc.c', ] -if not get_option('gstreamer-device-provider').disabled() +if get_option('gstreamer-device-provider').allowed() pipewire_gst_sources += [ 'gstpipewiredeviceprovider.c' ] endif
View file
pipewire-0.3.45.tar.gz/src/meson.build -> pipewire-0.3.47.tar.gz/src/meson.build
Changed
@@ -3,10 +3,10 @@ subdir('daemon') subdir('tools') subdir('modules') -if not get_option('examples').disabled() +if get_option('examples').allowed() subdir('examples') endif -if not get_option('tests').disabled() +if get_option('tests').allowed() subdir('tests') endif
View file
pipewire-0.3.45.tar.gz/src/modules/meson.build -> pipewire-0.3.47.tar.gz/src/modules/meson.build
Changed
@@ -10,6 +10,7 @@ 'module-echo-cancel.c', 'module-example-sink.c', 'module-example-source.c', + 'module-fallback-sink.c', 'module-filter-chain.c', 'module-link-factory.c', 'module-loopback.c', @@ -109,22 +110,15 @@ pipewire_module_echo_cancel_sources = [ 'module-echo-cancel.c', - 'module-echo-cancel/aec-null.c', ] -if webrtc_dep.found() - pipewire_module_echo_cancel_sources += [ - 'module-echo-cancel/aec-webrtc.cpp' - ] -endif - pipewire_module_echo_cancel = shared_library('pipewire-module-echo-cancel', pipewire_module_echo_cancel_sources, include_directories : [configinc], install : true, install_dir : modules_install_dir, install_rpath: modules_install_dir, - dependencies : [mathlib, dl_lib, pipewire_dep, webrtc_dep], + dependencies : [mathlib, dl_lib, pipewire_dep], ) pipewire_module_profiler = shared_library('pipewire-module-profiler', @@ -223,7 +217,6 @@ 'module-protocol-pulse/extensions/ext-stream-restore.c', 'module-protocol-pulse/format.c', 'module-protocol-pulse/manager.c', - 'module-protocol-pulse/media-roles.c', 'module-protocol-pulse/message.c', 'module-protocol-pulse/message-handler.c', 'module-protocol-pulse/module.c', @@ -231,6 +224,7 @@ 'module-protocol-pulse/pending-sample.c', 'module-protocol-pulse/pulse-server.c', 'module-protocol-pulse/quirks.c', + 'module-protocol-pulse/remap.c', 'module-protocol-pulse/reply.c', 'module-protocol-pulse/sample.c', 'module-protocol-pulse/sample-play.c', @@ -238,6 +232,7 @@ 'module-protocol-pulse/stream.c', 'module-protocol-pulse/utils.c', 'module-protocol-pulse/volume.c', + 'module-protocol-pulse/modules/module-always-sink.c', 'module-protocol-pulse/modules/module-combine-sink.c', 'module-protocol-pulse/modules/module-echo-cancel.c', 'module-protocol-pulse/modules/module-ladspa-sink.c', @@ -265,7 +260,6 @@ 'module-protocol-pulse/dbus-name.c', ] pipewire_module_protocol_pulse_deps += dbus_dep - cdata.set('HAVE_DBUS', 1) endif if avahi_dep.found() @@ -274,7 +268,7 @@ 'module-zeroconf-discover/avahi-poll.c', ] pipewire_module_protocol_pulse_deps += avahi_dep - cdata.set('HAVE_AVAHI', 1) + cdata.set('HAVE_AVAHI', true) endif pipewire_module_protocol_pulse = shared_library('pipewire-module-protocol-pulse', @@ -499,3 +493,12 @@ ) endif summary({'x11-bell': build_module_x11_bell}, bool_yn: true, section: 'Optional Modules') + +pipewire_module_fallback_sink = shared_library('pipewire-module-fallback-sink', + [ 'module-fallback-sink.c' ], + include_directories : [configinc], + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : [mathlib, dl_lib, rt_lib, pipewire_dep], +)
View file
pipewire-0.3.45.tar.gz/src/modules/module-access.c -> pipewire-0.3.47.tar.gz/src/modules/module-access.c
Changed
@@ -32,10 +32,10 @@ #include "config.h" -#if HAVE_SYS_VFS_H +#ifdef HAVE_SYS_VFS_H #include <sys/vfs.h> #endif -#if HAVE_SYS_MOUNT_H +#ifdef HAVE_SYS_MOUNT_H #include <sys/mount.h> #endif
View file
pipewire-0.3.45.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.47.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -47,28 +47,14 @@ /** \cond */ -#define MAX_INPUTS 1024 -#define MAX_OUTPUTS 1024 - #define MAX_BUFFERS 64 #define MAX_METAS 16u #define MAX_DATAS 64u #define MAX_AREAS 2048 -#define MAX_MIX 128 - -#define CHECK_IN_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_INPUTS) -#define CHECK_OUT_PORT_ID(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_OUTPUTS) -#define CHECK_PORT_ID(this,d,p) (CHECK_IN_PORT_ID(this,d,p) || CHECK_OUT_PORT_ID(this,d,p)) -#define CHECK_FREE_IN_PORT(this,d,p) (CHECK_IN_PORT_ID(this,d,p) && (this)->in_ports[p] == NULL) -#define CHECK_FREE_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p] == NULL) -#define CHECK_FREE_PORT(this,d,p) (CHECK_FREE_IN_PORT (this,d,p) || CHECK_FREE_OUT_PORT (this,d,p)) -#define CHECK_IN_PORT(this,d,p) (CHECK_IN_PORT_ID(this,d,p) && (this)->in_ports[p]) -#define CHECK_OUT_PORT(this,d,p) (CHECK_OUT_PORT_ID(this,d,p) && (this)->out_ports[p]) -#define CHECK_PORT(this,d,p) (CHECK_IN_PORT (this,d,p) || CHECK_OUT_PORT (this,d,p)) - -#define GET_IN_PORT(this,p) (this->in_ports[p]) -#define GET_OUT_PORT(this,p) (this->out_ports[p]) -#define GET_PORT(this,d,p) (d == SPA_DIRECTION_INPUT ? GET_IN_PORT(this,p) : GET_OUT_PORT(this,p)) + +#define CHECK_FREE_PORT(this,d,p) (p <= pw_map_get_size(&this->ports[d]) && !CHECK_PORT(this,d,p)) +#define CHECK_PORT(this,d,p) (pw_map_lookup(&this->ports[d], p) != NULL) +#define GET_PORT(this,d,p) (pw_map_lookup(&this->ports[d], p)) #define CHECK_PORT_BUFFER(this,b,p) (b < p->n_buffers) @@ -129,10 +115,7 @@ struct spa_source data_source; int writefd; - uint32_t n_inputs; - uint32_t n_outputs; - struct port *in_ports[MAX_INPUTS]; - struct port *out_ports[MAX_OUTPUTS]; + struct pw_map ports[2]; struct port dummy; @@ -213,8 +196,7 @@ mix_id = 0; else mix_id++; - if (mix_id >= MAX_MIX) - return NULL; + len = pw_array_get_len(&p->mix, struct mix); if (mix_id >= len) { size_t need = sizeof(struct mix) * (mix_id + 1 - len); @@ -432,19 +414,19 @@ { struct node *this = object; struct spa_hook_list save; - uint32_t i; + union pw_map_item *item; spa_return_val_if_fail(this != NULL, -EINVAL); spa_hook_list_isolate(&this->hooks, &save, listener, events, data); - for (i = 0; i < MAX_INPUTS; i++) { - if (this->in_ports[i]) - emit_port_info(this, this->in_ports[i]); + pw_array_for_each(item, &this->ports[SPA_DIRECTION_INPUT].items) { + if (item->data) + emit_port_info(this, item->data); } - for (i = 0; i < MAX_OUTPUTS; i++) { - if (this->out_ports[i]) - emit_port_info(this, this->out_ports[i]); + pw_array_for_each(item, &this->ports[SPA_DIRECTION_OUTPUT].items) { + if (item->data) + emit_port_info(this, item->data); } spa_hook_list_join(&this->hooks, &save); @@ -537,18 +519,8 @@ pw_array_clear(&port->mix); pw_array_init(&port->mix, sizeof(struct mix) * 2); - if (port->direction == SPA_DIRECTION_INPUT) { - if (this->in_ports[port->id] == port) { - this->in_ports[port->id] = NULL; - this->n_inputs--; - } - } - else { - if (this->out_ports[port->id] == port) { - this->out_ports[port->id] = NULL; - this->n_outputs--; - } - } + pw_map_insert_at(&this->ports[port->direction], port->id, NULL); + if (!port->removed) spa_node_emit_port_info(&this->hooks, port->direction, port->id, NULL); } @@ -598,9 +570,9 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); - spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); port = GET_PORT(this, direction, port_id); + spa_return_val_if_fail(port != NULL, -EINVAL); pw_log_debug("%p: seq:%d port %d.%d id:%u start:%u num:%u n_params:%d", this, seq, direction, port_id, id, start, num, port->n_params); @@ -649,15 +621,15 @@ struct mix *mix; spa_return_val_if_fail(this != NULL, -EINVAL); - if(!CHECK_PORT(this, direction, port_id)) + + port = GET_PORT(this, direction, port_id); + if(port == NULL) return param == NULL ? 0 : -EINVAL; pw_log_debug("%p: port %d.%d set param %s %d", this, direction, port_id, spa_debug_type_find_name(spa_type_param, id), id); - port = GET_PORT(this, direction, port_id); - if (id == SPA_PARAM_Format) { pw_array_for_each(mix, &port->mix) clear_buffers(this, mix); @@ -687,10 +659,9 @@ direction == SPA_DIRECTION_INPUT ? "input" : "output", port_id, mix_id, data, size); - if (!CHECK_PORT(this, direction, port_id)) - return data == NULL ? 0 : -EINVAL; - port = GET_PORT(this, direction, port_id); + if (port == NULL) + return data == NULL ? 0 : -EINVAL; if ((mix = find_mix(port, mix_id)) == NULL || !mix->valid) return -EINVAL; @@ -752,13 +723,13 @@ uint32_t i, j, peer_id; struct pw_client_node_buffer *mb; - if (!CHECK_PORT(this, direction, port_id)) + p = GET_PORT(this, direction, port_id); + if (p == NULL) return n_buffers == 0 ? 0 : -EINVAL; if (n_buffers > MAX_BUFFERS) return -ENOSPC; - p = GET_PORT(this, direction, port_id); spa_log_debug(this->log, "%p: %s port %d.%d use buffers %p %u flags:%08x", this, direction == SPA_DIRECTION_INPUT ? "input" : "output", @@ -920,7 +891,7 @@ struct node *this = object; spa_return_val_if_fail(this != NULL, -EINVAL); - spa_return_val_if_fail(CHECK_OUT_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL); + spa_return_val_if_fail(CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL); spa_log_trace_fp(this->log, "reuse buffer %d", buffer_id); @@ -1011,8 +982,6 @@ spa_log_debug(this->log, "%p: got port update change:%08x params:%d", this, change_mask, n_params); - if (!CHECK_PORT_ID(this, direction, port_id)) - return -EINVAL; remove = (change_mask == 0); @@ -1027,6 +996,9 @@ struct port *target; if (port == NULL) { + if (!CHECK_FREE_PORT(this, direction, port_id)) + return -EINVAL; + target = &this->dummy; spa_zero(this->dummy); target->direction = direction; @@ -1076,9 +1048,8 @@ direction == SPA_DIRECTION_INPUT ? "input" : "output", port_id, mix_id, buffers, n_buffers); - spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); - p = GET_PORT(this, direction, port_id); + spa_return_val_if_fail(p != NULL, -EINVAL); if (direction == SPA_DIRECTION_OUTPUT) mix_id = SPA_ID_INVALID; @@ -1374,6 +1345,8 @@ if (impl->io_areas) pw_memblock_unref(impl->io_areas); + pw_map_clear(&impl->node.ports[0]); + pw_map_clear(&impl->node.ports[1]); pw_map_clear(&impl->io_map); if (impl->fds[0] != -1) @@ -1565,13 +1538,7 @@ &impl_port_mix, p); ensure_mix(impl, p, SPA_ID_INVALID); - if (p->direction == SPA_DIRECTION_INPUT) { - this->in_ports[p->id] = p; - this->n_inputs++; - } else { - this->out_ports[p->id] = p; - this->n_outputs++; - } + pw_map_insert_at(&this->ports[p->direction], p->id, p); return; } @@ -1741,6 +1708,8 @@ impl->node.client = client; this->flags = do_register ? 0 : 1; + pw_map_init(&impl->node.ports[0], 64, 64); + pw_map_init(&impl->node.ports[1], 64, 64); pw_map_init(&impl->io_map, 64, 64); this->resource = resource;
View file
pipewire-0.3.45.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.47.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -42,7 +42,6 @@ #include "pipewire/extensions/client-node.h" #define MAX_BUFFERS 64 -#define MAX_MIX 4096 PW_LOG_TOPIC_EXTERN(mod_topic); #define PW_LOG_TOPIC_DEFAULT mod_topic @@ -74,7 +73,6 @@ int rtwritefd; struct pw_memmap *activation; - struct mix mix_pool[MAX_MIX]; struct spa_list mix[2]; struct spa_list free_mix; @@ -241,15 +239,17 @@ if ((mix = find_mix(data, direction, port_id, mix_id))) return mix; - if (spa_list_is_empty(&data->free_mix)) - return NULL; - port = pw_impl_node_find_port(data->node, direction, port_id); if (port == NULL) return NULL; - mix = spa_list_first(&data->free_mix, struct mix, link); - spa_list_remove(&mix->link); + if (spa_list_is_empty(&data->free_mix)) { + if ((mix = calloc(1, sizeof(*mix))) == NULL) + return NULL; + } else { + mix = spa_list_first(&data->free_mix, struct mix, link); + spa_list_remove(&mix->link); + } mix_init(mix, port, mix_id); spa_list_append(&data->mix[direction], &mix->link); @@ -986,21 +986,24 @@ clear_buffers(data, mix); pw_array_clear(&mix->buffers); - spa_list_remove(&mix->mix.link); spa_list_append(&data->free_mix, &mix->link); pw_impl_port_release_mix(mix->port, &mix->mix); } static void clean_node(struct node_data *d) { - struct mix *mix, *tmp; + struct mix *mix; if (d->have_transport) { - spa_list_for_each_safe(mix, tmp, &d->mix[SPA_DIRECTION_INPUT], link) + spa_list_consume(mix, &d->mix[SPA_DIRECTION_INPUT], link) clear_mix(d, mix); - spa_list_for_each_safe(mix, tmp, &d->mix[SPA_DIRECTION_OUTPUT], link) + spa_list_consume(mix, &d->mix[SPA_DIRECTION_OUTPUT], link) clear_mix(d, mix); } + spa_list_consume(mix, &d->free_mix, link) { + spa_list_remove(&mix->link); + free(mix); + } clean_transport(d); } @@ -1121,6 +1124,7 @@ pw_log_debug("%p: removed", data); spa_hook_remove(&data->proxy_client_node_listener); + spa_hook_remove(&data->client_node_listener); if (data->node) { spa_hook_remove(&data->node_listener); @@ -1220,7 +1224,6 @@ struct pw_impl_node *node = object; struct pw_proxy *client_node; struct node_data *data; - int i; user_data_size = SPA_ROUND_UP_N(user_data_size, __alignof__(struct node_data)); @@ -1254,8 +1257,6 @@ spa_list_init(&data->free_mix); spa_list_init(&data->mix[0]); spa_list_init(&data->mix[1]); - for (i = 0; i < MAX_MIX; i++) - spa_list_append(&data->free_mix, &data->mix_pool[i].link); spa_list_init(&data->links);
View file
pipewire-0.3.45.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.47.tar.gz/src/modules/module-echo-cancel.c
Changed
@@ -43,10 +43,14 @@ #include <spa/param/audio/raw.h> #include <spa/param/profiler.h> #include <spa/pod/builder.h> +#include <spa/support/plugin.h> #include <spa/utils/json.h> +#include <spa/utils/names.h> #include <spa/utils/result.h> #include <spa/utils/ringbuffer.h> #include <spa/utils/string.h> +#include <spa/support/plugin-loader.h> +#include <spa/interfaces/audio/aec.h> #include <pipewire/private.h> #include <pipewire/impl.h> @@ -54,8 +58,6 @@ #include <pipewire/extensions/profiler.h> -#include "module-echo-cancel/echo-cancel.h" - /** \page page_module_echo_cancel PipeWire Module: Echo Cancel * * The `echo-cancel` module performs echo cancellation. The module creates @@ -68,8 +70,8 @@ * * - `source.props = {}`: properties to be passed to the source stream * - `sink.props = {}`: properties to be passed to the sink stream - * - `aec.method = <str>`: the echo cancellation method. Currently supported: - * `webrtc`. Leave unset to use the default method (`webrtc`). + * - `library.name = <str>`: the echo cancellation library Currently supported: + * `aec/libspa-aec-exaudio`. Leave unset to use the default method (`aec/libspa-aec-exaudio`). * - `aec.args = <str>`: arguments to pass to the echo cancellation method * * ## General options @@ -94,7 +96,7 @@ * context.modules = [ * { name = libpipewire-module-echo-cancel * args = { - * # aec.method = webrtc + * # library.name = aec/libspa-aec-exaudio * # node.latency = 1024/48000 * source.props = { * node.name = "Echo Cancellation Source" @@ -138,7 +140,7 @@ "[ audio.position=<channel map> ] " "[ buffer.max_size=<max buffer size in ms> ] " "[ buffer.play_delay=<play delay in ms> ] " - "[ aec.method=<aec method> ] " + "[ library.name =<library name> ] " "[ aec.args=<aec arguments> ] " "[ source.props=<properties> ] " "[ sink.props=<properties> ] " }, @@ -185,8 +187,7 @@ uint32_t out_ringsize; struct spa_ringbuffer out_ring; - const struct echo_cancel_info *aec_info; - void *aec; + struct spa_audio_aec *aec; uint32_t aec_blocksize; unsigned int capture_ready:1; @@ -197,6 +198,9 @@ uint32_t max_buffer_size; uint32_t buffer_delay; + + struct spa_handle *spa_handle; + struct spa_plugin_loader *loader; }; static void do_unload_module(void *obj, void *data, int res, uint32_t id) @@ -283,7 +287,7 @@ pw_stream_queue_buffer(impl->playback, pout); /* Now run the canceller */ - echo_cancel_run(impl->aec_info, impl->aec, rec, play_delayed, out, size / sizeof(float)); + spa_audio_aec_run(impl->aec, rec, play_delayed, out, size / sizeof(float)); /* Next, copy over the output to the output ringbuffer */ avail = spa_ringbuffer_get_write_index(&impl->out_ring, &oindex); @@ -647,8 +651,8 @@ pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str); if ((str = pw_properties_get(impl->source_props, PW_KEY_NODE_LATENCY)) != NULL) pw_properties_set(props, PW_KEY_NODE_LATENCY, str); - else if (impl->aec_info->latency) - pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency); + else if (impl->aec->latency) + pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec->latency); impl->capture = pw_stream_new(impl->core, "Echo-Cancel Capture", props); @@ -680,8 +684,8 @@ pw_properties_set(props, PW_KEY_NODE_LINK_GROUP, str); if ((str = pw_properties_get(impl->sink_props, PW_KEY_NODE_LATENCY)) != NULL) pw_properties_set(props, PW_KEY_NODE_LATENCY, str); - else if (impl->aec_info->latency) - pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency); + else if (impl->aec->latency) + pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec->latency); impl->playback = pw_stream_new(impl->core, "Echo-Cancel Playback", props); @@ -803,8 +807,8 @@ pw_stream_destroy(impl->sink); if (impl->core && impl->do_disconnect) pw_core_disconnect(impl->core); - if (impl->aec) - echo_cancel_destroy(impl->aec_info, impl->aec); + if (impl->spa_handle) + spa_plugin_loader_unload(impl->loader, impl->spa_handle); pw_properties_free(impl->source_props); pw_properties_free(impl->sink_props); @@ -893,7 +897,10 @@ struct impl *impl; uint32_t id = pw_global_get_id(pw_impl_module_get_global(module)); const char *str; - int res; + const char *path; + int res = 0; + struct spa_handle *handle = NULL; + void *iface; PW_LOG_TOPIC_INIT(mod_topic); @@ -967,31 +974,66 @@ if (pw_properties_get(impl->sink_props, PW_KEY_MEDIA_CLASS) == NULL) pw_properties_set(impl->sink_props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - if ((str = pw_properties_get(props, "aec.method")) == NULL) - str = "webrtc"; + if ((str = pw_properties_get(props, "aec.method")) != NULL) + pw_log_warn("aec.method is not supported anymore use library.name"); -#ifdef HAVE_WEBRTC - if (spa_streq(str, "webrtc")) - impl->aec_info = echo_cancel_webrtc; - else -#endif - impl->aec_info = echo_cancel_null; + /* Use webrtc as default */ + if ((path = pw_properties_get(props, "library.name")) == NULL) + path = "aec/libspa-aec-webrtc"; + + struct spa_dict_item info_items[] = { + { SPA_KEY_LIBRARY_NAME, path }, + }; + struct spa_dict info = SPA_DICT_INIT_ARRAY(info_items); + + impl->loader = spa_support_find(context->support, context->n_support, SPA_TYPE_INTERFACE_PluginLoader); + if (impl->loader == NULL) { + pw_log_error("a plugin loader is needed"); + return -EINVAL; + } + + handle = spa_plugin_loader_load(impl->loader, SPA_NAME_AEC, &info); + if (handle == NULL) { + pw_log_error("AEC codec plugin %s not available library.name %s", SPA_NAME_AEC, path); + return -ENOENT; + } + + if ((res = spa_handle_get_interface(handle, SPA_TYPE_INTERFACE_AUDIO_AEC, &iface)) < 0) { + pw_log_error("can't get %s interface %d", SPA_TYPE_INTERFACE_AUDIO_AEC, res); + return res; + } + impl->aec = iface; + impl->spa_handle = handle; + if (impl->aec->iface.version != SPA_VERSION_AUDIO_AEC) { + pw_log_error("codec plugin %s has incompatible ABI version (%d != %d)", + SPA_NAME_AEC, impl->aec->iface.version, SPA_VERSION_AUDIO_AEC); + res = -ENOENT; + goto error; + } + + (void)SPA_SUPPORT_INIT(SPA_TYPE_INTERFACE_AUDIO_AEC, (struct spa_audio_aec *)impl->aec); + + pw_log_info("Using plugin AEC %s", impl->aec->name); if ((str = pw_properties_get(props, "aec.args")) != NULL) aec_props = pw_properties_new_string(str); else aec_props = pw_properties_new(NULL, NULL); - impl->aec = echo_cancel_create(impl->aec_info, aec_props, &impl->info); + if (spa_audio_aec_init(impl->aec, &aec_props->dict, &impl->info)) { + pw_log_error("codec plugin %s create failed", impl->aec->name); + res = -ENOENT; + goto error; + } pw_properties_free(aec_props); - if (impl->aec_info->latency) { + if (impl->aec->latency) { unsigned int num, denom, req_num, req_denom; unsigned int factor = 0; unsigned int new_num = 0; - spa_assert_se(sscanf(impl->aec_info->latency, "%u/%u", &num, &denom) == 2); + spa_assert_se(sscanf(impl->aec->latency, "%u/%u", &num, &denom) == 2); if ((str = pw_properties_get(props, PW_KEY_NODE_LATENCY)) != NULL) { sscanf(str, "%u/%u", &req_num, &req_denom); @@ -1000,8 +1042,8 @@ } if (factor == 0 || new_num == 0) { - pw_log_info("Setting node latency to %s", impl->aec_info->latency); - pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec_info->latency); + pw_log_info("Setting node latency to %s", impl->aec->latency); + pw_properties_set(props, PW_KEY_NODE_LATENCY, impl->aec->latency); impl->aec_blocksize = sizeof(float) * impl->info.rate * num / denom; } else { pw_log_info("Setting node latency to %u/%u", new_num, req_denom);
View file
pipewire-0.3.47.tar.gz/src/modules/module-fallback-sink.c
Added
@@ -0,0 +1,473 @@ +/* PipeWire + * + * Copyright © 2021 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include "config.h" + +#include <spa/utils/result.h> +#include <spa/utils/string.h> +#include <spa/param/audio/raw.h> + +#include <pipewire/impl.h> +#include <pipewire/i18n.h> + +/** \page page_module_fallback_sink PipeWire Module: Fallback Sink + * + * Fallback sink, which appear dynamically when no other sinks are + * present. This is only useful for Pulseaudio compatibility. + */ + +#define NAME "fallback-sink" + +#define DEFAULT_SINK_NAME "auto_null" +#define DEFAULT_SINK_DESCRIPTION _("Dummy Output") + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +#define MODULE_USAGE ("[ sink.name=<str> ] " \ + "[ sink.description=<str> ] ") + +static const struct spa_dict_item module_props[] = { + { PW_KEY_MODULE_AUTHOR, "Pauli Virtanen <pav@iki.fi>" }, + { PW_KEY_MODULE_DESCRIPTION, "Dynamically appearing fallback sink" }, + { PW_KEY_MODULE_USAGE, MODULE_USAGE }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +struct bitmap { + uint8_t *data; + size_t size; + size_t items; +}; + +struct impl { + struct pw_context *context; + + struct pw_impl_module *module; + struct spa_hook module_listener; + + struct pw_core *core; + struct pw_registry *registry; + struct pw_proxy *sink; + + struct spa_hook core_listener; + struct spa_hook core_proxy_listener; + struct spa_hook registry_listener; + struct spa_hook sink_listener; + + struct pw_properties *properties; + + struct bitmap sink_ids; + struct bitmap fallback_sink_ids; + + int check_seq; + + unsigned int do_disconnect:1; + unsigned int scheduled:1; +}; + +static int bitmap_add(struct bitmap *map, uint32_t i) +{ + const uint32_t pos = (i >> 3); + const uint8_t mask = 1 << (i & 0x7); + + if (pos >= map->size) { + size_t new_size = map->size + pos + 16; + void *p; + + p = realloc(map->data, new_size); + if (!p) + return -errno; + + memset((uint8_t*)p + map->size, 0, new_size - map->size); + map->data = p; + map->size = new_size; + } + + if (map->data[pos] & mask) + return 1; + + map->data[pos] |= mask; + ++map->items; + + return 0; +} + +static bool bitmap_remove(struct bitmap *map, uint32_t i) +{ + const uint32_t pos = (i >> 3); + const uint8_t mask = 1 << (i & 0x7); + + if (pos >= map->size) + return false; + + if (!(map->data[pos] & mask)) + return false; + + map->data[pos] &= ~mask; + --map->items; + + return true; +} + +static void bitmap_free(struct bitmap *map) +{ + free(map->data); + spa_zero(*map); +} + +static int add_id(struct bitmap *map, uint32_t id) +{ + int res; + + if (id == SPA_ID_INVALID) + return -EINVAL; + + if ((res = bitmap_add(map, id)) < 0) + pw_log_error("%s", spa_strerror(res)); + + return res; +} + +static void reschedule_check(struct impl *impl) +{ + if (!impl->scheduled) + return; + + impl->check_seq = pw_core_sync(impl->core, 0, impl->check_seq); +} + +static void schedule_check(struct impl *impl) +{ + if (impl->scheduled) + return; + + impl->scheduled = true; + impl->check_seq = pw_core_sync(impl->core, 0, impl->check_seq); +} + +static void sink_proxy_removed(void *data) +{ + struct impl *impl = data; + + pw_proxy_destroy(impl->sink); +} + +static void sink_proxy_bound(void *data, uint32_t id) +{ + struct impl *impl = data; + + add_id(&impl->sink_ids, id); + add_id(&impl->fallback_sink_ids, id); + + reschedule_check(impl); + schedule_check(impl); +} + +static void sink_proxy_destroy(void *data) +{ + struct impl *impl = data; + + pw_log_debug("fallback dummy sink destroyed"); + + spa_hook_remove(&impl->sink_listener); + impl->sink = NULL; +} + +static const struct pw_proxy_events sink_proxy_events = { + PW_VERSION_PROXY_EVENTS, + .removed = sink_proxy_removed, + .bound = sink_proxy_bound, + .destroy = sink_proxy_destroy, +}; + +static int sink_create(struct impl *impl) +{ + if (impl->sink) + return 0; + + pw_log_info("creating fallback dummy sink"); + + impl->sink = pw_core_create_object(impl->core, + "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, + impl->properties ? &impl->properties->dict : NULL, 0); + if (impl->sink == NULL) + return -errno; + + pw_proxy_add_listener(impl->sink, &impl->sink_listener, &sink_proxy_events, impl); + + return 0; +} + +static void sink_destroy(struct impl *impl) +{ + if (!impl->sink) + return; + + pw_log_info("removing fallback dummy sink"); + pw_proxy_destroy(impl->sink); +} + +static void check_sinks(struct impl *impl) +{ + int res; + + pw_log_debug("seeing %zu sink(s), %zu fallback sink(s)", + impl->sink_ids.items, impl->fallback_sink_ids.items); + + if (impl->sink_ids.items > impl->fallback_sink_ids.items) { + sink_destroy(impl); + } else { + if ((res = sink_create(impl)) < 0) + pw_log_error("error creating sink: %s", spa_strerror(res)); + } +} + +static void registry_event_global(void *data, uint32_t id, + uint32_t permissions, const char *type, uint32_t version, + const struct spa_dict *props) +{ + struct impl *impl = data; + const char *str; + + reschedule_check(impl); + + if (!props) + return; + + if (!spa_streq(type, PW_TYPE_INTERFACE_Node)) + return; + + str = spa_dict_lookup(props, PW_KEY_MEDIA_CLASS); + if (!(spa_streq(str, "Audio/Sink") || spa_streq(str, "Audio/Sink/Virtual"))) + return; + + add_id(&impl->sink_ids, id); + schedule_check(impl); +} + +static void registry_event_global_remove(void *data, uint32_t id) +{ + struct impl *impl = data; + + reschedule_check(impl); + + bitmap_remove(&impl->fallback_sink_ids, id); + if (bitmap_remove(&impl->sink_ids, id)) + schedule_check(impl); +} + +static const struct pw_registry_events registry_events = { + PW_VERSION_REGISTRY_EVENTS, + .global = registry_event_global, + .global_remove = registry_event_global_remove, +}; + +static void core_done(void *data, uint32_t id, int seq) +{ + struct impl *impl = data; + + if (seq == impl->check_seq) { + impl->scheduled = false; + check_sinks(impl); + } +} + +static const struct pw_core_events core_events = { + PW_VERSION_CORE_EVENTS, + .done = core_done, +}; + +static void core_proxy_removed(void *data) +{ + struct impl *impl = data; + + if (impl->registry) { + spa_hook_remove(&impl->registry_listener); + pw_proxy_destroy((struct pw_proxy*)impl->registry); + impl->registry = NULL; + } +} + +static void core_proxy_destroy(void *data) +{ + struct impl *impl = data; + + spa_hook_remove(&impl->core_listener); + spa_hook_remove(&impl->core_proxy_listener); + impl->core = NULL; +} + +static const struct pw_proxy_events core_proxy_events = { + PW_VERSION_PROXY_EVENTS, + .destroy = core_proxy_destroy, + .removed = core_proxy_removed, +}; + +static void impl_destroy(struct impl *impl) +{ + sink_destroy(impl); + + if (impl->registry) { + spa_hook_remove(&impl->registry_listener); + pw_proxy_destroy((struct pw_proxy*)impl->registry); + impl->registry = NULL; + } + + if (impl->core) { + spa_hook_remove(&impl->core_listener); + spa_hook_remove(&impl->core_proxy_listener); + if (impl->do_disconnect) + pw_core_disconnect(impl->core); + impl->core = NULL; + } + + if (impl->properties) { + pw_properties_free(impl->properties); + impl->properties = NULL; + } + + bitmap_free(&impl->sink_ids); + bitmap_free(&impl->fallback_sink_ids); + + free(impl); +} + +static void module_destroy(void *data) +{ + struct impl *impl = data; + spa_hook_remove(&impl->module_listener); + impl_destroy(impl); +} + +static const struct pw_impl_module_events module_events = { + PW_VERSION_IMPL_MODULE_EVENTS, + .destroy = module_destroy, +}; + +SPA_EXPORT +int pipewire__module_init(struct pw_impl_module *module, const char *args) +{ + struct pw_context *context = pw_impl_module_get_context(module); + struct pw_properties *props = NULL; + struct impl *impl = NULL; + const char *str; + int res; + + PW_LOG_TOPIC_INIT(mod_topic); + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + goto error_errno; + + pw_log_debug("module %p: new %s", impl, args); + + if (args == NULL) + args = ""; + + impl->module = module; + impl->context = context; + + props = pw_properties_new_string(args); + if (props == NULL) + goto error_errno; + + impl->properties = pw_properties_new(NULL, NULL); + if (impl->properties == NULL) + goto error_errno; + + if ((str = pw_properties_get(props, "sink.name")) == NULL) + str = DEFAULT_SINK_NAME; + pw_properties_set(impl->properties, PW_KEY_NODE_NAME, str); + + if ((str = pw_properties_get(props, "sink.description")) == NULL) + str = DEFAULT_SINK_DESCRIPTION; + pw_properties_set(impl->properties, PW_KEY_NODE_DESCRIPTION, str); + + pw_properties_setf(impl->properties, SPA_KEY_AUDIO_RATE, "%u", 48000); + pw_properties_setf(impl->properties, SPA_KEY_AUDIO_CHANNELS, "%u", 2); + pw_properties_set(impl->properties, SPA_KEY_AUDIO_POSITION, "FL,FR"); + + pw_properties_set(impl->properties, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + pw_properties_set(impl->properties, PW_KEY_FACTORY_NAME, "support.null-audio-sink"); + pw_properties_set(impl->properties, PW_KEY_NODE_VIRTUAL, "true"); + pw_properties_set(impl->properties, "monitor.channel-volumes", "true"); + + impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); + if (impl->core == NULL) { + str = pw_properties_get(props, PW_KEY_REMOTE_NAME); + impl->core = pw_context_connect(impl->context, + pw_properties_new( + PW_KEY_REMOTE_NAME, str, + NULL), + 0); + impl->do_disconnect = true; + } + if (impl->core == NULL) { + res = -errno; + pw_log_error("can't connect: %m"); + goto error; + } + + pw_proxy_add_listener((struct pw_proxy*)impl->core, + &impl->core_proxy_listener, &core_proxy_events, + impl); + + pw_core_add_listener(impl->core, &impl->core_listener, &core_events, impl); + + impl->registry = pw_core_get_registry(impl->core, + PW_VERSION_REGISTRY, 0); + if (impl->registry == NULL) + goto error_errno; + + pw_registry_add_listener(impl->registry, + &impl->registry_listener, + ®istry_events, impl); + + pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); + + pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props)); + + schedule_check(impl); + + pw_properties_free(props); + return 0; + +error_errno: + res = -errno; +error: + if (props) + pw_properties_free(props); + if (impl) + impl_destroy(impl); + return res; +}
View file
pipewire-0.3.45.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.47.tar.gz/src/modules/module-profiler.c
Changed
@@ -214,10 +214,17 @@ spa_list_for_each(t, &node->rt.target_list, link) { struct pw_impl_node *n = t->node; struct pw_node_activation *na; + struct spa_fraction latency; if (n == NULL || n == node) continue; + latency = n->latency; + if (n->force_quantum != 0) + latency.num = n->force_quantum; + if (n->force_rate != 0) + latency.denom = n->force_rate; + na = n->rt.activation; spa_pod_builder_prop(&b, SPA_PROFILER_followerBlock, 0); spa_pod_builder_add_struct(&b, @@ -228,7 +235,7 @@ SPA_POD_Long(na->awake_time), SPA_POD_Long(na->finish_time), SPA_POD_Int(na->status), - SPA_POD_Fraction(&n->latency)); + SPA_POD_Fraction(&latency)); } spa_pod_builder_pop(&b, &f[0]);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -35,7 +35,7 @@ #include <fcntl.h> #include <sys/file.h> #include <ctype.h> -#if HAVE_PWD_H +#ifdef HAVE_PWD_H #include <pwd.h> #endif #if defined(__FreeBSD__)
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-native/local-socket.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-native/local-socket.c
Changed
@@ -35,7 +35,7 @@ #include <sys/stat.h> #include <fcntl.h> #include <sys/file.h> -#if HAVE_PWD_H +#ifdef HAVE_PWD_H #include <pwd.h> #endif
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
@@ -313,7 +313,7 @@ } /* returns true if an event with the (mask, event, index) triplet should be dropped because it is redundant */ -static bool client_prune_subscribe_events(struct client *client, uint32_t mask, uint32_t event, uint32_t index) +static bool client_prune_subscribe_events(struct client *client, uint32_t event, uint32_t index) { struct message *m, *t; @@ -376,7 +376,7 @@ pw_log_debug("client %p: SUBSCRIBE event:%08x index:%u", client, event, index); - if (client_prune_subscribe_events(client, mask, event, index)) + if (client_prune_subscribe_events(client, event, index)) return 0; struct message *reply = message_alloc(client->impl, -1, 0);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-device-restore.c
Changed
@@ -43,7 +43,6 @@ #include "../extension.h" #include "../format.h" #include "../manager.h" -#include "../media-roles.h" #include "../message.h" #include "../reply.h" #include "../volume.h"
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/extensions/ext-stream-restore.c
Changed
@@ -42,8 +42,8 @@ #include "../extension.h" #include "../format.h" #include "../manager.h" -#include "../media-roles.h" #include "../message.h" +#include "../remap.h" #include "../reply.h" #include "../volume.h" #include "registry.h"
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/message.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/message.c
Changed
@@ -28,15 +28,14 @@ #include <spa/debug/buffer.h> #include <spa/utils/defs.h> #include <spa/utils/string.h> -#include <pipewire/keys.h> #include <pipewire/log.h> #include "defs.h" #include "format.h" #include "internal.h" #include "log.h" -#include "media-roles.h" #include "message.h" +#include "remap.h" #include "volume.h" #define MAX_SIZE (256*1024) @@ -65,20 +64,6 @@ return v * v * v; } -static const struct str_map key_table[] = { - { PW_KEY_DEVICE_BUS_PATH, "device.bus_path" }, - { PW_KEY_DEVICE_FORM_FACTOR, "device.form_factor" }, - { PW_KEY_DEVICE_ICON_NAME, "device.icon_name" }, - { PW_KEY_DEVICE_INTENDED_ROLES, "device.intended_roles" }, - { PW_KEY_NODE_DESCRIPTION, "device.description" }, - { PW_KEY_MEDIA_ICON_NAME, "media.icon_name" }, - { PW_KEY_APP_ICON_NAME, "application.icon_name" }, - { PW_KEY_APP_PROCESS_MACHINE_ID, "application.process.machine_id" }, - { PW_KEY_APP_PROCESS_SESSION_ID, "application.process.session_id" }, - { PW_KEY_MEDIA_ROLE, "media.role", media_role_map }, - { NULL, NULL }, -}; - static int read_u8(struct message *m, uint8_t *val) { if (m->offset + 1 > m->length) @@ -153,7 +138,7 @@ TAG_INVALID)) < 0) return res; - if (remap && (map = str_map_find(key_table, NULL, key)) != NULL) { + if (remap && (map = str_map_find(props_key_map, NULL, key)) != NULL) { key = map->pw_str; if (map->child != NULL && (map = str_map_find(map->child, NULL, data)) != NULL) @@ -567,7 +552,7 @@ int l; const struct str_map *map; - if (remap && (map = str_map_find(key_table, key, NULL)) != NULL) { + if (remap && (map = str_map_find(props_key_map, key, NULL)) != NULL) { key = map->pa_str; if (map->child != NULL && (map = str_map_find(map->child, val, NULL)) != NULL)
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
@@ -25,6 +25,7 @@ #include <stdlib.h> #include <string.h> +#include <ctype.h> #include <spa/utils/defs.h> #include <spa/utils/list.h> @@ -41,6 +42,7 @@ #include "internal.h" #include "log.h" #include "module.h" +#include "remap.h" static void on_module_unload(void *obj, void *data, int res, uint32_t index) { @@ -139,8 +141,11 @@ { char *s = strdup(str), *p = s, *e, f; const char *k, *v; + const struct str_map *map; while (*p) { + while (*p && isspace(*p)) + p++; e = strchr(p, '='); if (e == NULL) break; @@ -168,6 +173,13 @@ if (*e != '\0') p++; *e = '\0'; + + if ((map = str_map_find(props_key_map, NULL, k)) != NULL) { + k = map->pw_str; + if (map->child != NULL && + (map = str_map_find(map->child, NULL, v)) != NULL) + v = map->pw_str; + } pw_properties_set(props, k, v); } free(s); @@ -248,29 +260,30 @@ #include "modules/registry.h" static const struct module_info module_list[] = { - { "module-combine-sink", create_module_combine_sink, }, - { "module-echo-cancel", create_module_echo_cancel, }, - { "module-ladspa-sink", create_module_ladspa_sink, }, - { "module-ladspa-source", create_module_ladspa_source, }, - { "module-loopback", create_module_loopback, }, - { "module-null-sink", create_module_null_sink, }, - { "module-native-protocol-tcp", create_module_native_protocol_tcp, }, - { "module-pipe-source", create_module_pipe_source, }, - { "module-pipe-sink", create_module_pipe_sink, }, - { "module-raop-discover", create_module_raop_discover, }, - { "module-remap-sink", create_module_remap_sink, }, - { "module-remap-source", create_module_remap_source, }, - { "module-simple-protocol-tcp", create_module_simple_protocol_tcp, }, - { "module-switch-on-connect", create_module_switch_on_connect, }, - { "module-tunnel-sink", create_module_tunnel_sink, }, - { "module-tunnel-source", create_module_tunnel_source, }, - { "module-zeroconf-discover", create_module_zeroconf_discover, }, + { "module-always-sink", 1, create_module_always_sink, }, + { "module-combine-sink", 0, create_module_combine_sink, }, + { "module-echo-cancel", 0, create_module_echo_cancel, }, + { "module-ladspa-sink", 0, create_module_ladspa_sink, }, + { "module-ladspa-source", 0, create_module_ladspa_source, }, + { "module-loopback", 0, create_module_loopback, }, + { "module-null-sink", 0, create_module_null_sink, }, + { "module-native-protocol-tcp", 0, create_module_native_protocol_tcp, }, + { "module-pipe-source", 0, create_module_pipe_source, }, + { "module-pipe-sink", 0, create_module_pipe_sink, }, + { "module-raop-discover", 1, create_module_raop_discover, }, + { "module-remap-sink", 0, create_module_remap_sink, }, + { "module-remap-source", 0, create_module_remap_source, }, + { "module-simple-protocol-tcp", 0, create_module_simple_protocol_tcp, }, + { "module-switch-on-connect", 1, create_module_switch_on_connect, }, + { "module-tunnel-sink", 0, create_module_tunnel_sink, }, + { "module-tunnel-source", 0, create_module_tunnel_source, }, + { "module-zeroconf-discover", 1, create_module_zeroconf_discover, }, #ifdef HAVE_AVAHI - { "module-zeroconf-publish", create_module_zeroconf_publish, }, + { "module-zeroconf-publish", 0, create_module_zeroconf_publish, }, #endif - { "module-roc-sink", create_module_roc_sink, }, - { "module-roc-source", create_module_roc_source, }, - { "module-x11-bell", create_module_x11_bell, }, + { "module-roc-sink", 0, create_module_roc_sink, }, + { "module-roc-source", 0, create_module_roc_source, }, + { "module-x11-bell", 0, create_module_x11_bell, }, }; static const struct module_info *find_module_info(const char *name) @@ -285,6 +298,13 @@ return NULL; } +static int find_module_by_name(void *item_data, void *data) +{ + const char *name = data; + const struct module *module = item_data; + return spa_streq(module->name, name) ? 1 : 0; +} + struct module *module_create(struct client *client, const char *name, const char *args) { struct impl *impl = client->impl; @@ -296,6 +316,17 @@ errno = ENOENT; return NULL; } + + if (info->load_once) { + int exists; + exists = pw_map_for_each(&impl->modules, find_module_by_name, + (void *)name); + if (exists) { + errno = EEXIST; + return NULL; + } + } + module = info->create(impl, args); if (module == NULL) return NULL;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/module.h
Changed
@@ -37,6 +37,7 @@ struct module_info { const char *name; + unsigned int load_once:1; struct module *(*create) (struct impl *impl, const char *args); };
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-always-sink.c
Added
@@ -0,0 +1,136 @@ +/* PipeWire + * + * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <pipewire/pipewire.h> + +#include "../module.h" + +#define NAME "always-sink" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct module_always_sink_data { + struct module *module; + + struct pw_impl_module *mod; + struct spa_hook mod_listener; +}; + +static void module_destroy(void *data) +{ + struct module_always_sink_data *d = data; + spa_hook_remove(&d->mod_listener); + d->mod = NULL; + module_schedule_unload(d->module); +} + +static const struct pw_impl_module_events module_events = { + PW_VERSION_IMPL_MODULE_EVENTS, + .destroy = module_destroy +}; + +static int module_always_sink_load(struct client *client, struct module *module) +{ + struct module_always_sink_data *data = module->user_data; + FILE *f; + char *args; + const char *str; + size_t size; + + f = open_memstream(&args, &size); + fprintf(f, "{"); + if ((str = pw_properties_get(module->props, "sink_name")) != NULL) + fprintf(f, " sink.name = \"%s\"", str); + fprintf(f, " }"); + fclose(f); + + data->mod = pw_context_load_module(module->impl->context, + "libpipewire-module-fallback-sink", + args, NULL); + free(args); + + if (data->mod == NULL) + return -errno; + + pw_impl_module_add_listener(data->mod, + &data->mod_listener, + &module_events, data); + return 0; +} + +static int module_always_sink_unload(struct module *module) +{ + struct module_always_sink_data *d = module->user_data; + + if (d->mod) { + spa_hook_remove(&d->mod_listener); + pw_impl_module_destroy(d->mod); + d->mod = NULL; + } + return 0; +} + +static const struct module_methods module_always_sink_methods = { + VERSION_MODULE_METHODS, + .load = module_always_sink_load, + .unload = module_always_sink_unload, +}; + +static const struct spa_dict_item module_always_sink_info[] = { + { PW_KEY_MODULE_AUTHOR, "Pauli Virtanen <pav@iki.fi>" }, + { PW_KEY_MODULE_DESCRIPTION, "Always keeps at least one sink loaded even if it's a null one" }, + { PW_KEY_MODULE_USAGE, "sink_name=<name of sink>" }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +struct module *create_module_always_sink(struct impl *impl, const char *argument) +{ + struct module *module; + struct pw_properties *props = NULL; + int res; + + PW_LOG_TOPIC_INIT(mod_topic); + + props = pw_properties_new_dict(&SPA_DICT_INIT_ARRAY(module_always_sink_info)); + if (props == NULL) { + res = -EINVAL; + goto out; + } + if (argument) + module_args_add_props(props, argument); + + module = module_new(impl, &module_always_sink_methods, sizeof(struct module_always_sink_data)); + if (module == NULL) { + res = -errno; + goto out; + } + module->props = props; + + return module; +out: + pw_properties_free(props); + errno = -res; + return NULL; +}
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
@@ -39,6 +39,8 @@ #define MAX_SINKS 64 /* ... good enough for anyone */ +#define TIMEOUT_SINKS_MSEC 2000 + static const struct spa_dict_item module_combine_sink_info[] = { { PW_KEY_MODULE_AUTHOR, "Arun Raghavan <arun@asymptotic.io>" }, { PW_KEY_MODULE_DESCRIPTION, "Combine multiple sinks into a single sink" }, @@ -61,6 +63,7 @@ struct spa_hook stream_listener; struct module_combine_sink_data *data; bool cleanup; + bool started; }; struct module_combine_sink_data { @@ -80,8 +83,14 @@ struct combine_stream streams[MAX_SINKS]; struct spa_source *cleanup; + struct spa_source *sinks_timeout; struct spa_audio_info_raw info; + + unsigned int sinks_pending; + unsigned int source_started:1; + unsigned int load_emitted:1; + unsigned int start_error:1; }; /* Core connection: mainly to unload the module if the connection errors out */ @@ -161,6 +170,24 @@ pw_stream_queue_buffer(data->sink, in); } +static void check_initialized(struct module_combine_sink_data *data) +{ + struct module *module = data->module; + + if (data->load_emitted) + return; + + if (data->start_error) { + pw_log_debug("module load error"); + data->load_emitted = true; + module_emit_loaded(module, -EIO); + } else if (data->sinks_pending == 0 && data->source_started) { + pw_log_debug("module loaded"); + data->load_emitted = true; + module_emit_loaded(module, 0); + } +} + static void on_in_stream_state_changed(void *d, enum pw_stream_state old, enum pw_stream_state state, const char *error) { @@ -168,6 +195,14 @@ struct module *module = data->module; uint32_t i; + if (!data->source_started && state != PW_STREAM_STATE_CONNECTING) { + /* Input stream appears on server */ + data->source_started = true; + if (state < PW_STREAM_STATE_PAUSED) + data->start_error = true; + check_initialized(data); + } + switch (state) { case PW_STREAM_STATE_PAUSED: pw_stream_flush(data->sink, false); @@ -199,6 +234,16 @@ { struct combine_stream *s = data; + if (!s->started && state != PW_STREAM_STATE_CONNECTING) { + /* Output stream appears on server */ + s->started = true; + if (s->data->sinks_pending > 0) + --s->data->sinks_pending; + if (state < PW_STREAM_STATE_PAUSED) + s->data->start_error = true; + check_initialized(s->data); + } + if (state == PW_STREAM_STATE_UNCONNECTED) { s->cleanup = true; pw_loop_signal_event(s->data->module->impl->loop, s->data->cleanup); @@ -270,12 +315,13 @@ pw_properties_set(props, PW_KEY_NODE_DONT_RECONNECT, "true"); pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); pw_properties_set(props, PW_KEY_NODE_PASSIVE, "true"); + pw_properties_setf(props, "pulse.module.id", "%u", data->module->index); cstream->data = data; cstream->stream = pw_stream_new(data->core, NULL, props); if (cstream->stream == NULL) { pw_log_error("Could not create stream"); - return; + goto error; } pw_stream_add_listener(cstream->stream, @@ -295,8 +341,14 @@ PW_STREAM_FLAG_RT_PROCESS, params, n_params)) < 0) { pw_log_error("Could not connect to sink '%s'", sink_name); - return; + goto error; } + + return; + +error: + data->start_error = true; + check_initialized(data); } static const struct pw_manager_events manager_events = { @@ -325,6 +377,17 @@ } } +static void on_sinks_timeout(void *d, uint64_t count) +{ + struct module_combine_sink_data *data = d; + + if (data->load_emitted) + return; + + data->start_error = true; + check_initialized(data); +} + static int module_combine_sink_load(struct client *client, struct module *module) { struct module_combine_sink_data *data = module->user_data; @@ -354,6 +417,7 @@ pw_properties_setf(props, PW_KEY_NODE_GROUP, "combine_sink-%u", data->module->index); pw_properties_setf(props, PW_KEY_NODE_LINK_GROUP, "combine_sink-%u", data->module->index); pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); + pw_properties_setf(props, "pulse.module.id", "%u", module->index); if ((str = pw_properties_get(module->props, "sink_properties")) != NULL) module_args_add_props(props, str); @@ -379,7 +443,7 @@ return res; data->manager = pw_manager_new(data->core); - if (client->manager == NULL) + if (data->manager == NULL) return -errno; pw_manager_add_listener(data->manager, &data->manager_listener, @@ -387,7 +451,15 @@ data->cleanup = pw_loop_add_event(module->impl->loop, on_cleanup, data); - return 0; + data->sinks_timeout = pw_loop_add_timer(module->impl->loop, on_sinks_timeout, data); + if (data->sinks_timeout) { + struct timespec timeout = {0}, interval = {0}; + timeout.tv_sec = TIMEOUT_SINKS_MSEC / 1000; + timeout.tv_nsec = (TIMEOUT_SINKS_MSEC % 1000) * SPA_NSEC_PER_MSEC; + pw_loop_update_timer(module->impl->loop, data->sinks_timeout, &timeout, &interval, false); + } + + return data->load_emitted ? 0 : SPA_RESULT_RETURN_ASYNC(0); } static int module_combine_sink_unload(struct module *module) @@ -398,6 +470,9 @@ if (d->cleanup != NULL) pw_loop_destroy_source(module->impl->loop, d->cleanup); + if (d->sinks_timeout != NULL) + pw_loop_destroy_source(module->impl->loop, d->sinks_timeout); + /* Note that we explicitly disconnect the hooks to avoid having the * cleanup triggered again in those callbacks */ if (d->sink != NULL) { @@ -440,7 +515,8 @@ const char *str; char *sink_name = NULL, **sink_names = NULL; struct spa_audio_info_raw info = { 0 }; - int i, n, res; + int i, res; + int num_sinks = 0; PW_LOG_TOPIC_INIT(mod_topic); @@ -460,7 +536,7 @@ } if ((str = pw_properties_get(props, "slaves")) != NULL) { - sink_names = pw_split_strv(str, ",", MAX_SINKS, &n); + sink_names = pw_split_strv(str, ",", MAX_SINKS, &num_sinks); pw_properties_set(props, "slaves", NULL); } @@ -491,6 +567,7 @@ d->info = info; d->sink_name = sink_name; d->sink_names = sink_names; + d->sinks_pending = (sink_names == NULL) ? 0 : num_sinks; for (i = 0; i < MAX_SINKS; i++) { d->streams[i].stream = NULL; d->streams[i].cleanup = false;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
@@ -75,6 +75,8 @@ pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-sink-%u", module->index); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -215,6 +217,14 @@ if (pw_properties_get(capture_props, PW_KEY_DEVICE_CLASS) == NULL) pw_properties_set(capture_props, PW_KEY_DEVICE_CLASS, "filter"); + if ((str = pw_properties_get(capture_props, PW_KEY_NODE_DESCRIPTION)) == NULL) { + str = pw_properties_get(capture_props, PW_KEY_NODE_NAME); + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "%s Sink", str); + } else { + pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); + } + if ((str = pw_properties_get(props, "master")) != NULL || (str = pw_properties_get(props, "sink_master")) != NULL) { pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
@@ -75,6 +75,8 @@ pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "ladspa-source-%u", module->index); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{"); @@ -203,11 +205,11 @@ module_args_add_props(props, argument); if ((str = pw_properties_get(props, "source_name")) != NULL) { - pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); + pw_properties_set(playback_props, PW_KEY_NODE_NAME, str); pw_properties_set(props, "source_name", NULL); } if ((str = pw_properties_get(props, "source_properties")) != NULL) { - module_args_add_props(capture_props, str); + module_args_add_props(playback_props, str); pw_properties_set(props, "source_properties", NULL); } if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL) @@ -215,17 +217,25 @@ if (pw_properties_get(playback_props, PW_KEY_DEVICE_CLASS) == NULL) pw_properties_set(playback_props, PW_KEY_DEVICE_CLASS, "filter"); + if ((str = pw_properties_get(playback_props, PW_KEY_NODE_DESCRIPTION)) == NULL) { + str = pw_properties_get(playback_props, PW_KEY_NODE_NAME); + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "%s Source", str); + } else { + pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); + } + if ((str = pw_properties_get(props, "master")) != NULL || (str = pw_properties_get(props, "source_master")) != NULL) { - pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str); + pw_properties_set(capture_props, PW_KEY_NODE_TARGET, str); pw_properties_set(props, "master", NULL); } - if (module_args_to_audioinfo(impl, props, &capture_info) < 0) { + if (module_args_to_audioinfo(impl, props, &playback_info) < 0) { res = -EINVAL; goto out; } - playback_info = capture_info; + capture_info = playback_info; position_to_props(&capture_info, capture_props); position_to_props(&playback_info, playback_props);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
@@ -72,6 +72,8 @@ pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "loopback-%u", module->index); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{");
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
@@ -115,6 +115,8 @@ pw_core_add_listener(d->core, &d->core_listener, &core_events, module); + pw_properties_setf(module->props, "pulse.module.id", "%u", module->index); + d->proxy = pw_core_create_object(d->core, "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, module->props ? &module->props->dict : NULL, 0);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c
Changed
@@ -159,6 +159,8 @@ &data->core_listener, &core_events, data); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + data->capture = pw_stream_new(data->core, "pipesink capture", data->capture_props); data->capture_props = NULL;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c
Changed
@@ -180,6 +180,9 @@ &data->core_listener, &core_events, data); + pw_properties_setf(data->playback_props, "pulse.module.id", + "%u", module->index); + data->playback = pw_stream_new(data->core, "pipesource playback", data->playback_props); data->playback_props = NULL;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
@@ -69,6 +69,8 @@ pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-sink-%u", module->index); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{");
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
@@ -69,6 +69,8 @@ pw_properties_setf(data->capture_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index); pw_properties_setf(data->playback_props, PW_KEY_NODE_GROUP, "remap-source-%u", module->index); + pw_properties_setf(data->capture_props, "pulse.module.id", "%u", module->index); + pw_properties_setf(data->playback_props, "pulse.module.id", "%u", module->index); f = open_memstream(&args, &size); fprintf(f, "{");
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
@@ -67,22 +67,15 @@ { struct module_roc_sink_data *data = module->user_data; FILE *f; - const char *str; char *args; size_t size; + pw_properties_setf(data->sink_props, "pulse.module.id", + "%u", module->index); + f = open_memstream(&args, &size); fprintf(f, "{"); - /* Can't just serialise this dict because the "null" method gets - * interpreted as a JSON null */ - if ((str = pw_properties_get(data->roc_props, "local.ip"))) - fprintf(f, " local.ip = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "remote.ip"))) - fprintf(f, " remote.ip = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "remote.source.port"))) - fprintf(f, " remote.source.port = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "remote.repair.port"))) - fprintf(f, " remote.repair.port = \"%s\"", str); + pw_properties_serialize_dict(f, &data->roc_props->dict, 0); fprintf(f, " } sink.props = {"); pw_properties_serialize_dict(f, &data->sink_props->dict, 0); fprintf(f, " } }");
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
@@ -67,24 +67,15 @@ { struct module_roc_source_data *data = module->user_data; FILE *f; - const char *str; char *args; size_t size; + pw_properties_setf(data->source_props, "pulse.module.id", + "%u", module->index); + f = open_memstream(&args, &size); fprintf(f, "{"); - /* Can't just serialise this dict because the "null" method gets - * interpreted as a JSON null */ - if ((str = pw_properties_get(data->roc_props, "local.ip"))) - fprintf(f, " local.ip = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "local.source.port"))) - fprintf(f, " local.source.port = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "local.repair.port"))) - fprintf(f, " local.repair.port = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "sess.latency.msec"))) - fprintf(f, " sess.latency.msec = \"%s\"", str); - if ((str = pw_properties_get(data->roc_props, "resampler.profile"))) - fprintf(f, " resampler.profile = \"%s\"", str); + pw_properties_serialize_dict(f, &data->roc_props->dict, 0); fprintf(f, " } source.props = {"); pw_properties_serialize_dict(f, &data->source_props->dict, 0); fprintf(f, " } }");
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
@@ -73,6 +73,9 @@ server = pw_properties_get(module->props, "server"); + pw_properties_setf(data->stream_props, "pulse.module.id", + "%u", module->index); + f = open_memstream(&args, &size); fprintf(f, "{"); pw_properties_serialize_dict(f, &module->props->dict, 0);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
@@ -71,6 +71,9 @@ size_t size; const char *server; + pw_properties_setf(data->stream_props, "pulse.module.id", + "%u", module->index); + server = pw_properties_get(module->props, "server"); f = open_memstream(&args, &size);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c
Changed
@@ -591,7 +591,7 @@ } data->manager = pw_manager_new(data->core); - if (client->manager == NULL) { + if (data->manager == NULL) { pw_log_error("failed to create pipewire manager: %m"); return -errno; }
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/registry.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/modules/registry.h
Changed
@@ -28,6 +28,7 @@ struct impl; +struct module *create_module_always_sink(struct impl *impl, const char *argument); struct module *create_module_combine_sink(struct impl *impl, const char *argument); struct module *create_module_echo_cancel(struct impl *impl, const char *argument); struct module *create_module_ladspa_sink(struct impl *impl, const char *argument);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/operation.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.c
Changed
@@ -33,7 +33,9 @@ #include "operation.h" #include "reply.h" -int operation_new(struct client *client, uint32_t tag) +int operation_new_cb(struct client *client, uint32_t tag, + void (*callback)(void *data, struct client *client, uint32_t tag), + void *data) { struct operation *o; @@ -42,6 +44,8 @@ o->client = client; o->tag = tag; + o->callback = callback; + o->data = data; spa_list_append(&client->operations, &o->link); pw_manager_sync(client->manager); @@ -51,6 +55,11 @@ return 0; } +int operation_new(struct client *client, uint32_t tag) +{ + return operation_new_cb(client, tag, NULL, NULL); +} + void operation_free(struct operation *o) { spa_list_remove(&o->link); @@ -63,6 +72,9 @@ pw_log_info("[%s]: tag:%u complete", client->name, o->tag); - reply_simple_ack(client, o->tag); + if (o->callback) + o->callback(o->data, client, o->tag); + else + reply_simple_ack(client, o->tag); operation_free(o); }
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/operation.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/operation.h
Changed
@@ -35,9 +35,14 @@ struct spa_list link; struct client *client; uint32_t tag; + void (*callback) (void *data, struct client *client, uint32_t tag); + void *data; }; int operation_new(struct client *client, uint32_t tag); +int operation_new_cb(struct client *client, uint32_t tag, + void (*callback) (void *data, struct client *client, uint32_t tag), + void *data); void operation_free(struct operation *o); void operation_complete(struct operation *o);
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -209,14 +209,14 @@ } static int send_object_event(struct client *client, struct pw_manager_object *o, - uint32_t facility) + uint32_t type) { uint32_t event = 0, mask = 0, res_index = o->index; if (pw_manager_object_is_sink(o)) { client_queue_subscribe_event(client, SUBSCRIPTION_MASK_SINK, - SUBSCRIPTION_EVENT_SINK | facility, + SUBSCRIPTION_EVENT_SINK | type, res_index); } if (pw_manager_object_is_source_or_monitor(o)) { @@ -248,7 +248,7 @@ if (event != SPA_ID_INVALID) client_queue_subscribe_event(client, mask, - event | facility, + event | type, res_index); return 0; } @@ -374,15 +374,14 @@ if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH) attr->maxlength = MAXLENGTH; - attr->maxlength -= attr->maxlength % frame_size; - attr->maxlength = SPA_MAX(attr->maxlength, frame_size); + attr->maxlength = SPA_ROUND_UP(attr->maxlength, frame_size); + + minreq = SPA_MIN(minreq, attr->maxlength); if (attr->tlength == (uint32_t) -1) attr->tlength = frac_to_bytes_round_up(s->default_tlength, &s->ss); - if (attr->tlength > attr->maxlength) - attr->tlength = attr->maxlength; - attr->tlength -= attr->tlength % frame_size; - attr->tlength = SPA_MAX(attr->tlength, frame_size); + attr->tlength = SPA_MIN(attr->tlength, attr->maxlength); + attr->tlength = SPA_ROUND_UP(attr->tlength, frame_size); attr->tlength = SPA_MAX(attr->tlength, minreq); if (attr->minreq == (uint32_t) -1) { @@ -390,13 +389,13 @@ /* With low-latency, tlength/4 gives a decent default in all of traditional, * adjust latency and early request modes. */ uint32_t m = attr->tlength / 4; - m -= m % frame_size; + m = SPA_ROUND_DOWN(m, frame_size); attr->minreq = SPA_MIN(process, m); } attr->minreq = SPA_MAX(attr->minreq, minreq); if (attr->tlength < attr->minreq+frame_size) - attr->tlength = attr->minreq + frame_size; + attr->tlength = SPA_MIN(attr->minreq + frame_size, attr->maxlength); if (s->early_requests) { latency = attr->minreq; @@ -406,7 +405,7 @@ else latency = attr->minreq; - latency -= latency % frame_size; + latency = SPA_ROUND_DOWN(latency, frame_size); if (attr->tlength >= latency) attr->tlength -= latency; @@ -418,20 +417,20 @@ } if (attr->tlength < latency + 2 * attr->minreq) - attr->tlength = latency + 2 * attr->minreq; + attr->tlength = SPA_MIN(latency + 2 * attr->minreq, attr->maxlength); - attr->minreq -= attr->minreq % frame_size; + attr->minreq = SPA_ROUND_DOWN(attr->minreq, frame_size); if (attr->minreq <= 0) { attr->minreq = frame_size; attr->tlength += frame_size*2; } if (attr->tlength <= attr->minreq) - attr->tlength = attr->minreq*2 + frame_size; + attr->tlength = SPA_MIN(attr->minreq*2 + frame_size, attr->maxlength); max_prebuf = attr->tlength + frame_size - attr->minreq; if (attr->prebuf == (uint32_t) -1 || attr->prebuf > max_prebuf) attr->prebuf = max_prebuf; - attr->prebuf -= attr->prebuf % frame_size; + attr->prebuf = SPA_ROUND_DOWN(attr->prebuf, frame_size); attr->fragsize = 0; @@ -947,6 +946,9 @@ pw_log_info("[%s] SUBSCRIBE tag:%u mask:%08x", client->name, tag, mask); + if (mask & ~SUBSCRIPTION_MASK_ALL) + return -EINVAL; + client->subscribed = mask; return reply_simple_ack(client, tag); @@ -2322,11 +2324,11 @@ return o; } -static void sample_play_ready(void *data, uint32_t index) +static void sample_play_ready_reply(void *data, struct client *client, uint32_t tag) { struct pending_sample *ps = data; - struct client *client = ps->client; struct message *reply; + uint32_t index = id_to_index(client->manager, ps->play->id); pw_log_info("[%s] PLAY_SAMPLE tag:%u index:%u", client->name, ps->tag, index); @@ -2340,6 +2342,13 @@ client_queue_message(client, reply); } +static void sample_play_ready(void *data, uint32_t id) +{ + struct pending_sample *ps = data; + struct client *client = ps->client; + operation_new_cb(client, ps->tag, sample_play_ready_reply, ps); +} + static void on_sample_done(void *obj, void *data, int res, uint32_t id) { struct pending_sample *ps = obj; @@ -3556,6 +3565,9 @@ snprintf(monitor_name, size, "%s.monitor", name); if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL) + module_id = id_to_index(manager, (uint32_t)atoi(str)); + if (module_id == SPA_ID_INVALID && + (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL) module_id = (uint32_t)atoi(str); if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL) card_id = (uint32_t)atoi(str); @@ -3601,7 +3613,7 @@ TAG_STRING, desc, TAG_SAMPLE_SPEC, &dev_info.ss, TAG_CHANNEL_MAP, &dev_info.map, - TAG_U32, id_to_index(manager, module_id), /* module index */ + TAG_U32, module_id, /* module index */ TAG_CVOLUME, &dev_info.volume_info.volume, TAG_BOOLEAN, dev_info.volume_info.mute, TAG_U32, o->index, /* monitor source index */ @@ -3760,6 +3772,9 @@ snprintf(monitor_desc, size, "Monitor of %s", desc); if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL) + module_id = id_to_index(manager, (uint32_t)atoi(str)); + if (module_id == SPA_ID_INVALID && + (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL) module_id = (uint32_t)atoi(str); if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_ID)) != NULL) card_id = (uint32_t)atoi(str); @@ -3804,7 +3819,7 @@ TAG_STRING, is_monitor ? monitor_desc : desc, TAG_SAMPLE_SPEC, &dev_info.ss, TAG_CHANNEL_MAP, &dev_info.map, - TAG_U32, id_to_index(manager, module_id), /* module index */ + TAG_U32, module_id, /* module index */ TAG_CVOLUME, &dev_info.volume_info.volume, TAG_BOOLEAN, dev_info.volume_info.mute, TAG_U32, is_monitor ? o->index : SPA_ID_INVALID,/* monitor of sink */ @@ -3908,7 +3923,11 @@ return -ENOENT; if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL) + module_id = id_to_index(manager, (uint32_t)atoi(str)); + if (module_id == SPA_ID_INVALID && + (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL) module_id = (uint32_t)atoi(str); + if (!pw_manager_object_is_virtual(o) && (str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL) client_id = (uint32_t)atoi(str); @@ -3929,7 +3948,7 @@ message_put(m, TAG_U32, o->index, /* sink_input index */ TAG_STRING, get_media_name(info), - TAG_U32, id_to_index(manager, module_id), /* module index */ + TAG_U32, module_id, /* module index */ TAG_U32, id_to_index(manager, client_id), /* client index */ TAG_U32, peer_index, /* sink index */ TAG_SAMPLE_SPEC, &dev_info.ss, @@ -3984,7 +4003,11 @@ return -ENOENT; if ((str = spa_dict_lookup(info->props, PW_KEY_MODULE_ID)) != NULL) + module_id = id_to_index(manager, (uint32_t)atoi(str)); + if (module_id == SPA_ID_INVALID && + (str = spa_dict_lookup(info->props, "pulse.module.id")) != NULL) module_id = (uint32_t)atoi(str); + if (!pw_manager_object_is_virtual(o) && (str = spa_dict_lookup(info->props, PW_KEY_CLIENT_ID)) != NULL) client_id = (uint32_t)atoi(str); @@ -4005,7 +4028,7 @@ message_put(m, TAG_U32, o->index, /* source_output index */ TAG_STRING, get_media_name(info), - TAG_U32, id_to_index(manager, module_id), /* module index */ + TAG_U32, module_id, /* module index */ TAG_U32, id_to_index(manager, client_id), /* client index */ TAG_U32, peer_index, /* source index */ TAG_SAMPLE_SPEC, &dev_info.ss, @@ -4684,8 +4707,8 @@ spa_assert(!SPA_RESULT_IS_ASYNC(result)); if (SPA_RESULT_IS_OK(result)) { - pw_log_info("[%s] loaded module index:%u name:%s", - client_name, module->index, module->name); + pw_log_info("[%s] loaded module index:%u name:%s tag:%d", + client_name, module->index, module->name, tag); module->loaded = true; @@ -4704,9 +4727,9 @@ } } else { - pw_log_warn("%p: [%s] failed to load module index:%u name:%s result:%d (%s)", + pw_log_warn("%p: [%s] failed to load module index:%u name:%s tag:%d result:%d (%s)", impl, client_name, - module->index, module->name, + module->index, module->name, tag, result, spa_strerror(result)); module_schedule_unload(module); @@ -4723,34 +4746,92 @@ struct module *module; struct spa_hook module_listener; + struct spa_hook manager_listener; + uint32_t tag; + + int result; + bool wait_sync; }; +static void finish_pending_module(struct pending_module *pm) +{ + spa_hook_remove(&pm->module_listener); + + if (pm->client != NULL) { + spa_hook_remove(&pm->client_listener); + spa_hook_remove(&pm->manager_listener); + } + + handle_module_loaded(pm->module, pm->client, pm->tag, pm->result); + free(pm); +} + +static void on_load_module_manager_sync(void *data) +{ + struct pending_module *pm = data; + + pw_log_debug("pending module %p: manager sync wait_sync:%d tag:%d", + pm, pm->wait_sync, pm->tag); + + if (!pm->wait_sync) + return; + + finish_pending_module(pm); +} + static void on_module_loaded(void *data, int result) { struct pending_module *pm = data; - if (pm->client != NULL) - spa_hook_remove(&pm->client_listener); + pw_log_debug("pending module %p: loaded, result:%d tag:%d", + pm, result, pm->tag); - spa_hook_remove(&pm->module_listener); + pm->result = result; - handle_module_loaded(pm->module, pm->client, pm->tag, result); + /* + * Do manager sync first: the module may have its own core, so + * although things are completed on the server, our client + * might not yet see them. + */ - free(pm); + if (pm->client == NULL) { + finish_pending_module(pm); + } else { + pw_log_debug("pending module %p: wait manager sync tag:%d", pm, pm->tag); + pm->wait_sync = true; + pw_manager_sync(pm->client->manager); + } } static void on_module_destroy(void *data) { - on_module_loaded(data, -ECANCELED); + struct pending_module *pm = data; + + pw_log_debug("pending module %p: destroyed, tag:%d", + pm, pm->tag); + + pm->result = -ECANCELED; + finish_pending_module(pm); } static void on_client_disconnect(void *data) { struct pending_module *pm = data; + pw_log_debug("pending module %p: client disconnect tag:%d", pm, pm->tag); + spa_hook_remove(&pm->client_listener); + spa_hook_remove(&pm->manager_listener); pm->client = NULL; + + if (pm->wait_sync) + finish_pending_module(pm); +} + +static void on_load_module_manager_disconnect(void *data) +{ + on_client_disconnect(data); } static int do_load_module(struct client *client, uint32_t command, uint32_t tag, struct message *m) @@ -4764,9 +4845,15 @@ VERSION_CLIENT_EVENTS, .disconnect = on_client_disconnect, }; + static const struct pw_manager_events manager_events = { + PW_VERSION_MANAGER_EVENTS, + .disconnect = on_load_module_manager_disconnect, + .sync = on_load_module_manager_sync, + }; const char *name, *argument; struct module *module; + struct pending_module *pm; int r; if (message_get(m, @@ -4782,21 +4869,24 @@ if (module == NULL) return -errno; + pm = calloc(1, sizeof(*pm)); + if (pm == NULL) + return -errno; + + pm->tag = tag; + pm->client = client; + pm->module = module; + + pw_log_debug("pending module %p: start tag:%d", pm, tag); + r = module_load(client, module); - if (SPA_RESULT_IS_ASYNC(r)) { - struct pending_module *pm = calloc(1, sizeof(*pm)); - if (pm == NULL) - return -errno; - - pm->tag = tag; - pm->client = client; - pm->module = module; - module_add_listener(module, &pm->module_listener, &module_events, pm); - client_add_listener(client, &pm->client_listener, &client_events, pm); - } else { - handle_module_loaded(module, client, tag, r); - } + module_add_listener(module, &pm->module_listener, &module_events, pm); + client_add_listener(client, &pm->client_listener, &client_events, pm); + pw_manager_add_listener(client->manager, &pm->manager_listener, &manager_events, pm); + + if (!SPA_RESULT_IS_ASYNC(r)) + on_module_loaded(pm, r); /* * return 0 to prevent `handle_packet()` from sending a reply @@ -4830,7 +4920,7 @@ module_unload(module); - return reply_simple_ack(client, tag); + return operation_new(client, tag); } static int do_send_object_message(struct client *client, uint32_t command, uint32_t tag, struct message *m) @@ -5105,7 +5195,7 @@ pw_map_for_each(&impl->modules, impl_unload_module, impl); pw_map_clear(&impl->modules); -#if HAVE_DBUS +#ifdef HAVE_DBUS if (impl->dbus_name) { dbus_release_name(impl->dbus_name); impl->dbus_name = NULL; @@ -5276,7 +5366,7 @@ pw_context_add_listener(context, &impl->context_listener, &context_events, impl); -#if HAVE_DBUS +#ifdef HAVE_DBUS impl->dbus_name = dbus_request_name(context, "org.pulseaudio.Server"); #endif
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/quirks.c
Changed
@@ -46,111 +46,8 @@ return 0; } -static bool find_match(struct spa_json *arr, const struct spa_dict *props) -{ - struct spa_json it[1]; - - while (spa_json_enter_object(arr, &it[0]) > 0) { - char key[256], val[1024]; - const char *str, *value; - int match = 0, fail = 0; - int len; - - while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { - bool success = false; - - if ((len = spa_json_next(&it[0], &value)) <= 0) - break; - - str = spa_dict_lookup(props, key); - - if (spa_json_is_null(value, len)) { - success = str == NULL; - } else { - if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) - continue; - value = val; - len = strlen(val); - } - if (str != NULL) { - if (value[0] == '~') { - regex_t preg; - if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { - if (regexec(&preg, str, 0, NULL, 0) == 0) - success = true; - regfree(&preg); - } - } else if (strncmp(str, value, len) == 0 && - strlen(str) == (size_t)len) { - success = true; - } - } - if (success) { - match++; - pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value); - } - else - fail++; - } - if (match > 0 && fail == 0) - return true; - } - return false; -} - -static int pw_conf_match_rules(const char *rules, size_t size, const struct spa_dict *props, - int (*matched) (void *data, const char *action, const char *val, int len), - void *data) -{ - const char *val; - struct spa_json it[4], actions; - int count = 0; - - spa_json_init(&it[0], rules, size); - if (spa_json_enter_array(&it[0], &it[1]) < 0) - return 0; - - while (spa_json_enter_object(&it[1], &it[2]) > 0) { - char key[64]; - bool have_match = false, have_actions = false; - - while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) { - if (spa_streq(key, "matches")) { - if (spa_json_enter_array(&it[2], &it[3]) < 0) - break; - - have_match = find_match(&it[3], props); - } - else if (spa_streq(key, "actions")) { - if (spa_json_enter_object(&it[2], &actions) > 0) - have_actions = true; - } - else if (spa_json_next(&it[2], &val) <= 0) - break; - } - if (!have_match || !have_actions) - continue; - - while (spa_json_get_string(&actions, key, sizeof(key)) > 0) { - int res, len; - pw_log_debug("action %s", key); - - if ((len = spa_json_next(&actions, &val)) <= 0) - break; - - if (spa_json_is_container(val, len)) - len = spa_json_container_len(&actions, val, len); - - if ((res = matched(data, key, val, len)) < 0) - return res; - - count += res; - } - } - return count; -} - -static int client_rule_matched(void *data, const char *action, const char *val, int len) +static int apply_match(void *data, const char *location, const char *action, + const char *val, size_t len) { struct client *client = data; @@ -170,19 +67,10 @@ return 0; } -static int apply_pulse_rules(void *data, const char *location, const char *section, - const char *str, size_t len) -{ - struct client *client = data; - pw_conf_match_rules(str, len, &client->props->dict, - client_rule_matched, client); - return 0; -} - int client_update_quirks(struct client *client) { struct impl *impl = client->impl; struct pw_context *context = impl->context; - return pw_context_conf_section_for_each(context, "pulse.rules", - apply_pulse_rules, client); + return pw_context_conf_section_match_rules(context, "pulse.rules", + &client->props->dict, apply_match, client); }
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/remap.c
Added
@@ -0,0 +1,56 @@ +/* PipeWire + * + * Copyright © 2020 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stddef.h> + +#include <pipewire/keys.h> + +#include "remap.h" + +const struct str_map media_role_map[] = { + { "Movie", "video", }, + { "Music", "music", }, + { "Game", "game", }, + { "Notification", "event", }, + { "Communication", "phone", }, + { "Movie", "animation", }, + { "Production", "production", }, + { "Accessibility", "a11y", }, + { "Test", "test", }, + { NULL, NULL }, +}; + +const struct str_map props_key_map[] = { + { PW_KEY_DEVICE_BUS_PATH, "device.bus_path" }, + { PW_KEY_DEVICE_FORM_FACTOR, "device.form_factor" }, + { PW_KEY_DEVICE_ICON_NAME, "device.icon_name" }, + { PW_KEY_DEVICE_INTENDED_ROLES, "device.intended_roles" }, + { PW_KEY_NODE_DESCRIPTION, "device.description" }, + { PW_KEY_MEDIA_ICON_NAME, "media.icon_name" }, + { PW_KEY_APP_ICON_NAME, "application.icon_name" }, + { PW_KEY_APP_PROCESS_MACHINE_ID, "application.process.machine_id" }, + { PW_KEY_APP_PROCESS_SESSION_ID, "application.process.session_id" }, + { PW_KEY_MEDIA_ROLE, "media.role", media_role_map }, + { NULL, NULL }, +};
View file
pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/remap.h
Added
@@ -0,0 +1,52 @@ +/* PipeWire + * + * Copyright © 2020 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#ifndef PULSE_SERVER_REMAP_H +#define PULSE_SERVER_REMAP_H + +#include <stddef.h> + +#include <spa/utils/string.h> + +struct str_map { + const char *pw_str; + const char *pa_str; + const struct str_map *child; +}; + +extern const struct str_map media_role_map[]; + +extern const struct str_map props_key_map[]; + +static inline const struct str_map *str_map_find(const struct str_map *map, const char *pw, const char *pa) +{ + size_t i; + for (i = 0; map[i].pw_str; i++) + if ((pw && spa_streq(map[i].pw_str, pw)) || + (pa && spa_streq(map[i].pa_str, pa))) + return &map[i]; + return NULL; +} + +#endif /* PULSE_SERVER_REMAP_H */
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/sample-play.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/sample-play.c
Changed
@@ -53,8 +53,8 @@ sample_play_emit_done(p, -EIO); break; case PW_STREAM_STATE_PAUSED: - p->index = pw_stream_get_node_id(p->stream); - sample_play_emit_ready(p, p->index); + p->id = pw_stream_get_node_id(p->stream); + sample_play_emit_ready(p, p->id); break; default: break;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/sample-play.h -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/sample-play.h
Changed
@@ -56,7 +56,7 @@ struct sample *sample; struct pw_stream *stream; struct spa_io_rate_match *rate_match; - uint32_t index; + uint32_t id; struct spa_hook listener; struct pw_context *context; struct pw_loop *main_loop;
View file
pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.47.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -226,7 +226,8 @@ if (errno == EINTR) continue; res = -errno; - if (res != -EAGAIN && res != -EWOULDBLOCK) + if (res != -EAGAIN && res != -EWOULDBLOCK && + res != -EPIPE && res != -ECONNRESET) pw_log_warn("recv client:%p res %zd: %m", client, r); goto exit; } @@ -327,6 +328,7 @@ error: switch (res) { case -EPIPE: + case -ECONNRESET: pw_log_info("server %p: client %p [%s] disconnected", client->server, client, client->name); SPA_FALLTHROUGH;
View file
pipewire-0.3.45.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.47.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -93,6 +93,8 @@ #define DEFAULT_CHANNELS "2" #define DEFAULT_POSITION "[ FL FR ]" +#define DEFAULT_LATENCY (DEFAULT_RATE*2) + #define MODULE_USAGE "[ node.latency=<latency as fraction> ] " \ "[ node.name=<name of the nodes> ] " \ "[ node.description=<description of the nodes> ] " \ @@ -687,7 +689,9 @@ if ((str = spa_dict_lookup(headers, "Audio-Latency")) != NULL) { if (!spa_atou32(str, &impl->latency, 0)) - impl->latency = 0; + impl->latency = DEFAULT_LATENCY; + } else { + impl->latency = DEFAULT_LATENCY; } spa_zero(latency);
View file
pipewire-0.3.45.tar.gz/src/pipewire/conf.c -> pipewire-0.3.47.tar.gz/src/pipewire/conf.c
Changed
@@ -34,7 +34,8 @@ #include <unistd.h> #include <sys/wait.h> #include <dirent.h> -#if HAVE_PWD_H +#include <regex.h> +#ifdef HAVE_PWD_H #include <pwd.h> #endif #ifdef __FreeBSD__ @@ -733,6 +734,16 @@ if (pid == 0) { char *cmd, **argv; + /* Double fork to avoid zombies; we don't want to set SIGCHLD handler */ + pid = fork(); + + if (pid < 0) { + pw_log_error("fork error: %m"); + exit(1); + } else if (pid != 0) { + exit(0); + } + cmd = spa_aprintf("%s %s", key, args ? args : ""); argv = pw_split_strv(cmd, " \t", INT_MAX, &n_args); free(cmd); @@ -744,13 +755,18 @@ if (res == -1) { res = -errno; pw_log_error("execvp error '%s': %m", key); - return res; } - } - else { + + exit(1); + } else if (pid < 0) { + pw_log_error("fork error: %m"); + } else { int status = 0; - res = waitpid(pid, &status, WNOHANG); - pw_log_info("exec got pid %d res:%d status:%d", pid, res, status); + do { + errno = 0; + res = waitpid(pid, &status, 0); + } while (res < 0 && errno == EINTR); + pw_log_debug("exec got pid %d res:%d status:%d", (int)pid, res, status); } return 0; } @@ -810,6 +826,7 @@ return res; } + SPA_EXPORT int pw_context_conf_section_for_each(struct pw_context *context, const char *section, int (*callback) (void *data, const char *location, const char *section, @@ -819,7 +836,7 @@ struct pw_properties *conf = context->conf; const char *path = NULL; const struct spa_dict_item *it; - int res; + int res = 0; spa_dict_for_each(it, &conf->dict) { if (spa_strendswith(it->key, "config.path")) { @@ -882,3 +899,153 @@ update_props, &data); return data.count; } + +struct match { + const struct spa_dict *props; + int (*matched) (void *data, const char *location, const char *action, + const char *val, size_t len); + void *data; +}; + +/* + * { + * # all keys must match the value. ~ in value starts regex. + * <key> = <value> + * ... + * } + */ +static bool find_match(struct spa_json *arr, const struct spa_dict *props) +{ + struct spa_json it[1]; + + while (spa_json_enter_object(arr, &it[0]) > 0) { + char key[256], val[1024]; + const char *str, *value; + int match = 0, fail = 0; + int len; + + while (spa_json_get_string(&it[0], key, sizeof(key)) > 0) { + bool success = false; + + if ((len = spa_json_next(&it[0], &value)) <= 0) + break; + + str = spa_dict_lookup(props, key); + + if (spa_json_is_null(value, len)) { + success = str == NULL; + } else { + if (spa_json_parse_stringn(value, len, val, sizeof(val)) < 0) + continue; + value = val; + len = strlen(val); + } + if (str != NULL) { + if (value[0] == '~') { + regex_t preg; + if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { + if (regexec(&preg, str, 0, NULL, 0) == 0) + success = true; + regfree(&preg); + } + } else if (strncmp(str, value, len) == 0 && + strlen(str) == (size_t)len) { + success = true; + } + } + if (success) { + match++; + pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value); + } + else + fail++; + } + if (match > 0 && fail == 0) + return true; + } + return false; +} + +/** + * rules = [ + * { + * matches = [ + * # any of the items in matches needs to match, it one does, + * # actions are emited. + * { + * # all keys must match the value. ~ in value starts regex. + * <key> = <value> + * ... + * } + * ... + * ] + * actions = { + * <action> = <value> + * ... + * } + * } + * ] + */ +static int match_rules(void *data, const char *location, const char *section, + const char *str, size_t len) +{ + struct match *match = data; + const struct spa_dict *props = match->props; + const char *val; + struct spa_json it[4], actions; + + spa_json_init(&it[0], str, len); + if (spa_json_enter_array(&it[0], &it[1]) < 0) + return 0; + + while (spa_json_enter_object(&it[1], &it[2]) > 0) { + char key[64]; + bool have_match = false, have_actions = false; + + while (spa_json_get_string(&it[2], key, sizeof(key)) > 0) { + if (spa_streq(key, "matches")) { + if (spa_json_enter_array(&it[2], &it[3]) < 0) + break; + + have_match = find_match(&it[3], props); + } + else if (spa_streq(key, "actions")) { + if (spa_json_enter_object(&it[2], &actions) > 0) + have_actions = true; + } + else if (spa_json_next(&it[2], &val) <= 0) + break; + } + if (!have_match || !have_actions) + continue; + + while (spa_json_get_string(&actions, key, sizeof(key)) > 0) { + int res, len; + pw_log_debug("action %s", key); + + if ((len = spa_json_next(&actions, &val)) <= 0) + break; + + if (spa_json_is_container(val, len)) + len = spa_json_container_len(&actions, val, len); + + if ((res = match->matched(match->data, location, key, val, len)) < 0) + return res; + } + } + return 0; +} + +SPA_EXPORT +int pw_context_conf_section_match_rules(struct pw_context *context, const char *section, + struct spa_dict *props, + int (*callback) (void *data, const char *location, const char *action, + const char *str, size_t len), + void *data) +{ + struct match match = { + .props = props, + .matched = callback, + .data = data }; + return pw_context_conf_section_for_each(context, section, match_rules, &match); +}
View file
pipewire-0.3.45.tar.gz/src/pipewire/context.c -> pipewire-0.3.47.tar.gz/src/pipewire/context.c
Changed
@@ -1068,7 +1068,7 @@ struct pw_impl_node *n, *s, *target, *fallback; uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum; uint32_t *rates, n_rates, def_rate; - bool freewheel = false, global_force_rate, force_rate, global_force_quantum; + bool freewheel = false, global_force_rate, force_rate, force_quantum, global_force_quantum; pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason); @@ -1083,7 +1083,7 @@ get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum); rates = get_rates(context, &def_rate, &n_rates, &global_force_rate); - global_force_quantum = rate_quantum == 0; + force_quantum = global_force_quantum = rate_quantum == 0; force_rate = global_force_rate; /* start from all drivers and group all nodes that are linked @@ -1183,6 +1183,7 @@ def_quantum = min_quantum = max_quantum = s->force_quantum; rate_quantum = 0; quantum_stamp = s->stamp; + force_quantum = true; } if (!global_force_rate && s->force_rate > 0 && s->stamp > rate_stamp) { @@ -1213,6 +1214,8 @@ running = !n->passive; } + if (force_quantum) + lock_quantum = false; if (force_rate) lock_rate = false;
View file
pipewire-0.3.45.tar.gz/src/pipewire/context.h -> pipewire-0.3.47.tar.gz/src/pipewire/context.h
Changed
@@ -123,6 +123,12 @@ int (*callback) (void *data, const char *location, const char *section, const char *str, size_t len), void *data); +/** emit callback for all matched properties. Since 0.3.46 */ +int pw_context_conf_section_match_rules(struct pw_context *context, const char *section, + struct spa_dict *props, + int (*callback) (void *data, const char *location, const char *action, + const char *str, size_t len), + void *data); /** Get the context support objects */ const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support);
View file
pipewire-0.3.45.tar.gz/src/pipewire/filter.c -> pipewire-0.3.47.tar.gz/src/pipewire/filter.c
Changed
@@ -50,7 +50,6 @@ #define MAX_BUFFERS 64 #define MASK_BUFFERS (MAX_BUFFERS-1) -#define MAX_PORTS 1024 static bool mlock_warned = false; @@ -142,7 +141,7 @@ } rt; struct spa_list port_list; - struct port *ports[2][MAX_PORTS]; + struct pw_map ports[2]; uint32_t change_mask_all; struct spa_node_info info; @@ -306,27 +305,17 @@ enum spa_direction direction, uint32_t user_data_size) { struct port *p; - int i; - - for (i = 0; i < MAX_PORTS; i++) { - if ((filter->ports[direction][i]) == NULL) - break; - } - if (i == MAX_PORTS) - return NULL; p = calloc(1, sizeof(struct port) + user_data_size); p->filter = filter; p->direction = direction; - p->id = i; p->latency[SPA_DIRECTION_INPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT); p->latency[SPA_DIRECTION_OUTPUT] = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT); spa_list_init(&p->param_list); spa_ringbuffer_init(&p->dequeued.ring); spa_ringbuffer_init(&p->queued.ring); - - filter->ports[direction][i] = p; + p->id = pw_map_insert_new(&filter->ports[direction], p); spa_list_append(&filter->port_list, &p->link); return p; @@ -334,10 +323,9 @@ static inline struct port *get_port(struct filter *filter, enum spa_direction direction, uint32_t port_id) { - if ((direction != SPA_DIRECTION_INPUT && direction != SPA_DIRECTION_OUTPUT) || - port_id >= MAX_PORTS) + if ((direction != SPA_DIRECTION_INPUT && direction != SPA_DIRECTION_OUTPUT)) return NULL; - return filter->ports[direction][port_id]; + return pw_map_lookup(&filter->ports[direction], port_id); } static inline int push_queue(struct port *port, struct queue *queue, struct buffer *buffer) @@ -1241,6 +1229,8 @@ spa_list_init(&impl->param_list); spa_list_init(&impl->port_list); + pw_map_init(&impl->ports[SPA_DIRECTION_INPUT], 32, 32); + pw_map_init(&impl->ports[SPA_DIRECTION_OUTPUT], 32, 32); spa_hook_list_init(&this->listener_list); spa_list_init(&this->controls); @@ -1377,6 +1367,9 @@ spa_hook_list_clean(&impl->hooks); spa_hook_list_clean(&filter->listener_list); + pw_map_clear(&impl->ports[SPA_DIRECTION_INPUT]); + pw_map_clear(&impl->ports[SPA_DIRECTION_OUTPUT]); + free(filter->name); if (impl->data.context) @@ -1496,8 +1489,8 @@ SPA_NODE_CHANGE_MASK_PARAMS; impl->info = SPA_NODE_INFO_INIT(); - impl->info.max_input_ports = MAX_PORTS; - impl->info.max_output_ports = MAX_PORTS; + impl->info.max_input_ports = UINT32_MAX; + impl->info.max_output_ports = UINT32_MAX; impl->info.flags = impl->process_rt ? SPA_NODE_FLAG_RT : 0; impl->info.props = &filter->properties->dict; impl->params[IDX_Props] = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); @@ -1722,7 +1715,7 @@ spa_node_emit_port_info(&impl->hooks, port->direction, port->id, NULL); spa_list_remove(&port->link); - impl->ports[port->direction][port->id] = NULL; + pw_map_remove(&impl->ports[port->direction], port->id); clear_buffers(port); clear_params(impl, port, SPA_ID_INVALID);
View file
pipewire-0.3.45.tar.gz/src/pipewire/map.h -> pipewire-0.3.47.tar.gz/src/pipewire/map.h
Changed
@@ -115,7 +115,7 @@ */ static inline void pw_map_init(struct pw_map *map, size_t size, size_t extend) { - pw_array_init(&map->items, extend); + pw_array_init(&map->items, extend * sizeof(union pw_map_item)); pw_array_ensure_size(&map->items, size * sizeof(union pw_map_item)); map->free_list = SPA_ID_INVALID; }
View file
pipewire-0.3.45.tar.gz/src/pipewire/proxy.c -> pipewire-0.3.47.tar.gz/src/pipewire/proxy.c
Changed
@@ -256,9 +256,6 @@ pw_proxy_emit_destroy(proxy); } - spa_hook_list_clean(&proxy->listener_list); - spa_hook_list_clean(&proxy->object_listener_list); - pw_proxy_unref(proxy); } @@ -298,6 +295,22 @@ pw_log_debug("%p: free %u", proxy, proxy->id); /** client must explicitly destroy all proxies */ assert(proxy->destroyed); + +#if DEBUG_LISTENERS + { + struct spa_hook *h; + spa_list_for_each(h, &proxy->object_listener_list.list, link) { + pw_log_warn("%p: proxy %u: leaked object listener %p", + proxy, proxy->id, h); + break; + } + spa_list_for_each(h, &proxy->listener_list.list, link) { + pw_log_warn("%p: proxy %u: leaked listener %p", + proxy, proxy->id, h); + break; + } + } +#endif free(proxy); }
View file
pipewire-0.3.45.tar.gz/src/pipewire/stream.c -> pipewire-0.3.47.tar.gz/src/pipewire/stream.c
Changed
@@ -48,7 +48,6 @@ #define MAX_BUFFERS 64 #define MASK_BUFFERS (MAX_BUFFERS-1) -#define MAX_PORTS 1 static bool mlock_warned = false;
View file
pipewire-0.3.45.tar.gz/src/pipewire/utils.c -> pipewire-0.3.47.tar.gz/src/pipewire/utils.c
Changed
@@ -27,7 +27,7 @@ #include <fcntl.h> #include <unistd.h> #include <errno.h> -#if HAVE_SYS_RANDOM_H +#ifdef HAVE_SYS_RANDOM_H #include <sys/random.h> #endif #include <string.h>
View file
pipewire-0.3.45.tar.gz/src/tools/meson.build -> pipewire-0.3.47.tar.gz/src/tools/meson.build
Changed
@@ -34,7 +34,7 @@ endif build_pw_cat = false -if not get_option('pw-cat').disabled() and sndfile_dep.found() +if get_option('pw-cat').allowed() and sndfile_dep.found() build_pw_cat = true pwcat_sources = [
View file
pipewire-0.3.45.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.47.tar.gz/src/tools/pw-cat.c
Changed
@@ -648,7 +648,7 @@ struct data *data = userdata; if (data->verbose) - fprintf(stdout, "remote %"PRIu32" is named \"%s\"\n", + printf("remote %"PRIu32" is named \"%s\"\n", info->id, info->name); } @@ -808,7 +808,7 @@ id, type, name, media_class, desc ? : "", prio); spa_dict_for_each(item, props) { - fprintf(stdout, "\t\t%s = \"%s\"\n", item->key, item->value); + printf("\t\t%s = \"%s\"\n", item->key, item->value); } } @@ -1533,7 +1533,7 @@ return EXIT_SUCCESS; case OPT_VERSION: - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", prog, @@ -1930,14 +1930,21 @@ } error_connect_fail: - if (data.stream) + if (data.stream) { + spa_hook_remove(&data.stream_listener); pw_stream_destroy(data.stream); + } error_no_stream: - if (data.metadata) + if (data.metadata) { + spa_hook_remove(&data.metadata_listener); pw_proxy_destroy((struct pw_proxy*)data.metadata); - if (data.registry) + } + if (data.registry) { + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + } error_no_registry: + spa_hook_remove(&data.core_listener); pw_core_disconnect(data.core); error_ctx_connect_failed: pw_context_destroy(data.context);
View file
pipewire-0.3.45.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.47.tar.gz/src/tools/pw-cli.c
Changed
@@ -40,7 +40,7 @@ #define FNM_EXTMATCH 0 #endif -#define spa_debug(...) fprintf(stdout,__VA_ARGS__);fputc('\n', stdout) +#define spa_debug(fmt,...) printf(fmt, ## __VA_ARGS__) #include <spa/utils/result.h> #include <spa/utils/string.h> @@ -157,15 +157,15 @@ const struct spa_dict_item *item; if (header) - fprintf(stdout, "%c\tproperties:\n", mark); + printf("%c\tproperties:\n", mark); if (props == NULL || props->n_items == 0) { if (header) - fprintf(stdout, "\t\tnone\n"); + printf("\t\tnone\n"); return; } spa_dict_for_each(item, props) { - fprintf(stdout, "%c\t\t%s = \"%s\"\n", mark, item->key, item->value); + printf("%c\t\t%s = \"%s\"\n", mark, item->key, item->value); } } @@ -174,16 +174,16 @@ uint32_t i; if (header) - fprintf(stdout, "%c\tparams: (%u)\n", mark, n_params); + printf("%c\tparams: (%u)\n", mark, n_params); if (params == NULL || n_params == 0) { if (header) - fprintf(stdout, "\t\tnone\n"); + printf("\t\tnone\n"); return; } for (i = 0; i < n_params; i++) { const struct spa_type_info *type_info = spa_type_param; - fprintf(stdout, "%c\t %d (%s) %c%c\n", + printf("%c\t %d (%s) %c%c\n", params[i].user > 0 ? mark : ' ', params[i].id, spa_debug_type_find_name(type_info, params[i].id), params[i].flags & SPA_PARAM_INFO_READ ? 'r' : '-', @@ -257,9 +257,9 @@ { size_t i; - fprintf(stdout, "Available commands:\n"); + printf("Available commands:\n"); for (i = 0; i < SPA_N_ELEMENTS(command_list); i++) { - fprintf(stdout, "\t%-20.20s\t%s\n", command_list[i].name, command_list[i].description); + printf("\t%-20.20s\t%s\n", command_list[i].name, command_list[i].description); } return true; } @@ -284,7 +284,7 @@ } id = pw_map_insert_new(&data->vars, module); - fprintf(stdout, "%d = @module:%d\n", id, pw_global_get_id(pw_impl_module_get_global(module))); + printf("%d = @module:%d\n", id, pw_global_get_id(pw_impl_module_get_global(module))); return true; } @@ -295,7 +295,7 @@ free(rd->name); rd->name = info->name ? strdup(info->name) : NULL; if (rd->data->interactive) - fprintf(stdout, "remote %d is named '%s'\n", rd->id, rd->name); + printf("remote %d is named '%s'\n", rd->id, rd->name); } static void set_prompt(struct remote_data *rd) @@ -353,7 +353,7 @@ if (filter && !global_matches(global, filter)) return 0; - fprintf(stdout, "\tid %d, type %s/%d\n", global->id, + printf("\tid %d, type %s/%d\n", global->id, global->type, global->version); if (global->properties) print_properties(&global->properties->dict, ' ', false); @@ -383,7 +383,7 @@ global->properties = props ? pw_properties_new_dict(props) : NULL; if (rd->data->monitoring) { - fprintf(stdout, "remote %d added global: ", rd->id); + printf("remote %d added global: ", rd->id); print_global(global, NULL); } @@ -396,7 +396,7 @@ ret = bind_global(rd, global, &error); if (!ret) { if (rd->data->interactive) - fprintf(stdout, "Error: \"%s\"\n", error); + fprintf(stderr, "Error: \"%s\"\n", error); free(error); } } @@ -424,12 +424,12 @@ global = pw_map_lookup(&rd->globals, id); if (global == NULL) { - fprintf(stdout, "remote %d removed unknown global %d\n", rd->id, id); + fprintf(stderr, "remote %d removed unknown global %d\n", rd->id, id); return; } if (rd->data->monitoring) { - fprintf(stdout, "remote %d removed global: ", rd->id); + printf("remote %d removed global: ", rd->id); print_global(global, NULL); } @@ -536,7 +536,7 @@ spa_list_append(&data->remotes, &rd->link); if (rd->data->interactive) - fprintf(stdout, "%d = @remote:%p\n", rd->id, rd->core); + printf("%d = @remote:%p\n", rd->id, rd->core); data->current = rd; @@ -592,7 +592,7 @@ struct remote_data *rd; spa_list_for_each(rd, &data->remotes, link) - fprintf(stdout, "\t%d = @remote:%p '%s'\n", rd->id, rd->core, rd->name); + printf("\t%d = @remote:%p '%s'\n", rd->id, rd->core, rd->name); return true; } @@ -631,10 +631,10 @@ if (global == NULL) return; - fprintf(stdout, "\tid: %d\n", global->id); - fprintf(stdout, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", global->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(global->permissions)); - fprintf(stdout, "\ttype: %s/%d\n", global->type, global->version); + printf("\ttype: %s/%d\n", global->type, global->version); } static void info_core(struct proxy_data *pd) @@ -642,11 +642,11 @@ struct pw_core_info *info = pd->info; info_global(pd); - fprintf(stdout, "\tcookie: %u\n", info->cookie); - fprintf(stdout, "\tuser-name: \"%s\"\n", info->user_name); - fprintf(stdout, "\thost-name: \"%s\"\n", info->host_name); - fprintf(stdout, "\tversion: \"%s\"\n", info->version); - fprintf(stdout, "\tname: \"%s\"\n", info->name); + printf("\tcookie: %u\n", info->cookie); + printf("\tuser-name: \"%s\"\n", info->user_name); + printf("\thost-name: \"%s\"\n", info->host_name); + printf("\tversion: \"%s\"\n", info->version); + printf("\tname: \"%s\"\n", info->name); print_properties(info->props, MARK_CHANGE(PW_CORE_CHANGE_MASK_PROPS), true); info->change_mask = 0; } @@ -656,9 +656,9 @@ struct pw_module_info *info = pd->info; info_global(pd); - fprintf(stdout, "\tname: \"%s\"\n", info->name); - fprintf(stdout, "\tfilename: \"%s\"\n", info->filename); - fprintf(stdout, "\targs: \"%s\"\n", info->args); + printf("\tname: \"%s\"\n", info->name); + printf("\tfilename: \"%s\"\n", info->filename); + printf("\targs: \"%s\"\n", info->args); print_properties(info->props, MARK_CHANGE(PW_MODULE_CHANGE_MASK_PROPS), true); info->change_mask = 0; } @@ -668,16 +668,16 @@ struct pw_node_info *info = pd->info; info_global(pd); - fprintf(stdout, "%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), + printf("%c\tinput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), info->n_input_ports, info->max_input_ports); - fprintf(stdout, "%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), + printf("%c\toutput ports: %u/%u\n", MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), info->n_output_ports, info->max_output_ports); - fprintf(stdout, "%c\tstate: \"%s\"", MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE), + printf("%c\tstate: \"%s\"", MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE), pw_node_state_as_string(info->state)); if (info->state == PW_NODE_STATE_ERROR && info->error) - fprintf(stdout, " \"%s\"\n", info->error); + printf(" \"%s\"\n", info->error); else - fprintf(stdout, "\n"); + printf("\n"); print_properties(info->props, MARK_CHANGE(PW_NODE_CHANGE_MASK_PROPS), true); print_params(info->params, info->n_params, MARK_CHANGE(PW_NODE_CHANGE_MASK_PARAMS), true); info->change_mask = 0; @@ -688,7 +688,7 @@ struct pw_port_info *info = pd->info; info_global(pd); - fprintf(stdout, "\tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); + 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); info->change_mask = 0; @@ -699,8 +699,8 @@ struct pw_factory_info *info = pd->info; info_global(pd); - fprintf(stdout, "\tname: \"%s\"\n", info->name); - fprintf(stdout, "\tobject-type: %s/%d\n", info->type, info->version); + 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); info->change_mask = 0; } @@ -719,22 +719,22 @@ struct pw_link_info *info = pd->info; info_global(pd); - fprintf(stdout, "\toutput-node-id: %u\n", info->output_node_id); - fprintf(stdout, "\toutput-port-id: %u\n", info->output_port_id); - fprintf(stdout, "\tinput-node-id: %u\n", info->input_node_id); - fprintf(stdout, "\tinput-port-id: %u\n", info->input_port_id); + 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); + printf("\tinput-port-id: %u\n", info->input_port_id); - fprintf(stdout, "%c\tstate: \"%s\"", MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE), + printf("%c\tstate: \"%s\"", MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE), pw_link_state_as_string(info->state)); if (info->state == PW_LINK_STATE_ERROR && info->error) printf(" \"%s\"\n", info->error); else printf("\n"); - fprintf(stdout, "%c\tformat:\n", MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT)); + printf("%c\tformat:\n", MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT)); if (info->format) spa_debug_pod(2, NULL, info->format); else - fprintf(stdout, "\t\tnone\n"); + printf("\t\tnone\n"); print_properties(info->props, MARK_CHANGE(PW_LINK_CHANGE_MASK_PROPS), true); info->change_mask = 0; } @@ -765,8 +765,8 @@ const char *direction; info_global(pd); - fprintf(stdout, "\tname: %s\n", info->name); - fprintf(stdout, "\tmedia-class: %s\n", info->media_class); + printf("\tname: %s\n", info->name); + printf("\tmedia-class: %s\n", info->media_class); switch(info->direction) { case PW_DIRECTION_OUTPUT: direction = "source"; @@ -778,10 +778,10 @@ direction = "invalid"; break; } - fprintf(stdout, "\tdirection: %s\n", direction); - fprintf(stdout, "\tflags: 0x%x\n", info->flags); - fprintf(stdout, "%c\tstreams: %u\n", MARK_CHANGE(0), info->n_streams); - fprintf(stdout, "%c\tsession: %u\n", MARK_CHANGE(1), info->session_id); + printf("\tdirection: %s\n", direction); + printf("\tflags: 0x%x\n", info->flags); + printf("%c\tstreams: %u\n", MARK_CHANGE(0), info->n_streams); + printf("%c\tsession: %u\n", MARK_CHANGE(1), info->session_id); print_properties(info->props, MARK_CHANGE(2), true); print_params(info->params, info->n_params, MARK_CHANGE(3), true); info->change_mask = 0; @@ -792,9 +792,9 @@ struct pw_endpoint_stream_info *info = pd->info; info_global(pd); - fprintf(stdout, "\tid: %u\n", info->id); - fprintf(stdout, "\tendpoint-id: %u\n", info->endpoint_id); - fprintf(stdout, "\tname: %s\n", info->name); + printf("\tid: %u\n", info->id); + printf("\tendpoint-id: %u\n", info->endpoint_id); + printf("\tname: %s\n", info->name); print_properties(info->props, MARK_CHANGE(1), true); print_params(info->params, info->n_params, MARK_CHANGE(2), true); info->change_mask = 0; @@ -805,7 +805,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d core %d changed\n", rd->id, info->id); + printf("remote %d core %d changed\n", rd->id, info->id); pd->info = pw_core_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -826,7 +826,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d module %d changed\n", rd->id, info->id); + printf("remote %d module %d changed\n", rd->id, info->id); pd->info = pw_module_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -846,7 +846,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d node %d changed\n", rd->id, info->id); + printf("remote %d node %d changed\n", rd->id, info->id); pd->info = pw_node_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -863,7 +863,7 @@ struct remote_data *rd = data->rd; if (rd->data->interactive) - fprintf(stdout, "remote %d object %d param %d index %d\n", + printf("remote %d object %d param %d index %d\n", rd->id, data->global->id, id, index); spa_debug_pod(2, NULL, param); @@ -881,7 +881,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d port %d changed\n", rd->id, info->id); + printf("remote %d port %d changed\n", rd->id, info->id); pd->info = pw_port_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -902,7 +902,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d factory %d changed\n", rd->id, info->id); + printf("remote %d factory %d changed\n", rd->id, info->id); pd->info = pw_factory_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -922,7 +922,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d client %d changed\n", rd->id, info->id); + printf("remote %d client %d changed\n", rd->id, info->id); pd->info = pw_client_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -939,15 +939,15 @@ struct remote_data *rd = data->rd; uint32_t i; - fprintf(stdout, "remote %d node %d index %d\n", + printf("remote %d node %d index %d\n", rd->id, data->global->id, index); for (i = 0; i < n_permissions; i++) { if (permissions[i].id == PW_ID_ANY) - fprintf(stdout, " default:"); + printf(" default:"); else - fprintf(stdout, " %u:", permissions[i].id); - fprintf(stdout, " "PW_PERMISSION_FORMAT"\n", + printf(" %u:", permissions[i].id); + printf(" "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(permissions[i].permissions)); } } @@ -963,7 +963,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d link %d changed\n", rd->id, info->id); + printf("remote %d link %d changed\n", rd->id, info->id); pd->info = pw_link_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -984,7 +984,7 @@ struct proxy_data *pd = object; struct remote_data *rd = pd->rd; if (pd->info) - fprintf(stdout, "remote %d device %d changed\n", rd->id, info->id); + printf("remote %d device %d changed\n", rd->id, info->id); pd->info = pw_device_info_update(pd->info, info); if (pd->global == NULL) pd->global = pw_map_lookup(&rd->globals, info->id); @@ -1431,7 +1431,7 @@ pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd); id = pw_map_insert_new(&data->vars, proxy); - fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id(proxy)); + printf("%d = @proxy:%d\n", id, pw_proxy_get_id(proxy)); return true; } @@ -1470,7 +1470,7 @@ pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd); id = pw_map_insert_new(&data->vars, proxy); - fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id(proxy)); + printf("%d = @proxy:%d\n", id, pw_proxy_get_id(proxy)); return true; } @@ -1543,7 +1543,7 @@ pw_proxy_add_listener(proxy, &pd->proxy_listener, &proxy_events, pd); id = pw_map_insert_new(&data->vars, proxy); - fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy)); + printf("%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy)); return true; } @@ -1583,7 +1583,7 @@ proxy = pw_core_export(rd->core, PW_TYPE_INTERFACE_Node, NULL, node, 0); id = pw_map_insert_new(&data->vars, proxy); - fprintf(stdout, "%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy)); + printf("%d = @proxy:%d\n", id, pw_proxy_get_id((struct pw_proxy*)proxy)); return true; @@ -1736,7 +1736,7 @@ } p = strtol(a[2], NULL, 0); - fprintf(stderr, "setting permissions: "PW_PERMISSION_FORMAT"\n", + printf("setting permissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(p)); permissions[0] = PW_PERMISSION_INIT(atoi(a[1]), p); @@ -2131,7 +2131,7 @@ ind = INDENT(level + 2); spa_dict_for_each(item, props) { - fprintf(stdout, "%s%s = \"%s\"", + printf("%s%s = \"%s\"", ind, item->key, item->value); extra = NULL; @@ -2154,9 +2154,9 @@ } if (extra) - fprintf(stdout, " (\"%s\")", extra); + printf(" (\"%s\")", extra); - fprintf(stdout, "\n"); + printf("\n"); } } @@ -2175,7 +2175,7 @@ for (i = 0; i < n_params; i++) { const struct spa_type_info *type_info = spa_type_param; - fprintf(stdout, "%s %d (%s) %c%c\n", ind, + printf("%s %d (%s) %c%c\n", ind, params[i].id, spa_debug_type_find_name(type_info, params[i].id), params[i].flags & SPA_PARAM_INFO_READ ? 'r' : '-', @@ -2192,16 +2192,16 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sid: %"PRIu32"\n", ind, global->id); - fprintf(stdout, "%spermissions: "PW_PERMISSION_FORMAT"\n", ind, + printf("%sid: %"PRIu32"\n", ind, global->id); + printf("%spermissions: "PW_PERMISSION_FORMAT"\n", ind, PW_PERMISSION_ARGS(global->permissions)); - fprintf(stdout, "%stype: %s/%d\n", ind, + printf("%stype: %s/%d\n", ind, global->type, global->version); } else { ind = INDENT(level); - fprintf(stdout, "%s%"PRIu32":", ind, global->id); + printf("%s%"PRIu32":", ind, global->id); if (!(flags & is_notype)) - fprintf(stdout, " %s", pw_interface_short(global->type)); + printf(" %s", pw_interface_short(global->type)); } } @@ -2221,17 +2221,17 @@ info = pd->info; if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%scookie: %u\n", ind, info->cookie); - fprintf(stdout, "%suser-name: \"%s\"\n", ind, info->user_name); - fprintf(stdout, "%shost-name: \"%s\"\n", ind, info->host_name); - fprintf(stdout, "%sversion: \"%s\"\n", ind, info->version); - fprintf(stdout, "%sname: \"%s\"\n", ind, info->name); - fprintf(stdout, "%sproperties:\n", ind); + printf("%scookie: %u\n", ind, info->cookie); + printf("%suser-name: \"%s\"\n", ind, info->user_name); + printf("%shost-name: \"%s\"\n", ind, info->host_name); + printf("%sversion: \"%s\"\n", ind, info->version); + printf("%sname: \"%s\"\n", ind, info->name); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); } else { - fprintf(stdout, " u=\"%s\" h=\"%s\" v=\"%s\" n=\"%s\"", + printf(" u=\"%s\" h=\"%s\" v=\"%s\" n=\"%s\"", info->user_name, info->host_name, info->version, info->name); - fprintf(stdout, "\n"); + printf("\n"); } return true; @@ -2259,15 +2259,15 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sname: \"%s\"\n", ind, info->name); - fprintf(stdout, "%sfilename: \"%s\"\n", ind, info->filename); - fprintf(stdout, "%sargs: \"%s\"\n", ind, info->args); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sname: \"%s\"\n", ind, info->name); + printf("%sfilename: \"%s\"\n", ind, info->filename); + printf("%sargs: \"%s\"\n", ind, info->args); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); } else { desc = spa_dict_lookup(info->props, PW_KEY_MODULE_DESCRIPTION); args = info->args && strcmp(info->args, "(null)") ? info->args : NULL; - fprintf(stdout, " n=\"%s\" f=\"%s\"" "%s%s%s" "%s%s%s", + printf(" n=\"%s\" f=\"%s\"" "%s%s%s" "%s%s%s", info->name, info->filename, args ? " a=\"" : "", args ? args : "", @@ -2275,7 +2275,7 @@ desc ? " d=\"" : "", desc ? desc : "", desc ? "\"" : ""); - fprintf(stdout, "\n"); + printf("\n"); } if (!(flags & is_deep)) @@ -2284,7 +2284,7 @@ factory_count = children_of(rd, global->id, PW_TYPE_INTERFACE_Factory, &factories); if (factory_count >= 0) { ind = INDENT(level + 1); - fprintf(stdout, "%sfactories:\n", ind); + printf("%sfactories:\n", ind); for (i = 0; i < factory_count; i++) { global_factory = obj_global(rd, factories[i]); if (!global_factory) @@ -2320,9 +2320,9 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { media_class = spa_dict_lookup(info->props, PW_KEY_MEDIA_CLASS); @@ -2330,7 +2330,7 @@ desc = spa_dict_lookup(info->props, PW_KEY_DEVICE_DESCRIPTION); api = spa_dict_lookup(info->props, PW_KEY_DEVICE_API); - fprintf(stdout, "%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s", + printf("%s%s%s" "%s%s%s" "%s%s%s" "%s%s%s", media_class ? " c=\"" : "", media_class ? media_class : "", media_class ? "\"" : "", @@ -2350,7 +2350,7 @@ alsa_path = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_PATH); alsa_card_id = spa_dict_lookup(info->props, SPA_KEY_API_ALSA_CARD_ID); - fprintf(stdout, "%s%s%s" "%s%s%s", + printf("%s%s%s" "%s%s%s", alsa_path ? " p=\"" : "", alsa_path ? alsa_path : "", alsa_path ? "\"" : "", @@ -2359,7 +2359,7 @@ alsa_card_id ? "\"" : ""); } - fprintf(stdout, "\n"); + printf("\n"); } if (!(flags & is_deep)) @@ -2368,7 +2368,7 @@ node_count = children_of(rd, global->id, PW_TYPE_INTERFACE_Node, &nodes); if (node_count >= 0) { ind = INDENT(level + 1); - fprintf(stdout, "%snodes:\n", ind); + printf("%snodes:\n", ind); for (i = 0; i < node_count; i++) { global_node = obj_global(rd, nodes[i]); if (!global_node) @@ -2403,31 +2403,31 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sinput ports: %u/%u\n", ind, info->n_input_ports, info->max_input_ports); - fprintf(stdout, "%soutput ports: %u/%u\n", ind, info->n_output_ports, info->max_output_ports); - fprintf(stdout, "%sstate: \"%s\"", ind, pw_node_state_as_string(info->state)); + printf("%sinput ports: %u/%u\n", ind, info->n_input_ports, info->max_input_ports); + printf("%soutput ports: %u/%u\n", ind, info->n_output_ports, info->max_output_ports); + printf("%sstate: \"%s\"", ind, pw_node_state_as_string(info->state)); if (info->state == PW_NODE_STATE_ERROR && info->error) - fprintf(stdout, " \"%s\"\n", info->error); + printf(" \"%s\"\n", info->error); else - fprintf(stdout, "\n"); - fprintf(stdout, "%sproperties:\n", ind); + printf("\n"); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { name = spa_dict_lookup(info->props, PW_KEY_NODE_NAME); path = spa_dict_lookup(info->props, SPA_KEY_OBJECT_PATH); - fprintf(stdout, " s=\"%s\"", pw_node_state_as_string(info->state)); + printf(" s=\"%s\"", pw_node_state_as_string(info->state)); if (info->max_input_ports) { - fprintf(stdout, " i=%u/%u", info->n_input_ports, info->max_input_ports); + printf(" i=%u/%u", info->n_input_ports, info->max_input_ports); } if (info->max_output_ports) { - fprintf(stdout, " o=%u/%u", info->n_output_ports, info->max_output_ports); + printf(" o=%u/%u", info->n_output_ports, info->max_output_ports); } - fprintf(stdout, "%s%s%s" "%s%s%s", + printf("%s%s%s" "%s%s%s", name ? " n=\"" : "", name ? name : "", name ? "\"" : "", @@ -2435,7 +2435,7 @@ path ? path : "", path ? "\"" : ""); - fprintf(stdout, "\n"); + printf("\n"); } if (!(flags & is_deep)) @@ -2444,7 +2444,7 @@ port_count = children_of(rd, global->id, PW_TYPE_INTERFACE_Port, &ports); if (port_count >= 0) { ind = INDENT(level + 1); - fprintf(stdout, "%sports:\n", ind); + printf("%sports:\n", ind); for (i = 0; i < port_count; i++) { global_port = obj_global(rd, ports[i]); if (!global_port) @@ -2475,19 +2475,19 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sdirection: \"%s\"\n", ind, + printf("%sdirection: \"%s\"\n", ind, pw_direction_as_string(info->direction)); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { - fprintf(stdout, " d=\"%s\"", pw_direction_as_string(info->direction)); + printf(" d=\"%s\"", pw_direction_as_string(info->direction)); name = spa_dict_lookup(info->props, PW_KEY_PORT_NAME); format = spa_dict_lookup(info->props, PW_KEY_FORMAT_DSP); - fprintf(stdout, "%s%s%s" "%s%s%s", + printf("%s%s%s" "%s%s%s", name ? " n=\"" : "", name ? name : "", name ? "\"" : "", @@ -2495,7 +2495,7 @@ format ? format : "", format ? "\"" : ""); - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2522,21 +2522,21 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sname: \"%s\"\n", ind, info->name); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sname: \"%s\"\n", ind, info->name); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); } else { - fprintf(stdout, " n=\"%s\"", info->name); + printf(" n=\"%s\"", info->name); module_id = spa_dict_lookup(info->props, PW_KEY_MODULE_ID); module_name = module_id ? obj_lookup(rd, atoi(module_id), PW_KEY_MODULE_NAME) : NULL; - fprintf(stdout, "%s%s%s", + printf("%s%s%s", module_name ? " m=\"" : "", module_name ? module_name : "", module_name ? "\"" : ""); - fprintf(stdout, "\n"); + printf("\n"); } return true; @@ -2561,13 +2561,13 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); } else { app_name = spa_dict_lookup(info->props, PW_KEY_APP_NAME); app_pid = spa_dict_lookup(info->props, PW_KEY_APP_PROCESS_ID); - fprintf(stdout, "%s%s%s" "%s%s%s", + printf("%s%s%s" "%s%s%s", app_name ? " ap=\"" : "", app_name ? app_name : "", app_name ? "\"" : "", @@ -2575,7 +2575,7 @@ app_pid ? app_pid : "", app_pid ? "\"" : ""); - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2603,24 +2603,24 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%soutput-node-id: %u\n", ind, info->output_node_id); - fprintf(stdout, "%soutput-port-id: %u\n", ind, info->output_port_id); - fprintf(stdout, "%sinput-node-id: %u\n", ind, info->input_node_id); - fprintf(stdout, "%sinput-port-id: %u\n", ind, info->input_port_id); + printf("%soutput-node-id: %u\n", ind, info->output_node_id); + printf("%soutput-port-id: %u\n", ind, info->output_port_id); + printf("%sinput-node-id: %u\n", ind, info->input_node_id); + printf("%sinput-port-id: %u\n", ind, info->input_port_id); - fprintf(stdout, "%sstate: \"%s\"", ind, + printf("%sstate: \"%s\"", ind, pw_link_state_as_string(info->state)); if (info->state == PW_LINK_STATE_ERROR && info->error) printf(" \"%s\"\n", info->error); else printf("\n"); - fprintf(stdout, "%sformat:\n", ind); + printf("%sformat:\n", ind); if (info->format) spa_debug_pod(8 * (level + 1) + 2, NULL, info->format); else - fprintf(stdout, "%s\tnone\n", ind); + printf("%s\tnone\n", ind); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); } else { out_node_name = obj_lookup(rd, info->output_node_id, PW_KEY_NODE_NAME); @@ -2628,16 +2628,16 @@ out_port_name = obj_lookup(rd, info->output_port_id, PW_KEY_PORT_NAME); in_port_name = obj_lookup(rd, info->input_port_id, PW_KEY_PORT_NAME); - fprintf(stdout, " s=\"%s\"", pw_link_state_as_string(info->state)); + printf(" s=\"%s\"", pw_link_state_as_string(info->state)); if (out_node_name && out_port_name) - fprintf(stdout, " on=\"%s\"" " op=\"%s\"", + printf(" on=\"%s\"" " op=\"%s\"", out_node_name, out_port_name); if (in_node_name && in_port_name) - fprintf(stdout, " in=\"%s\"" " ip=\"%s\"", + printf(" in=\"%s\"" " ip=\"%s\"", in_node_name, in_port_name); - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2663,12 +2663,12 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2707,21 +2707,21 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sname: %s\n", ind, info->name); - fprintf(stdout, "%smedia-class: %s\n", ind, info->media_class); - fprintf(stdout, "%sdirection: %s\n", ind, direction); - fprintf(stdout, "%sflags: 0x%x\n", ind, info->flags); - fprintf(stdout, "%sstreams: %u\n", ind, info->n_streams); - fprintf(stdout, "%ssession: %u\n", ind, info->session_id); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sname: %s\n", ind, info->name); + printf("%smedia-class: %s\n", ind, info->media_class); + printf("%sdirection: %s\n", ind, direction); + printf("%sflags: 0x%x\n", ind, info->flags); + printf("%sstreams: %u\n", ind, info->n_streams); + printf("%ssession: %u\n", ind, info->session_id); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { - fprintf(stdout, " n=\"%s\" c=\"%s\" d=\"%s\" s=%u si=%"PRIu32"", + printf(" n=\"%s\" c=\"%s\" d=\"%s\" s=%u si=%"PRIu32"", info->name, info->media_class, direction, info->n_streams, info->session_id); - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2747,17 +2747,17 @@ if (!(flags & is_short)) { ind = INDENT(level + 1); - fprintf(stdout, "%sid: %u\n", ind, info->id); - fprintf(stdout, "%sendpoint-id: %u\n", ind, info->endpoint_id); - fprintf(stdout, "%sname: %s\n", ind, info->name); - fprintf(stdout, "%sproperties:\n", ind); + printf("%sid: %u\n", ind, info->id); + printf("%sendpoint-id: %u\n", ind, info->endpoint_id); + printf("%sname: %s\n", ind, info->name); + printf("%sproperties:\n", ind); dump_properties(data, global, flags, level); - fprintf(stdout, "%sparams:\n", ind); + printf("%sparams:\n", ind); dump_params(data, global, info->params, info->n_params, flags, level); } else { - fprintf(stdout, " n=\"%s\" i=%"PRIu32" ei=%"PRIu32"", + printf(" n=\"%s\" i=%"PRIu32" ei=%"PRIu32"", info->name, info->id, info->endpoint_id); - fprintf(stdout, "\n"); + printf("\n"); } (void)rd; @@ -2964,7 +2964,7 @@ if (line[0] != '\0') { add_history(line); if (!parse(d, line, &error)) { - fprintf(stdout, "Error: \"%s\"\n", error); + fprintf(stderr, "Error: \"%s\"\n", error); free(error); } } @@ -3045,9 +3045,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(struct data *data, const char *name) +static void show_help(struct data *data, const char *name, bool error) { - fprintf(stdout, _("%s [options] [command]\n" + fprintf(error ? stderr : stdout, _("%s [options] [command]\n" " -h, --help Show this help\n" " --version Show version\n" " -d, --daemon Start as daemon (Default false)\n" @@ -3074,15 +3074,17 @@ }; int c, i; + setlinebuf(stdout); + pw_init(&argc, &argv); while ((c = getopt_long(argc, argv, "hVdr:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(&data, argv[0]); + show_help(&data, argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -3096,7 +3098,7 @@ opt_remote = optarg; break; default: - show_help(&data, argv[0]); + show_help(&data, argv[0], true); return -1; } } @@ -3133,7 +3135,7 @@ if (optind == argc) { data.interactive = true; - fprintf(stdout, "Welcome to PipeWire version %s. Type 'help' for usage.\n", + printf("Welcome to PipeWire version %s. Type 'help' for usage.\n", pw_get_library_version()); readline_init(); @@ -3155,7 +3157,7 @@ pw_main_loop_run(data.loop); if (!parse(&data, buf, &error)) { - fprintf(stdout, "Error: \"%s\"\n", error); + fprintf(stderr, "Error: \"%s\"\n", error); free(error); } if (!data.quit && data.current) {
View file
pipewire-0.3.45.tar.gz/src/tools/pw-dot.c -> pipewire-0.3.47.tar.gz/src/tools/pw-dot.c
Changed
@@ -609,6 +609,8 @@ static void destroy_proxy(void *user_data) { struct global *g = user_data; + spa_hook_remove(&g->object_listener); + spa_hook_remove(&g->proxy_listener); pw_properties_free(g->props); if (g->info) g->info_destroy(g->info); @@ -760,9 +762,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -a, --all Show all object types\n" @@ -801,10 +803,10 @@ while ((c = getopt_long(argc, argv, "hVasdr:o:L9", long_options, NULL)) != -1) { switch (c) { case 'h' : - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V' : - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -840,7 +842,7 @@ fprintf(stderr, "orthogonal edges enabled\n"); break; default: - show_help(argv[0]); + show_help(argv[0], true); return -1; } } @@ -891,7 +893,9 @@ draw_graph(&data, dot_path); dot_str_clear(&data.dot_str); + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop); pw_deinit();
View file
pipewire-0.3.45.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.47.tar.gz/src/tools/pw-dump.c
Changed
@@ -1458,9 +1458,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(struct data *data, const char *name) +static void show_help(struct data *data, const char *name, bool error) { - fprintf(stdout, "%s [options] [<id>]\n" + fprintf(error ? stderr : stdout, "%s [options] [<id>]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n" @@ -1492,14 +1492,15 @@ data.out = stdout; if (isatty(fileno(data.out)) && getenv("NO_COLOR") == NULL) colors = true; + setlinebuf(data.out); while ((c = getopt_long(argc, argv, "hVr:mNC", long_options, NULL)) != -1) { switch (c) { case 'h' : - show_help(&data, argv[0]); + show_help(&data, argv[0], false); return 0; case 'V' : - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -1524,12 +1525,13 @@ else if (!strcmp(optarg, "always")) colors = true; else { - show_help(&data, argv[0]); + fprintf(stderr, "Unknown color: %s\n", optarg); + show_help(&data, argv[0], true); return -1; } break; default: - show_help(&data, argv[0]); + show_help(&data, argv[0], true); return -1; } } @@ -1581,7 +1583,9 @@ if (data.info) pw_core_info_free(data.info); + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop); pw_deinit();
View file
pipewire-0.3.45.tar.gz/src/tools/pw-link.c -> pipewire-0.3.47.tar.gz/src/tools/pw-link.c
Changed
@@ -179,15 +179,15 @@ prefix2 = " "; } - fprintf(stdout, "%s%s%s%s\n", data->prefix, prefix, + printf("%s%s%s%s\n", data->prefix, prefix, id, port_name(buffer, sizeof(buffer), n, p)); if (verbose) { port_path(buffer, sizeof(buffer), n, p); if (buffer[0] != '\0') - fprintf(stdout, "%s %s%s%s\n", data->prefix, prefix2, prefix, buffer); + printf("%s %s%s%s\n", data->prefix, prefix2, prefix, buffer); port_alias(buffer, sizeof(buffer), n, p); if (buffer[0] != '\0') - fprintf(stdout, "%s %s%s%s\n", data->prefix, prefix2, prefix, buffer); + printf("%s %s%s%s\n", data->prefix, prefix2, prefix, buffer); } } @@ -426,7 +426,7 @@ if (data->opt_id) snprintf(id, sizeof(id), "%4d ", link->id); - fprintf(stdout, "%s%s%s -> %s\n", data->prefix, id, + printf("%s%s%s -> %s\n", data->prefix, id, port_name(buffer1, sizeof(buffer1), n1, p1), port_name(buffer2, sizeof(buffer2), n2, p2)); return 0; @@ -552,9 +552,9 @@ pw_main_loop_quit(data->loop); } -static void show_help(struct data *data, const char *name) +static void show_help(struct data *data, const char *name, bool error) { - fprintf(stdout, "%1$s : PipeWire port and link manager.\n" + fprintf(error ? stderr : stdout, "%1$s : PipeWire port and link manager.\n" "Generic: %1$s [options]\n" " -h, --help Show this help\n" " --version Show version\n" @@ -563,11 +563,11 @@ " -o, --output List output ports\n" " -i, --input List input ports\n" " -l, --links List links\n" - " -m, --monitor Monitor links\n" + " -m, --monitor Monitor links and ports\n" " -I, --id List IDs\n" " -v, --verbose Verbose port properties\n" "Connect: %1$s [options] output input\n" - " -L, --linger Linger (for use with -m)\n" + " -L, --linger Linger (default, unless -m is used)\n" " -P, --passive Passive link\n" " -p, --props=PROPS Properties as JSON object\n" "Disconnect: %1$s -d [options] output input\n" @@ -602,6 +602,8 @@ pw_init(&argc, &argv); spa_list_init(&data.objects); + setlinebuf(stdout); + data.props = pw_properties_new(NULL, NULL); if (data.props == NULL) { fprintf(stderr, "can't create properties: %m\n"); @@ -611,10 +613,10 @@ while ((c = getopt_long(argc, argv, "hVr:oilmIvLPp:d", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(&data, argv[0]); + show_help(&data, argv[0], NULL); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -655,12 +657,17 @@ data.opt_mode |= MODE_DISCONNECT; break; default: - show_help(&data, argv[0]); + show_help(&data, argv[0], true); return -1; } } if (argc == 1) - show_help(&data, argv[0]); + show_help(&data, argv[0], true); + + if (data.opt_id && (data.opt_mode & MODE_LIST) == 0) { + fprintf(stderr, "-I option needs one or more of -l, -i or -o\n"); + return -1; + } if ((data.opt_mode & MODE_MONITOR) == 0) pw_properties_set(data.props, PW_KEY_OBJECT_LINGER, "true"); @@ -729,7 +736,7 @@ do_list(&data); } else if (data.opt_mode & MODE_DISCONNECT) { if (data.opt_output == NULL) { - fprintf(stderr, "missing link-id or output and input port names\n"); + fprintf(stderr, "missing link-id or output and input port names to disconnect\n"); return -1; } if ((res = do_unlink_ports(&data)) < 0) { @@ -739,7 +746,7 @@ } else { if (data.opt_output == NULL || data.opt_input == NULL) { - fprintf(stderr, "missing output and input port names\n"); + fprintf(stderr, "missing output and input port names to connect\n"); return -1; } if ((res = do_link_ports(&data)) < 0) { @@ -758,7 +765,9 @@ regfree(data.out_regex); if (data.in_regex) regfree(data.in_regex); + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_core_disconnect(data.core); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop);
View file
pipewire-0.3.45.tar.gz/src/tools/pw-loopback.c -> pipewire-0.3.47.tar.gz/src/tools/pw-loopback.c
Changed
@@ -80,9 +80,9 @@ }; -static void show_help(struct data *data, const char *name) +static void show_help(struct data *data, const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n" @@ -142,10 +142,10 @@ while ((c = getopt_long(argc, argv, "hVr:g:c:m:l:C:P:i:o:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(&data, argv[0]); + show_help(&data, argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -180,7 +180,7 @@ pw_properties_update_string(data.playback_props, optarg, strlen(optarg)); break; default: - show_help(&data, argv[0]); + show_help(&data, argv[0], true); return -1; } }
View file
pipewire-0.3.45.tar.gz/src/tools/pw-metadata.c -> pipewire-0.3.47.tar.gz/src/tools/pw-metadata.c
Changed
@@ -70,11 +70,11 @@ if ((d->opt_id == SPA_ID_INVALID || d->opt_id == id) && (d->opt_key == NULL || spa_streq(d->opt_key, key))) { if (key == NULL) { - fprintf(stdout, "remove: id:%u all keys\n", id); + printf("remove: id:%u all keys\n", id); } else if (value == NULL) { - fprintf(stdout, "remove: id:%u key:'%s'\n", id, key); + printf("remove: id:%u key:'%s'\n", id, key); } else { - fprintf(stdout, "update: id:%u key:'%s' value:'%s' type:'%s'\n", id, key, value, type); + printf("update: id:%u key:'%s' value:'%s' type:'%s'\n", id, key, value, type); } } @@ -106,23 +106,23 @@ return; } - fprintf(stdout, "Found \"%s\" metadata %d\n", d->opt_name, id); + printf("Found \"%s\" metadata %d\n", d->opt_name, id); d->metadata = pw_registry_bind(d->registry, id, type, PW_VERSION_METADATA, 0); if (d->opt_delete) { if (d->opt_id != SPA_ID_INVALID) { if (d->opt_key != NULL) - fprintf(stdout, "delete property: id:%u key:%s\n", d->opt_id, d->opt_key); + printf("delete property: id:%u key:%s\n", d->opt_id, d->opt_key); else - fprintf(stdout, "delete properties: id:%u\n", d->opt_id); + printf("delete properties: id:%u\n", d->opt_id); pw_metadata_set_property(d->metadata, d->opt_id, d->opt_key, NULL, NULL); } else { - fprintf(stdout, "delete all properties\n"); + printf("delete all properties\n"); pw_metadata_clear(d->metadata); } } else if (d->opt_id != SPA_ID_INVALID && d->opt_key != NULL && d->opt_value != NULL) { - fprintf(stdout, "set property: id:%u key:%s value:%s type:%s\n", + printf("set property: id:%u key:%s value:%s type:%s\n", d->opt_id, d->opt_key, d->opt_value, d->opt_type); pw_metadata_set_property(d->metadata, d->opt_id, d->opt_key, d->opt_type, d->opt_value); } else { @@ -170,9 +170,9 @@ pw_main_loop_quit(data->loop); } -static void show_help(struct data *data, const char *name) +static void show_help(struct data *data, const char *name, bool error) { - fprintf(stdout, "%s [options] [ id [ key [ value [ type ] ] ] ]\n" + fprintf(error ? stderr : stdout, "%s [options] [ id [ key [ value [ type ] ] ] ]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n" @@ -196,6 +196,8 @@ { NULL, 0, NULL, 0} }; + setlinebuf(stdout); + pw_init(&argc, &argv); data.opt_name = "default"; @@ -203,10 +205,10 @@ while ((c = getopt_long(argc, argv, "hVr:mdn:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(&data, argv[0]); + show_help(&data, argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -226,7 +228,7 @@ data.opt_name = optarg; break; default: - show_help(&data, argv[0]); + show_help(&data, argv[0], true); return -1; } } @@ -281,7 +283,9 @@ if (data.metadata) pw_proxy_destroy((struct pw_proxy*)data.metadata); + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_core_disconnect(data.core); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop);
View file
pipewire-0.3.45.tar.gz/src/tools/pw-mididump.c -> pipewire-0.3.47.tar.gz/src/tools/pw-mididump.c
Changed
@@ -113,7 +113,7 @@ ev.data = SPA_POD_BODY(&c->value), ev.size = SPA_POD_BODY_SIZE(&c->value); - fprintf(stdout, "%4d: ", c->offset); + printf("%4d: ", c->offset); midi_file_dump_event(stdout, &ev); } @@ -175,9 +175,9 @@ return 0; } -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options] [FILE]\n" + fprintf(error ? stderr : stdout, "%s [options] [FILE]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n", @@ -197,13 +197,15 @@ pw_init(&argc, &argv); + setlinebuf(stdout); + while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -214,7 +216,7 @@ data.opt_remote = optarg; break; default: - show_help(argv[0]); + show_help(argv[0], true); return -1; } }
View file
pipewire-0.3.45.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.47.tar.gz/src/tools/pw-mon.c
Changed
@@ -48,10 +48,10 @@ { .prefix = "*", .suffix = "" }, }; -#define with_prefix(use_prefix_, stream_) \ - for (bool once_ = !!fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).prefix); \ +#define with_prefix(use_prefix_) \ + for (bool once_ = !!printf("%s", (pprefix[!!(use_prefix_)]).prefix); \ once_; \ - once_ = false, fprintf(stream_, "%s", (pprefix[!!(use_prefix_)]).suffix)) + once_ = false, printf("%s", (pprefix[!!(use_prefix_)]).suffix)) struct param { @@ -175,13 +175,13 @@ { struct param *p; - with_prefix(use_prefix, stderr) { - fprintf(stderr, "\tparams:\n"); + with_prefix(use_prefix) { + printf("\tparams:\n"); } spa_list_for_each(p, &data->param_list, link) { - with_prefix(p->changed, stderr) { - fprintf(stderr, "\t id:%u (%s)\n", + with_prefix(p->changed) { + printf("\t id:%u (%s)\n", p->id, spa_debug_type_find_name(spa_type_param, p->id)); if (spa_pod_is_object_type(p->param, SPA_TYPE_OBJECT_Format)) @@ -197,20 +197,20 @@ { const struct spa_dict_item *item; - with_prefix(use_prefix, stderr) { - fprintf(stderr, "\tproperties:\n"); + with_prefix(use_prefix) { + printf("\tproperties:\n"); if (props == NULL || props->n_items == 0) { - fprintf(stderr, "\t\tnone\n"); + printf("\t\tnone\n"); return; } } spa_dict_for_each(item, props) { - with_prefix(use_prefix, stderr) { + with_prefix(use_prefix) { if (item->value) - fprintf(stderr, "\t\t%s = \"%s\"\n", item->key, item->value); + printf("\t\t%s = \"%s\"\n", item->key, item->value); else - fprintf(stderr, "\t\t%s = (null)\n", item->key); + printf("\t\t%s = (null)\n", item->key); } } } @@ -221,12 +221,12 @@ { bool print_all = true, print_mark = true; - fprintf(stderr, "\ttype: %s\n", PW_TYPE_INTERFACE_Core); - fprintf(stderr, "\tcookie: %u\n", info->cookie); - fprintf(stderr, "\tuser-name: \"%s\"\n", info->user_name); - fprintf(stderr, "\thost-name: \"%s\"\n", info->host_name); - fprintf(stderr, "\tversion: \"%s\"\n", info->version); - fprintf(stderr, "\tname: \"%s\"\n", info->name); + printf("\ttype: %s\n", PW_TYPE_INTERFACE_Core); + printf("\tcookie: %u\n", info->cookie); + printf("\tuser-name: \"%s\"\n", info->user_name); + printf("\thost-name: \"%s\"\n", info->host_name); + printf("\tversion: \"%s\"\n", info->version); + printf("\tname: \"%s\"\n", info->name); if (print_all) { print_properties(info->props, MARK_CHANGE(PW_CORE_CHANGE_MASK_PROPS)); } @@ -239,23 +239,23 @@ print_all = true; if (data->info == NULL) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } info = data->info = pw_module_info_update(data->info, info); - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); - fprintf(stderr, "\tname: \"%s\"\n", info->name); - fprintf(stderr, "\tfilename: \"%s\"\n", info->filename); - fprintf(stderr, "\targs: \"%s\"\n", info->args); + printf("\ttype: %s (version %d)\n", data->type, data->version); + printf("\tname: \"%s\"\n", info->name); + printf("\tfilename: \"%s\"\n", info->filename); + printf("\targs: \"%s\"\n", info->args); if (print_all) { print_properties(info->props, MARK_CHANGE(PW_MODULE_CHANGE_MASK_PROPS)); } @@ -273,37 +273,37 @@ print_all = true; if (data->first) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; data->first = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); if (print_all) { print_params(data, MARK_CHANGE(PW_NODE_CHANGE_MASK_PARAMS)); - with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS), stderr) { - fprintf(stderr, "\tinput ports: %u/%u\n", + with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_INPUT_PORTS)) { + printf("\tinput ports: %u/%u\n", info->n_input_ports, info->max_input_ports); } - with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS), stderr) { - fprintf(stderr, "\toutput ports: %u/%u\n", + with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_OUTPUT_PORTS)) { + printf("\toutput ports: %u/%u\n", info->n_output_ports, info->max_output_ports); } - with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE), stderr) { - fprintf(stderr, "\tstate: \"%s\"", + with_prefix(MARK_CHANGE(PW_NODE_CHANGE_MASK_STATE)) { + printf("\tstate: \"%s\"", pw_node_state_as_string(info->state)); } if (info->state == PW_NODE_STATE_ERROR && info->error) - fprintf(stderr, " \"%s\"\n", info->error); + printf(" \"%s\"\n", info->error); else - fprintf(stderr, "\n"); + printf("\n"); print_properties(info->props, MARK_CHANGE(PW_NODE_CHANGE_MASK_PROPS)); } } @@ -346,21 +346,21 @@ print_all = true; if (data->first) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; data->first = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); - fprintf(stderr, "\tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); + printf("\tdirection: \"%s\"\n", pw_direction_as_string(info->direction)); if (print_all) { print_params(data, MARK_CHANGE(PW_PORT_CHANGE_MASK_PARAMS)); print_properties(info->props, MARK_CHANGE(PW_PORT_CHANGE_MASK_PROPS)); @@ -405,23 +405,23 @@ print_all = true; if (data->info == NULL) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } info = data->info = pw_factory_info_update(data->info, info); - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); - fprintf(stderr, "\tname: \"%s\"\n", info->name); - fprintf(stderr, "\tobject-type: %s/%d\n", info->type, info->version); + printf("\tname: \"%s\"\n", info->name); + printf("\tobject-type: %s/%d\n", info->type, info->version); if (print_all) { print_properties(info->props, MARK_CHANGE(PW_FACTORY_CHANGE_MASK_PROPS)); } @@ -439,20 +439,20 @@ print_all = true; if (data->info == NULL) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } info = data->info = pw_client_info_update(data->info, info); - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); if (print_all) { print_properties(info->props, MARK_CHANGE(PW_CLIENT_CHANGE_MASK_PROPS)); @@ -471,40 +471,40 @@ print_all = true; if (data->info == NULL) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } info = data->info = pw_link_info_update(data->info, info); - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); - fprintf(stderr, "\toutput-node-id: %u\n", info->output_node_id); - fprintf(stderr, "\toutput-port-id: %u\n", info->output_port_id); - fprintf(stderr, "\tinput-node-id: %u\n", info->input_node_id); - fprintf(stderr, "\tinput-port-id: %u\n", info->input_port_id); + 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); + printf("\tinput-port-id: %u\n", info->input_port_id); if (print_all) { - with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE), stderr) { - fprintf(stderr, "\tstate: \"%s\"", + with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_STATE)) { + printf("\tstate: \"%s\"", pw_link_state_as_string(info->state)); } if (info->state == PW_LINK_STATE_ERROR && info->error) - fprintf(stderr, " \"%s\"\n", info->error); + printf(" \"%s\"\n", info->error); else - fprintf(stderr, "\n"); - with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT), stderr) { - fprintf(stderr, "\tformat:\n"); + printf("\n"); + with_prefix(MARK_CHANGE(PW_LINK_CHANGE_MASK_FORMAT)) { + printf("\tformat:\n"); if (info->format) spa_debug_format(2, NULL, info->format); else - fprintf(stderr, "\t\tnone\n"); + printf("\t\tnone\n"); } print_properties(info->props, MARK_CHANGE(PW_LINK_CHANGE_MASK_PROPS)); } @@ -522,19 +522,19 @@ print_all = true; if (data->first) { - fprintf(stderr, "added:\n"); + printf("added:\n"); print_mark = false; data->first = false; } else { - fprintf(stderr, "changed:\n"); + printf("changed:\n"); print_mark = true; } - fprintf(stderr, "\tid: %d\n", data->id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("\tid: %d\n", data->id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(data->permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", data->type, data->version); + printf("\ttype: %s (version %d)\n", data->type, data->version); if (print_all) { print_params(data, MARK_CHANGE(PW_DEVICE_CHANGE_MASK_PARAMS)); @@ -587,6 +587,9 @@ spa_list_remove(&pd->global_link); + spa_hook_remove(&pd->object_listener); + spa_hook_remove(&pd->proxy_listener); + clear_params(pd); remove_pending(pd); free(pd->type); @@ -648,11 +651,11 @@ client_version = PW_VERSION_LINK; destroy = (pw_destroy_t) pw_link_info_free; } else { - fprintf(stderr, "added:\n"); - fprintf(stderr, "\tid: %u\n", id); - fprintf(stderr, "\tpermissions: "PW_PERMISSION_FORMAT"\n", + printf("added:\n"); + printf("\tid: %u\n", id); + printf("\tpermissions: "PW_PERMISSION_FORMAT"\n", PW_PERMISSION_ARGS(permissions)); - fprintf(stderr, "\ttype: %s (version %d)\n", type, version); + printf("\ttype: %s (version %d)\n", type, version); print_properties(props, false); return; } @@ -701,8 +704,8 @@ struct data *d = object; struct proxy_data *pd; - fprintf(stderr, "removed:\n"); - fprintf(stderr, "\tid: %u\n", id); + printf("removed:\n"); + printf("\tid: %u\n", id); pd = find_proxy(d, id); if (pd == NULL) @@ -741,9 +744,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n" @@ -770,16 +773,18 @@ pw_init(&argc, &argv); + setlinebuf(stdout); + if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL) colors = true; while ((c = getopt_long(argc, argv, "hVr:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -801,12 +806,13 @@ else if (!strcmp(optarg, "always")) colors = true; else { - show_help(argv[0]); + fprintf(stderr, "Invalid color: %s\n", optarg); + show_help(argv[0], true); return -1; } break; default: - show_help(argv[0]); + show_help(argv[0], true); return -1; } } @@ -856,7 +862,9 @@ pw_main_loop_run(data.loop); + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop); pw_deinit();
View file
pipewire-0.3.45.tar.gz/src/tools/pw-profiler.c -> pipewire-0.3.47.tar.gz/src/tools/pw-profiler.c
Changed
@@ -131,7 +131,7 @@ if (d->driver_id == 0) { d->driver_id = driver_id; - fprintf(stderr, "logging driver %u\n", driver_id); + printf("logging driver %u\n", driver_id); } else if (d->driver_id != driver_id) return -1; @@ -162,7 +162,7 @@ strncpy(d->followers[idx].name, name, MAX_NAME); d->followers[idx].name[MAX_NAME-1] = '\0'; d->followers[idx].id = id; - fprintf(stderr, "logging follower %u (\"%s\")\n", id, name); + printf("logging follower %u (\"%s\")\n", id, name); return idx; } @@ -243,7 +243,7 @@ d->last_status = point->clock.nsec; } else if (point->clock.nsec - d->last_status > SPA_NSEC_PER_SEC) { - fprintf(stderr, "logging %"PRIi64" samples %"PRIi64" seconds [CPU %f %f %f]\r", + printf("logging %"PRIi64" samples %"PRIi64" seconds [CPU %f %f %f]\r", d->count, (int64_t) ((d->last_status - d->start_status) / SPA_NSEC_PER_SEC), point->cpu_load[0], point->cpu_load[1], point->cpu_load[2]); d->last_status = point->clock.nsec; @@ -259,7 +259,7 @@ if (d->driver_id == 0) return; - fprintf(stderr, "\ndumping scripts for %d followers\n", d->n_followers); + printf("\ndumping scripts for %d followers\n", d->n_followers); out = fopen("Timing1.plot", "w"); if (out == NULL) { @@ -420,7 +420,7 @@ "gnuplot Timing5.plot\n"); fclose(out); } - fprintf(stderr, "run 'sh generate_timings.sh' and load Timings.html in a browser\n"); + printf("run 'sh generate_timings.sh' and load Timings.html in a browser\n"); } static void profiler_profile(void *data, const struct spa_pod *pod) @@ -487,7 +487,7 @@ if (proxy == NULL) goto error_proxy; - fprintf(stderr, "Attaching to Profiler id:%d\n", id); + printf("Attaching to Profiler id:%d\n", id); d->profiler = proxy; pw_proxy_add_object_listener(proxy, &d->profiler_listener, &profiler_events, d); @@ -539,9 +539,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n" @@ -570,10 +570,10 @@ while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -587,7 +587,7 @@ opt_remote = optarg; break; default: - show_help(argv[0]); + show_help(argv[0], true); return -1; } } @@ -628,7 +628,7 @@ return -1; } - fprintf(stderr, "Logging to %s\n", data.filename); + printf("Logging to %s\n", data.filename); pw_core_add_listener(data.core, &data.core_listener, @@ -643,8 +643,13 @@ pw_main_loop_run(data.loop); - pw_proxy_destroy((struct pw_proxy*)data.profiler); + if (data.profiler) { + spa_hook_remove(&data.profiler_listener); + pw_proxy_destroy((struct pw_proxy*)data.profiler); + } + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop);
View file
pipewire-0.3.45.tar.gz/src/tools/pw-reserve.c -> pipewire-0.3.47.tar.gz/src/tools/pw-reserve.c
Changed
@@ -50,24 +50,24 @@ static void reserve_acquired(void *data, struct rd_device *d) { - fprintf(stdout, "reserve acquired\n"); + printf("reserve acquired\n"); } static void reserve_release(void *data, struct rd_device *d, int forced) { struct impl *impl = data; - fprintf(stdout, "reserve release\n"); + printf("reserve release\n"); rd_device_complete_release(impl->device, true); } static void reserve_busy(void *data, struct rd_device *d, const char *name, int32_t prio) { - fprintf(stdout, "reserve busy %s, prio %d\n", name, prio); + printf("reserve busy %s, prio %d\n", name, prio); } static void reserve_available(void *data, struct rd_device *d, const char *name) { - fprintf(stdout, "reserve available %s\n", name); + printf("reserve available %s\n", name); } static const struct rd_device_callbacks reserve_callbacks = { @@ -86,9 +86,9 @@ #define DEFAULT_APPNAME "pw-reserve" #define DEFAULT_PRIORITY 0 -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -n, --name Name to reserve (Audio0, Midi0, Video0, ..)\n" @@ -119,15 +119,17 @@ { NULL, 0, NULL, 0} }; + setlinebuf(stdout); + pw_init(&argc, &argv); while ((c = getopt_long(argc, argv, "hVn:a:p:m", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -147,7 +149,7 @@ opt_monitor = true; break; default: - fprintf(stderr, "invalid option '%c'\n", c); + show_help(argv[0], true); return -1; } }
View file
pipewire-0.3.45.tar.gz/src/tools/pw-top.c -> pipewire-0.3.47.tar.gz/src/tools/pw-top.c
Changed
@@ -374,7 +374,7 @@ } } else if (spa_streq(type, PW_TYPE_INTERFACE_Profiler)) { if (d->profiler != NULL) { - fprintf(stderr, "Ignoring profiler %d: already attached\n", id); + printf("Ignoring profiler %d: already attached\n", id); return; } @@ -443,9 +443,9 @@ pw_main_loop_quit(d->loop); } -static void show_help(const char *name) +static void show_help(const char *name, bool error) { - fprintf(stdout, "%s [options]\n" + fprintf(error ? stderr : stdout, "%s [options]\n" " -h, --help Show this help\n" " --version Show version\n" " -r, --remote Remote daemon name\n", @@ -506,10 +506,10 @@ while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) { switch (c) { case 'h': - show_help(argv[0]); + show_help(argv[0], false); return 0; case 'V': - fprintf(stdout, "%s\n" + printf("%s\n" "Compiled with libpipewire %s\n" "Linked with libpipewire %s\n", argv[0], @@ -520,7 +520,7 @@ opt_remote = optarg; break; default: - show_help(argv[0]); + show_help(argv[0], true); return -1; } } @@ -584,8 +584,13 @@ spa_list_consume(n, &data.node_list, link) remove_node(&data, n); - pw_proxy_destroy((struct pw_proxy*)data.profiler); + if (data.profiler) { + spa_hook_remove(&data.profiler_listener); + pw_proxy_destroy((struct pw_proxy*)data.profiler); + } + spa_hook_remove(&data.registry_listener); pw_proxy_destroy((struct pw_proxy*)data.registry); + spa_hook_remove(&data.core_listener); pw_context_destroy(data.context); pw_main_loop_destroy(data.loop);
View file
pipewire-0.3.45.tar.gz/test/meson.build -> pipewire-0.3.47.tar.gz/test/meson.build
Changed
@@ -75,6 +75,14 @@ link_with: pwtest_lib) ) +test('test-loop', + executable('test-loop', + 'test-loop.c', + include_directories: pwtest_inc, + dependencies: [ spa_dep ], + link_with: pwtest_lib) +) + test('test-context', executable('test-context', 'test-context.c',
View file
pipewire-0.3.45.tar.gz/test/pwtest-compat.c -> pipewire-0.3.47.tar.gz/test/pwtest-compat.c
Changed
@@ -24,7 +24,7 @@ #include "config.h" -#if !HAVE_SIGABBREV_NP +#ifndef HAVE_SIGABBREV_NP #include <stddef.h> #include <signal.h>
View file
pipewire-0.3.45.tar.gz/test/pwtest.c -> pipewire-0.3.47.tar.gz/test/pwtest.c
Changed
@@ -36,10 +36,10 @@ #include <stdio.h> #include <unistd.h> #include <signal.h> -#if HAVE_PIDFD_OPEN +#ifdef HAVE_PIDFD_OPEN #include <sys/syscall.h> #endif -#if HAVE_LIBCAP +#ifdef HAVE_LIBCAP #include <sys/capability.h> #endif #include <sys/epoll.h> @@ -177,7 +177,7 @@ static void pwtest_backtrace(pid_t p) { -#if HAVE_GSTACK +#ifdef HAVE_GSTACK char pid[11]; pid_t parent, child; int status; @@ -305,12 +305,14 @@ struct spa_handle **hnd; SPA_FOR_EACH_ELEMENT(plugin->handles, hnd) { - if (*hnd) + if (*hnd) { + spa_handle_clear(*hnd); free(*hnd); + } } SPA_FOR_EACH_ELEMENT(plugin->dlls, dll) { if (*dll) - dlclose(dll); + dlclose(*dll); } free(plugin); } @@ -362,12 +364,13 @@ r = spa_handle_factory_init(factory, handle, info, plugin->support, plugin->nsupport); pwtest_neg_errno_ok(r); if ((r = spa_handle_get_interface(handle, interface_name, &iface)) != 0) { - dlclose(hnd); + spa_handle_clear(handle); free(handle); + dlclose(hnd); return -ENOSYS; } - plugin->handles[plugin->ndlls++] = hnd; + plugin->dlls[plugin->ndlls++] = hnd; plugin->handles[plugin->nhandles++] = handle; plugin->support[plugin->nsupport++] = SPA_SUPPORT_INIT(interface_name, iface); @@ -820,7 +823,7 @@ size_t nevents = 0; int r; -#if HAVE_PIDFD_OPEN +#ifdef HAVE_PIDFD_OPEN pidfd = syscall(SYS_pidfd_open, pid, 0); #else errno = ENOSYS; @@ -1168,7 +1171,7 @@ static bool is_debugger_attached(void) { bool rc = false; -#if HAVE_LIBCAP +#ifdef HAVE_LIBCAP int status; int pid = fork();
View file
pipewire-0.3.45.tar.gz/test/test-context.c -> pipewire-0.3.47.tar.gz/test/test-context.c
Changed
@@ -233,7 +233,7 @@ SPA_TYPE_INTERFACE_Loop, SPA_TYPE_INTERFACE_LoopUtils, SPA_TYPE_INTERFACE_Log, -#if HAVE_DBUS +#ifdef HAVE_DBUS SPA_TYPE_INTERFACE_DBus, #endif SPA_TYPE_INTERFACE_CPU
View file
pipewire-0.3.45.tar.gz/test/test-lib.c -> pipewire-0.3.47.tar.gz/test/test-lib.c
Changed
@@ -44,6 +44,8 @@ pwtest_str_eq(headerversion, version_expected); pwtest_str_eq(libversion, version_expected); + pw_deinit(); + return PWTEST_PASS; }
View file
pipewire-0.3.47.tar.gz/test/test-loop.c
Added
@@ -0,0 +1,237 @@ +/* PipeWire + * + * Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/eventfd.h> + +#include "pwtest.h" + +#include <pipewire/pipewire.h> + +struct obj { + int x; + struct spa_source source; +}; + +struct data { + struct pw_main_loop *ml; + struct pw_loop *l; + struct obj *a, *b; + int count; +}; + +static void on_event(struct spa_source *source) +{ + struct data *d = source->data; + + pw_loop_remove_source(d->l, &d->a->source); + pw_loop_remove_source(d->l, &d->b->source); + close(d->a->source.fd); + close(d->b->source.fd); + free(d->a); + free(d->b); + + pw_main_loop_quit(d->ml); +} + +PWTEST(pwtest_loop_destroy2) +{ + struct data data; + + pw_init(0, NULL); + + spa_zero(data); + data.ml = pw_main_loop_new(NULL); + pwtest_ptr_notnull(data.ml); + + data.l = pw_main_loop_get_loop(data.ml); + pwtest_ptr_notnull(data.l); + + data.a = calloc(1, sizeof(*data.a)); + data.b = calloc(1, sizeof(*data.b)); + + data.a->source.func = on_event; + data.a->source.fd = eventfd(0, 0); + data.a->source.mask = SPA_IO_IN; + data.a->source.data = &data; + data.b->source.func = on_event; + data.b->source.fd = eventfd(0, 0); + data.b->source.mask = SPA_IO_IN; + data.b->source.data = &data; + + pw_loop_add_source(data.l, &data.a->source); + pw_loop_add_source(data.l, &data.b->source); + + write(data.a->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + write(data.b->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + + pw_main_loop_run(data.ml); + pw_main_loop_destroy(data.ml); + + pw_deinit(); + + return PWTEST_PASS; +} + +static void +on_event_recurse1(struct spa_source *source) +{ + static bool first = true; + struct data *d = source->data; + uint64_t val; + + ++d->count; + pwtest_int_lt(d->count, 3); + + read(source->fd, &val, sizeof(val)); + + if (first) { + first = false; + pw_loop_enter(d->l); + pw_loop_iterate(d->l, -1); + pw_loop_leave(d->l); + } + pw_main_loop_quit(d->ml); +} + +PWTEST(pwtest_loop_recurse1) +{ + struct data data; + + pw_init(0, NULL); + + spa_zero(data); + data.ml = pw_main_loop_new(NULL); + pwtest_ptr_notnull(data.ml); + + data.l = pw_main_loop_get_loop(data.ml); + pwtest_ptr_notnull(data.l); + + data.a = calloc(1, sizeof(*data.a)); + data.b = calloc(1, sizeof(*data.b)); + + data.a->source.func = on_event_recurse1; + data.a->source.fd = eventfd(0, 0); + data.a->source.mask = SPA_IO_IN; + data.a->source.data = &data; + data.b->source.func = on_event_recurse1; + data.b->source.fd = eventfd(0, 0); + data.b->source.mask = SPA_IO_IN; + data.b->source.data = &data; + + pw_loop_add_source(data.l, &data.a->source); + pw_loop_add_source(data.l, &data.b->source); + + write(data.a->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + write(data.b->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + + pw_main_loop_run(data.ml); + pw_main_loop_destroy(data.ml); + + pw_deinit(); + + free(data.a); + free(data.b); + + return PWTEST_PASS; +} + +static void +on_event_recurse2(struct spa_source *source) +{ + static bool first = true; + struct data *d = source->data; + uint64_t val; + + ++d->count; + pwtest_int_lt(d->count, 3); + + read(source->fd, &val, sizeof(val)); + + if (first) { + first = false; + pw_loop_enter(d->l); + pw_loop_iterate(d->l, -1); + pw_loop_leave(d->l); + } else { + pw_loop_remove_source(d->l, &d->a->source); + pw_loop_remove_source(d->l, &d->b->source); + close(d->a->source.fd); + close(d->b->source.fd); + free(d->a); + free(d->b); + } + pw_main_loop_quit(d->ml); +} + +PWTEST(pwtest_loop_recurse2) +{ + struct data data; + + pw_init(0, NULL); + + spa_zero(data); + data.ml = pw_main_loop_new(NULL); + pwtest_ptr_notnull(data.ml); + + data.l = pw_main_loop_get_loop(data.ml); + pwtest_ptr_notnull(data.l); + + data.a = calloc(1, sizeof(*data.a)); + data.b = calloc(1, sizeof(*data.b)); + + data.a->source.func = on_event_recurse2; + data.a->source.fd = eventfd(0, 0); + data.a->source.mask = SPA_IO_IN; + data.a->source.data = &data; + data.b->source.func = on_event_recurse2; + data.b->source.fd = eventfd(0, 0); + data.b->source.mask = SPA_IO_IN; + data.b->source.data = &data; + + pw_loop_add_source(data.l, &data.a->source); + pw_loop_add_source(data.l, &data.b->source); + + write(data.a->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + write(data.b->source.fd, &(uint64_t){1}, sizeof(uint64_t)); + + pw_main_loop_run(data.ml); + pw_main_loop_destroy(data.ml); + + pw_deinit(); + + return PWTEST_PASS; +} + +PWTEST_SUITE(support) +{ + pwtest_add(pwtest_loop_destroy2, PWTEST_NOARG); + pwtest_add(pwtest_loop_recurse1, PWTEST_NOARG); + pwtest_add(pwtest_loop_recurse2, PWTEST_NOARG); + + return PWTEST_PASS; +}
View file
pipewire-0.3.45.tar.gz/test/test-pwtest.c -> pipewire-0.3.47.tar.gz/test/test-pwtest.c
Changed
@@ -32,7 +32,7 @@ PWTEST(compat_sigabbrev_np) { -#if !HAVE_SIGABBREV_NP +#ifndef HAVE_SIGABBREV_NP pwtest_str_eq(sigabbrev_np(SIGABRT), "ABRT"); pwtest_str_eq(sigabbrev_np(SIGSEGV), "SEGV"); pwtest_str_eq(sigabbrev_np(SIGSTOP), "STOP");
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
.