Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 3
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,10 @@ ------------------------------------------------------------------- +Fri Feb 4 06:41:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.45 + * Add explicit pipewire-spa-plugins-0_2 Requires. + +------------------------------------------------------------------- Sun Jan 30 16:36:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.44
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.44 +Version: 0.3.45 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT @@ -16,7 +16,7 @@ BuildRequires: c++_compiler BuildRequires: c_compiler -BuildRequires: meson >= 0.49.0 +BuildRequires: meson >= 0.59.0 BuildRequires: pkgconfig BuildRequires: pkgconfig(bluez) BuildRequires: pkgconfig(dbus-1) @@ -24,6 +24,7 @@ BuildRequires: pkgconfig(sbc) Requires: pipewire >= %{version} +Requires: pipewire-spa-plugins-%{soversion} >= %{version} Supplements: (pipewire and pipewire-spa-plugins-%{soversion}) %description
View file
pipewire-0.3.44.tar.gz/.gitlab-ci.yml -> pipewire-0.3.45.tar.gz/.gitlab-ci.yml
Changed
@@ -18,18 +18,23 @@ - project: 'freedesktop/ci-templates' ref: *templates_sha file: '/templates/ubuntu.yml' + - project: 'freedesktop/ci-templates' + ref: *templates_sha + file: '/templates/alpine.yml' .fedora: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2022-01-27.1' + FDO_DISTRIBUTION_TAG: '2022-01-28.0' FDO_DISTRIBUTION_VERSION: '35' FDO_DISTRIBUTION_PACKAGES: >- alsa-lib-devel + avahi-devel bluez-libs-devel clang dbus-devel doxygen + fdk-aac-free-devel findutils gcc gcc-c++ @@ -39,10 +44,15 @@ gstreamer1-devel gstreamer1-plugins-base-devel jack-audio-connection-kit-devel + libcanberra-devel + libldac-devel libsndfile-devel + libusb-devel + lilv-devel libv4l-devel libva-devel libX11-devel + openssl-devel pulseaudio-libs-devel python3-docutils sbc-devel @@ -90,6 +100,39 @@ FDO_DISTRIBUTION_EXEC: >- pip3 install meson +.alpine: + variables: + # Update this tag when you want to trigger a rebuild + FDO_DISTRIBUTION_TAG: '2022-01-28.2' + FDO_DISTRIBUTION_VERSION: '3.15' + FDO_DISTRIBUTION_PACKAGES: >- + alsa-lib-dev + avahi-dev + bash + bluez-dev + gcc + g++ + dbus-dev + doxygen + eudev-dev + fdk-aac-dev + git + glib-dev + graphviz + gst-plugins-base-dev + gstreamer-dev + jack-dev + libfreeaptx-dev + libusb-dev + libx11-dev + meson + ncurses-dev + pulseaudio-dev + readline-dev + sbc-dev + vulkan-loader-dev + xmltoman + .coverity: variables: FDO_REPO_SUFFIX: 'coverity' @@ -154,6 +197,14 @@ variables: GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image +container_alpine: + extends: + - .alpine + - .fdo.container-build@alpine + stage: container + variables: + GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image + container_coverity: extends: - .fedora @@ -202,6 +253,26 @@ - build-*/meson-logs - prefix-* +build_on_alpine: + extends: + - .alpine + - .not_coverity + - .fdo.distribution-image@alpine + - .build + stage: build + +# build with all auto() options enabled +build_all: + extends: + - .build_on_fedora + variables: + # Fedora doesn't have libfreeaptx or roc + # libcamera has no stable API, so let's not chase that target + MESON_OPTIONS: "-Dauto_features=enabled -Dbluez5-codec-aptx=disabled -Droc=disabled -Dlibcamera=disabled" + parallel: + matrix: + - CC: [gcc, clang] + # build with all options on auto() or their default values build_with_no_commandline_options: extends:
View file
pipewire-0.3.44.tar.gz/NEWS -> pipewire-0.3.45.tar.gz/NEWS
Changed
@@ -1,3 +1,70 @@ +# PipeWire 0.3.45 (2022-02-03) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Zoom, telegram and other apps should be able to play sound again. + - Implement a better way to force and lock JACK buffersize. + - Default sink and source names and properties are improved. + - The config loader can now load and merge fragments in conf.d directories + for easier user configuration of config files. + - Many small bug fixes and improvements. + +## PipeWire + - pw-cli can now also send Commands to nodes. This can be used to Suspend + a device, for example. + - The eventfd was removed from loops and invoke is now used to stop the loop, + this saves an fd. + - New Alpine CI target to test musl builds, various build fixes. + - Add force-quantum and force-rate properties. + - The config loader can now load and merge fragments in conf.d directories. + (#207) + - resource error methods can be called without a resource and then just + log an error message. + - link-factory can now also work from the config. (#2095) + +## modules + - module-simple-protocol has better argument parsing and can handle + channelmap now. (#2068) It's also possible to configure latency and + rate. + - The native protocol now does extra checks for invalid data. (#2070) + +## ALSA + - TI2902 chips as found in various Behringer cards should have inputs + again. + - Better handling of busy devices in udev, retry when the inotify close + event is emited. + +## SPA + - plugins now handle alignment properly and only expect the max alignment + required for the CPU. (#2074) + +## Bluetooth + - SBC-XQ is now enabled for the JBL Endurance RUN BT headset. + - Support for non-hexadecimal XAPL version strings to improve compatibility. + - Use HCI commands again to probe the adapter msbc capability. This improves + compatibility with some adapters. (#2030) + - Set the right startup volume. + - Better A2DP source idle handling. + - Fix a timer bug in SCO sink that could cause busy looping. + +## pulse-server + - A playback issue when the tlength > maxlength was fixed. (#2069) This + affected Zoom and other applications. + - The STREAM_BUFFER_ATTR command is now implemented. + - Module names are improved. (#2076) + - Many small fixes and improvements. + - Fix a pavucontrol crash with invalid channels. (#1442) + +## JACK + - Use the new force-quantum and force-rate properties in the JACK API to + 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 @@ -133,9 +200,6 @@ properties can also be configured. - Fix a regression in telegram sounds not playing. - -Older versions: - # PipeWire 0.3.43 (2022-01-05) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.44.tar.gz/meson.build -> pipewire-0.3.45.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', ['c' ], - version : '0.3.44', + version : '0.3.45', license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ], meson_version : '>= 0.59.0', default_options : [ 'warning_level=3', @@ -77,10 +77,12 @@ '-Wmissing-braces', '-Wtype-limits', '-Wvariadic-macros', + '-Wmaybe-uninitialized', '-Wno-missing-field-initializers', '-Wno-unused-parameter', '-Wno-pedantic', '-Wold-style-declaration', + '-Wdeprecated-declarations', '-Wunused-result', ] @@ -424,10 +426,9 @@ : dependency('', required: false)) # On FreeBSD, libintl library is required for gettext -libintl_dep = dependency('intl', required: false) - +libintl_dep = cc.find_library('intl', required: false) if not libintl_dep.found() - libintl_dep = cc.find_library('intl', required: false) + libintl_dep = dependency('intl', required: false) endif summary({'intl support': libintl_dep.found()}, bool_yn: true)
View file
pipewire-0.3.44.tar.gz/pipewire-jack/src/match-rules.c -> pipewire-0.3.45.tar.gz/pipewire-jack/src/match-rules.c
Changed
@@ -89,7 +89,7 @@ } 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, int len), + int (*matched) (void *data, const char *action, const char *val, size_t len), void *data) { const char *val;
View file
pipewire-0.3.44.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.45.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -274,6 +274,7 @@ struct metadata { struct pw_metadata *proxy; + struct spa_hook proxy_listener; struct spa_hook listener; char default_audio_sink[1024]; @@ -862,6 +863,8 @@ pw_log_warn("sync requested from callback"); return 0; } + if (client->error) + return client->last_res; client->pending_sync = pw_proxy_sync((struct pw_proxy*)client->core, client->pending_sync); @@ -2593,6 +2596,26 @@ .property = metadata_property }; +static void metadata_proxy_removed(void *data) +{ + struct client *c = data; + pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy); +} + +static void metadata_proxy_destroy(void *data) +{ + struct client *c = data; + spa_hook_remove(&c->metadata->proxy_listener); + spa_hook_remove(&c->metadata->listener); + c->metadata = NULL; +} + +static const struct pw_proxy_events metadata_proxy_events = { + PW_VERSION_PROXY_EVENTS, + .removed = metadata_proxy_removed, + .destroy = metadata_proxy_destroy, +}; + static void proxy_removed(void *data) { struct object *o = data; @@ -2917,6 +2940,9 @@ c->metadata->default_audio_sink[0] = '\0'; c->metadata->default_audio_source[0] = '\0'; + pw_proxy_add_listener(proxy, + &c->metadata->proxy_listener, + &metadata_proxy_events, c); pw_metadata_add_listener(proxy, &c->metadata->listener, &metadata_events, c); @@ -3069,6 +3095,19 @@ 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, @@ -3126,22 +3165,15 @@ client->allow_mlock = client->context.context->settings.mem_allow_mlock; client->warn_mlock = client->context.context->settings.mem_warn_mlock; - if ((str = pw_context_get_conf_section(client->context.context, - "jack.properties")) != NULL) - pw_properties_update_string(client->props, str, strlen(str)); + pw_context_conf_update_props(client->context.context, + "jack.properties", client->props); if ((str = getenv("PIPEWIRE_PROPS")) != NULL) pw_properties_update_string(client->props, str, strlen(str)); - if ((str = pw_context_get_conf_section(client->context.context, - "jack.rules")) != NULL) { - const struct pw_properties *p = - pw_context_get_properties(client->context.context); - if (p != NULL) - pw_jack_match_rules(str, strlen(str), &p->dict, - execute_match, client); - } + pw_context_conf_section_for_each(client->context.context, "jack.rules", + apply_jack_rules, 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); @@ -3973,6 +4005,7 @@ 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; c->info.props = &c->props->dict;
View file
pipewire-0.3.44.tar.gz/spa/include/spa/monitor/type-info.h -> pipewire-0.3.45.tar.gz/spa/include/spa/monitor/type-info.h
Changed
@@ -45,7 +45,7 @@ #define SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE SPA_TYPE_INFO_DeviceEventId ":" static const struct spa_type_info spa_type_device_event_id[] = { - { SPA_DEVICE_EVENT_ObjectConfig, SPA_TYPE_Int, SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE "ObjectConfig", NULL }, + { SPA_DEVICE_EVENT_ObjectConfig, SPA_TYPE_EVENT_Device, SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE "ObjectConfig", NULL }, { 0, 0, NULL, NULL }, };
View file
pipewire-0.3.44.tar.gz/spa/include/spa/node/type-info.h -> pipewire-0.3.45.tar.gz/spa/include/spa/node/type-info.h
Changed
@@ -61,10 +61,10 @@ #define SPA_TYPE_INFO_NODE_EVENT_BASE SPA_TYPE_INFO_NodeEvent ":" static const struct spa_type_info spa_type_node_event_id[] = { - { SPA_NODE_EVENT_Error, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL }, - { SPA_NODE_EVENT_Buffering, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL }, - { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL }, - { SPA_NODE_EVENT_RequestProcess, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestProcess", NULL }, + { SPA_NODE_EVENT_Error, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL }, + { SPA_NODE_EVENT_Buffering, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL }, + { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL }, + { SPA_NODE_EVENT_RequestProcess, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestProcess", NULL }, { 0, 0, NULL, NULL }, }; @@ -77,17 +77,17 @@ #define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":" static const struct spa_type_info spa_type_node_command_id[] = { - { SPA_NODE_COMMAND_Suspend, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL }, - { SPA_NODE_COMMAND_Pause, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL }, - { SPA_NODE_COMMAND_Start, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL }, - { SPA_NODE_COMMAND_Enable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL }, - { SPA_NODE_COMMAND_Disable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL }, - { SPA_NODE_COMMAND_Flush, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL }, - { SPA_NODE_COMMAND_Drain, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL }, - { SPA_NODE_COMMAND_Marker, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL }, - { SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL }, - { SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL }, - { SPA_NODE_COMMAND_RequestProcess, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "RequestProcess", NULL }, + { SPA_NODE_COMMAND_Suspend, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL }, + { SPA_NODE_COMMAND_Pause, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL }, + { SPA_NODE_COMMAND_Start, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL }, + { SPA_NODE_COMMAND_Enable, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL }, + { SPA_NODE_COMMAND_Disable, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL }, + { SPA_NODE_COMMAND_Flush, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL }, + { SPA_NODE_COMMAND_Drain, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL }, + { SPA_NODE_COMMAND_Marker, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL }, + { SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL }, + { SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL }, + { SPA_NODE_COMMAND_RequestProcess, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "RequestProcess", NULL }, { 0, 0, NULL, NULL }, };
View file
pipewire-0.3.44.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules -> pipewire-0.3.45.tar.gz/spa/plugins/alsa/90-pipewire-alsa.rules
Changed
@@ -113,7 +113,7 @@ ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{ACP_PROFILE_SET}="sb-omni-surround-5.1.conf" ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf" ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="402e", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf" -#ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf" +ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf" ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0269", ENV{ACP_PROFILE_SET}="hp-tbt-dock-120w-g2.conf" ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0567", ENV{ACP_PROFILE_SET}="hp-tbt-dock-audio-module.conf"
View file
pipewire-0.3.44.tar.gz/spa/plugins/alsa/alsa-udev.c -> pipewire-0.3.45.tar.gz/spa/plugins/alsa/alsa-udev.c
Changed
@@ -29,6 +29,7 @@ #include <sys/stat.h> #include <sys/inotify.h> #include <fcntl.h> +#include <dirent.h> #include <libudev.h> #include <alsa/asoundlib.h> @@ -47,9 +48,6 @@ #define MAX_DEVICES 64 -#define RETRY_COUNT 1 -#define RETRY_MSEC 2000 - #define ACTION_ADD 0 #define ACTION_REMOVE 1 #define ACTION_DISABLE 2 @@ -57,7 +55,7 @@ struct device { uint32_t id; struct udev_device *dev; - uint8_t retry; + unsigned int unavailable:1; unsigned int accessible:1; unsigned int ignored:1; unsigned int emitted:1; @@ -84,7 +82,6 @@ struct spa_source source; struct spa_source notify; - struct spa_source retry_timer; unsigned int use_acp:1; }; @@ -184,7 +181,7 @@ { const char *s; char *d; - int h1, h2; + int h1 = 0, h2 = 0; enum { TEXT, BACKSLASH, EX, FIRST } state = TEXT; for (s = src, d = dst; *s; s++) { @@ -249,37 +246,94 @@ *d = 0; } -static int check_device_busy(struct impl *this, struct device *device, snd_ctl_t *ctl_hndl) +static int check_device_available(struct impl *this, struct device *device, int *num_pcm) { - int dev; + char path[PATH_MAX]; + DIR *card = NULL, *pcm = NULL; + FILE *f; + char buf[16]; + size_t sz; + struct dirent *entry, *entry_pcm; + int res; + + /* + * 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. + */ + + *num_pcm = 0; - /* Check if some pcm devices of the card cannot be opened because they are busy */ + spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id); - for (dev = -1; snd_ctl_pcm_next_device(ctl_hndl, &dev) >= 0 && dev >= 0;) { - char devpath[64]; - int i; + if ((card = opendir(path)) == NULL) + goto done; - snprintf(devpath, sizeof(devpath), "hw:%u,%u", device->id, dev); + while ((errno = 0, entry = readdir(card)) != NULL) { + if (!(entry->d_type == DT_DIR && + spa_strstartswith(entry->d_name, "pcm"))) + continue; - for (i = 0; i < 2; ++i) { - snd_pcm_t *handle; - int res; + /* Check device class */ + spa_scnprintf(path, sizeof(path), "/sys/class/sound/pcmC%uD%s/pcm_class", + (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")) + continue; - res = snd_pcm_open(&handle, devpath, - (i == 0) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE, - SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE | - SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT); - if (res == -EBUSY) { - spa_log_debug(this->log, "pcm device %s busy", devpath); - return -EBUSY; - } else if (res >= 0) { - snd_pcm_close(handle); + /* Check busy status */ + spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s", + (unsigned int)device->id, entry->d_name); + if ((pcm = opendir(path)) == NULL) + goto done; + + while ((errno = 0, entry_pcm = readdir(pcm)) != NULL) { + if (!(entry_pcm->d_type == DT_DIR && + spa_strstartswith(entry_pcm->d_name, "sub"))) + continue; + + spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s/%s/status", + (unsigned int)device->id, entry->d_name, entry_pcm->d_name); + + f = fopen(path, "r"); + if (f == NULL) + goto done; + sz = fread(buf, 1, 6, f); + buf[sz] = '\0'; + fclose(f); + + 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; + goto done; } + spa_log_debug(this->log, "card %u pcm device %s free", + (unsigned int)device->id, entry->d_name); } - spa_log_debug(this->log, "pcm device %s free", devpath); - } + if (errno != 0) + goto done; - return 0; + ++*num_pcm; + + closedir(pcm); + pcm = NULL; + } + if (errno != 0) + goto done; + +done: + res = -errno; + if (card) + closedir(card); + if (pcm) + closedir(pcm); + return res; } static int emit_object_info(struct impl *this, struct device *device) @@ -287,42 +341,28 @@ struct spa_device_object_info info; uint32_t id = device->id; struct udev_device *dev = device->dev; - snd_ctl_t *ctl_hndl; const char *str; char path[32], *cn = NULL, *cln = NULL; struct spa_dict_item items[25]; uint32_t n_items = 0; int res, pcm; - snprintf(path, sizeof(path), "hw:%u", id); - spa_log_debug(this->log, "open card %s", path); + /* + * inotify close events under /dev/snd must not be emitted, except after setting + * device->emitted to true. alsalib functions can be used after that. + */ - if ((res = snd_ctl_open(&ctl_hndl, path, 0)) < 0) { - spa_log_error(this->log, "can't open control for card %s: %s", - path, snd_strerror(res)); + if ((res = check_device_available(this, device, &pcm)) < 0) return res; - } - - pcm = -1; - res = snd_ctl_pcm_next_device(ctl_hndl, &pcm); - - if (res < 0) { - spa_log_error(this->log, "error iterating devices: %s", snd_strerror(res)); - device->ignored = true; - } else if (pcm < 0) { + if (pcm == 0) { spa_log_debug(this->log, "no pcm devices for %s", path); device->ignored = true; - res = 0; - } else if (device->retry > 0) { - /* Check if we can open all PCM devices (retry later if not) */ - res = check_device_busy(this, device, ctl_hndl);
View file
pipewire-0.3.44.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf -> pipewire-0.3.45.tar.gz/spa/plugins/alsa/mixer/profile-sets/texas-instruments-pcm2902.conf
Changed
@@ -16,12 +16,15 @@ ; Texas Instruments PCM2902 ; ; This is a generic chip used in multiple products, including at least -; Behringer U-Phoria UMC22, Intopic Jazz-UB700 and some unbranded "usb mini -; microphone". +; Behringer U-Phoria UMC22, 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. ; +; Some devices have a mic input path, but at least Behringer Xenyx 302USB +; doesn't have any input mixer controls. +; ; Since the UMC22 card has only stereo input PCM device but is commonly used ; with mono mics, we define special mono mappings using "mono,aux1" and ; "aux1,mono" channel maps. If we had only had the standard stereo input @@ -40,28 +43,28 @@ [Mapping analog-stereo-input] device-strings = hw:%f channel-map = left,right -paths-input = analog-input-mic +paths-input = analog-input-mic analog-input direction = input priority = 4 [Mapping analog-mono] device-strings = hw:%f channel-map = mono -paths-input = analog-input-mic +paths-input = analog-input-mic analog-input direction = input priority = 3 [Mapping analog-mono-left] device-strings = hw:%f channel-map = mono,aux1 -paths-input = analog-input-mic +paths-input = analog-input-mic analog-input direction = input priority = 2 [Mapping analog-mono-right] device-strings = hw:%f channel-map = aux1,mono -paths-input = analog-input-mic +paths-input = analog-input-mic analog-input direction = input priority = 1
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix-ops.h -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/channelmix-ops.h
Changed
@@ -93,6 +93,8 @@ uint32_t n_src, const void * SPA_RESTRICT src[n_src], \ uint32_t n_samples); +#define CHANNELMIX_OPS_MAX_ALIGN 16 + DEFINE_FUNCTION(copy, c); DEFINE_FUNCTION(f32_n_m, c); DEFINE_FUNCTION(f32_1_2, c);
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/channelmix.c
Changed
@@ -50,6 +50,7 @@ #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS +#define MAX_ALIGN CHANNELMIX_OPS_MAX_ALIGN #define DEFAULT_CONTROL_BUFFER_SIZE 32768 @@ -164,6 +165,7 @@ unsigned int started:1; unsigned int is_passthrough:1; uint32_t cpu_flags; + uint32_t max_align; }; #define IS_CONTROL_PORT(this,d,id) (id == 1 && d == SPA_DIRECTION_INPUT) @@ -1207,7 +1209,7 @@ buffers[i]); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[j].data, 16)) { + if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) { spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned", this, j, i); } @@ -1559,8 +1561,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } spa_hook_list_init(&this->hooks);
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmt-ops.h -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/fmt-ops.h
Changed
@@ -200,6 +200,8 @@ void conv_##name##_##arch(struct convert *conv, void * SPA_RESTRICT dst[], \ const void * SPA_RESTRICT src[], uint32_t n_samples) \ +#define FMT_OPS_MAX_ALIGN 32 + DEFINE_FUNCTION(copy8d, c); DEFINE_FUNCTION(copy8, c); DEFINE_FUNCTION(copy16d, c);
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmtconvert.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/fmtconvert.c
Changed
@@ -53,7 +53,7 @@ #define DEFAULT_CHANNELS 2 #define MAX_BUFFERS 32 -#define MAX_ALIGN 16 +#define MAX_ALIGN FMT_OPS_MAX_ALIGN #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS #define PROP_DEFAULT_TRUNCATE false @@ -118,6 +118,7 @@ struct spa_log *log; struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t max_align; uint32_t quantum_limit; struct spa_io_position *io_position; @@ -812,7 +813,7 @@ this, j, i); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) { + if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) { spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned", this, j, i); } @@ -1091,8 +1092,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key;
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/merger.c
Changed
@@ -55,7 +55,7 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define MAX_ALIGN 16 +#define MAX_ALIGN FMT_OPS_MAX_ALIGN #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS #define MAX_PORTS SPA_AUDIO_MAX_CHANNELS @@ -146,6 +146,7 @@ struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t max_align; uint32_t quantum_limit; struct spa_io_position *io_position; @@ -1265,7 +1266,7 @@ this, j, i, d[j].type, d[j].data); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) { + if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) { spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned", this, j, i); } @@ -1576,8 +1577,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key;
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/resample.c
Changed
@@ -48,7 +48,6 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 -#define MAX_ALIGN 16 #define MAX_BUFFERS 32 struct impl;
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/splitter.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/splitter.c
Changed
@@ -53,7 +53,7 @@ #define DEFAULT_CHANNELS 2 #define DEFAULT_MASK (1LL << SPA_AUDIO_CHANNEL_FL) | (1LL << SPA_AUDIO_CHANNEL_FR) -#define MAX_ALIGN 16 +#define MAX_ALIGN FMT_OPS_MAX_ALIGN #define MAX_BUFFERS 32 #define MAX_DATAS SPA_AUDIO_MAX_CHANNELS #define MAX_PORTS SPA_AUDIO_MAX_CHANNELS @@ -107,6 +107,7 @@ struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t max_align; uint32_t quantum_limit; struct spa_io_position *io_position; @@ -916,7 +917,7 @@ this, j, i, d[j].type, d[j].data); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) { + if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) { spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned", this, j, i); } @@ -1164,8 +1165,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key;
View file
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/volume-ops.h -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/volume-ops.h
Changed
@@ -56,6 +56,8 @@ const void * SPA_RESTRICT src, \ float volume, uint32_t n_samples); +#define VOLUME_OPS_MAX_ALIGN 16 + DEFINE_FUNCTION(f32, c); #if defined (HAVE_SSE)
View file
pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.45.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -48,6 +48,7 @@ #define MAX_BUFFERS 64 #define MAX_PORTS 128 #define MAX_CHANNELS 64 +#define MAX_ALIGN MIX_OPS_MAX_ALIGN #define PORT_DEFAULT_VOLUME 1.0 #define PORT_DEFAULT_MUTE false @@ -103,6 +104,7 @@ struct spa_log *log; struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t max_align; uint32_t quantum_limit; struct mix_ops ops; @@ -658,7 +660,7 @@ buffers[i]); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[0].data, 16)) { + if (!SPA_IS_ALIGNED(d[0].data, this->max_align)) { spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i); } if (direction == SPA_DIRECTION_OUTPUT) @@ -888,8 +890,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key;
View file
pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/mix-ops.h -> pipewire-0.3.45.tar.gz/spa/plugins/audiomixer/mix-ops.h
Changed
@@ -125,6 +125,8 @@ const void * SPA_RESTRICT src[], uint32_t n_src, \ uint32_t n_samples) \ +#define MIX_OPS_MAX_ALIGN 32 + DEFINE_FUNCTION(s8, c); DEFINE_FUNCTION(u8, c); DEFINE_FUNCTION(s16, c);
View file
pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.45.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
@@ -47,7 +47,7 @@ #define MAX_BUFFERS 64 #define MAX_PORTS 128 -#define MAX_ALIGN 64 +#define MAX_ALIGN MIX_OPS_MAX_ALIGN #define PORT_DEFAULT_VOLUME 1.0 #define PORT_DEFAULT_MUTE false @@ -103,6 +103,7 @@ struct spa_log *log; struct spa_cpu *cpu; uint32_t cpu_flags; + uint32_t max_align; uint32_t quantum_limit; @@ -604,7 +605,7 @@ spa_log_error(this->log, "%p: invalid memory on buffer %d", this, i); return -EINVAL; } - if (!SPA_IS_ALIGNED(d[0].data, 32)) { + if (!SPA_IS_ALIGNED(d[0].data, this->max_align)) { spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i); } if (direction == SPA_DIRECTION_OUTPUT) @@ -831,8 +832,10 @@ spa_log_topic_init(this->log, log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); - if (this->cpu) + if (this->cpu) { this->cpu_flags = spa_cpu_get_flags(this->cpu); + this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu)); + } for (i = 0; info && i < info->n_items; i++) { const char *k = info->items[i].key;
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -201,12 +201,6 @@ td = t->user_data; td->rfcomm = rfcomm; - for (int i = 0; i < SPA_BT_VOLUME_ID_TERM ; ++i) { - rfcomm->volumes[i].hw_volume = SPA_BT_VOLUME_INVALID; - t->volumes[i].active = rfcomm->volumes[i].active; - t->volumes[i].hw_volume_max = SPA_BT_VOLUME_HS_MAX; - } - if (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY) { t->volumes[SPA_BT_VOLUME_ID_RX].volume = DEFAULT_AG_VOLUME; t->volumes[SPA_BT_VOLUME_ID_TX].volume = DEFAULT_AG_VOLUME; @@ -215,6 +209,14 @@ t->volumes[SPA_BT_VOLUME_ID_TX].volume = DEFAULT_TX_VOLUME; } + for (int i = 0; i < SPA_BT_VOLUME_ID_TERM ; ++i) { + t->volumes[i].active = rfcomm->volumes[i].active; + t->volumes[i].hw_volume_max = SPA_BT_VOLUME_HS_MAX; + if (rfcomm->volumes[i].active && rfcomm->volumes[i].hw_volume != SPA_BT_VOLUME_INVALID) + t->volumes[i].volume = + spa_bt_volume_hw_to_linear(rfcomm->volumes[i].hw_volume, t->volumes[i].hw_volume_max); + } + spa_bt_transport_add_listener(t, &rfcomm->transport_listener, &transport_events, rfcomm); finish: @@ -550,11 +552,10 @@ #ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE -static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapter, bool msbc); - static bool device_supports_required_mSBC_transport_modes( - struct impl *backend, struct spa_bt_device *device) { - int sock; + struct impl *backend, struct spa_bt_device *device) +{ + int res; bool msbc_ok, msbc_alt1_ok; uint32_t bt_features; @@ -575,43 +576,20 @@ if (!msbc_ok && !msbc_alt1_ok) return false; - /* - * Check if adapter supports BT_VOICE_TRANSPARENT. Do this without - * directly probing HCI properties. - */ - sock = sco_create_socket(backend, device->adapter, true); - if (sock < 0) { + res = spa_bt_adapter_has_msbc(device->adapter); + if (res < 0) { + spa_log_warn(backend->log, + "adapter %s: failed to determine msbc/esco capability (%d)", + device->adapter->path, res); + } else if (res == 0) { + spa_log_info(backend->log, + "adapter %s: no msbc/esco transport", + device->adapter->path); return false; } else { - struct sockaddr_sco addr; - socklen_t len; - int res; - - /* Connect to non-existent address */ - len = sizeof(addr); - memset(&addr, 0, len); - addr.sco_family = AF_BLUETOOTH; - bacpy(&addr.sco_bdaddr, BDADDR_LOCAL); - - spa_log_debug(backend->log, "connect to determine adapter msbc support..."); - - /* Linux kernel code checks for features needed for BT_VOICE_TRANSPARENT - * among the first checks it does, and fails with EOPNOTSUPP if not - * supported. The connection generally timeouts, so set it - * nonblocking since we are just checking. - */ - fcntl(sock, F_SETFL, O_NONBLOCK); - res = connect(sock, (struct sockaddr *) &addr, len); - if (res < 0) - res = errno; - else - res = 0; - close(sock); - - spa_log_debug(backend->log, "determined adapter-msbc:%d res:%d", - (res != EOPNOTSUPP), res); - if (res == EOPNOTSUPP) - return false; + spa_log_debug(backend->log, + "adapter %s: has msbc/esco transport", + device->adapter->path); } /* Check if USB ALT6 is really available on the device */ @@ -705,7 +683,6 @@ unsigned int indicator_value; int xapl_vendor; int xapl_product; - int xapl_version; int xapl_features; if (sscanf(buf, "AT+BRSF=%u", &features) == 1) { @@ -889,7 +866,7 @@ rfcomm_send_reply(rfcomm, "OK"); } else if (sscanf(buf, "AT+BIEV=%u,%u", &indicator, &indicator_value) == 2) { process_hfp_hf_indicator(rfcomm, indicator, indicator_value); - } else if (sscanf(buf, "AT+XAPL=%04x-%04x-%04x,%u", &xapl_vendor, &xapl_product, &xapl_version, &xapl_features) == 4) { + } else if (sscanf(buf, "AT+XAPL=%04x-%04x-%*[^,],%u", &xapl_vendor, &xapl_product, &xapl_features) == 3) { if (xapl_features & SPA_BT_HFP_HF_XAPL_FEATURE_BATTERY_REPORTING) { /* claim, that we support battery status reports */ rfcomm_send_reply(rfcomm, "+XAPL=iPhone,%u", SPA_BT_HFP_HF_XAPL_FEATURE_BATTERY_REPORTING); @@ -1155,6 +1132,7 @@ { struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this); struct spa_bt_device *d = t->device; + struct transport_data *td = t->user_data; struct sockaddr_sco addr; socklen_t len; int err; @@ -1189,6 +1167,21 @@ goto again; } else if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) { spa_log_error(backend->log, "connect(): %s", strerror(errno)); +#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE + if (errno == EOPNOTSUPP && t->codec == HFP_AUDIO_CODEC_MSBC && + td->rfcomm->msbc_supported_by_hfp) { + /* Adapter doesn't support msbc. Renegotiate. */ + d->adapter->msbc_probed = true; + d->adapter->has_msbc = false; + td->rfcomm->msbc_supported_by_hfp = false; + if (t->profile == SPA_BT_PROFILE_HFP_HF) { + td->rfcomm->hfp_ag_switching_codec = true; + rfcomm_send_reply(td->rfcomm, "+BCS: 1"); + } else if (t->profile == SPA_BT_PROFILE_HFP_AG) { + rfcomm_send_cmd(td->rfcomm, "AT+BAC=1"); + } + } +#endif goto fail_close; } @@ -1209,10 +1202,6 @@ spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t); -#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE - rfcomm_hfp_ag_set_cind(td->rfcomm, true); -#endif - if (optional || t->fd > 0) sock = t->fd; else @@ -1221,6 +1210,10 @@ if (sock < 0) goto fail; +#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE + rfcomm_hfp_ag_set_cind(td->rfcomm, true); +#endif + t->fd = sock; /* Fallback value */
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez-hardware.conf -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/bluez-hardware.conf
Changed
@@ -34,7 +34,7 @@ { name = "BAA 100", no-features = [ hw-volume ] }, # Buxton BAA 100, doesn't remember volume, #pipewire-1449 { name = "D50s", address = "~^00:13:ef:", no-features = [ hw-volume ] }, # volume has no effect, #pipewire-1562 { name = "FiiO BTR3", address = "~^40:ed:98:", no-features = [ faststream ] }, # #pipewire-1658 - { name = "JBL Endurance RUN BT", no-features = [ msbc-alt1, msbc-alt1-rtl, sbc-xq ] }, + { name = "JBL Endurance RUN BT", no-features = [ msbc-alt1, msbc-alt1-rtl ] }, { name = "JBL LIVE650BTNC" }, { name = "Motorola DC800", no-features = [ sbc-xq ] }, # #pipewire-1590 { name = "Motorola S305", no-features = [ sbc-xq ] }, # #pipewire-1590
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -1823,6 +1823,8 @@ spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_IDLE); + spa_bt_transport_keepalive(transport, false); + spa_bt_transport_emit_destroy(transport); spa_bt_transport_stop_volume_timer(transport); @@ -1857,6 +1859,23 @@ free(transport); } +int spa_bt_transport_keepalive(struct spa_bt_transport *t, bool keepalive) +{ + if (keepalive) { + t->keepalive = true; + return 0; + } + + t->keepalive = false; + + if (t->acquire_refcount == 0 && t->acquired) { + t->acquire_refcount = 1; + return spa_bt_transport_release(t); + } + + return 0; +} + int spa_bt_transport_acquire(struct spa_bt_transport *transport, bool optional) { struct spa_bt_monitor *monitor = transport->monitor; @@ -1869,10 +1888,15 @@ } spa_assert(transport->acquire_refcount == 0); - res = spa_bt_transport_impl(transport, acquire, 0, optional); + if (!transport->acquired) + res = spa_bt_transport_impl(transport, acquire, 0, optional); + else + res = 0; - if (res >= 0) + if (res >= 0) { transport->acquire_refcount = 1; + transport->acquired = true; + } return res; } @@ -1892,14 +1916,22 @@ return 0; } spa_assert(transport->acquire_refcount == 1); + spa_assert(transport->acquired); if (SPA_BT_TRANSPORT_IS_SCO(transport)) { /* Postpone SCO transport releases, since we might need it again soon */ res = spa_bt_transport_start_release_timer(transport); + } else if (transport->keepalive) { + res = 0; + transport->acquire_refcount = 0; + spa_log_debug(monitor->log, "transport %p: keepalive %s on release", + transport, transport->path); } else { res = spa_bt_transport_impl(transport, release, 0); - if (res >= 0) + if (res >= 0) { transport->acquire_refcount = 0; + transport->acquired = false; + } } return res; @@ -1909,13 +1941,15 @@ { int res; - if (transport->acquire_refcount == 0) + if (!transport->acquired) return 0; spa_bt_transport_stop_release_timer(transport); res = spa_bt_transport_impl(transport, release, 0); - if (res >= 0) + if (res >= 0) { transport->acquire_refcount = 0; + transport->acquired = false; + } return res; } @@ -1974,11 +2008,18 @@ struct spa_bt_monitor *monitor = transport->monitor; spa_assert(transport->acquire_refcount >= 1); + spa_assert(transport->acquired); spa_bt_transport_stop_release_timer(transport); if (transport->acquire_refcount == 1) { - spa_bt_transport_impl(transport, release, 0); + if (!transport->keepalive) { + spa_bt_transport_impl(transport, release, 0); + transport->acquired = false; + } else { + spa_log_debug(monitor->log, "transport %p: keepalive %s on release", + transport, transport->path); + } } else { spa_log_debug(monitor->log, "transport %p: delayed decref %s", transport, transport->path); }
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -519,11 +519,13 @@ if (state >= SPA_BT_TRANSPORT_STATE_PENDING && old < SPA_BT_TRANSPORT_STATE_PENDING) { if (!SPA_FLAG_IS_SET(this->id, DYNAMIC_NODE_ID_FLAG)) { SPA_FLAG_SET(this->id, DYNAMIC_NODE_ID_FLAG); + spa_bt_transport_keepalive(t, true); emit_node(impl, t, this->id, this->factory_name, this->a2dp_duplex); } } else if (state < SPA_BT_TRANSPORT_STATE_PENDING && old >= SPA_BT_TRANSPORT_STATE_PENDING) { if (SPA_FLAG_IS_SET(this->id, DYNAMIC_NODE_ID_FLAG)) { SPA_FLAG_CLEAR(this->id, DYNAMIC_NODE_ID_FLAG); + spa_bt_transport_keepalive(t, false); spa_device_emit_object_info(&impl->hooks, this->id, NULL); } }
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/defs.h
Changed
@@ -332,11 +332,13 @@ uint32_t bluetooth_class; uint32_t profiles; int powered; + unsigned int has_msbc:1; + unsigned int msbc_probed:1; unsigned int endpoints_registered:1; unsigned int application_registered:1; unsigned int player_registered:1; - unsigned int has_battery_provider; - unsigned int battery_provider_unavailable; + unsigned int has_battery_provider:1; + unsigned int battery_provider_unavailable:1; }; enum spa_bt_form_factor { @@ -581,6 +583,8 @@ struct spa_bt_transport_volume volumes[SPA_BT_VOLUME_ID_TERM]; int acquire_refcount; + bool acquired; + bool keepalive; int fd; uint16_t read_mtu; uint16_t write_mtu; @@ -610,6 +614,7 @@ int spa_bt_transport_acquire(struct spa_bt_transport *t, bool optional); int spa_bt_transport_release(struct spa_bt_transport *t); +int spa_bt_transport_keepalive(struct spa_bt_transport *t, bool keepalive); int spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop); #define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \ @@ -696,6 +701,8 @@ uint32_t *features); void spa_bt_quirks_destroy(struct spa_bt_quirks *quirks); +int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter); + struct spa_bt_backend_implementation { #define SPA_VERSION_BT_BACKEND_IMPLEMENTATION 0 uint32_t version;
View file
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/hci.c
Added
@@ -0,0 +1,93 @@ +/* Spa HSP/HFP native backend HCI support + * + * Copyright © 2022 Pauli Virtanen + * + * 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 <errno.h> +#include <unistd.h> +#include <stdarg.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <poll.h> +#include <sys/uio.h> +#include <sys/socket.h> + +#include "defs.h" + +#ifndef HAVE_BLUEZ_5_HCI + +int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter) +{ + if (adapter->msbc_probed) + return adapter->has_msbc; + return -EOPNOTSUPP; +} + +#else + +#include <bluetooth/bluetooth.h> +#include <bluetooth/hci.h> +#include <bluetooth/hci_lib.h> + +int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter) +{ + int hci_id, res; + int sock = -1; + uint8_t features[8], max_page = 0; + struct sockaddr_hci a; + const char *str; + + if (adapter->msbc_probed) + return adapter->has_msbc; + + str = strrchr(adapter->path, '/'); /* hciXX */ + if (str == NULL || sscanf(str, "/hci%d", &hci_id) != 1 || hci_id < 0) + return -ENOENT; + + sock = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI); + if (sock < 0) + goto error; + + memset(&a, 0, sizeof(a)); + a.hci_family = AF_BLUETOOTH; + a.hci_dev = hci_id; + if (bind(sock, (struct sockaddr *) &a, sizeof(a)) < 0) + goto error; + + if (hci_read_local_ext_features(sock, 0, &max_page, features, 1000) < 0) + goto error; + + close(sock); + + adapter->msbc_probed = true; + adapter->has_msbc = ((features[2] & LMP_TRSP_SCO) && (features[3] & LMP_ESCO)) ? 1 : 0; + return adapter->has_msbc; + +error: + res = -errno; + if (sock >= 0) + close(sock); + return res; +} + +#endif
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/meson.build
Changed
@@ -20,6 +20,10 @@ 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 + bluez5_sources = [ 'plugin.c', 'codec-loader.c', @@ -32,7 +36,8 @@ 'quirks.c', 'player.c', 'bluez5-device.c', - 'bluez5-dbus.c' + 'bluez5-dbus.c', + 'hci.c' ] bluez5_data = ['bluez-hardware.conf']
View file
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/sco-sink.c
Changed
@@ -269,7 +269,7 @@ static uint64_t get_next_timeout(struct impl *this, uint64_t now_time, uint64_t processed_samples) { struct port *port = &this->port; - uint64_t playback_time = 0, elapsed_time = 0, next_time = 1; + uint64_t playback_time = 0, elapsed_time = 0, next_time = 0; this->total_samples += processed_samples; @@ -380,7 +380,6 @@ { struct port *port = &this->port; struct spa_data *datas; - uint64_t next_timeout = 1; const uint32_t min_in_size = (this->transport->codec == HFP_AUDIO_CODEC_MSBC) ? MSBC_DECODED_SIZE : this->transport->write_mtu; @@ -391,7 +390,8 @@ if (this->transport == NULL || this->transport->sco_io == NULL) return; - if (!spa_list_is_empty(&port->ready)) { +again: + while (!spa_list_is_empty(&port->ready) && port->write_buffer_size < min_in_size) { /* get buffer */ if (!port->current_buffer) { spa_return_if_fail(!spa_list_is_empty(&port->ready)); @@ -434,6 +434,7 @@ int processed = 0; ssize_t out_encoded; int written; + uint64_t next_timeout; spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now); now_time = SPA_TIMESPEC_TO_NSEC(&this->now); @@ -468,7 +469,6 @@ written, spa_strerror(written)); goto stop; } - spa_log_trace(this->log, "wrote socket data %d", written); this->buffer_head += written; @@ -507,17 +507,29 @@ next_timeout = get_next_timeout(this, now_time, processed / port->frame_size); - if (this->clock) { + if (!this->following && this->clock) { this->clock->nsec = now_time; this->clock->position = this->total_samples; this->clock->delay = processed / port->frame_size; this->clock->rate_diff = 1.0f; - this->clock->next_nsec = next_timeout; + this->clock->next_nsec = now_time + next_timeout; } + + if (next_timeout == 0) + goto again; + + spa_log_trace(this->log, "timeout %"PRIu64" ns", next_timeout); + set_timeout(this, next_timeout); + } else { + /* As follower, driver will wake us up when there is data */ + if (this->following) + return; + + /* As driver, run timeout now to schedule data */ + spa_log_trace(this->log, "timeout 1 ns (driver: schedule now)"); + set_timeout(this, 1); } - /* schedule next timeout */ - set_timeout(this, next_timeout); return; stop:
View file
pipewire-0.3.44.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.45.tar.gz/spa/plugins/v4l2/v4l2-udev.c
Changed
@@ -169,7 +169,7 @@ { const char *s; char *d; - int h1, h2; + int h1 = 0, h2 = 0; enum { TEXT, BACKSLASH, EX, FIRST } state = TEXT; for (s = src, d = dst; *s; s++) {
View file
pipewire-0.3.45.tar.gz/src/daemon/filter-chain/duplicate-FL.conf
Added
@@ -0,0 +1,48 @@ +# An example filter chain for duplicating the FL channel +# to FL and FR. +# +# Copy this file into a conf.d/ directory +# +context.modules = [ + { name = libpipewire-module-filter-chain + args = { + node.name = "remap-FL-to-FL-FR" + node.description = "Remap example" + media.name = "Remap example" + filter.graph = { + nodes = [ + { + name = copyIL + type = builtin + label = copy + } + { + name = copyOL + type = builtin + label = copy + } + { + name = copyOR + type = builtin + label = copy + } + ] + links = [ + # we can only tee from nodes, not inputs so we need + # to copy the inputs and then tee. + { output = "copyIL:Out" input = "copyOL:In" } + { output = "copyIL:Out" input = "copyOR:In" } + ] + inputs = [ "copyIL:In" ] + outputs = [ "copyOL:Out" "copyOR:Out" ] + } + capture.props = { + audio.position = [ FL ] + stream.dont-remix = true + } + playback.props = { + audio.position = [ FL FR ] + } + } + } +]
View file
pipewire-0.3.44.tar.gz/src/daemon/filter-chain/meson.build -> pipewire-0.3.45.tar.gz/src/daemon/filter-chain/meson.build
Changed
@@ -1,5 +1,6 @@ conf_files = [ [ 'demonic.conf', 'demonic.conf' ], + [ 'duplicate-FL.conf', 'duplicate-FL.conf' ], [ 'sink-virtual-surround-5.1-kemar.conf', 'sink-virtual-surround-5.1-kemar.conf' ], [ 'sink-virtual-surround-7.1-hesuvi.conf', 'sink-virtual-surround-7.1-hesuvi.conf' ], [ 'sink-dolby-surround.conf', 'sink-dolby-surround.conf' ],
View file
pipewire-0.3.44.tar.gz/src/examples/audio-dsp-filter.c -> pipewire-0.3.45.tar.gz/src/examples/audio-dsp-filter.c
Changed
@@ -79,6 +79,9 @@ in = pw_filter_get_dsp_buffer(data->in_port, n_samples); out = pw_filter_get_dsp_buffer(data->out_port, n_samples); + if (in == NULL || out == NULL) + return; + memcpy(out, in, n_samples * sizeof(float)); }
View file
pipewire-0.3.44.tar.gz/src/examples/audio-dsp-src.c -> pipewire-0.3.45.tar.gz/src/examples/audio-dsp-src.c
Changed
@@ -77,6 +77,8 @@ pw_log_trace("do process %d", n_samples); out = pw_filter_get_dsp_buffer(out_port, n_samples); + if (out == NULL) + return; for (i = 0; i < n_samples; i++) { out_port->accumulator += M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE;
View file
pipewire-0.3.44.tar.gz/src/modules/module-adapter.c -> pipewire-0.3.45.tar.gz/src/modules/module-adapter.c
Changed
@@ -243,21 +243,16 @@ error_properties: res = -EINVAL; - pw_log_error("factory %p: usage: " FACTORY_USAGE, d->this); - if (resource) - pw_resource_errorf_id(resource, new_id, res, "usage: " FACTORY_USAGE); + pw_resource_errorf_id(resource, new_id, res, "usage: " FACTORY_USAGE); goto error_cleanup; error_errno: res = -errno; - pw_log_error("can't create node: %m"); - if (resource) - pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res)); + pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res)); goto error_cleanup; error_usage: res = -EINVAL; pw_log_error("usage: "ADAPTER_USAGE); - if (resource) - pw_resource_errorf_id(resource, new_id, res, "usage: "ADAPTER_USAGE); + pw_resource_errorf_id(resource, new_id, res, "usage: "ADAPTER_USAGE); goto error_cleanup; error_cleanup: pw_properties_free(properties);
View file
pipewire-0.3.44.tar.gz/src/modules/module-client-device/protocol-native.c -> pipewire-0.3.45.tar.gz/src/modules/module-client-device/protocol-native.c
Changed
@@ -32,6 +32,9 @@ #include <pipewire/extensions/protocol-native.h> +#define MAX_DICT 256 +#define MAX_PARAM_INFO 128 + static inline void push_item(struct spa_pod_builder *b, const struct spa_dict_item *item) { const char *str; @@ -55,16 +58,41 @@ return 0; } -static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict) -{ - uint32_t i; - int res; - for (i = 0; i < dict->n_items; i++) { - if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0) - return res; - } - return 0; -} +#define parse_dict(prs,d) \ +do { \ + uint32_t i; \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&(d)->n_items), NULL) < 0) \ + return -EINVAL; \ + if ((d)->n_items > 0) { \ + if ((d)->n_items > MAX_DICT) \ + return -ENOSPC; \ + (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \ + for (i = 0; i < (d)->n_items; i++) { \ + if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) + +#define parse_param_info(prs,n_params,params) \ +do { \ + uint32_t i; \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&(n_params)), NULL) < 0) \ + return -EINVAL; \ + if (n_params > 0) { \ + if (n_params > MAX_PARAM_INFO) \ + return -ENOSPC; \ + params = alloca(n_params * sizeof(struct spa_param_info)); \ + for (i = 0; i < n_params; i++) { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Id(&(params[i]).id), \ + SPA_POD_Int(&(params[i]).flags), NULL) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) static int device_marshal_add_listener(void *object, struct spa_hook *listener, @@ -242,7 +270,6 @@ struct spa_pod *ipod; struct spa_device_info info = SPA_DEVICE_INFO_INIT(), *infop; struct spa_dict props = SPA_DICT_INIT(NULL, 0); - uint32_t i; spa_pod_parser_init(&prs, msg->data, msg->size); @@ -259,34 +286,18 @@ if (spa_pod_parser_push_struct(&p2, &f2) < 0 || spa_pod_parser_get(&p2, SPA_POD_Long(&info.change_mask), - SPA_POD_Long(&info.flags), - SPA_POD_Int(&props.n_items), NULL) < 0) + SPA_POD_Long(&info.flags), NULL) < 0) return -EINVAL; info.change_mask &= SPA_DEVICE_CHANGE_MASK_FLAGS | SPA_DEVICE_CHANGE_MASK_PROPS | SPA_DEVICE_CHANGE_MASK_PARAMS; - if (props.n_items > 0) { + parse_dict(&p2, &props); + if (props.n_items > 0) info.props = &props; - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&p2, &props) < 0) - return -EINVAL; - } - if (spa_pod_parser_get(&p2, - SPA_POD_Int(&info.n_params), NULL) < 0) - return -EINVAL; - - if (info.n_params > 0) { - info.params = alloca(info.n_params * sizeof(struct spa_param_info)); - for (i = 0; i < info.n_params; i++) { - if (spa_pod_parser_get(&p2, - SPA_POD_Id(&info.params[i].id), - SPA_POD_Int(&info.params[i].flags), NULL) < 0) - return -EINVAL; - } - } + parse_param_info(&p2, info.n_params, info.params); } else { infop = NULL; @@ -467,20 +478,15 @@ spa_pod_parser_get(&p2, SPA_POD_String(&info.type), SPA_POD_Long(&info.change_mask), - SPA_POD_Long(&info.flags), - SPA_POD_Int(&props.n_items), NULL) < 0) + SPA_POD_Long(&info.flags), NULL) < 0) return -EINVAL; info.change_mask &= SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS | SPA_DEVICE_CHANGE_MASK_PROPS; - if (props.n_items > 0) { + parse_dict(&p2, &props); + if (props.n_items > 0) info.props = &props; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&p2, &props) < 0) - return -EINVAL; - } } else { infop = NULL; }
View file
pipewire-0.3.44.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.45.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -755,6 +755,9 @@ if (!CHECK_PORT(this, direction, port_id)) 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,
View file
pipewire-0.3.44.tar.gz/src/modules/module-client-node/protocol-native.c -> pipewire-0.3.45.tar.gz/src/modules/module-client-node/protocol-native.c
Changed
@@ -33,6 +33,13 @@ #include <pipewire/extensions/protocol-native.h> #include <pipewire/extensions/client-node.h> +#define MAX_DICT 256 +#define MAX_PARAMS 128 +#define MAX_PARAM_INFO 128 +#define MAX_BUFFERS 64 +#define MAX_METAS 16u +#define MAX_DATAS 64u + PW_LOG_TOPIC_EXTERN(mod_topic); #define PW_LOG_TOPIC_DEFAULT mod_topic @@ -73,16 +80,70 @@ return 0; } -static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict) -{ - uint32_t i; - int res; - for (i = 0; i < dict->n_items; i++) { - if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0) - return res; - } - return 0; -} +#define parse_dict(prs,d) \ +do { \ + uint32_t i; \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&(d)->n_items), NULL) < 0) \ + return -EINVAL; \ + (d)->items = NULL; \ + if ((d)->n_items > 0) { \ + if ((d)->n_items > MAX_DICT) \ + return -ENOSPC; \ + (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \ + for (i = 0; i < (d)->n_items; i++) { \ + if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) + +#define parse_dict_struct(prs,f,dict) \ +do { \ + if (spa_pod_parser_push_struct(prs, f) < 0) \ + return -EINVAL; \ + parse_dict(prs, dict); \ + spa_pod_parser_pop(prs, f); \ +} while(0) + +#define parse_params(prs,n_params,params) \ +do { \ + uint32_t i; \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&n_params), NULL) < 0) \ + return -EINVAL; \ + params = NULL; \ + if (n_params > 0) { \ + if (n_params > MAX_PARAMS) \ + return -ENOSPC; \ + params = alloca(n_params * sizeof(struct spa_pod *)); \ + for (i = 0; i < n_params; i++) { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_PodObject(¶ms[i]), NULL) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) + +#define parse_param_info(prs,n_params,params) \ +do { \ + uint32_t i; \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&(n_params)), NULL) < 0) \ + return -EINVAL; \ + params = NULL; \ + if (n_params > 0) { \ + if (n_params > MAX_PARAM_INFO) \ + return -ENOSPC; \ + params = alloca(n_params * sizeof(struct spa_param_info)); \ + for (i = 0; i < n_params; i++) { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Id(&(params[i]).id), \ + SPA_POD_Int(&(params[i]).flags), NULL) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) static int client_node_marshal_add_listener(void *object, struct spa_hook *listener, @@ -407,15 +468,7 @@ SPA_POD_Int(&port_id), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0) - return -EINVAL; - if (spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL; + parse_dict_struct(&prs, &f[1], &props); pw_proxy_notify(proxy, struct pw_client_node_events, add_port, 0, direction, port_id, props.n_items ? &props : NULL); @@ -478,6 +531,9 @@ SPA_POD_Int(&n_buffers), NULL) < 0) return -EINVAL; + if (n_buffers > MAX_BUFFERS) + return -ENOSPC; + buffers = alloca(sizeof(struct pw_client_node_buffer) * n_buffers); for (i = 0; i < n_buffers; i++) { struct spa_buffer *buf = buffers[i].buffer = alloca(sizeof(struct spa_buffer)); @@ -489,6 +545,9 @@ SPA_POD_Int(&buf->n_metas), NULL) < 0) return -EINVAL; + if (buf->n_metas > MAX_METAS) + return -ENOSPC; + buf->metas = alloca(sizeof(struct spa_meta) * buf->n_metas); for (j = 0; j < buf->n_metas; j++) { struct spa_meta *m = &buf->metas[j]; @@ -502,6 +561,9 @@ SPA_POD_Int(&buf->n_datas), NULL) < 0) return -EINVAL; + if (buf->n_datas > MAX_DATAS) + return -ENOSPC; + buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas); for (j = 0; j < buf->n_datas; j++) { struct spa_data *d = &buf->datas[j]; @@ -594,15 +656,7 @@ SPA_POD_Int(&peer_id), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0) - return -EINVAL; - if (spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL; + parse_dict_struct(&prs, &f[1], &props); pw_proxy_notify(proxy, struct pw_client_node_events, port_set_mix_info, 1, direction, port_id, mix_id, @@ -926,24 +980,18 @@ struct spa_pod_parser prs; struct spa_pod_frame f[2]; uint32_t change_mask, n_params; - const struct spa_pod **params; + const struct spa_pod **params = NULL; struct spa_node_info info = SPA_NODE_INFO_INIT(), *infop = NULL; struct spa_pod *ipod; struct spa_dict props = SPA_DICT_INIT(NULL, 0); - uint32_t i; spa_pod_parser_init(&prs, msg->data, msg->size); if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || spa_pod_parser_get(&prs, - SPA_POD_Int(&change_mask), - SPA_POD_Int(&n_params), NULL) < 0) + SPA_POD_Int(&change_mask), NULL) < 0) return -EINVAL; - params = alloca(n_params * sizeof(struct spa_pod *)); - for (i = 0; i < n_params; i++) - if (spa_pod_parser_get(&prs, - SPA_POD_PodObject(¶ms[i]), NULL) < 0) - return -EINVAL; + parse_params(&prs, n_params, params); if (spa_pod_parser_get(&prs, SPA_POD_PodStruct(&ipod), NULL) < 0) @@ -960,34 +1008,18 @@ SPA_POD_Int(&info.max_input_ports), SPA_POD_Int(&info.max_output_ports), SPA_POD_Long(&info.change_mask), - SPA_POD_Long(&info.flags), - SPA_POD_Int(&props.n_items), NULL) < 0) + SPA_POD_Long(&info.flags), NULL) < 0) return -EINVAL; info.change_mask &= SPA_NODE_CHANGE_MASK_FLAGS | SPA_NODE_CHANGE_MASK_PROPS | SPA_NODE_CHANGE_MASK_PARAMS;
View file
pipewire-0.3.44.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.45.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -41,7 +41,8 @@ #include "pipewire/extensions/protocol-native.h" #include "pipewire/extensions/client-node.h" -#define MAX_MIX 4096 +#define MAX_BUFFERS 64 +#define MAX_MIX 4096 PW_LOG_TOPIC_EXTERN(mod_topic); #define PW_LOG_TOPIC_DEFAULT mod_topic @@ -629,6 +630,9 @@ goto error_exit; } + if (n_buffers > MAX_BUFFERS) + return -ENOSPC; + prot = PW_MEMMAP_FLAG_READWRITE; /* clear previous buffers */
View file
pipewire-0.3.44.tar.gz/src/modules/module-link-factory.c -> pipewire-0.3.45.tar.gz/src/modules/module-link-factory.c
Changed
@@ -57,6 +57,7 @@ struct factory_data { struct pw_impl_module *module; + struct pw_context *context; struct pw_impl_factory *this; struct spa_list link_list; @@ -125,9 +126,13 @@ static void link_initialized(void *data) { struct link_data *ld = data; - struct pw_impl_client *client = pw_resource_get_client(ld->factory_resource); + struct pw_impl_client *client; int res; + if (ld->factory_resource == NULL) + return; + + client = pw_resource_get_client(ld->factory_resource); ld->global = pw_impl_link_get_global(ld->link); pw_global_add_listener(ld->global, &ld->global_listener, &global_events, ld); @@ -364,7 +369,7 @@ struct pw_impl_client *client = NULL; struct pw_impl_node *output_node, *input_node; struct pw_impl_port *outport = NULL, *inport = NULL; - struct pw_context *context; + struct pw_context *context = d->context; struct pw_impl_link *link; const char *output_node_str, *input_node_str; const char *output_port_str, *input_port_str; @@ -372,9 +377,6 @@ int res; bool linger; - client = pw_resource_get_client(resource); - context = pw_impl_client_get_context(client); - if (properties == NULL) goto error_properties; @@ -406,7 +408,9 @@ pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d", pw_impl_factory_get_info(d->this)->id); - if (!linger) + + client = resource ? pw_resource_get_client(resource) : NULL; + if (client && !linger) pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d", pw_impl_client_get_info(client)->id); @@ -524,6 +528,7 @@ data = pw_impl_factory_get_user_data(factory); data->this = factory; data->module = module; + data->context = context; data->work = pw_context_get_work_queue(context); if (data->work == NULL) { res = -errno;
View file
pipewire-0.3.44.tar.gz/src/modules/module-metadata.c -> pipewire-0.3.45.tar.gz/src/modules/module-metadata.c
Changed
@@ -121,15 +121,11 @@ return result; error_resource: - pw_log_error("can't create resource: %s", spa_strerror(res)); - if (resource) - pw_resource_errorf_id(resource, new_id, res, + pw_resource_errorf_id(resource, new_id, res, "can't create resource: %s", spa_strerror(res)); goto error_exit; error_node: - pw_log_error("can't create metadata: %s", spa_strerror(res)); - if (resource) - pw_resource_errorf_id(resource, new_id, res, + pw_resource_errorf_id(resource, new_id, res, "can't create metadata: %s", spa_strerror(res)); goto error_exit_free;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -264,8 +264,7 @@ return res; error: - if (client->core_resource) - pw_resource_errorf(client->core_resource, res, "client error %d (%s)", + pw_resource_errorf(client->core_resource, res, "client error %d (%s)", res, spa_strerror(res)); goto done; }
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-native/protocol-native.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-native/protocol-native.c
Changed
@@ -34,6 +34,10 @@ #include "connection.h" +#define MAX_DICT 256 +#define MAX_PARAM_INFO 128 +#define MAX_PERMISSIONS 1024 + PW_LOG_TOPIC_EXTERN(mod_topic); #define PW_LOG_TOPIC_DEFAULT mod_topic @@ -167,16 +171,31 @@ return 0; } -static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict) -{ - uint32_t i; - int res; - for (i = 0; i < dict->n_items; i++) { - if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0) - return res; - } - return 0; -} +#define parse_dict(prs,d) \ +do { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&(d)->n_items), NULL) < 0) \ + return -EINVAL; \ + (d)->items = NULL; \ + if ((d)->n_items > 0) { \ + uint32_t i; \ + if ((d)->n_items > MAX_DICT) \ + return -ENOSPC; \ + (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \ + for (i = 0; i < (d)->n_items; i++) { \ + if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \ + return -EINVAL; \ + } \ + } \ +} while(0) + +#define parse_dict_struct(prs,f,dict) \ +do { \ + if (spa_pod_parser_push_struct(prs, f) < 0) \ + return -EINVAL; \ + parse_dict(prs, dict); \ + spa_pod_parser_pop(prs, f); \ +} while(0) static void push_params(struct spa_pod_builder *b, uint32_t n_params, const struct spa_param_info *params) @@ -193,6 +212,52 @@ spa_pod_builder_pop(b, &f); } + +#define parse_params_struct(prs,f,params,n_params) \ +do { \ + if (spa_pod_parser_push_struct(prs, f) < 0 || \ + spa_pod_parser_get(prs, \ + SPA_POD_Int(&(n_params)), NULL) < 0) \ + return -EINVAL; \ + params = NULL; \ + if (n_params > 0) { \ + uint32_t i; \ + if (n_params > MAX_PARAM_INFO) \ + return -ENOSPC; \ + params = alloca(n_params * sizeof(struct spa_param_info)); \ + for (i = 0; i < n_params; i++) { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Id(&(params)[i].id), \ + SPA_POD_Int(&(params)[i].flags), NULL) < 0) \ + return -EINVAL; \ + } \ + } \ + spa_pod_parser_pop(prs, f); \ +} while(0) + + +#define parse_permissions_struct(prs,f,n_permissions,permissions) \ +do { \ + if (spa_pod_parser_push_struct(prs, f) < 0 || \ + spa_pod_parser_get(prs, \ + SPA_POD_Int(&n_permissions), NULL) < 0) \ + return -EINVAL; \ + permissions = NULL; \ + if (n_permissions > 0) { \ + uint32_t i; \ + if (n_permissions > MAX_PERMISSIONS) \ + return -ENOSPC; \ + permissions = alloca(n_permissions * sizeof(struct pw_permission)); \ + for (i = 0; i < n_permissions; i++) { \ + if (spa_pod_parser_get(prs, \ + SPA_POD_Int(&permissions[i].id), \ + SPA_POD_Int(&permissions[i].permissions), NULL) < 0) \ + return -EINVAL; \ + } \ + } \ + spa_pod_parser_pop(prs, f); \ +} while(0) + static void * core_method_marshal_create_object(void *object, const char *factory_name, @@ -247,8 +312,8 @@ { struct pw_proxy *proxy = object; struct spa_dict props = SPA_DICT_INIT(NULL, 0); + struct pw_core_info info = { .props = &props }; struct spa_pod_frame f[2]; - struct pw_core_info info; struct spa_pod_parser prs; spa_pod_parser_init(&prs, msg->data, msg->size); @@ -264,16 +329,8 @@ SPA_POD_Long(&info.change_mask), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0) - return -EINVAL; - if (spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - info.props = &props; - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL; + parse_dict_struct(&prs, &f[1], &props); return pw_proxy_notify(proxy, struct pw_core_events, info, 0, &info); } @@ -611,15 +668,7 @@ NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || - spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL; - spa_pod_parser_pop(&prs, &f[1]); + parse_dict_struct(&prs, &f[1], &props); if (spa_pod_parser_get(&prs, SPA_POD_Int(&new_id), NULL) < 0) @@ -770,7 +819,7 @@ struct spa_pod_parser prs; struct spa_pod_frame f[2]; struct spa_dict props = SPA_DICT_INIT(NULL, 0); - struct pw_module_info info; + struct pw_module_info info = { .props = &props }; spa_pod_parser_init(&prs, msg->data, msg->size); if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || @@ -782,15 +831,7 @@ SPA_POD_Long(&info.change_mask), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || - spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - - info.props = &props; - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL; + parse_dict_struct(&prs, &f[1], &props); return pw_proxy_notify(proxy, struct pw_module_events, info, 0, &info); } @@ -831,8 +872,7 @@ struct spa_pod_parser prs; struct spa_pod_frame f[2]; struct spa_dict props = SPA_DICT_INIT(NULL, 0); - struct pw_device_info info; - uint32_t i; + struct pw_device_info info = { .props = &props }; spa_pod_parser_init(&prs, msg->data, msg->size); if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 || @@ -841,30 +881,8 @@ SPA_POD_Long(&info.change_mask), NULL) < 0) return -EINVAL; - if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 || - spa_pod_parser_get(&prs, - SPA_POD_Int(&props.n_items), NULL) < 0) - return -EINVAL; - - info.props = &props; - props.items = alloca(props.n_items * sizeof(struct spa_dict_item)); - if (parse_dict(&prs, &props) < 0) - return -EINVAL;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/client.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/client.c
Changed
@@ -99,6 +99,7 @@ /* remove from the `server->clients` list */ spa_list_remove(&client->link); + spa_list_append(&impl->cleanup_clients, &client->link); server->n_clients--; if (server->wait_clients > 0 && --server->wait_clients == 0) { @@ -125,15 +126,18 @@ spa_assert(client->server == NULL); client->disconnect = true; - spa_list_append(&impl->cleanup_clients, &client->link); pw_map_for_each(&client->streams, client_free_stream, client); - if (client->source) + if (client->source) { pw_loop_destroy_source(impl->loop, client->source); + client->source = NULL; + } - if (client->manager) + if (client->manager) { pw_manager_destroy(client->manager); + client->manager = NULL; + } } void client_free(struct client *client) @@ -163,13 +167,13 @@ spa_list_consume(o, &client->operations, link) operation_free(o); - if (client->core) { - client->disconnecting = true; + if (client->core) pw_core_disconnect(client->core); - } pw_map_clear(&client->streams); + pw_work_queue_cancel(impl->work_queue, client, SPA_ID_INVALID); + free(client->default_sink); free(client->default_source);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/client.h -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/client.h
Changed
@@ -95,7 +95,6 @@ struct spa_list pending_streams; unsigned int disconnect:1; - unsigned int disconnecting:1; unsigned int new_msg_since_last_flush:1; unsigned int authenticated:1;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/defs.h -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/defs.h
Changed
@@ -52,7 +52,7 @@ #define MIN_BUFFERS 1u #define MAX_BUFFERS 4u -#define MAXLENGTH (4*1024*1024) /* 4MB */ +#define MAXLENGTH (4u*1024*1024) /* 4MB */ #define SCACHE_ENTRY_SIZE_MAX (1024*1024*16)
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/format.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/format.c
Changed
@@ -475,10 +475,7 @@ return -ENOTSUP; info.info.raw.format = SPA_AUDIO_FORMAT_S16; - info.info.raw.channels = 2; info.info.raw.rate = iec.rate; - info.info.raw.position[0] = SPA_AUDIO_CHANNEL_FL; - info.info.raw.position[1] = SPA_AUDIO_CHANNEL_FR; break; } default: @@ -493,9 +490,11 @@ ss->channels = info.info.raw.channels; } if (map) { - map->channels = info.info.raw.channels; - for (i = 0; i < map->channels; i++) - map->map[i] = info.info.raw.position[i]; + if (info.info.raw.channels) { + map->channels = info.info.raw.channels; + for (i = 0; i < map->channels; i++) + map->map[i] = info.info.raw.position[i]; + } } return 0; }
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.c
Changed
@@ -45,7 +45,7 @@ static void on_module_unload(void *obj, void *data, int res, uint32_t index) { struct module *module = obj; - module_unload(NULL, module); + module_unload(module); } void module_schedule_unload(struct module *module) @@ -110,7 +110,7 @@ free(module); } -int module_unload(struct client *client, struct module *module) +int module_unload(struct module *module) { struct impl *impl = module->impl; int res = 0; @@ -121,7 +121,7 @@ pw_log_info("unload module index:%u name:%s", module->index, module->name); if (module->methods->unload) - res = module->methods->unload(client, module); + res = module->methods->unload(module); if (module->loaded) broadcast_subscribe_event(impl, @@ -302,7 +302,7 @@ module->index = pw_map_insert_new(&impl->modules, module); if (module->index == SPA_ID_INVALID) { - module_unload(client, module); + module_unload(module); return NULL; } module->name = strdup(name);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/module.h -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/module.h
Changed
@@ -53,7 +53,7 @@ uint32_t version; int (*load) (struct client *client, struct module *module); - int (*unload) (struct client *client, struct module *module); + int (*unload) (struct module *module); }; struct module { @@ -76,7 +76,7 @@ void module_free(struct module *module); struct module *module_new(struct impl *impl, const struct module_methods *methods, size_t user_data); int module_load(struct client *client, struct module *module); -int module_unload(struct client *client, struct module *module); +int module_unload(struct module *module); void module_schedule_unload(struct module *module); void module_add_listener(struct module *module,
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-combine-sink.c
Changed
@@ -390,7 +390,7 @@ return 0; } -static int module_combine_sink_unload(struct client *client, struct module *module) +static int module_combine_sink_unload(struct module *module) { struct module_combine_sink_data *d = module->user_data; int i;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-echo-cancel.c
Changed
@@ -108,7 +108,7 @@ return 0; } -static int module_echo_cancel_unload(struct client *client, struct module *module) +static int module_echo_cancel_unload(struct module *module) { struct module_echo_cancel_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-sink.c
Changed
@@ -124,7 +124,7 @@ return 0; } -static int module_ladspa_sink_unload(struct client *client, struct module *module) +static int module_ladspa_sink_unload(struct module *module) { struct module_ladspa_sink_data *d = module->user_data; @@ -212,6 +212,8 @@ } if (pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS) == NULL) pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + 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(props, "master")) != NULL || (str = pw_properties_get(props, "sink_master")) != NULL) {
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-ladspa-source.c
Changed
@@ -124,7 +124,7 @@ return 0; } -static int module_ladspa_source_unload(struct client *client, struct module *module) +static int module_ladspa_source_unload(struct module *module) { struct module_ladspa_source_data *d = module->user_data; @@ -212,6 +212,8 @@ } if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL) pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source"); + 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(props, "master")) != NULL || (str = pw_properties_get(props, "source_master")) != NULL) {
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-loopback.c
Changed
@@ -107,7 +107,7 @@ return 0; } -static int module_loopback_unload(struct client *client, struct module *module) +static int module_loopback_unload(struct module *module) { struct module_loopback_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-native-protocol-tcp.c
Changed
@@ -58,7 +58,7 @@ return 0; } -static int module_native_protocol_tcp_unload(struct client *client, struct module *module) +static int module_native_protocol_tcp_unload(struct module *module) { struct module_native_protocol_tcp_data *d = module->user_data; struct server **s;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-null-sink.c
Changed
@@ -126,7 +126,7 @@ return SPA_RESULT_RETURN_ASYNC(0); } -static int module_null_sink_unload(struct client *client, struct module *module) +static int module_null_sink_unload(struct module *module) { struct module_null_sink_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-sink.c
Changed
@@ -185,7 +185,7 @@ return 0; } -static int module_pipesink_unload(struct client *client, struct module *module) +static int module_pipesink_unload(struct module *module) { struct module_pipesink_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-pipe-source.c
Changed
@@ -206,7 +206,7 @@ return 0; } -static int module_pipesource_unload(struct client *client, struct module *module) +static int module_pipesource_unload(struct module *module) { struct module_pipesrc_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-raop-discover.c
Changed
@@ -73,7 +73,7 @@ return 0; } -static int module_raop_discover_unload(struct client *client, struct module *module) +static int module_raop_discover_unload(struct module *module) { struct module_raop_discover_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-sink.c
Changed
@@ -95,7 +95,7 @@ return 0; } -static int module_remap_sink_unload(struct client *client, struct module *module) +static int module_remap_sink_unload(struct module *module) { struct module_remap_sink_data *d = module->user_data; @@ -151,7 +151,7 @@ struct module *module; struct module_remap_sink_data *d; struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL; - const char *str; + const char *str, *master; struct spa_audio_info_raw capture_info = { 0 }; struct spa_audio_info_raw playback_info = { 0 }; int res; @@ -168,16 +168,40 @@ if (argument) module_args_add_props(props, argument); + master = pw_properties_get(props, "master"); + if (pw_properties_get(props, "sink_name") == NULL) { + pw_properties_setf(props, "sink_name", "%s.remapped", + master ? master : "default"); + } if ((str = pw_properties_get(props, "sink_name")) != NULL) { pw_properties_set(capture_props, PW_KEY_NODE_NAME, str); + pw_properties_setf(playback_props, PW_KEY_NODE_NAME, "output.%s", str); pw_properties_set(props, "sink_name", NULL); } if ((str = pw_properties_get(props, "sink_properties")) != NULL) { module_args_add_props(capture_props, str); pw_properties_set(props, "sink_properties", NULL); } - pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - + if (pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS) == NULL) + pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + 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_MEDIA_NAME)) != NULL) + pw_properties_set(props, PW_KEY_MEDIA_NAME, str); + if ((str = pw_properties_get(capture_props, PW_KEY_NODE_DESCRIPTION)) != NULL) { + pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); + } else { + str = pw_properties_get(capture_props, PW_KEY_NODE_NAME); + if (master != NULL || str == NULL) { + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "Remapped %s sink", + master ? master : "default"); + } else { + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "%s sink", str); + } + } if ((str = pw_properties_get(props, "master")) != NULL) { pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str); pw_properties_set(props, "master", NULL);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-remap-source.c
Changed
@@ -95,7 +95,7 @@ return 0; } -static int module_remap_source_unload(struct client *client, struct module *module) +static int module_remap_source_unload(struct module *module) { struct module_remap_source_data *d = module->user_data; @@ -151,7 +151,7 @@ struct module *module; struct module_remap_source_data *d; struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL; - const char *str; + const char *str, *master; struct spa_audio_info_raw capture_info = { 0 }; struct spa_audio_info_raw playback_info = { 0 }; int res; @@ -168,16 +168,40 @@ if (argument) module_args_add_props(props, argument); + master = pw_properties_get(props, "master"); + if (pw_properties_get(props, "source_name") == NULL) { + pw_properties_setf(props, "source_name", "%s.remapped", + master ? master : "default"); + } if ((str = pw_properties_get(props, "source_name")) != NULL) { pw_properties_set(playback_props, PW_KEY_NODE_NAME, str); + pw_properties_setf(capture_props, PW_KEY_NODE_NAME, "input.%s", str); pw_properties_set(props, "source_name", NULL); } if ((str = pw_properties_get(props, "source_properties")) != NULL) { module_args_add_props(playback_props, str); pw_properties_set(props, "source_properties", NULL); } - pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source"); - + if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL) + pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source"); + 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_MEDIA_NAME)) != NULL) + pw_properties_set(props, PW_KEY_MEDIA_NAME, str); + if ((str = pw_properties_get(playback_props, PW_KEY_NODE_DESCRIPTION)) != NULL) { + pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str); + } else { + str = pw_properties_get(playback_props, PW_KEY_NODE_NAME); + if (master != NULL || str == NULL) { + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "Remapped %s source", + master ? master : "default"); + } else { + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "%s source", str); + } + } if ((str = pw_properties_get(props, "master")) != NULL) { pw_properties_set(capture_props, PW_KEY_NODE_TARGET, str); pw_properties_set(props, "master", NULL);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-sink.c
Changed
@@ -104,7 +104,7 @@ return 0; } -static int module_roc_sink_unload(struct client *client, struct module *module) +static int module_roc_sink_unload(struct module *module) { struct module_roc_sink_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-roc-source.c
Changed
@@ -106,7 +106,7 @@ return 0; } -static int module_roc_source_unload(struct client *client, struct module *module) +static int module_roc_source_unload(struct module *module) { struct module_roc_source_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-simple-protocol-tcp.c
Changed
@@ -36,9 +36,12 @@ struct module_simple_protocol_tcp_data { struct module *module; - struct pw_properties *module_props; struct pw_impl_module *mod; struct spa_hook mod_listener; + + struct pw_properties *module_props; + + struct spa_audio_info_raw info; }; static void module_destroy(void *data) @@ -61,29 +64,26 @@ struct module_simple_protocol_tcp_data *data = module->user_data; struct impl *impl = client->impl; char *args; - const char *str; size_t size; + uint32_t i; FILE *f; f = open_memstream(&args, &size); - if ((str = pw_properties_get(data->module_props, "audio.format")) != NULL) - fprintf(f, "audio.format=%s ", str); - if ((str = pw_properties_get(data->module_props, "audio.rate")) != NULL) - fprintf(f, "audio.rate=%s ", str); - if ((str = pw_properties_get(data->module_props, "audio.channels")) != NULL) - fprintf(f, "audio.channels=%s ", str); - if ((str = pw_properties_get(data->module_props, "server.address")) != NULL) - fprintf(f, "server.address=%s ", str); - if ((str = pw_properties_get(data->module_props, "capture")) != NULL) - fprintf(f, "capture=%s ", str); - if ((str = pw_properties_get(data->module_props, "playback")) != NULL) - fprintf(f, "playback=%s ", str); - if ((str = pw_properties_get(data->module_props, "capture.node")) != NULL) - fprintf(f, "capture.node=\"%s\" ", str); - if ((str = pw_properties_get(data->module_props, "playback.node")) != NULL) - fprintf(f, "playback.node=\"%s\" ", str); - if ((str = pw_properties_get(data->module_props, PW_KEY_STREAM_CAPTURE_SINK)) != NULL) - fprintf(f, PW_KEY_STREAM_CAPTURE_SINK"=\"%s\" ", str); + fprintf(f, "{"); + if (data->info.rate != 0) + fprintf(f, " \"audio.rate\": %u,", data->info.rate); + if (data->info.channels != 0) { + fprintf(f, " \"audio.channels\": %u,", data->info.channels); + if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) { + fprintf(f, " \"audio.position\": [ "); + for (i = 0; i < data->info.channels; i++) + fprintf(f, "%s\"%s\"", i == 0 ? "" : ",", + channel_id2name(data->info.position[i])); + fprintf(f, " ],"); + } + } + pw_properties_serialize_dict(f, &data->module_props->dict, 0); + fprintf(f, "}"); fclose(f); data->mod = pw_context_load_module(impl->context, @@ -99,7 +99,7 @@ return 0; } -static int module_simple_protocol_tcp_unload(struct client *client, struct module *module) +static int module_simple_protocol_tcp_unload(struct module *module) { struct module_simple_protocol_tcp_data *d = module->user_data; @@ -125,6 +125,7 @@ { PW_KEY_MODULE_USAGE, "rate=<sample rate> " "format=<sample format> " "channels=<number of channels> " + "channel_map=<number of channels> " "sink=<sink to connect to> " "source=<source to connect to> " "playback=<enable playback?> " @@ -140,6 +141,7 @@ struct module_simple_protocol_tcp_data *d; struct pw_properties *props = NULL, *module_props = NULL; const char *str, *port, *listen; + struct spa_audio_info_raw info = { 0 }; int res; PW_LOG_TOPIC_INIT(mod_topic); @@ -158,17 +160,14 @@ goto out; } - if ((str = pw_properties_get(props, "rate")) != NULL) { - pw_properties_set(module_props, "audio.rate", str); - pw_properties_set(props, "rate", NULL); - } if ((str = pw_properties_get(props, "format")) != NULL) { - pw_properties_set(module_props, "audio.format", format_id2name(format_paname2id(str, strlen(str)))); + pw_properties_set(module_props, "audio.format", + format_id2name(format_paname2id(str, strlen(str)))); pw_properties_set(props, "format", NULL); } - if ((str = pw_properties_get(props, "channels")) != NULL) { - pw_properties_set(module_props, "audio.channels", str); - pw_properties_set(props, "channels", NULL); + if (module_args_to_audioinfo(impl, props, &info) < 0) { + res = -EINVAL; + goto out; } if ((str = pw_properties_get(props, "playback")) != NULL) { pw_properties_set(module_props, "playback", str); @@ -213,6 +212,7 @@ d = module->user_data; d->module = module; d->module_props = module_props; + d->info = info; return module; out:
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c
Changed
@@ -209,7 +209,7 @@ return res; } -static int module_switch_on_connect_unload(struct client *client, struct module *module) +static int module_switch_on_connect_unload(struct module *module) { struct module_switch_on_connect_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-sink.c
Changed
@@ -100,7 +100,7 @@ return 0; } -static int module_tunnel_sink_unload(struct client *client, struct module *module) +static int module_tunnel_sink_unload(struct module *module) { struct module_tunnel_sink_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-tunnel-source.c
Changed
@@ -100,7 +100,7 @@ return 0; } -static int module_tunnel_source_unload(struct client *client, struct module *module) +static int module_tunnel_source_unload(struct module *module) { struct module_tunnel_source_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-x11-bell.c
Changed
@@ -86,7 +86,7 @@ return 0; } -static int module_x11_bell_unload(struct client *client, struct module *module) +static int module_x11_bell_unload(struct module *module) { struct module_x11_bell_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-discover.c
Changed
@@ -73,7 +73,7 @@ return 0; } -static int module_zeroconf_discover_unload(struct client *client, struct module *module) +static int module_zeroconf_discover_unload(struct module *module) { struct module_zeroconf_discover_data *d = module->user_data;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c
Changed
@@ -602,7 +602,7 @@ return 0; } -static int module_zeroconf_publish_unload(struct client *client, struct module *module) +static int module_zeroconf_publish_unload(struct module *module) { struct module_zeroconf_publish_data *d = module->user_data; struct service *s;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/pending-sample.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/pending-sample.c
Changed
@@ -41,7 +41,5 @@ spa_hook_remove(&ps->listener); pw_work_queue_cancel(impl->work_queue, ps, SPA_ID_INVALID); - client->ref--; - sample_play_destroy(ps->play); }
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/pending-sample.h -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/pending-sample.h
Changed
@@ -39,7 +39,6 @@ struct sample_play *play; struct spa_hook listener; uint32_t tag; - unsigned int done:1; }; void pending_sample_free(struct pending_sample *ps);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -22,8 +22,6 @@ * DEALINGS IN THE SOFTWARE. */ -#include "pipewire/core.h" - #include "config.h" #include <errno.h> @@ -444,55 +442,66 @@ return latency / frame_size; } -static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer) +static uint64_t set_playback_buffer_attr(struct stream *s, struct buffer_attr *attr) { - struct client *client = stream->client; - struct pw_manager *manager = client->manager; - struct message *reply; - uint32_t missing, peer_index; + struct spa_fraction lat; + uint64_t lat_usec; struct spa_dict_item items[5]; char latency[32]; char attr_maxlength[32]; char attr_tlength[32]; char attr_prebuf[32]; char attr_minreq[32]; - const char *peer_name; - struct spa_fraction lat; - uint64_t lat_usec; - lat.denom = stream->ss.rate; - lat.num = fix_playback_buffer_attr(stream, &stream->attr); + lat.denom = s->ss.rate; + lat.num = fix_playback_buffer_attr(s, attr); - stream->buffer = calloc(1, stream->attr.maxlength); - if (stream->buffer == NULL) - return -errno; + s->attr = *attr; - if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num) - lat.num = (stream->min_quantum.num * lat.denom + - (stream->min_quantum.denom -1)) / stream->min_quantum.denom; + if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num) + lat.num = (s->min_quantum.num * lat.denom + + (s->min_quantum.denom -1)) / s->min_quantum.denom; lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); - snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", stream->attr.maxlength); - snprintf(attr_tlength, sizeof(attr_tlength), "%u", stream->attr.tlength); - snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", stream->attr.prebuf); - snprintf(attr_minreq, sizeof(attr_minreq), "%u", stream->attr.minreq); + snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength); + snprintf(attr_tlength, sizeof(attr_tlength), "%u", s->attr.tlength); + snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", s->attr.prebuf); + snprintf(attr_minreq, sizeof(attr_minreq), "%u", s->attr.minreq); items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); items[2] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength); items[3] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf); items[4] = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq); - pw_stream_update_properties(stream->stream, &SPA_DICT_INIT(items, 5)); + pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 5)); - if (stream->attr.prebuf > 0) - stream->in_prebuf = true; + if (s->attr.prebuf > 0) + s->in_prebuf = true; + + return lat_usec; +} + +static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer) +{ + struct client *client = stream->client; + struct pw_manager *manager = client->manager; + struct message *reply; + uint32_t missing, peer_index; + const char *peer_name; + uint64_t lat_usec; + + stream->buffer = calloc(1, MAXLENGTH); + if (stream->buffer == NULL) + return -errno; + + lat_usec = set_playback_buffer_attr(stream, &stream->attr); missing = stream_pop_missing(stream); stream->index = id_to_index(manager, stream->id); - pw_log_info("[%s] reply CREATE_PLAYBACK_STREAM tag:%u index:%u missing:%u latency:%s", - client->name, stream->create_tag, stream->index, missing, latency); + pw_log_info("[%s] reply CREATE_PLAYBACK_STREAM tag:%u index:%u missing:%u lat:%"PRIu64, + client->name, stream->create_tag, stream->index, missing, lat_usec); reply = reply_new(client, stream->create_tag); message_put(reply, @@ -584,47 +593,56 @@ return latency / frame_size; } -static int reply_create_record_stream(struct stream *stream, struct pw_manager_object *peer) +static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr) { - struct client *client = stream->client; - struct pw_manager *manager = client->manager; - struct message *reply; struct spa_dict_item items[3]; - char latency[32], *tmp; + char latency[32]; char attr_maxlength[32]; char attr_fragsize[32]; - const char *peer_name, *name; - uint32_t peer_index; struct spa_fraction lat; uint64_t lat_usec; - lat.denom = stream->ss.rate; - lat.num = fix_record_buffer_attr(stream, &stream->attr); - - stream->buffer = calloc(1, stream->attr.maxlength); - if (stream->buffer == NULL) - return -errno; + lat.denom = s->ss.rate; + lat.num = fix_record_buffer_attr(s, &s->attr); - if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num) - lat.num = (stream->min_quantum.num * lat.denom + - (stream->min_quantum.denom -1)) / stream->min_quantum.denom; + if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num) + lat.num = (s->min_quantum.num * lat.denom + + (s->min_quantum.denom -1)) / s->min_quantum.denom; lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); - snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", stream->attr.maxlength); - snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", stream->attr.fragsize); + snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength); + snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", s->attr.fragsize); items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency); items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength); items[2] = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize); - pw_stream_update_properties(stream->stream, - &SPA_DICT_INIT(items, 3)); + pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 3)); + + return lat_usec; +} + +static int reply_create_record_stream(struct stream *stream, struct pw_manager_object *peer) +{ + struct client *client = stream->client; + struct pw_manager *manager = client->manager; + char *tmp; + struct message *reply; + const char *peer_name, *name; + uint32_t peer_index; + uint64_t lat_usec; + + stream->buffer = calloc(1, MAXLENGTH); + if (stream->buffer == NULL) + return -errno; + + lat_usec = set_record_buffer_attr(stream, &stream->attr); stream->index = id_to_index(manager, stream->id); - pw_log_info("[%s] reply CREATE_RECORD_STREAM tag:%u index:%u latency:%s", - client->name, stream->create_tag, stream->index, latency); + pw_log_info("[%s] reply CREATE_RECORD_STREAM tag:%u index:%u latency:%"PRIu64, + client->name, stream->create_tag, stream->index, lat_usec); reply = reply_new(client, stream->create_tag); message_put(reply, @@ -837,7 +855,7 @@ static void do_free_client(void *obj, void *data, int res, uint32_t id) { - struct client *client = data; + struct client *client = obj; client_free(client); } @@ -845,8 +863,8 @@ { struct client *client = data; pw_log_debug("manager_disconnect()"); - pw_work_queue_add(client->impl->work_queue, NULL, 0, - do_free_client, client); + pw_work_queue_add(client->impl->work_queue, client, 0, + do_free_client, NULL); } static const struct pw_manager_events manager_events = {
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/quirks.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/quirks.c
Changed
@@ -170,15 +170,19 @@ 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; - const char *rules; - - if ((rules = pw_context_get_conf_section(context, "pulse.rules")) == NULL) - return 0; - - return pw_conf_match_rules(rules, strlen(rules), &client->props->dict, - client_rule_matched, client); + return pw_context_conf_section_for_each(context, "pulse.rules", + apply_pulse_rules, client); }
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -178,10 +178,10 @@ /* always write data to ringbuffer, we expect the other side * to recover */ spa_ringbuffer_write_data(&stream->ring, - stream->buffer, stream->attr.maxlength, - index % stream->attr.maxlength, + stream->buffer, MAXLENGTH, + index % MAXLENGTH, msg->data, - SPA_MIN(msg->length, stream->attr.maxlength)); + SPA_MIN(msg->length, MAXLENGTH)); index += msg->length; stream->write_index += msg->length; spa_ringbuffer_write_update(&stream->ring, index);
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
@@ -38,6 +38,7 @@ #include "client.h" #include "commands.h" +#include "defs.h" #include "internal.h" #include "log.h" #include "message.h" @@ -331,7 +332,12 @@ if (new_tlength <= old_tlength) return 0; + if (new_tlength > MAXLENGTH) + new_tlength = MAXLENGTH; + stream->attr.tlength = new_tlength; + if (stream->attr.tlength > stream->attr.maxlength) + stream->attr.maxlength = stream->attr.tlength; if (client->version >= 15) { struct message *msg;
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
@@ -111,7 +111,6 @@ unsigned int adjust_latency:1; unsigned int is_underrun:1; unsigned int in_prebuf:1; - unsigned int done:1; unsigned int killed:1; unsigned int pending:1; };
View file
pipewire-0.3.44.tar.gz/src/modules/module-protocol-simple.c -> pipewire-0.3.45.tar.gz/src/modules/module-protocol-simple.c
Changed
@@ -64,13 +64,15 @@ #define DEFAULT_RATE "44100" #define DEFAULT_CHANNELS 2 #define DEFAULT_POSITION "[ FL FR ]" -#define DEFAULT_LATENCY "1024/48000" +#define DEFAULT_LATENCY "1024/44100" #define MAX_CLIENTS 10 #define MODULE_USAGE "[ capture=<bool> ] " \ "[ playback=<bool> ] " \ - "[ capture.node=<source-target> ] " \ + "[ node.latency=<num/denom, default:"DEFAULT_LATENCY"> ] " \ + "[ node.rate=<1/rate, default:1/"DEFAULT_RATE"> ] " \ + "[ capture.node=<source-target> [ stream.capture.sink=true ]] " \ "[ playback.node=<sink-target> ] " \ "[ audio.rate=<sample-rate, default:"DEFAULT_RATE"> ] " \ "[ audio.format=<format, default:"DEFAULT_FORMAT"> ] " \ @@ -384,12 +386,17 @@ uint8_t buffer[1024]; struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); struct pw_properties *props; + const char *latency; int res; + if ((latency = pw_properties_get(impl->props, PW_KEY_NODE_LATENCY)) == NULL) + latency = DEFAULT_LATENCY; + if (impl->capture) { props = pw_properties_new( PW_KEY_NODE_GROUP, "pipewire.dummy", - PW_KEY_NODE_LATENCY, DEFAULT_LATENCY, + PW_KEY_NODE_LATENCY, latency, + PW_KEY_NODE_RATE, pw_properties_get(impl->props, PW_KEY_NODE_RATE), PW_KEY_NODE_TARGET, pw_properties_get(impl->props, "capture.node"), PW_KEY_STREAM_CAPTURE_SINK, pw_properties_get(impl->props, PW_KEY_STREAM_CAPTURE_SINK), @@ -412,7 +419,8 @@ if (impl->playback) { props = pw_properties_new( PW_KEY_NODE_GROUP, "pipewire.dummy", - PW_KEY_NODE_LATENCY, DEFAULT_LATENCY, + PW_KEY_NODE_LATENCY, latency, + PW_KEY_NODE_RATE, pw_properties_get(impl->props, PW_KEY_NODE_RATE), PW_KEY_NODE_TARGET, pw_properties_get(impl->props, "playback.node"), PW_KEY_NODE_NETWORK, "true", NULL);
View file
pipewire-0.3.44.tar.gz/src/modules/module-session-manager/protocol-native.c -> pipewire-0.3.45.tar.gz/src/modules/module-session-manager/protocol-native.c
Changed
@@ -32,6 +32,10 @@ #include <pipewire/extensions/session-manager.h> #include <pipewire/extensions/protocol-native.h> +#define MAX_DICT 256 +#define MAX_PARAMS 128 +#define MAX_PARAM_INFO 128 + static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict) { struct spa_pod_frame f; @@ -61,6 +65,8 @@ return -EINVAL; \ \ if ((dict)->n_items > 0) { \ + if ((dict)->n_items > MAX_DICT) \ + return -ENOSPC; \ (dict)->items = alloca((dict)->n_items * sizeof(struct spa_dict_item)); \ for (i = 0; i < (dict)->n_items; i++) { \ if (spa_pod_parser_get(p, \ @@ -100,6 +106,8 @@ return -EINVAL; \ \ if (*(n_params_p) > 0) { \ + if (*(n_params_p) > MAX_PARAM_INFO) \ + return -ENOSPC; \ *(params_p) = alloca(*(n_params_p) * sizeof(struct spa_param_info)); \ for (i = 0; i < *(n_params_p); i++) { \ if (spa_pod_parser_get(p, \ @@ -553,6 +561,8 @@ SPA_POD_Int(&n_params), NULL) < 0) return -EINVAL; + if (n_params > MAX_PARAMS) + return -ENOSPC; if (n_params > 0) params = alloca(n_params * sizeof(struct spa_pod *)); for (i = 0; i < n_params; i++) @@ -593,6 +603,8 @@ SPA_POD_Int(&n_params), NULL) < 0) return -EINVAL; + if (n_params > MAX_PARAMS) + return -ENOSPC; if (n_params > 0) params = alloca(n_params * sizeof(struct spa_pod *)); for (i = 0; i < n_params; i++) @@ -867,6 +879,8 @@ SPA_POD_Int(&n_params), NULL) < 0) return -EINVAL; + if (n_params > MAX_PARAMS) + return -ENOSPC; if (n_params > 0) params = alloca(n_params * sizeof(struct spa_pod *)); for (i = 0; i < n_params; i++) @@ -907,6 +921,8 @@ SPA_POD_Int(&n_params), NULL) < 0) return -EINVAL; + if (n_params > MAX_PARAMS) + return -ENOSPC; if (n_params > 0) params = alloca(n_params * sizeof(struct spa_pod *)); for (i = 0; i < n_params; i++)
View file
pipewire-0.3.44.tar.gz/src/modules/spa/module-device-factory.c -> pipewire-0.3.45.tar.gz/src/modules/spa/module-device-factory.c
Changed
@@ -165,15 +165,10 @@ error_properties: res = -EINVAL; - pw_log_error("factory %p: usage: " FACTORY_USAGE, data->this); - if (resource) - pw_resource_errorf_id(resource, new_id, res, - "usage: "FACTORY_USAGE); + pw_resource_errorf_id(resource, new_id, res, "usage: "FACTORY_USAGE); goto error_exit_cleanup; error_device: - pw_log_debug("can't create device %s: %s", factory_name, spa_strerror(res)); - if (resource) - pw_resource_errorf_id(resource, new_id, res, + pw_resource_errorf_id(resource, new_id, res, "can't create device %s: %s", factory_name, spa_strerror(res)); goto error_exit;
View file
pipewire-0.3.44.tar.gz/src/modules/spa/module-node-factory.c -> pipewire-0.3.45.tar.gz/src/modules/spa/module-node-factory.c
Changed
@@ -163,16 +163,11 @@ error_properties: res = -EINVAL; - pw_log_error("factory %p: usage: " FACTORY_USAGE, data->this); - if (resource) - pw_resource_errorf_id(resource, new_id, res, - "usage: "FACTORY_USAGE); + pw_resource_errorf_id(resource, new_id, res, "usage: "FACTORY_USAGE); goto error_exit_cleanup; error_create_node: res = -errno; - pw_log_error("can't create node: %m"); - if (resource) - pw_resource_errorf_id(resource, new_id, res, + pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res)); goto error_exit; error_bind:
View file
pipewire-0.3.44.tar.gz/src/pipewire/conf.c -> pipewire-0.3.45.tar.gz/src/pipewire/conf.c
Changed
@@ -33,6 +33,7 @@ #include <fcntl.h> #include <unistd.h> #include <sys/wait.h> +#include <dirent.h> #if HAVE_PWD_H #include <pwd.h> #endif @@ -45,6 +46,7 @@ #include <spa/utils/json.h> #include <pipewire/impl.h> +#include <pipewire/private.h> PW_LOG_TOPIC_EXTERN(log_conf); #define PW_LOG_TOPIC_DEFAULT log_conf @@ -65,34 +67,21 @@ return 0; } -static int get_config_path(char *path, size_t size, const char *prefix, const char *name) +static int get_abs_path(char *path, size_t size, const char *prefix, const char *name) { - const char *dir; - char buffer[4096]; - - if (name[0] == '/') { - const char *paths[] = { name, NULL }; - if (make_path(path, size, paths) == 0 && - access(path, R_OK) == 0) - return 1; - return -ENOENT; - } - - if (prefix && prefix[0] == '/') { + if (prefix[0] == '/') { const char *paths[] = { prefix, name, NULL }; if (make_path(path, size, paths) == 0 && access(path, R_OK) == 0) return 1; return -ENOENT; } + return 0; +} - if (prefix == NULL) { - prefix = name; - name = NULL; - } - - if (pw_check_option("no-config", "true")) - goto no_config; +static int get_envconf_path(char *path, size_t size, const char *prefix, const char *name) +{ + const char *dir; dir = getenv("PIPEWIRE_CONFIG_DIR"); if (dir != NULL) { @@ -100,7 +89,15 @@ if (make_path(path, size, paths) == 0 && access(path, R_OK) == 0) return 1; + return -ENOENT; } + return 0; +} + +static int get_homeconf_path(char *path, size_t size, const char *prefix, const char *name) +{ + char buffer[4096]; + const char *dir; dir = getenv("XDG_CONFIG_HOME"); if (dir != NULL) { @@ -121,7 +118,12 @@ access(path, R_OK) == 0) return 1; } + return 0; +} +static int get_configdir_path(char *path, size_t size, const char *prefix, const char *name) +{ + const char *dir; dir = PIPEWIRE_CONFIG_DIR; if (dir != NULL) { const char *paths[] = { dir, prefix, name, NULL }; @@ -129,7 +131,12 @@ access(path, R_OK) == 0) return 1; } -no_config: + return 0; +} + +static int get_confdata_path(char *path, size_t size, const char *prefix, const char *name) +{ + const char *dir; dir = PIPEWIRE_CONFDATADIR; if (dir != NULL) { const char *paths[] = { dir, prefix, name, NULL }; @@ -140,39 +147,93 @@ return 0; } -static int get_state_path(char *path, size_t size, const char *prefix, const char *name) +static int get_config_path(char *path, size_t size, const char *prefix, const char *name) { - const char *dir; - char buffer[4096]; + int res; - if (name[0] == '/') { - const char *paths[] = { name, NULL }; - if (make_path(path, size, paths) == 0 && - access(path, R_OK) == 0) - return 1; - return -ENOENT; + if (prefix == NULL) { + prefix = name; + name = NULL; } + if ((res = get_abs_path(path, size, prefix, name)) != 0) + return res; - if (prefix && prefix[0] == '/') { - const char *paths[] = { prefix, name, NULL }; - if (make_path(path, size, paths) == 0 && - access(path, R_OK) == 0) - return 1; - return -ENOENT; - } + if (pw_check_option("no-config", "true")) + goto no_config; + + if ((res = get_envconf_path(path, size, prefix, name)) != 0) + return res; + + if ((res = get_homeconf_path(path, size, prefix, name)) != 0) + return res; + + if ((res = get_configdir_path(path, size, prefix, name)) != 0) + return res; +no_config: + if ((res = get_confdata_path(path, size, prefix, name)) != 0) + return res; + return 0; +} + +static int get_config_dir(char *path, size_t size, const char *prefix, const char *name, int *level) +{ + int res; if (prefix == NULL) { prefix = name; name = NULL; } + if ((res = get_abs_path(path, size, prefix, name)) != 0) { + if ((*level)++ == 0) + return res; + return -ENOENT; + } + + if ((res = get_envconf_path(path, size, prefix, name)) != 0) { + if ((*level)++ == 0) + return res; + return -ENOENT; + } + + if (*level == 0) { + (*level)++; + if ((res = get_confdata_path(path, size, prefix, name)) != 0) + return res; + } + if (pw_check_option("no-config", "true")) + return 0; + if (*level == 1) { + (*level)++; + if ((res = get_configdir_path(path, size, prefix, name)) != 0) + return res; + } + if (*level == 2) { + (*level)++; + if ((res = get_homeconf_path(path, size, prefix, name)) != 0) + return res; + } + return 0; +} + +static int get_envstate_path(char *path, size_t size, const char *prefix, const char *name) +{ + const char *dir; dir = getenv("PIPEWIRE_STATE_DIR"); if (dir != NULL) { const char *paths[] = { dir, prefix, name, NULL }; if (make_path(path, size, paths) == 0 && access(path, R_OK) == 0) return 1; + return -ENOENT;
View file
pipewire-0.3.44.tar.gz/src/pipewire/conf.h -> pipewire-0.3.45.tar.gz/src/pipewire/conf.h
Changed
@@ -37,8 +37,6 @@ int pw_conf_load_state(const char *prefix, const char *name, struct pw_properties *conf); int pw_conf_save_state(const char *prefix, const char *name, const struct pw_properties *conf); -int pw_context_parse_conf_section(struct pw_context *context, - struct pw_properties *conf, const char *section); /** * \}
View file
pipewire-0.3.44.tar.gz/src/pipewire/context.c -> pipewire-0.3.45.tar.gz/src/pipewire/context.c
Changed
@@ -273,10 +273,8 @@ n_support = pw_get_support(this->support, SPA_N_ELEMENTS(this->support) - 6); cpu = spa_support_find(this->support, n_support, SPA_TYPE_INTERFACE_CPU); - if ((str = pw_properties_get(conf, "context.properties")) != NULL) { - pw_properties_update_string(properties, str, strlen(str)); - pw_log_info("%p: parsed context.properties section", this); - } + res = pw_context_conf_update_props(this, "context.properties", properties); + pw_log_info("%p: parsed %d context.properties items", this, res); if ((str = getenv("PIPEWIRE_CORE"))) { pw_log_info("using core.name from environment: %s", str); @@ -1066,10 +1064,11 @@ int pw_context_recalc_graph(struct pw_context *context, const char *reason) { struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this); + struct settings *settings = &context->settings; 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, force_rate; + bool freewheel = false, global_force_rate, force_rate, global_force_quantum; pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason); @@ -1082,7 +1081,10 @@ impl->recalc = true; get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum); - rates = get_rates(context, &def_rate, &n_rates, &force_rate); + rates = get_rates(context, &def_rate, &n_rates, &global_force_rate); + + global_force_quantum = rate_quantum == 0; + force_rate = global_force_rate; /* start from all drivers and group all nodes that are linked * to it. Some nodes are not (yet) linked to anything and they @@ -1164,6 +1166,7 @@ struct spa_fraction max_latency = SPA_FRACTION(0, 0); struct spa_fraction rate = SPA_FRACTION(0, 0); uint32_t quantum, target_rate, current_rate; + uint64_t quantum_stamp = 0, rate_stamp = 0; if (!n->driving || n->exported) continue; @@ -1175,6 +1178,20 @@ lock_quantum |= s->lock_quantum; lock_rate |= s->lock_rate; } + if (!global_force_quantum && s->force_quantum > 0 && + s->stamp > quantum_stamp) { + def_quantum = min_quantum = max_quantum = s->force_quantum; + rate_quantum = 0; + quantum_stamp = s->stamp; + } + if (!global_force_rate && s->force_rate > 0 && + s->stamp > rate_stamp) { + def_rate = s->force_rate; + force_rate = true; + n_rates = 1; + rates = &s->force_rate; + rate_stamp = s->stamp; + } /* smallest latencies */ if (latency.denom == 0 || @@ -1221,7 +1238,7 @@ target_rate); if (force_rate) { - if (context->settings.clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD) + if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD) suspend_driver(context, n); } else { if (n->info.state >= PW_NODE_STATE_IDLE) @@ -1253,7 +1270,7 @@ quantum = SPA_CLAMP(quantum, min_quantum, max_quantum); quantum = SPA_MIN(quantum, lim_quantum); - if (context->settings.clock_power_of_two_quantum) + if (settings->clock_power_of_two_quantum) quantum = flp2(quantum); if (running && quantum != n->current_quantum && !lock_quantum) {
View file
pipewire-0.3.44.tar.gz/src/pipewire/context.h -> pipewire-0.3.45.tar.gz/src/pipewire/context.h
Changed
@@ -108,8 +108,21 @@ /** Update the context properties */ int pw_context_update_properties(struct pw_context *context, const struct spa_dict *dict); -/** Get a config section for this context. Since 0.3.22 */ +/** Get a config section for this context. Since 0.3.22, deprecated, + * use pw_context_conf_section_for_each(). */ const char *pw_context_get_conf_section(struct pw_context *context, const char *section); +/** Parse a standard config section for this context. Since 0.3.22 */ +int pw_context_parse_conf_section(struct pw_context *context, + struct pw_properties *conf, const char *section); + +/** update properties from a section into props. Since 0.3.45 */ +int pw_context_conf_update_props(struct pw_context *context, const char *section, + struct pw_properties *props); +/** emit callback for all config sections. Since 0.3.45 */ +int pw_context_conf_section_for_each(struct pw_context *context, const char *section, + int (*callback) (void *data, const char *location, const char *section, + 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.44.tar.gz/src/pipewire/data-loop.c -> pipewire-0.3.45.tar.gz/src/pipewire/data-loop.c
Changed
@@ -90,11 +90,13 @@ return NULL; } -static void do_stop(void *data, uint64_t count) +static int do_stop(struct spa_loop *loop, bool async, uint32_t seq, + const void *data, size_t size, void *user_data) { - struct pw_data_loop *this = data; + struct pw_data_loop *this = user_data; pw_log_debug("%p: stopping", this); this->running = false; + return 0; } static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props) @@ -122,23 +124,14 @@ } this->loop = loop; - if (props == NULL || - (str = spa_dict_lookup(props, "loop.cancel")) == NULL || - pw_properties_parse_bool(str) == false) { - this->event = pw_loop_add_event(this->loop, do_stop, this); - if (this->event == NULL) { - res = -errno; - pw_log_error("%p: can't add event: %m", this); - goto error_loop_destroy; - } - } + if (props != NULL && + (str = spa_dict_lookup(props, "loop.cancel")) != NULL) + this->cancel = pw_properties_parse_bool(str); + spa_hook_list_init(&this->listener_list); return this; -error_loop_destroy: - if (this->created && this->loop) - pw_loop_destroy(this->loop); error_free: free(this); error_cleanup: @@ -169,8 +162,6 @@ pw_data_loop_stop(loop); - if (loop->event) - pw_loop_destroy_source(loop->loop, loop->event); if (loop->created) pw_loop_destroy(loop->loop); @@ -232,12 +223,12 @@ { pw_log_debug("%p stopping", loop); if (loop->running) { - if (loop->event) { - pw_log_debug("%p signal", loop); - pw_loop_signal_event(loop->loop, loop->event); - } else { + if (loop->cancel) { pw_log_debug("%p cancel", loop); pthread_cancel(loop->thread); + } else { + pw_log_debug("%p signal", loop); + pw_loop_invoke(loop->loop, do_stop, 1, NULL, 0, false, loop); } pw_log_debug("%p join", loop); pw_thread_utils_join((struct spa_thread*)loop->thread, NULL);
View file
pipewire-0.3.44.tar.gz/src/pipewire/filter.c -> pipewire-0.3.45.tar.gz/src/pipewire/filter.c
Changed
@@ -1209,8 +1209,7 @@ res = -errno; goto error_properties; } - if ((str = pw_context_get_conf_section(context, "filter.properties")) != NULL) - pw_properties_update_string(props, str, strlen(str)); + pw_context_conf_update_props(context, "filter.properties", props); if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) { str = pw_properties_get(extra, PW_KEY_APP_NAME);
View file
pipewire-0.3.44.tar.gz/src/pipewire/global.c -> pipewire-0.3.45.tar.gz/src/pipewire/global.c
Changed
@@ -36,8 +36,6 @@ PW_LOG_TOPIC_EXTERN(log_global); #define PW_LOG_TOPIC_DEFAULT log_global -static uint64_t serial = 0; - /** \cond */ struct impl { struct pw_global this; @@ -122,10 +120,11 @@ SPA_EXPORT uint64_t pw_global_get_serial(struct pw_global *global) { + struct pw_context *context = global->context; if (global->serial == SPA_ID_INVALID) - global->serial = serial++; - if ((uint32_t)serial == SPA_ID_INVALID) - serial++; + global->serial = context->serial++; + if ((uint32_t)context->serial == SPA_ID_INVALID) + context->serial++; return global->serial; }
View file
pipewire-0.3.44.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.45.tar.gz/src/pipewire/impl-node.c
Changed
@@ -857,6 +857,7 @@ struct pw_context *context = node->context; const char *str, *recalc_reason = NULL; struct spa_fraction frac; + uint32_t value; bool driver; if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) { @@ -935,6 +936,15 @@ } node->lock_quantum = pw_properties_get_bool(node->properties, PW_KEY_NODE_LOCK_QUANTUM, false); + if ((str = pw_properties_get(node->properties, PW_KEY_NODE_FORCE_QUANTUM))) { + if (spa_atou32(str, &value, 0) && + node->force_quantum != value) { + node->force_quantum = value; + node->stamp = ++context->stamp; + recalc_reason = "force quantum changed"; + } + } + if ((str = pw_properties_get(node->properties, PW_KEY_NODE_RATE))) { if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) { if (node->rate.num != frac.num || node->rate.denom != frac.denom) { @@ -948,6 +958,15 @@ } node->lock_rate = pw_properties_get_bool(node->properties, PW_KEY_NODE_LOCK_RATE, false); + if ((str = pw_properties_get(node->properties, PW_KEY_NODE_FORCE_RATE))) { + if (spa_atou32(str, &value, 0) && + node->force_rate != value) { + node->force_rate = value; + node->stamp = ++context->stamp; + recalc_reason = "force rate changed"; + } + } + pw_log_debug("%p: driver:%d recalc:%s active:%d", node, node->driver, recalc_reason, node->active); @@ -1787,6 +1806,7 @@ struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this); struct pw_impl_port *port; struct pw_impl_node *follower; + struct pw_context *context = node->context; bool active, had_driver; active = node->active; @@ -1836,7 +1856,7 @@ } if (active || had_driver) - pw_context_recalc_graph(node->context, + pw_context_recalc_graph(context, "active node destroy"); pw_log_debug("%p: free", node); @@ -1858,7 +1878,7 @@ clear_info(node); - spa_system_close(node->context->data_system, node->source.fd); + spa_system_close(context->data_system, node->source.fd); free(impl); }
View file
pipewire-0.3.44.tar.gz/src/pipewire/keys.h -> pipewire-0.3.45.tar.gz/src/pipewire/keys.h
Changed
@@ -161,10 +161,14 @@ * node as a fraction. Ex: 1024/48000 */ #define PW_KEY_NODE_LOCK_QUANTUM "node.lock-quantum" /**< don't change quantum when this node * is active */ +#define PW_KEY_NODE_FORCE_QUANTUM "node.force-quantum" /**< force a quantum while the node is + * active */ #define PW_KEY_NODE_RATE "node.rate" /**< the requested rate of the graph as * a fraction. Ex: 1/48000 */ #define PW_KEY_NODE_LOCK_RATE "node.lock-rate" /**< don't change rate when this node * is active */ +#define PW_KEY_NODE_FORCE_RATE "node.force-rate" /**< force a rate while the node is + * active */ #define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect" /**< don't reconnect this node */ #define PW_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< process even when unlinked */
View file
pipewire-0.3.44.tar.gz/src/pipewire/log.h -> pipewire-0.3.45.tar.gz/src/pipewire/log.h
Changed
@@ -140,6 +140,11 @@ #define pw_log_level_enabled(lev) (pw_log_level >= (lev)) #define pw_log_topic_enabled(lev,t) ((t) && (t)->has_custom_level ? (t)->level >= (lev) : pw_log_level_enabled((lev))) +#define pw_logtv(lev,topic,fmt,ap) \ +({ \ + if (SPA_UNLIKELY(pw_log_topic_enabled(lev,topic))) \ + pw_log_logtv(lev,topic,__FILE__,__LINE__,__func__,fmt,ap); \ +}) #define pw_logt(lev,topic,...) \ ({ \
View file
pipewire-0.3.44.tar.gz/src/pipewire/main-loop.c -> pipewire-0.3.45.tar.gz/src/pipewire/main-loop.c
Changed
@@ -29,11 +29,13 @@ PW_LOG_TOPIC_EXTERN(log_main_loop); #define PW_LOG_TOPIC_DEFAULT log_main_loop -static void do_stop(void *data, uint64_t count) +static int do_stop(struct spa_loop *loop, bool async, uint32_t seq, + const void *data, size_t size, void *user_data) { - struct pw_main_loop *this = data; + struct pw_main_loop *this = user_data; pw_log_debug("%p: do stop", this); this->running = false; + return 0; } static struct pw_main_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props) @@ -59,19 +61,10 @@ } this->loop = loop; - this->event = pw_loop_add_event(this->loop, do_stop, this); - if (this->event == NULL) { - res = -errno; - goto error_free_loop; - } - spa_hook_list_init(&this->listener_list); return this; -error_free_loop: - if (this->created && this->loop) - pw_loop_destroy(this->loop); error_free: free(this); error_cleanup: @@ -132,7 +125,7 @@ int pw_main_loop_quit(struct pw_main_loop *loop) { pw_log_debug("%p: quit", loop); - return pw_loop_signal_event(loop->loop, loop->event); + return pw_loop_invoke(loop->loop, do_stop, 1, NULL, 0, false, loop); } /** Start a main loop
View file
pipewire-0.3.44.tar.gz/src/pipewire/mem.c -> pipewire-0.3.45.tar.gz/src/pipewire/mem.c
Changed
@@ -508,6 +508,7 @@ } unlink(filename); #endif + pw_log_debug("%p: new fd:%d", pool, b->this.fd); if (ftruncate(b->this.fd, size) < 0) { res = -errno; @@ -535,7 +536,8 @@ b->this.id = pw_map_insert_new(&impl->map, b); spa_list_append(&impl->blocks, &b->link); - pw_log_debug("%p: block:%p id:%d type:%u size:%zu", pool, &b->this, b->this.id, type, size); + pw_log_debug("%p: block:%p id:%d type:%u size:%zu", pool, + &b->this, b->this.id, type, size); if (!SPA_FLAG_IS_SET(flags, PW_MEMBLOCK_FLAG_DONT_NOTIFY)) pw_mempool_emit_added(impl, &b->this);
View file
pipewire-0.3.44.tar.gz/src/pipewire/private.h -> pipewire-0.3.45.tar.gz/src/pipewire/private.h
Changed
@@ -360,7 +360,11 @@ buffer[1023] = '\0'; pw_log_debug("resource %p: id:%d seq:%d res:%d (%s) msg:\"%s\"", resource, id, seq, res, spa_strerror(res), buffer); - pw_core_resource_error(resource, id, seq, res, buffer); + if (resource) + pw_core_resource_error(resource, id, seq, res, buffer); + else + pw_log_error("id:%d seq:%d res:%d (%s) msg:\"%s\"", + id, seq, res, spa_strerror(res), buffer); } static inline SPA_PRINTF_FUNC(5,6) void @@ -424,6 +428,8 @@ struct pw_mempool *pool; /**< global memory pool */ + uint64_t stamp; + uint64_t serial; struct pw_map globals; /**< map of globals */ struct spa_list core_impl_list; /**< list of core_imp */ @@ -472,9 +478,9 @@ struct pw_loop *loop; struct spa_hook_list listener_list; - struct spa_source *event; pthread_t thread; + unsigned int cancel:1; unsigned int created:1; unsigned int running:1; }; @@ -486,7 +492,6 @@ struct pw_loop *loop; struct spa_hook_list listener_list; - struct spa_source *event; unsigned int created:1; unsigned int running:1; @@ -713,6 +718,9 @@ struct spa_fraction latency; /**< requested latency */ struct spa_fraction max_latency; /**< maximum latency */ struct spa_fraction rate; /**< requested rate */ + uint32_t force_quantum; /**< forced quantum */ + uint32_t force_rate; /**< forced rate */ + uint32_t stamp; /**< stamp of last update */ struct spa_source source; /**< source to remotely trigger this node */ struct pw_memblock *activation; struct {
View file
pipewire-0.3.44.tar.gz/src/pipewire/resource.c -> pipewire-0.3.45.tar.gz/src/pipewire/resource.c
Changed
@@ -31,8 +31,8 @@ #include <spa/debug/types.h> -PW_LOG_TOPIC_EXTERN(log_device); -#define PW_LOG_TOPIC_DEFAULT log_device +PW_LOG_TOPIC_EXTERN(log_resource); +#define PW_LOG_TOPIC_DEFAULT log_resource /** \cond */ struct impl { @@ -228,10 +228,16 @@ static void SPA_PRINTF_FUNC(4, 0) pw_resource_errorv_id(struct pw_resource *resource, uint32_t id, int res, const char *error, va_list ap) { - struct pw_impl_client *client = resource->client; - if (client->core_resource != NULL) - pw_core_resource_errorv(client->core_resource, - id, client->recv_seq, res, error, ap); + struct pw_impl_client *client; + + if (resource) { + client = resource->client; + if (client->core_resource != NULL) + pw_core_resource_errorv(client->core_resource, + id, client->recv_seq, res, error, ap); + } else { + pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap); + } } SPA_EXPORT @@ -239,7 +245,10 @@ { va_list ap; va_start(ap, error); - pw_resource_errorv_id(resource, resource->id, res, error, ap); + if (resource) + pw_resource_errorv_id(resource, resource->id, res, error, ap); + else + pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap); va_end(ap); } @@ -248,17 +257,25 @@ { va_list ap; va_start(ap, error); - pw_resource_errorv_id(resource, id, res, error, ap); + if (resource) + pw_resource_errorv_id(resource, id, res, error, ap); + else + pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap); va_end(ap); } SPA_EXPORT void pw_resource_error(struct pw_resource *resource, int res, const char *error) { - struct pw_impl_client *client = resource->client; - if (client->core_resource != NULL) - pw_core_resource_error(client->core_resource, - resource->id, client->recv_seq, res, error); + struct pw_impl_client *client; + if (resource) { + client = resource->client; + if (client->core_resource != NULL) + pw_core_resource_error(client->core_resource, + resource->id, client->recv_seq, res, error); + } else { + pw_log_error("%s: %s", error, spa_strerror(res)); + } } SPA_EXPORT
View file
pipewire-0.3.44.tar.gz/src/pipewire/stream.c -> pipewire-0.3.45.tar.gz/src/pipewire/stream.c
Changed
@@ -1342,8 +1342,7 @@ res = -errno; goto error_properties; } - if ((str = pw_context_get_conf_section(context, "stream.properties")) != NULL) - pw_properties_update_string(props, str, strlen(str)); + pw_context_conf_update_props(context, "stream.properties", props); if (pw_properties_get(props, PW_KEY_STREAM_IS_LIVE) == NULL) pw_properties_set(props, PW_KEY_STREAM_IS_LIVE, "true");
View file
pipewire-0.3.44.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.45.tar.gz/src/tools/pw-cli.c
Changed
@@ -36,6 +36,10 @@ #include <readline/readline.h> #include <readline/history.h> +#if !defined(FNM_EXTMATCH) +#define FNM_EXTMATCH 0 +#endif + #define spa_debug(...) fprintf(stdout,__VA_ARGS__);fputc('\n', stdout) #include <spa/utils/result.h> @@ -211,6 +215,7 @@ static bool do_set_param(struct data *data, const char *cmd, char *args, char **error); static bool do_permissions(struct data *data, const char *cmd, char *args, char **error); static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error); +static bool do_send_command(struct data *data, const char *cmd, char *args, char **error); static bool do_dump(struct data *data, const char *cmd, char *args, char **error); static bool do_quit(struct data *data, const char *cmd, char *args, char **error); @@ -235,6 +240,7 @@ { "set-param", "s", "Set param of an object <object-id> <param-id> <param-json>", do_set_param }, { "permissions", "sp", "Set permissions for a client <client-id> <object> <permission>", do_permissions }, { "get-permissions", "gp", "Get permissions of a client <client-id>", do_get_permissions }, + { "send-command", "c", "Send a command <object-id>", do_send_command }, { "dump", "D", "Dump objects in ways that are cleaner for humans to understand " "[short|deep|resolve|notype] [-sdrt] [all|"DUMP_NAMES"|<id>]", do_dump }, { "quit", "q", "Quit", do_quit }, @@ -1772,6 +1778,59 @@ return true; } +static bool do_send_command(struct data *data, const char *cmd, char *args, char **error) +{ + struct remote_data *rd = data->current; + char *a[3]; + int res, n; + struct global *global; + uint8_t buffer[1024]; + struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + const struct spa_type_info *ti; + struct spa_pod *pod; + + n = pw_split_ip(args, WHITESPACE, 3, a); + if (n < 3) { + *error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd); + return false; + } + + global = find_global(rd, a[0]); + if (global == NULL) { + *error = spa_aprintf("%s: unknown global '%s'", cmd, a[0]); + return false; + } + if (global->proxy == NULL) { + if (!bind_global(rd, global, error)) + return false; + } + + if (spa_streq(global->type, PW_TYPE_INTERFACE_Node)) { + ti = spa_debug_type_find_short(spa_type_node_command_id, a[1]); + } else { + *error = spa_aprintf("send-command not implemented on object %d type:%s", + atoi(a[0]), global->type); + return false; + } + + if (ti == NULL) { + *error = spa_aprintf("%s: unknown node command type: %s", cmd, a[1]); + return false; + } + if ((res = spa_json_to_pod(&b, 0, ti, a[2], strlen(a[2]))) < 0) { + *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); + return false; + } + if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) { + *error = spa_aprintf("%s: can't make pod", cmd); + return false; + } + spa_debug_pod(0, NULL, pod); + + pw_node_send_command((struct pw_node*)global->proxy, (struct spa_command*)pod); + return true; +} + static const char * pw_interface_short(const char *type) {
View file
pipewire-0.3.44.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.45.tar.gz/src/tools/pw-dump.c
Changed
@@ -32,6 +32,10 @@ #include <math.h> #include <fnmatch.h> +#if !defined(FNM_EXTMATCH) +#define FNM_EXTMATCH 0 +#endif + #include <spa/utils/result.h> #include <spa/utils/string.h> #include <spa/pod/iter.h>
View file
pipewire-0.3.44.tar.gz/test/test-config.c -> pipewire-0.3.45.tar.gz/test/test-config.c
Changed
@@ -46,6 +46,7 @@ pwtest_str_eq(pw_properties_get(props, "data"), "x"); pw_properties_free(props); +#if 0 /* Load with non-NULL abs prefix and abs path */ props = pw_properties_new("ignore", "me", NULL); r = pw_conf_load_conf("/dummy", path, props); @@ -59,6 +60,7 @@ pwtest_neg_errno_ok(r); pwtest_str_eq(pw_properties_get(props, "data"), "x"); pw_properties_free(props); +#endif /* Load with non-NULL abs prefix and relative path */ basename = rindex(path, '/'); /* basename(3) and dirname(3) are terrible */
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
.