Overview
pipewire-aptx.changes
Changed
x
1
2
-------------------------------------------------------------------
3
+Fri Feb 4 06:41:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
4
+
5
+- Update to version 0.3.45
6
+ * Add explicit pipewire-spa-plugins-0_2 Requires.
7
+
8
+-------------------------------------------------------------------
9
Sun Jan 30 16:36:30 UTC 2022 - Bjørn Lie <zaitor@opensuse.org>
10
11
- Update to version 0.3.44
12
pipewire-aptx.spec
Changed
27
1
2
%define soversion 0_2
3
4
Name: pipewire-aptx
5
-Version: 0.3.44
6
+Version: 0.3.45
7
Release: 0
8
Summary: PipeWire Bluetooth aptX codec plugin
9
License: MIT
10
11
12
BuildRequires: c++_compiler
13
BuildRequires: c_compiler
14
-BuildRequires: meson >= 0.49.0
15
+BuildRequires: meson >= 0.59.0
16
BuildRequires: pkgconfig
17
BuildRequires: pkgconfig(bluez)
18
BuildRequires: pkgconfig(dbus-1)
19
20
BuildRequires: pkgconfig(sbc)
21
22
Requires: pipewire >= %{version}
23
+Requires: pipewire-spa-plugins-%{soversion} >= %{version}
24
Supplements: (pipewire and pipewire-spa-plugins-%{soversion})
25
26
%description
27
pipewire-0.3.44.tar.gz/.gitlab-ci.yml -> pipewire-0.3.45.tar.gz/.gitlab-ci.yml
Changed
124
1
2
- project: 'freedesktop/ci-templates'
3
ref: *templates_sha
4
file: '/templates/ubuntu.yml'
5
+ - project: 'freedesktop/ci-templates'
6
+ ref: *templates_sha
7
+ file: '/templates/alpine.yml'
8
9
.fedora:
10
variables:
11
# Update this tag when you want to trigger a rebuild
12
- FDO_DISTRIBUTION_TAG: '2022-01-27.1'
13
+ FDO_DISTRIBUTION_TAG: '2022-01-28.0'
14
FDO_DISTRIBUTION_VERSION: '35'
15
FDO_DISTRIBUTION_PACKAGES: >-
16
alsa-lib-devel
17
+ avahi-devel
18
bluez-libs-devel
19
clang
20
dbus-devel
21
doxygen
22
+ fdk-aac-free-devel
23
findutils
24
gcc
25
gcc-c++
26
27
gstreamer1-devel
28
gstreamer1-plugins-base-devel
29
jack-audio-connection-kit-devel
30
+ libcanberra-devel
31
+ libldac-devel
32
libsndfile-devel
33
+ libusb-devel
34
+ lilv-devel
35
libv4l-devel
36
libva-devel
37
libX11-devel
38
+ openssl-devel
39
pulseaudio-libs-devel
40
python3-docutils
41
sbc-devel
42
43
FDO_DISTRIBUTION_EXEC: >-
44
pip3 install meson
45
46
+.alpine:
47
+ variables:
48
+ # Update this tag when you want to trigger a rebuild
49
+ FDO_DISTRIBUTION_TAG: '2022-01-28.2'
50
+ FDO_DISTRIBUTION_VERSION: '3.15'
51
+ FDO_DISTRIBUTION_PACKAGES: >-
52
+ alsa-lib-dev
53
+ avahi-dev
54
+ bash
55
+ bluez-dev
56
+ gcc
57
+ g++
58
+ dbus-dev
59
+ doxygen
60
+ eudev-dev
61
+ fdk-aac-dev
62
+ git
63
+ glib-dev
64
+ graphviz
65
+ gst-plugins-base-dev
66
+ gstreamer-dev
67
+ jack-dev
68
+ libfreeaptx-dev
69
+ libusb-dev
70
+ libx11-dev
71
+ meson
72
+ ncurses-dev
73
+ pulseaudio-dev
74
+ readline-dev
75
+ sbc-dev
76
+ vulkan-loader-dev
77
+ xmltoman
78
+
79
.coverity:
80
variables:
81
FDO_REPO_SUFFIX: 'coverity'
82
83
variables:
84
GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
85
86
+container_alpine:
87
+ extends:
88
+ - .alpine
89
+ - .fdo.container-build@alpine
90
+ stage: container
91
+ variables:
92
+ GIT_STRATEGY: none # no need to pull the whole tree for rebuilding the image
93
+
94
container_coverity:
95
extends:
96
- .fedora
97
98
- build-*/meson-logs
99
- prefix-*
100
101
+build_on_alpine:
102
+ extends:
103
+ - .alpine
104
+ - .not_coverity
105
+ - .fdo.distribution-image@alpine
106
+ - .build
107
+ stage: build
108
+
109
+# build with all auto() options enabled
110
+build_all:
111
+ extends:
112
+ - .build_on_fedora
113
+ variables:
114
+ # Fedora doesn't have libfreeaptx or roc
115
+ # libcamera has no stable API, so let's not chase that target
116
+ MESON_OPTIONS: "-Dauto_features=enabled -Dbluez5-codec-aptx=disabled -Droc=disabled -Dlibcamera=disabled"
117
+ parallel:
118
+ matrix:
119
+ - CC: [gcc, clang]
120
+
121
# build with all options on auto() or their default values
122
build_with_no_commandline_options:
123
extends:
124
pipewire-0.3.44.tar.gz/NEWS -> pipewire-0.3.45.tar.gz/NEWS
Changed
82
1
2
+# PipeWire 0.3.45 (2022-02-03)
3
+
4
+This is a bugfix release that is API and ABI compatible with previous
5
+0.3.x releases.
6
+
7
+## Highlights
8
+ - Zoom, telegram and other apps should be able to play sound again.
9
+ - Implement a better way to force and lock JACK buffersize.
10
+ - Default sink and source names and properties are improved.
11
+ - The config loader can now load and merge fragments in conf.d directories
12
+ for easier user configuration of config files.
13
+ - Many small bug fixes and improvements.
14
+
15
+## PipeWire
16
+ - pw-cli can now also send Commands to nodes. This can be used to Suspend
17
+ a device, for example.
18
+ - The eventfd was removed from loops and invoke is now used to stop the loop,
19
+ this saves an fd.
20
+ - New Alpine CI target to test musl builds, various build fixes.
21
+ - Add force-quantum and force-rate properties.
22
+ - The config loader can now load and merge fragments in conf.d directories.
23
+ (#207)
24
+ - resource error methods can be called without a resource and then just
25
+ log an error message.
26
+ - link-factory can now also work from the config. (#2095)
27
+
28
+## modules
29
+ - module-simple-protocol has better argument parsing and can handle
30
+ channelmap now. (#2068) It's also possible to configure latency and
31
+ rate.
32
+ - The native protocol now does extra checks for invalid data. (#2070)
33
+
34
+## ALSA
35
+ - TI2902 chips as found in various Behringer cards should have inputs
36
+ again.
37
+ - Better handling of busy devices in udev, retry when the inotify close
38
+ event is emited.
39
+
40
+## SPA
41
+ - plugins now handle alignment properly and only expect the max alignment
42
+ required for the CPU. (#2074)
43
+
44
+## Bluetooth
45
+ - SBC-XQ is now enabled for the JBL Endurance RUN BT headset.
46
+ - Support for non-hexadecimal XAPL version strings to improve compatibility.
47
+ - Use HCI commands again to probe the adapter msbc capability. This improves
48
+ compatibility with some adapters. (#2030)
49
+ - Set the right startup volume.
50
+ - Better A2DP source idle handling.
51
+ - Fix a timer bug in SCO sink that could cause busy looping.
52
+
53
+## pulse-server
54
+ - A playback issue when the tlength > maxlength was fixed. (#2069) This
55
+ affected Zoom and other applications.
56
+ - The STREAM_BUFFER_ATTR command is now implemented.
57
+ - Module names are improved. (#2076)
58
+ - Many small fixes and improvements.
59
+ - Fix a pavucontrol crash with invalid channels. (#1442)
60
+
61
+## JACK
62
+ - Use the new force-quantum and force-rate properties in the JACK API to
63
+ switch quantum and ensure it can't change for the lifetime of the JACK
64
+ app. (#2079)
65
+
66
+Older versions:
67
+
68
+
69
# PipeWire 0.3.44 (2022-01-27)
70
71
This is a bugfix release that is API and ABI compatible with previous
72
73
properties can also be configured.
74
- Fix a regression in telegram sounds not playing.
75
76
-
77
-Older versions:
78
-
79
# PipeWire 0.3.43 (2022-01-05)
80
81
This is a bugfix release that is API and ABI compatible with previous
82
pipewire-0.3.44.tar.gz/meson.build -> pipewire-0.3.45.tar.gz/meson.build
Changed
34
1
2
project('pipewire', ['c' ],
3
- version : '0.3.44',
4
+ version : '0.3.45',
5
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
6
meson_version : '>= 0.59.0',
7
default_options : [ 'warning_level=3',
8
9
'-Wmissing-braces',
10
'-Wtype-limits',
11
'-Wvariadic-macros',
12
+ '-Wmaybe-uninitialized',
13
'-Wno-missing-field-initializers',
14
'-Wno-unused-parameter',
15
'-Wno-pedantic',
16
'-Wold-style-declaration',
17
+ '-Wdeprecated-declarations',
18
'-Wunused-result',
19
]
20
21
22
: dependency('', required: false))
23
24
# On FreeBSD, libintl library is required for gettext
25
-libintl_dep = dependency('intl', required: false)
26
-
27
+libintl_dep = cc.find_library('intl', required: false)
28
if not libintl_dep.found()
29
- libintl_dep = cc.find_library('intl', required: false)
30
+ libintl_dep = dependency('intl', required: false)
31
endif
32
summary({'intl support': libintl_dep.found()}, bool_yn: true)
33
34
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
10
1
2
}
3
4
int pw_jack_match_rules(const char *rules, size_t size, const struct spa_dict *props,
5
- int (*matched) (void *data, const char *action, const char *val, int len),
6
+ int (*matched) (void *data, const char *action, const char *val, size_t len),
7
void *data)
8
{
9
const char *val;
10
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
110
1
2
3
struct metadata {
4
struct pw_metadata *proxy;
5
+ struct spa_hook proxy_listener;
6
struct spa_hook listener;
7
8
char default_audio_sink[1024];
9
10
pw_log_warn("sync requested from callback");
11
return 0;
12
}
13
+ if (client->error)
14
+ return client->last_res;
15
16
client->pending_sync = pw_proxy_sync((struct pw_proxy*)client->core, client->pending_sync);
17
18
19
.property = metadata_property
20
};
21
22
+static void metadata_proxy_removed(void *data)
23
+{
24
+ struct client *c = data;
25
+ pw_proxy_destroy((struct pw_proxy*)c->metadata->proxy);
26
+}
27
+
28
+static void metadata_proxy_destroy(void *data)
29
+{
30
+ struct client *c = data;
31
+ spa_hook_remove(&c->metadata->proxy_listener);
32
+ spa_hook_remove(&c->metadata->listener);
33
+ c->metadata = NULL;
34
+}
35
+
36
+static const struct pw_proxy_events metadata_proxy_events = {
37
+ PW_VERSION_PROXY_EVENTS,
38
+ .removed = metadata_proxy_removed,
39
+ .destroy = metadata_proxy_destroy,
40
+};
41
+
42
static void proxy_removed(void *data)
43
{
44
struct object *o = data;
45
46
c->metadata->default_audio_sink[0] = '\0';
47
c->metadata->default_audio_source[0] = '\0';
48
49
+ pw_proxy_add_listener(proxy,
50
+ &c->metadata->proxy_listener,
51
+ &metadata_proxy_events, c);
52
pw_metadata_add_listener(proxy,
53
&c->metadata->listener,
54
&metadata_events, c);
55
56
return 1;
57
}
58
59
+static int apply_jack_rules(void *data, const char *location, const char *section,
60
+ const char *str, size_t len)
61
+{
62
+ struct client *client = data;
63
+ const struct pw_properties *p =
64
+ pw_context_get_properties(client->context.context);
65
+
66
+ if (p != NULL)
67
+ pw_jack_match_rules(str, len, &p->dict, execute_match, client);
68
+
69
+ return 0;
70
+}
71
+
72
SPA_EXPORT
73
jack_client_t * jack_client_open (const char *client_name,
74
jack_options_t options,
75
76
client->allow_mlock = client->context.context->settings.mem_allow_mlock;
77
client->warn_mlock = client->context.context->settings.mem_warn_mlock;
78
79
- if ((str = pw_context_get_conf_section(client->context.context,
80
- "jack.properties")) != NULL)
81
- pw_properties_update_string(client->props, str, strlen(str));
82
+ pw_context_conf_update_props(client->context.context,
83
+ "jack.properties", client->props);
84
85
if ((str = getenv("PIPEWIRE_PROPS")) != NULL)
86
pw_properties_update_string(client->props, str, strlen(str));
87
88
89
- if ((str = pw_context_get_conf_section(client->context.context,
90
- "jack.rules")) != NULL) {
91
- const struct pw_properties *p =
92
- pw_context_get_properties(client->context.context);
93
- if (p != NULL)
94
- pw_jack_match_rules(str, strlen(str), &p->dict,
95
- execute_match, client);
96
- }
97
+ pw_context_conf_section_for_each(client->context.context, "jack.rules",
98
+ apply_jack_rules, client);
99
100
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
101
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", false);
102
103
104
pw_thread_loop_lock(c->context.loop);
105
pw_properties_set(c->props, PW_KEY_NODE_LATENCY, latency);
106
+ pw_properties_setf(c->props, PW_KEY_NODE_FORCE_QUANTUM, "%u", nframes);
107
108
c->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS;
109
c->info.props = &c->props->dict;
110
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
10
1
2
#define SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE SPA_TYPE_INFO_DeviceEventId ":"
3
4
static const struct spa_type_info spa_type_device_event_id[] = {
5
- { SPA_DEVICE_EVENT_ObjectConfig, SPA_TYPE_Int, SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE "ObjectConfig", NULL },
6
+ { SPA_DEVICE_EVENT_ObjectConfig, SPA_TYPE_EVENT_Device, SPA_TYPE_INFO_DEVICE_EVENT_ID_BASE "ObjectConfig", NULL },
7
{ 0, 0, NULL, NULL },
8
};
9
10
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
45
1
2
#define SPA_TYPE_INFO_NODE_EVENT_BASE SPA_TYPE_INFO_NodeEvent ":"
3
4
static const struct spa_type_info spa_type_node_event_id[] = {
5
- { SPA_NODE_EVENT_Error, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL },
6
- { SPA_NODE_EVENT_Buffering, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL },
7
- { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL },
8
- { SPA_NODE_EVENT_RequestProcess, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestProcess", NULL },
9
+ { SPA_NODE_EVENT_Error, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "Error", NULL },
10
+ { SPA_NODE_EVENT_Buffering, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "Buffering", NULL },
11
+ { SPA_NODE_EVENT_RequestRefresh, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestRefresh", NULL },
12
+ { SPA_NODE_EVENT_RequestProcess, SPA_TYPE_EVENT_Node, SPA_TYPE_INFO_NODE_EVENT_BASE "RequestProcess", NULL },
13
{ 0, 0, NULL, NULL },
14
};
15
16
17
#define SPA_TYPE_INFO_NODE_COMMAND_BASE SPA_TYPE_INFO_NodeCommand ":"
18
19
static const struct spa_type_info spa_type_node_command_id[] = {
20
- { SPA_NODE_COMMAND_Suspend, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL },
21
- { SPA_NODE_COMMAND_Pause, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL },
22
- { SPA_NODE_COMMAND_Start, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL },
23
- { SPA_NODE_COMMAND_Enable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL },
24
- { SPA_NODE_COMMAND_Disable, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL },
25
- { SPA_NODE_COMMAND_Flush, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL },
26
- { SPA_NODE_COMMAND_Drain, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL },
27
- { SPA_NODE_COMMAND_Marker, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL },
28
- { SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL },
29
- { SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL },
30
- { SPA_NODE_COMMAND_RequestProcess, SPA_TYPE_Int, SPA_TYPE_INFO_NODE_COMMAND_BASE "RequestProcess", NULL },
31
+ { SPA_NODE_COMMAND_Suspend, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Suspend", NULL },
32
+ { SPA_NODE_COMMAND_Pause, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Pause", NULL },
33
+ { SPA_NODE_COMMAND_Start, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Start", NULL },
34
+ { SPA_NODE_COMMAND_Enable, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Enable", NULL },
35
+ { SPA_NODE_COMMAND_Disable, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Disable", NULL },
36
+ { SPA_NODE_COMMAND_Flush, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Flush", NULL },
37
+ { SPA_NODE_COMMAND_Drain, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Drain", NULL },
38
+ { SPA_NODE_COMMAND_Marker, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "Marker", NULL },
39
+ { SPA_NODE_COMMAND_ParamBegin, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamBegin", NULL },
40
+ { SPA_NODE_COMMAND_ParamEnd, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "ParamEnd", NULL },
41
+ { SPA_NODE_COMMAND_RequestProcess, SPA_TYPE_COMMAND_Node, SPA_TYPE_INFO_NODE_COMMAND_BASE "RequestProcess", NULL },
42
{ 0, 0, NULL, NULL },
43
};
44
45
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
10
1
2
ATTRS{idVendor}=="041e", ATTRS{idProduct}=="322c", ENV{ACP_PROFILE_SET}="sb-omni-surround-5.1.conf"
3
ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="4014", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
4
ATTRS{idVendor}=="0bda", ATTRS{idProduct}=="402e", ENV{ACP_PROFILE_SET}="dell-dock-tb16-usb-audio.conf"
5
-#ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf"
6
+ATTRS{idVendor}=="08bb", ATTRS{idProduct}=="2902", ENV{ACP_PROFILE_SET}="texas-instruments-pcm2902.conf"
7
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0269", ENV{ACP_PROFILE_SET}="hp-tbt-dock-120w-g2.conf"
8
ATTRS{idVendor}=="03f0", ATTRS{idProduct}=="0567", ENV{ACP_PROFILE_SET}="hp-tbt-dock-audio-module.conf"
9
10
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
414
1
2
#include <sys/stat.h>
3
#include <sys/inotify.h>
4
#include <fcntl.h>
5
+#include <dirent.h>
6
7
#include <libudev.h>
8
#include <alsa/asoundlib.h>
9
10
11
#define MAX_DEVICES 64
12
13
-#define RETRY_COUNT 1
14
-#define RETRY_MSEC 2000
15
-
16
#define ACTION_ADD 0
17
#define ACTION_REMOVE 1
18
#define ACTION_DISABLE 2
19
20
struct device {
21
uint32_t id;
22
struct udev_device *dev;
23
- uint8_t retry;
24
+ unsigned int unavailable:1;
25
unsigned int accessible:1;
26
unsigned int ignored:1;
27
unsigned int emitted:1;
28
29
30
struct spa_source source;
31
struct spa_source notify;
32
- struct spa_source retry_timer;
33
unsigned int use_acp:1;
34
};
35
36
37
{
38
const char *s;
39
char *d;
40
- int h1, h2;
41
+ int h1 = 0, h2 = 0;
42
enum { TEXT, BACKSLASH, EX, FIRST } state = TEXT;
43
44
for (s = src, d = dst; *s; s++) {
45
46
*d = 0;
47
}
48
49
-static int check_device_busy(struct impl *this, struct device *device, snd_ctl_t *ctl_hndl)
50
+static int check_device_available(struct impl *this, struct device *device, int *num_pcm)
51
{
52
- int dev;
53
+ char path[PATH_MAX];
54
+ DIR *card = NULL, *pcm = NULL;
55
+ FILE *f;
56
+ char buf[16];
57
+ size_t sz;
58
+ struct dirent *entry, *entry_pcm;
59
+ int res;
60
+
61
+ /*
62
+ * Check if some pcm devices of the card are busy. Check it via /proc, as we
63
+ * don't want to actually open any devices using alsa-lib (generates uncontrolled
64
+ * number of inotify events), or replicate its subdevice logic.
65
+ */
66
+
67
+ *num_pcm = 0;
68
69
- /* Check if some pcm devices of the card cannot be opened because they are busy */
70
+ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u", (unsigned int)device->id);
71
72
- for (dev = -1; snd_ctl_pcm_next_device(ctl_hndl, &dev) >= 0 && dev >= 0;) {
73
- char devpath[64];
74
- int i;
75
+ if ((card = opendir(path)) == NULL)
76
+ goto done;
77
78
- snprintf(devpath, sizeof(devpath), "hw:%u,%u", device->id, dev);
79
+ while ((errno = 0, entry = readdir(card)) != NULL) {
80
+ if (!(entry->d_type == DT_DIR &&
81
+ spa_strstartswith(entry->d_name, "pcm")))
82
+ continue;
83
84
- for (i = 0; i < 2; ++i) {
85
- snd_pcm_t *handle;
86
- int res;
87
+ /* Check device class */
88
+ spa_scnprintf(path, sizeof(path), "/sys/class/sound/pcmC%uD%s/pcm_class",
89
+ (unsigned int)device->id, entry->d_name+3);
90
+ f = fopen(path, "r");
91
+ if (f == NULL)
92
+ goto done;
93
+ sz = fread(buf, 1, sizeof(buf) - 1, f);
94
+ buf[sz] = '\0';
95
+ fclose(f);
96
+ if (spa_strstartswith(buf, "modem"))
97
+ continue;
98
99
- res = snd_pcm_open(&handle, devpath,
100
- (i == 0) ? SND_PCM_STREAM_PLAYBACK : SND_PCM_STREAM_CAPTURE,
101
- SND_PCM_NONBLOCK | SND_PCM_NO_AUTO_RESAMPLE |
102
- SND_PCM_NO_AUTO_CHANNELS | SND_PCM_NO_AUTO_FORMAT);
103
- if (res == -EBUSY) {
104
- spa_log_debug(this->log, "pcm device %s busy", devpath);
105
- return -EBUSY;
106
- } else if (res >= 0) {
107
- snd_pcm_close(handle);
108
+ /* Check busy status */
109
+ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s",
110
+ (unsigned int)device->id, entry->d_name);
111
+ if ((pcm = opendir(path)) == NULL)
112
+ goto done;
113
+
114
+ while ((errno = 0, entry_pcm = readdir(pcm)) != NULL) {
115
+ if (!(entry_pcm->d_type == DT_DIR &&
116
+ spa_strstartswith(entry_pcm->d_name, "sub")))
117
+ continue;
118
+
119
+ spa_scnprintf(path, sizeof(path), "/proc/asound/card%u/%s/%s/status",
120
+ (unsigned int)device->id, entry->d_name, entry_pcm->d_name);
121
+
122
+ f = fopen(path, "r");
123
+ if (f == NULL)
124
+ goto done;
125
+ sz = fread(buf, 1, 6, f);
126
+ buf[sz] = '\0';
127
+ fclose(f);
128
+
129
+ if (!spa_strstartswith(buf, "closed")) {
130
+ spa_log_debug(this->log, "card %u pcm device %s busy",
131
+ (unsigned int)device->id, entry->d_name);
132
+ errno = EBUSY;
133
+ goto done;
134
}
135
+ spa_log_debug(this->log, "card %u pcm device %s free",
136
+ (unsigned int)device->id, entry->d_name);
137
}
138
- spa_log_debug(this->log, "pcm device %s free", devpath);
139
- }
140
+ if (errno != 0)
141
+ goto done;
142
143
- return 0;
144
+ ++*num_pcm;
145
+
146
+ closedir(pcm);
147
+ pcm = NULL;
148
+ }
149
+ if (errno != 0)
150
+ goto done;
151
+
152
+done:
153
+ res = -errno;
154
+ if (card)
155
+ closedir(card);
156
+ if (pcm)
157
+ closedir(pcm);
158
+ return res;
159
}
160
161
static int emit_object_info(struct impl *this, struct device *device)
162
163
struct spa_device_object_info info;
164
uint32_t id = device->id;
165
struct udev_device *dev = device->dev;
166
- snd_ctl_t *ctl_hndl;
167
const char *str;
168
char path[32], *cn = NULL, *cln = NULL;
169
struct spa_dict_item items[25];
170
uint32_t n_items = 0;
171
int res, pcm;
172
173
- snprintf(path, sizeof(path), "hw:%u", id);
174
- spa_log_debug(this->log, "open card %s", path);
175
+ /*
176
+ * inotify close events under /dev/snd must not be emitted, except after setting
177
+ * device->emitted to true. alsalib functions can be used after that.
178
+ */
179
180
- if ((res = snd_ctl_open(&ctl_hndl, path, 0)) < 0) {
181
- spa_log_error(this->log, "can't open control for card %s: %s",
182
- path, snd_strerror(res));
183
+ if ((res = check_device_available(this, device, &pcm)) < 0)
184
return res;
185
- }
186
-
187
- pcm = -1;
188
- res = snd_ctl_pcm_next_device(ctl_hndl, &pcm);
189
-
190
- if (res < 0) {
191
- spa_log_error(this->log, "error iterating devices: %s", snd_strerror(res));
192
- device->ignored = true;
193
- } else if (pcm < 0) {
194
+ if (pcm == 0) {
195
spa_log_debug(this->log, "no pcm devices for %s", path);
196
device->ignored = true;
197
- res = 0;
198
- } else if (device->retry > 0) {
199
- /* Check if we can open all PCM devices (retry later if not) */
200
- res = check_device_busy(this, device, ctl_hndl);
201
+ return 0;
202
}
203
204
- spa_log_debug(this->log, "close card %s", path);
205
- snd_ctl_close(ctl_hndl);
206
-
207
- if (res < 0 || device->ignored)
208
- return res;
209
+ snprintf(path, sizeof(path), "hw:%u", id);
210
+ spa_log_debug(this->log, "emitting card %s", path);
211
+ device->emitted = true;
212
213
info = SPA_DEVICE_OBJECT_INFO_INIT();
214
215
216
info.props = &SPA_DICT_INIT(items, n_items);
217
218
spa_device_emit_object_info(&this->hooks, id, &info);
219
- device->emitted = true;
220
free(cn);
221
free(cln);
222
223
return 1;
224
}
225
226
-static void start_retry(struct impl *this);
227
-
228
-static void stop_retry(struct impl *this);
229
-
230
-static void retry_timer_event(struct spa_source *source)
231
-{
232
- struct impl *this = source->data;
233
- bool have_retry = false;
234
- size_t i;
235
-
236
- stop_retry(this);
237
-
238
- for (i = 0; i < this->n_devices; ++i) {
239
- struct device *device = &this->devices[i];
240
- if (device->ignored)
241
- device->retry = 0;
242
- if (device->retry > 0) {
243
- --device->retry;
244
-
245
- spa_log_debug(this->log, "retrying device %u", device->id);
246
-
247
- if (emit_object_info(this, device) == -EBUSY) {
248
- spa_log_debug(this->log, "device %u busy (remaining retries %u)",
249
- device->id, device->retry);
250
- } else {
251
- device->retry = 0;
252
- }
253
- }
254
- if (device->retry > 0)
255
- have_retry = true;
256
- }
257
-
258
- if (have_retry)
259
- start_retry(this);
260
-}
261
-
262
-static void start_retry(struct impl *this)
263
-{
264
- struct itimerspec ts;
265
-
266
- spa_log_debug(this->log, "start retry");
267
-
268
- if (this->retry_timer.data == NULL) {
269
- this->retry_timer.data = this;
270
- this->retry_timer.func = retry_timer_event;
271
- this->retry_timer.mask = SPA_IO_IN;
272
- this->retry_timer.rmask = 0;
273
- spa_loop_add_source(this->main_loop, &this->retry_timer);
274
- }
275
-
276
- ts.it_value.tv_sec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) / SPA_NSEC_PER_SEC;
277
- ts.it_value.tv_nsec = ((uint64_t)RETRY_MSEC * SPA_NSEC_PER_MSEC) % SPA_NSEC_PER_SEC;
278
- ts.it_interval.tv_sec = 0;
279
- ts.it_interval.tv_nsec = 0;
280
- spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL);
281
-}
282
-
283
-static void stop_retry(struct impl *this)
284
-{
285
- struct itimerspec ts;
286
-
287
- if (this->retry_timer.data == NULL)
288
- return;
289
-
290
- spa_log_debug(this->log, "stop retry");
291
-
292
- spa_loop_remove_source(this->main_loop, &this->retry_timer);
293
- this->retry_timer.data = NULL;
294
-
295
- ts.it_value.tv_sec = 0;
296
- ts.it_value.tv_nsec = 0;
297
- ts.it_interval.tv_sec = 0;
298
- ts.it_interval.tv_nsec = 0;
299
- spa_system_timerfd_settime(this->main_system, this->retry_timer.fd, 0, &ts, NULL);
300
-}
301
-
302
static bool check_access(struct impl *this, struct device *device)
303
{
304
char path[128];
305
+ bool accessible;
306
307
snprintf(path, sizeof(path), "/dev/snd/controlC%u", device->id);
308
- device->accessible = access(path, R_OK|W_OK) >= 0;
309
- spa_log_debug(this->log, "%s accessible:%u", path, device->accessible);
310
+ accessible = access(path, R_OK|W_OK) >= 0;
311
+ if (accessible != device->accessible)
312
+ spa_log_debug(this->log, "%s accessible:%u", path, accessible);
313
+ device->accessible = accessible;
314
315
return device->accessible;
316
}
317
318
uint32_t id;
319
struct device *device;
320
bool emitted;
321
+ int res;
322
323
if ((id = get_card_id(this, dev)) == SPA_ID_INVALID)
324
return;
325
326
return;
327
if (!check_access(this, device))
328
return;
329
- device->retry = RETRY_COUNT;
330
- if (emit_object_info(this, device) == -EBUSY) {
331
- spa_log_debug(this->log, "device %u busy (remaining retries %u)",
332
- device->id, device->retry);
333
- start_retry(this);
334
+ res = emit_object_info(this, device);
335
+ if (res < 0) {
336
+ if (device->ignored)
337
+ spa_log_info(this->log, "ALSA card %u unavailable (%s): it is ignored",
338
+ device->id, spa_strerror(res));
339
+ else if (!device->unavailable)
340
+ spa_log_info(this->log, "ALSA card %u unavailable (%s): wait for it",
341
+ device->id, spa_strerror(res));
342
+ else
343
+ spa_log_debug(this->log, "ALSA card %u still unavailable (%s)",
344
+ device->id, spa_strerror(res));
345
+ device->unavailable = true;
346
} else {
347
- device->retry = 0;
348
+ if (device->unavailable)
349
+ spa_log_info(this->log, "ALSA card %u now available",
350
+ device->id);
351
+ device->unavailable = false;
352
}
353
break;
354
355
356
case ACTION_DISABLE:
357
if (device == NULL)
358
return;
359
- device->retry = 0;
360
if (device->emitted) {
361
device->emitted = false;
362
spa_device_emit_object_info(&this->hooks, id, NULL);
363
364
365
event = (const struct inotify_event *) p;
366
367
- if ((event->mask & IN_ATTRIB)) {
368
+ /* Device becomes accessible or not busy */
369
+ if ((event->mask & (IN_ATTRIB | IN_CLOSE_WRITE))) {
370
bool access;
371
- if (sscanf(event->name, "controlC%u", &id) != 1)
372
+
373
+ if ((event->mask & IN_ATTRIB) &&
374
+ spa_strstartswith(event->name, "pcm"))
375
+ continue;
376
+ if (sscanf(event->name, "controlC%u", &id) != 1 &&
377
+ sscanf(event->name, "pcmC%uD", &id) != 1)
378
continue;
379
if ((device = find_device(this, id)) == NULL)
380
continue;
381
+
382
access = check_access(this, device);
383
if (access && !device->emitted)
384
process_device(this, ACTION_ADD, device->dev);
385
386
struct impl *this = (struct impl *) handle;
387
stop_monitor(this);
388
impl_udev_close(this);
389
- stop_retry(this);
390
- if (this->retry_timer.fd >= 0)
391
- spa_system_close(this->main_system, this->retry_timer.fd);
392
- this->retry_timer.fd = -1;
393
return 0;
394
}
395
396
397
398
this = (struct impl *) handle;
399
this->notify.fd = -1;
400
- this->retry_timer.fd = -1;
401
402
this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log);
403
alsa_log_topic_init(this->log);
404
405
this->use_acp = spa_atob(str);
406
}
407
408
- this->retry_timer.fd = spa_system_timerfd_create(this->main_system,
409
- CLOCK_MONOTONIC, SPA_FD_CLOEXEC | SPA_FD_NONBLOCK);
410
-
411
return 0;
412
}
413
414
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
52
1
2
; Texas Instruments PCM2902
3
;
4
; This is a generic chip used in multiple products, including at least
5
-; Behringer U-Phoria UMC22, Intopic Jazz-UB700 and some unbranded "usb mini
6
-; microphone".
7
+; Behringer U-Phoria UMC22, Behringer Xenyx 302USB, Intopic Jazz-UB700 and
8
+; some unbranded "usb mini microphone".
9
;
10
; Behringer UMC22 has stereo input (representing two physical mono inputs),
11
; others have mono input.
12
;
13
+; Some devices have a mic input path, but at least Behringer Xenyx 302USB
14
+; doesn't have any input mixer controls.
15
+;
16
; Since the UMC22 card has only stereo input PCM device but is commonly used
17
; with mono mics, we define special mono mappings using "mono,aux1" and
18
; "aux1,mono" channel maps. If we had only had the standard stereo input
19
20
[Mapping analog-stereo-input]
21
device-strings = hw:%f
22
channel-map = left,right
23
-paths-input = analog-input-mic
24
+paths-input = analog-input-mic analog-input
25
direction = input
26
priority = 4
27
28
[Mapping analog-mono]
29
device-strings = hw:%f
30
channel-map = mono
31
-paths-input = analog-input-mic
32
+paths-input = analog-input-mic analog-input
33
direction = input
34
priority = 3
35
36
[Mapping analog-mono-left]
37
device-strings = hw:%f
38
channel-map = mono,aux1
39
-paths-input = analog-input-mic
40
+paths-input = analog-input-mic analog-input
41
direction = input
42
priority = 2
43
44
[Mapping analog-mono-right]
45
device-strings = hw:%f
46
channel-map = aux1,mono
47
-paths-input = analog-input-mic
48
+paths-input = analog-input-mic analog-input
49
direction = input
50
priority = 1
51
52
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
10
1
2
uint32_t n_src, const void * SPA_RESTRICT src[n_src], \
3
uint32_t n_samples);
4
5
+#define CHANNELMIX_OPS_MAX_ALIGN 16
6
+
7
DEFINE_FUNCTION(copy, c);
8
DEFINE_FUNCTION(f32_n_m, c);
9
DEFINE_FUNCTION(f32_1_2, c);
10
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/channelmix.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/channelmix.c
Changed
38
1
2
3
#define MAX_BUFFERS 32
4
#define MAX_DATAS SPA_AUDIO_MAX_CHANNELS
5
+#define MAX_ALIGN CHANNELMIX_OPS_MAX_ALIGN
6
7
#define DEFAULT_CONTROL_BUFFER_SIZE 32768
8
9
10
unsigned int started:1;
11
unsigned int is_passthrough:1;
12
uint32_t cpu_flags;
13
+ uint32_t max_align;
14
};
15
16
#define IS_CONTROL_PORT(this,d,id) (id == 1 && d == SPA_DIRECTION_INPUT)
17
18
buffers[i]);
19
return -EINVAL;
20
}
21
- if (!SPA_IS_ALIGNED(d[j].data, 16)) {
22
+ if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) {
23
spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned",
24
this, j, i);
25
}
26
27
spa_log_topic_init(this->log, log_topic);
28
29
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
30
- if (this->cpu)
31
+ if (this->cpu) {
32
this->cpu_flags = spa_cpu_get_flags(this->cpu);
33
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
34
+ }
35
36
spa_hook_list_init(&this->hooks);
37
38
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
10
1
2
void conv_##name##_##arch(struct convert *conv, void * SPA_RESTRICT dst[], \
3
const void * SPA_RESTRICT src[], uint32_t n_samples) \
4
5
+#define FMT_OPS_MAX_ALIGN 32
6
+
7
DEFINE_FUNCTION(copy8d, c);
8
DEFINE_FUNCTION(copy8, c);
9
DEFINE_FUNCTION(copy16d, c);
10
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/fmtconvert.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/fmtconvert.c
Changed
39
1
2
#define DEFAULT_CHANNELS 2
3
4
#define MAX_BUFFERS 32
5
-#define MAX_ALIGN 16
6
+#define MAX_ALIGN FMT_OPS_MAX_ALIGN
7
#define MAX_DATAS SPA_AUDIO_MAX_CHANNELS
8
9
#define PROP_DEFAULT_TRUNCATE false
10
11
struct spa_log *log;
12
struct spa_cpu *cpu;
13
uint32_t cpu_flags;
14
+ uint32_t max_align;
15
uint32_t quantum_limit;
16
17
struct spa_io_position *io_position;
18
19
this, j, i);
20
return -EINVAL;
21
}
22
- if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) {
23
+ if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) {
24
spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned",
25
this, j, i);
26
}
27
28
spa_log_topic_init(this->log, log_topic);
29
30
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
31
- if (this->cpu)
32
+ if (this->cpu) {
33
this->cpu_flags = spa_cpu_get_flags(this->cpu);
34
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
35
+ }
36
37
for (i = 0; info && i < info->n_items; i++) {
38
const char *k = info->items[i].key;
39
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/merger.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/merger.c
Changed
39
1
2
#define DEFAULT_RATE 48000
3
#define DEFAULT_CHANNELS 2
4
5
-#define MAX_ALIGN 16
6
+#define MAX_ALIGN FMT_OPS_MAX_ALIGN
7
#define MAX_BUFFERS 32
8
#define MAX_DATAS SPA_AUDIO_MAX_CHANNELS
9
#define MAX_PORTS SPA_AUDIO_MAX_CHANNELS
10
11
struct spa_cpu *cpu;
12
13
uint32_t cpu_flags;
14
+ uint32_t max_align;
15
uint32_t quantum_limit;
16
17
struct spa_io_position *io_position;
18
19
this, j, i, d[j].type, d[j].data);
20
return -EINVAL;
21
}
22
- if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) {
23
+ if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) {
24
spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned",
25
this, j, i);
26
}
27
28
spa_log_topic_init(this->log, log_topic);
29
30
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
31
- if (this->cpu)
32
+ if (this->cpu) {
33
this->cpu_flags = spa_cpu_get_flags(this->cpu);
34
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
35
+ }
36
37
for (i = 0; info && i < info->n_items; i++) {
38
const char *k = info->items[i].key;
39
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/resample.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/resample.c
Changed
9
1
2
#define DEFAULT_RATE 48000
3
#define DEFAULT_CHANNELS 2
4
5
-#define MAX_ALIGN 16
6
#define MAX_BUFFERS 32
7
8
struct impl;
9
pipewire-0.3.44.tar.gz/spa/plugins/audioconvert/splitter.c -> pipewire-0.3.45.tar.gz/spa/plugins/audioconvert/splitter.c
Changed
39
1
2
#define DEFAULT_CHANNELS 2
3
#define DEFAULT_MASK (1LL << SPA_AUDIO_CHANNEL_FL) | (1LL << SPA_AUDIO_CHANNEL_FR)
4
5
-#define MAX_ALIGN 16
6
+#define MAX_ALIGN FMT_OPS_MAX_ALIGN
7
#define MAX_BUFFERS 32
8
#define MAX_DATAS SPA_AUDIO_MAX_CHANNELS
9
#define MAX_PORTS SPA_AUDIO_MAX_CHANNELS
10
11
struct spa_cpu *cpu;
12
13
uint32_t cpu_flags;
14
+ uint32_t max_align;
15
uint32_t quantum_limit;
16
17
struct spa_io_position *io_position;
18
19
this, j, i, d[j].type, d[j].data);
20
return -EINVAL;
21
}
22
- if (!SPA_IS_ALIGNED(d[j].data, MAX_ALIGN)) {
23
+ if (!SPA_IS_ALIGNED(d[j].data, this->max_align)) {
24
spa_log_warn(this->log, "%p: memory %d on buffer %d not aligned",
25
this, j, i);
26
}
27
28
spa_log_topic_init(this->log, log_topic);
29
30
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
31
- if (this->cpu)
32
+ if (this->cpu) {
33
this->cpu_flags = spa_cpu_get_flags(this->cpu);
34
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
35
+ }
36
37
for (i = 0; info && i < info->n_items; i++) {
38
const char *k = info->items[i].key;
39
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
10
1
2
const void * SPA_RESTRICT src, \
3
float volume, uint32_t n_samples);
4
5
+#define VOLUME_OPS_MAX_ALIGN 16
6
+
7
DEFINE_FUNCTION(f32, c);
8
9
#if defined (HAVE_SSE)
10
pipewire-0.3.44.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.45.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
38
1
2
#define MAX_BUFFERS 64
3
#define MAX_PORTS 128
4
#define MAX_CHANNELS 64
5
+#define MAX_ALIGN MIX_OPS_MAX_ALIGN
6
7
#define PORT_DEFAULT_VOLUME 1.0
8
#define PORT_DEFAULT_MUTE false
9
10
struct spa_log *log;
11
struct spa_cpu *cpu;
12
uint32_t cpu_flags;
13
+ uint32_t max_align;
14
uint32_t quantum_limit;
15
16
struct mix_ops ops;
17
18
buffers[i]);
19
return -EINVAL;
20
}
21
- if (!SPA_IS_ALIGNED(d[0].data, 16)) {
22
+ if (!SPA_IS_ALIGNED(d[0].data, this->max_align)) {
23
spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i);
24
}
25
if (direction == SPA_DIRECTION_OUTPUT)
26
27
spa_log_topic_init(this->log, log_topic);
28
29
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
30
- if (this->cpu)
31
+ if (this->cpu) {
32
this->cpu_flags = spa_cpu_get_flags(this->cpu);
33
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
34
+ }
35
36
for (i = 0; info && i < info->n_items; i++) {
37
const char *k = info->items[i].key;
38
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
10
1
2
const void * SPA_RESTRICT src[], uint32_t n_src, \
3
uint32_t n_samples) \
4
5
+#define MIX_OPS_MAX_ALIGN 32
6
+
7
DEFINE_FUNCTION(s8, c);
8
DEFINE_FUNCTION(u8, c);
9
DEFINE_FUNCTION(s16, c);
10
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
39
1
2
3
#define MAX_BUFFERS 64
4
#define MAX_PORTS 128
5
-#define MAX_ALIGN 64
6
+#define MAX_ALIGN MIX_OPS_MAX_ALIGN
7
8
#define PORT_DEFAULT_VOLUME 1.0
9
#define PORT_DEFAULT_MUTE false
10
11
struct spa_log *log;
12
struct spa_cpu *cpu;
13
uint32_t cpu_flags;
14
+ uint32_t max_align;
15
16
uint32_t quantum_limit;
17
18
19
spa_log_error(this->log, "%p: invalid memory on buffer %d", this, i);
20
return -EINVAL;
21
}
22
- if (!SPA_IS_ALIGNED(d[0].data, 32)) {
23
+ if (!SPA_IS_ALIGNED(d[0].data, this->max_align)) {
24
spa_log_warn(this->log, "%p: memory on buffer %d not aligned", this, i);
25
}
26
if (direction == SPA_DIRECTION_OUTPUT)
27
28
spa_log_topic_init(this->log, log_topic);
29
30
this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
31
- if (this->cpu)
32
+ if (this->cpu) {
33
this->cpu_flags = spa_cpu_get_flags(this->cpu);
34
+ this->max_align = SPA_MIN(MAX_ALIGN, spa_cpu_get_max_align(this->cpu));
35
+ }
36
37
for (i = 0; info && i < info->n_items; i++) {
38
const char *k = info->items[i].key;
39
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
169
1
2
td = t->user_data;
3
td->rfcomm = rfcomm;
4
5
- for (int i = 0; i < SPA_BT_VOLUME_ID_TERM ; ++i) {
6
- rfcomm->volumes[i].hw_volume = SPA_BT_VOLUME_INVALID;
7
- t->volumes[i].active = rfcomm->volumes[i].active;
8
- t->volumes[i].hw_volume_max = SPA_BT_VOLUME_HS_MAX;
9
- }
10
-
11
if (t->profile & SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY) {
12
t->volumes[SPA_BT_VOLUME_ID_RX].volume = DEFAULT_AG_VOLUME;
13
t->volumes[SPA_BT_VOLUME_ID_TX].volume = DEFAULT_AG_VOLUME;
14
15
t->volumes[SPA_BT_VOLUME_ID_TX].volume = DEFAULT_TX_VOLUME;
16
}
17
18
+ for (int i = 0; i < SPA_BT_VOLUME_ID_TERM ; ++i) {
19
+ t->volumes[i].active = rfcomm->volumes[i].active;
20
+ t->volumes[i].hw_volume_max = SPA_BT_VOLUME_HS_MAX;
21
+ if (rfcomm->volumes[i].active && rfcomm->volumes[i].hw_volume != SPA_BT_VOLUME_INVALID)
22
+ t->volumes[i].volume =
23
+ spa_bt_volume_hw_to_linear(rfcomm->volumes[i].hw_volume, t->volumes[i].hw_volume_max);
24
+ }
25
+
26
spa_bt_transport_add_listener(t, &rfcomm->transport_listener, &transport_events, rfcomm);
27
28
finish:
29
30
31
#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
32
33
-static int sco_create_socket(struct impl *backend, struct spa_bt_adapter *adapter, bool msbc);
34
-
35
static bool device_supports_required_mSBC_transport_modes(
36
- struct impl *backend, struct spa_bt_device *device) {
37
- int sock;
38
+ struct impl *backend, struct spa_bt_device *device)
39
+{
40
+ int res;
41
bool msbc_ok, msbc_alt1_ok;
42
uint32_t bt_features;
43
44
45
if (!msbc_ok && !msbc_alt1_ok)
46
return false;
47
48
- /*
49
- * Check if adapter supports BT_VOICE_TRANSPARENT. Do this without
50
- * directly probing HCI properties.
51
- */
52
- sock = sco_create_socket(backend, device->adapter, true);
53
- if (sock < 0) {
54
+ res = spa_bt_adapter_has_msbc(device->adapter);
55
+ if (res < 0) {
56
+ spa_log_warn(backend->log,
57
+ "adapter %s: failed to determine msbc/esco capability (%d)",
58
+ device->adapter->path, res);
59
+ } else if (res == 0) {
60
+ spa_log_info(backend->log,
61
+ "adapter %s: no msbc/esco transport",
62
+ device->adapter->path);
63
return false;
64
} else {
65
- struct sockaddr_sco addr;
66
- socklen_t len;
67
- int res;
68
-
69
- /* Connect to non-existent address */
70
- len = sizeof(addr);
71
- memset(&addr, 0, len);
72
- addr.sco_family = AF_BLUETOOTH;
73
- bacpy(&addr.sco_bdaddr, BDADDR_LOCAL);
74
-
75
- spa_log_debug(backend->log, "connect to determine adapter msbc support...");
76
-
77
- /* Linux kernel code checks for features needed for BT_VOICE_TRANSPARENT
78
- * among the first checks it does, and fails with EOPNOTSUPP if not
79
- * supported. The connection generally timeouts, so set it
80
- * nonblocking since we are just checking.
81
- */
82
- fcntl(sock, F_SETFL, O_NONBLOCK);
83
- res = connect(sock, (struct sockaddr *) &addr, len);
84
- if (res < 0)
85
- res = errno;
86
- else
87
- res = 0;
88
- close(sock);
89
-
90
- spa_log_debug(backend->log, "determined adapter-msbc:%d res:%d",
91
- (res != EOPNOTSUPP), res);
92
- if (res == EOPNOTSUPP)
93
- return false;
94
+ spa_log_debug(backend->log,
95
+ "adapter %s: has msbc/esco transport",
96
+ device->adapter->path);
97
}
98
99
/* Check if USB ALT6 is really available on the device */
100
101
unsigned int indicator_value;
102
int xapl_vendor;
103
int xapl_product;
104
- int xapl_version;
105
int xapl_features;
106
107
if (sscanf(buf, "AT+BRSF=%u", &features) == 1) {
108
109
rfcomm_send_reply(rfcomm, "OK");
110
} else if (sscanf(buf, "AT+BIEV=%u,%u", &indicator, &indicator_value) == 2) {
111
process_hfp_hf_indicator(rfcomm, indicator, indicator_value);
112
- } else if (sscanf(buf, "AT+XAPL=%04x-%04x-%04x,%u", &xapl_vendor, &xapl_product, &xapl_version, &xapl_features) == 4) {
113
+ } else if (sscanf(buf, "AT+XAPL=%04x-%04x-%*[^,],%u", &xapl_vendor, &xapl_product, &xapl_features) == 3) {
114
if (xapl_features & SPA_BT_HFP_HF_XAPL_FEATURE_BATTERY_REPORTING) {
115
/* claim, that we support battery status reports */
116
rfcomm_send_reply(rfcomm, "+XAPL=iPhone,%u", SPA_BT_HFP_HF_XAPL_FEATURE_BATTERY_REPORTING);
117
118
{
119
struct impl *backend = SPA_CONTAINER_OF(t->backend, struct impl, this);
120
struct spa_bt_device *d = t->device;
121
+ struct transport_data *td = t->user_data;
122
struct sockaddr_sco addr;
123
socklen_t len;
124
int err;
125
126
goto again;
127
} else if (err < 0 && !(errno == EAGAIN || errno == EINPROGRESS)) {
128
spa_log_error(backend->log, "connect(): %s", strerror(errno));
129
+#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
130
+ if (errno == EOPNOTSUPP && t->codec == HFP_AUDIO_CODEC_MSBC &&
131
+ td->rfcomm->msbc_supported_by_hfp) {
132
+ /* Adapter doesn't support msbc. Renegotiate. */
133
+ d->adapter->msbc_probed = true;
134
+ d->adapter->has_msbc = false;
135
+ td->rfcomm->msbc_supported_by_hfp = false;
136
+ if (t->profile == SPA_BT_PROFILE_HFP_HF) {
137
+ td->rfcomm->hfp_ag_switching_codec = true;
138
+ rfcomm_send_reply(td->rfcomm, "+BCS: 1");
139
+ } else if (t->profile == SPA_BT_PROFILE_HFP_AG) {
140
+ rfcomm_send_cmd(td->rfcomm, "AT+BAC=1");
141
+ }
142
+ }
143
+#endif
144
goto fail_close;
145
}
146
147
148
149
spa_log_debug(backend->log, "transport %p: enter sco_acquire_cb", t);
150
151
-#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
152
- rfcomm_hfp_ag_set_cind(td->rfcomm, true);
153
-#endif
154
-
155
if (optional || t->fd > 0)
156
sock = t->fd;
157
else
158
159
if (sock < 0)
160
goto fail;
161
162
+#ifdef HAVE_BLUEZ_5_BACKEND_HFP_NATIVE
163
+ rfcomm_hfp_ag_set_cind(td->rfcomm, true);
164
+#endif
165
+
166
t->fd = sock;
167
168
/* Fallback value */
169
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
10
1
2
{ name = "BAA 100", no-features = [ hw-volume ] }, # Buxton BAA 100, doesn't remember volume, #pipewire-1449
3
{ name = "D50s", address = "~^00:13:ef:", no-features = [ hw-volume ] }, # volume has no effect, #pipewire-1562
4
{ name = "FiiO BTR3", address = "~^40:ed:98:", no-features = [ faststream ] }, # #pipewire-1658
5
- { name = "JBL Endurance RUN BT", no-features = [ msbc-alt1, msbc-alt1-rtl, sbc-xq ] },
6
+ { name = "JBL Endurance RUN BT", no-features = [ msbc-alt1, msbc-alt1-rtl ] },
7
{ name = "JBL LIVE650BTNC" },
8
{ name = "Motorola DC800", no-features = [ sbc-xq ] }, # #pipewire-1590
9
{ name = "Motorola S305", no-features = [ sbc-xq ] }, # #pipewire-1590
10
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
114
1
2
3
spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_IDLE);
4
5
+ spa_bt_transport_keepalive(transport, false);
6
+
7
spa_bt_transport_emit_destroy(transport);
8
9
spa_bt_transport_stop_volume_timer(transport);
10
11
free(transport);
12
}
13
14
+int spa_bt_transport_keepalive(struct spa_bt_transport *t, bool keepalive)
15
+{
16
+ if (keepalive) {
17
+ t->keepalive = true;
18
+ return 0;
19
+ }
20
+
21
+ t->keepalive = false;
22
+
23
+ if (t->acquire_refcount == 0 && t->acquired) {
24
+ t->acquire_refcount = 1;
25
+ return spa_bt_transport_release(t);
26
+ }
27
+
28
+ return 0;
29
+}
30
+
31
int spa_bt_transport_acquire(struct spa_bt_transport *transport, bool optional)
32
{
33
struct spa_bt_monitor *monitor = transport->monitor;
34
35
}
36
spa_assert(transport->acquire_refcount == 0);
37
38
- res = spa_bt_transport_impl(transport, acquire, 0, optional);
39
+ if (!transport->acquired)
40
+ res = spa_bt_transport_impl(transport, acquire, 0, optional);
41
+ else
42
+ res = 0;
43
44
- if (res >= 0)
45
+ if (res >= 0) {
46
transport->acquire_refcount = 1;
47
+ transport->acquired = true;
48
+ }
49
50
return res;
51
}
52
53
return 0;
54
}
55
spa_assert(transport->acquire_refcount == 1);
56
+ spa_assert(transport->acquired);
57
58
if (SPA_BT_TRANSPORT_IS_SCO(transport)) {
59
/* Postpone SCO transport releases, since we might need it again soon */
60
res = spa_bt_transport_start_release_timer(transport);
61
+ } else if (transport->keepalive) {
62
+ res = 0;
63
+ transport->acquire_refcount = 0;
64
+ spa_log_debug(monitor->log, "transport %p: keepalive %s on release",
65
+ transport, transport->path);
66
} else {
67
res = spa_bt_transport_impl(transport, release, 0);
68
- if (res >= 0)
69
+ if (res >= 0) {
70
transport->acquire_refcount = 0;
71
+ transport->acquired = false;
72
+ }
73
}
74
75
return res;
76
77
{
78
int res;
79
80
- if (transport->acquire_refcount == 0)
81
+ if (!transport->acquired)
82
return 0;
83
84
spa_bt_transport_stop_release_timer(transport);
85
res = spa_bt_transport_impl(transport, release, 0);
86
- if (res >= 0)
87
+ if (res >= 0) {
88
transport->acquire_refcount = 0;
89
+ transport->acquired = false;
90
+ }
91
92
return res;
93
}
94
95
struct spa_bt_monitor *monitor = transport->monitor;
96
97
spa_assert(transport->acquire_refcount >= 1);
98
+ spa_assert(transport->acquired);
99
100
spa_bt_transport_stop_release_timer(transport);
101
102
if (transport->acquire_refcount == 1) {
103
- spa_bt_transport_impl(transport, release, 0);
104
+ if (!transport->keepalive) {
105
+ spa_bt_transport_impl(transport, release, 0);
106
+ transport->acquired = false;
107
+ } else {
108
+ spa_log_debug(monitor->log, "transport %p: keepalive %s on release",
109
+ transport, transport->path);
110
+ }
111
} else {
112
spa_log_debug(monitor->log, "transport %p: delayed decref %s", transport, transport->path);
113
}
114
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
15
1
2
if (state >= SPA_BT_TRANSPORT_STATE_PENDING && old < SPA_BT_TRANSPORT_STATE_PENDING) {
3
if (!SPA_FLAG_IS_SET(this->id, DYNAMIC_NODE_ID_FLAG)) {
4
SPA_FLAG_SET(this->id, DYNAMIC_NODE_ID_FLAG);
5
+ spa_bt_transport_keepalive(t, true);
6
emit_node(impl, t, this->id, this->factory_name, this->a2dp_duplex);
7
}
8
} else if (state < SPA_BT_TRANSPORT_STATE_PENDING && old >= SPA_BT_TRANSPORT_STATE_PENDING) {
9
if (SPA_FLAG_IS_SET(this->id, DYNAMIC_NODE_ID_FLAG)) {
10
SPA_FLAG_CLEAR(this->id, DYNAMIC_NODE_ID_FLAG);
11
+ spa_bt_transport_keepalive(t, false);
12
spa_device_emit_object_info(&impl->hooks, this->id, NULL);
13
}
14
}
15
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/defs.h
Changed
43
1
2
uint32_t bluetooth_class;
3
uint32_t profiles;
4
int powered;
5
+ unsigned int has_msbc:1;
6
+ unsigned int msbc_probed:1;
7
unsigned int endpoints_registered:1;
8
unsigned int application_registered:1;
9
unsigned int player_registered:1;
10
- unsigned int has_battery_provider;
11
- unsigned int battery_provider_unavailable;
12
+ unsigned int has_battery_provider:1;
13
+ unsigned int battery_provider_unavailable:1;
14
};
15
16
enum spa_bt_form_factor {
17
18
struct spa_bt_transport_volume volumes[SPA_BT_VOLUME_ID_TERM];
19
20
int acquire_refcount;
21
+ bool acquired;
22
+ bool keepalive;
23
int fd;
24
uint16_t read_mtu;
25
uint16_t write_mtu;
26
27
28
int spa_bt_transport_acquire(struct spa_bt_transport *t, bool optional);
29
int spa_bt_transport_release(struct spa_bt_transport *t);
30
+int spa_bt_transport_keepalive(struct spa_bt_transport *t, bool keepalive);
31
int spa_bt_transport_ensure_sco_io(struct spa_bt_transport *t, struct spa_loop *data_loop);
32
33
#define spa_bt_transport_emit(t,m,v,...) spa_hook_list_call(&(t)->listener_list, \
34
35
uint32_t *features);
36
void spa_bt_quirks_destroy(struct spa_bt_quirks *quirks);
37
38
+int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter);
39
+
40
struct spa_bt_backend_implementation {
41
#define SPA_VERSION_BT_BACKEND_IMPLEMENTATION 0
42
uint32_t version;
43
pipewire-0.3.45.tar.gz/spa/plugins/bluez5/hci.c
Added
95
1
2
+/* Spa HSP/HFP native backend HCI support
3
+ *
4
+ * Copyright © 2022 Pauli Virtanen
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person obtaining a
7
+ * copy of this software and associated documentation files (the "Software"),
8
+ * to deal in the Software without restriction, including without limitation
9
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10
+ * and/or sell copies of the Software, and to permit persons to whom the
11
+ * Software is furnished to do so, subject to the following conditions:
12
+ *
13
+ * The above copyright notice and this permission notice (including the next
14
+ * paragraph) shall be included in all copies or substantial portions of the
15
+ * Software.
16
+ *
17
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23
+ * DEALINGS IN THE SOFTWARE.
24
+ */
25
+
26
+#include <errno.h>
27
+#include <unistd.h>
28
+#include <stdarg.h>
29
+#include <sys/types.h>
30
+#include <sys/stat.h>
31
+#include <fcntl.h>
32
+#include <poll.h>
33
+#include <sys/uio.h>
34
+#include <sys/socket.h>
35
+
36
+#include "defs.h"
37
+
38
+#ifndef HAVE_BLUEZ_5_HCI
39
+
40
+int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter)
41
+{
42
+ if (adapter->msbc_probed)
43
+ return adapter->has_msbc;
44
+ return -EOPNOTSUPP;
45
+}
46
+
47
+#else
48
+
49
+#include <bluetooth/bluetooth.h>
50
+#include <bluetooth/hci.h>
51
+#include <bluetooth/hci_lib.h>
52
+
53
+int spa_bt_adapter_has_msbc(struct spa_bt_adapter *adapter)
54
+{
55
+ int hci_id, res;
56
+ int sock = -1;
57
+ uint8_t features[8], max_page = 0;
58
+ struct sockaddr_hci a;
59
+ const char *str;
60
+
61
+ if (adapter->msbc_probed)
62
+ return adapter->has_msbc;
63
+
64
+ str = strrchr(adapter->path, '/'); /* hciXX */
65
+ if (str == NULL || sscanf(str, "/hci%d", &hci_id) != 1 || hci_id < 0)
66
+ return -ENOENT;
67
+
68
+ sock = socket(AF_BLUETOOTH, SOCK_RAW | SOCK_CLOEXEC, BTPROTO_HCI);
69
+ if (sock < 0)
70
+ goto error;
71
+
72
+ memset(&a, 0, sizeof(a));
73
+ a.hci_family = AF_BLUETOOTH;
74
+ a.hci_dev = hci_id;
75
+ if (bind(sock, (struct sockaddr *) &a, sizeof(a)) < 0)
76
+ goto error;
77
+
78
+ if (hci_read_local_ext_features(sock, 0, &max_page, features, 1000) < 0)
79
+ goto error;
80
+
81
+ close(sock);
82
+
83
+ adapter->msbc_probed = true;
84
+ adapter->has_msbc = ((features[2] & LMP_TRSP_SCO) && (features[3] & LMP_ESCO)) ? 1 : 0;
85
+ return adapter->has_msbc;
86
+
87
+error:
88
+ res = -errno;
89
+ if (sock >= 0)
90
+ close(sock);
91
+ return res;
92
+}
93
+
94
+#endif
95
pipewire-0.3.44.tar.gz/spa/plugins/bluez5/meson.build -> pipewire-0.3.45.tar.gz/spa/plugins/bluez5/meson.build
Changed
22
1
2
cdata.set('HAVE_BLUEZ_5_BACKEND_HSPHFPD', 1)
3
endif
4
5
+if dependency('bluez', version: '< 6', required: false).found()
6
+ cdata.set('HAVE_BLUEZ_5_HCI', 1)
7
+endif
8
+
9
bluez5_sources = [
10
'plugin.c',
11
'codec-loader.c',
12
13
'quirks.c',
14
'player.c',
15
'bluez5-device.c',
16
- 'bluez5-dbus.c'
17
+ 'bluez5-dbus.c',
18
+ 'hci.c'
19
]
20
21
bluez5_data = ['bluez-hardware.conf']
22
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
78
1
2
static uint64_t get_next_timeout(struct impl *this, uint64_t now_time, uint64_t processed_samples)
3
{
4
struct port *port = &this->port;
5
- uint64_t playback_time = 0, elapsed_time = 0, next_time = 1;
6
+ uint64_t playback_time = 0, elapsed_time = 0, next_time = 0;
7
8
this->total_samples += processed_samples;
9
10
11
{
12
struct port *port = &this->port;
13
struct spa_data *datas;
14
- uint64_t next_timeout = 1;
15
const uint32_t min_in_size =
16
(this->transport->codec == HFP_AUDIO_CODEC_MSBC) ?
17
MSBC_DECODED_SIZE : this->transport->write_mtu;
18
19
if (this->transport == NULL || this->transport->sco_io == NULL)
20
return;
21
22
- if (!spa_list_is_empty(&port->ready)) {
23
+again:
24
+ while (!spa_list_is_empty(&port->ready) && port->write_buffer_size < min_in_size) {
25
/* get buffer */
26
if (!port->current_buffer) {
27
spa_return_if_fail(!spa_list_is_empty(&port->ready));
28
29
int processed = 0;
30
ssize_t out_encoded;
31
int written;
32
+ uint64_t next_timeout;
33
34
spa_system_clock_gettime(this->data_system, CLOCK_MONOTONIC, &this->now);
35
now_time = SPA_TIMESPEC_TO_NSEC(&this->now);
36
37
written, spa_strerror(written));
38
goto stop;
39
}
40
- spa_log_trace(this->log, "wrote socket data %d", written);
41
42
this->buffer_head += written;
43
44
45
46
next_timeout = get_next_timeout(this, now_time, processed / port->frame_size);
47
48
- if (this->clock) {
49
+ if (!this->following && this->clock) {
50
this->clock->nsec = now_time;
51
this->clock->position = this->total_samples;
52
this->clock->delay = processed / port->frame_size;
53
this->clock->rate_diff = 1.0f;
54
- this->clock->next_nsec = next_timeout;
55
+ this->clock->next_nsec = now_time + next_timeout;
56
}
57
+
58
+ if (next_timeout == 0)
59
+ goto again;
60
+
61
+ spa_log_trace(this->log, "timeout %"PRIu64" ns", next_timeout);
62
+ set_timeout(this, next_timeout);
63
+ } else {
64
+ /* As follower, driver will wake us up when there is data */
65
+ if (this->following)
66
+ return;
67
+
68
+ /* As driver, run timeout now to schedule data */
69
+ spa_log_trace(this->log, "timeout 1 ns (driver: schedule now)");
70
+ set_timeout(this, 1);
71
}
72
73
- /* schedule next timeout */
74
- set_timeout(this, next_timeout);
75
return;
76
77
stop:
78
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
10
1
2
{
3
const char *s;
4
char *d;
5
- int h1, h2;
6
+ int h1 = 0, h2 = 0;
7
enum { TEXT, BACKSLASH, EX, FIRST } state = TEXT;
8
9
for (s = src, d = dst; *s; s++) {
10
pipewire-0.3.45.tar.gz/src/daemon/filter-chain/duplicate-FL.conf
Added
50
1
2
+# An example filter chain for duplicating the FL channel
3
+# to FL and FR.
4
+#
5
+# Copy this file into a conf.d/ directory
6
+#
7
+context.modules = [
8
+ { name = libpipewire-module-filter-chain
9
+ args = {
10
+ node.name = "remap-FL-to-FL-FR"
11
+ node.description = "Remap example"
12
+ media.name = "Remap example"
13
+ filter.graph = {
14
+ nodes = [
15
+ {
16
+ name = copyIL
17
+ type = builtin
18
+ label = copy
19
+ }
20
+ {
21
+ name = copyOL
22
+ type = builtin
23
+ label = copy
24
+ }
25
+ {
26
+ name = copyOR
27
+ type = builtin
28
+ label = copy
29
+ }
30
+ ]
31
+ links = [
32
+ # we can only tee from nodes, not inputs so we need
33
+ # to copy the inputs and then tee.
34
+ { output = "copyIL:Out" input = "copyOL:In" }
35
+ { output = "copyIL:Out" input = "copyOR:In" }
36
+ ]
37
+ inputs = [ "copyIL:In" ]
38
+ outputs = [ "copyOL:Out" "copyOR:Out" ]
39
+ }
40
+ capture.props = {
41
+ audio.position = [ FL ]
42
+ stream.dont-remix = true
43
+ }
44
+ playback.props = {
45
+ audio.position = [ FL FR ]
46
+ }
47
+ }
48
+ }
49
+]
50
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
8
1
2
conf_files = [
3
[ 'demonic.conf', 'demonic.conf' ],
4
+ [ 'duplicate-FL.conf', 'duplicate-FL.conf' ],
5
[ 'sink-virtual-surround-5.1-kemar.conf', 'sink-virtual-surround-5.1-kemar.conf' ],
6
[ 'sink-virtual-surround-7.1-hesuvi.conf', 'sink-virtual-surround-7.1-hesuvi.conf' ],
7
[ 'sink-dolby-surround.conf', 'sink-dolby-surround.conf' ],
8
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
11
1
2
in = pw_filter_get_dsp_buffer(data->in_port, n_samples);
3
out = pw_filter_get_dsp_buffer(data->out_port, n_samples);
4
5
+ if (in == NULL || out == NULL)
6
+ return;
7
+
8
memcpy(out, in, n_samples * sizeof(float));
9
}
10
11
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
10
1
2
pw_log_trace("do process %d", n_samples);
3
4
out = pw_filter_get_dsp_buffer(out_port, n_samples);
5
+ if (out == NULL)
6
+ return;
7
8
for (i = 0; i < n_samples; i++) {
9
out_port->accumulator += M_PI_M2 * DEFAULT_FREQ / DEFAULT_RATE;
10
pipewire-0.3.44.tar.gz/src/modules/module-adapter.c -> pipewire-0.3.45.tar.gz/src/modules/module-adapter.c
Changed
26
1
2
3
error_properties:
4
res = -EINVAL;
5
- pw_log_error("factory %p: usage: " FACTORY_USAGE, d->this);
6
- if (resource)
7
- pw_resource_errorf_id(resource, new_id, res, "usage: " FACTORY_USAGE);
8
+ pw_resource_errorf_id(resource, new_id, res, "usage: " FACTORY_USAGE);
9
goto error_cleanup;
10
error_errno:
11
res = -errno;
12
- pw_log_error("can't create node: %m");
13
- if (resource)
14
- pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res));
15
+ pw_resource_errorf_id(resource, new_id, res, "can't create node: %s", spa_strerror(res));
16
goto error_cleanup;
17
error_usage:
18
res = -EINVAL;
19
pw_log_error("usage: "ADAPTER_USAGE);
20
- if (resource)
21
- pw_resource_errorf_id(resource, new_id, res, "usage: "ADAPTER_USAGE);
22
+ pw_resource_errorf_id(resource, new_id, res, "usage: "ADAPTER_USAGE);
23
goto error_cleanup;
24
error_cleanup:
25
pw_properties_free(properties);
26
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
134
1
2
3
#include <pipewire/extensions/protocol-native.h>
4
5
+#define MAX_DICT 256
6
+#define MAX_PARAM_INFO 128
7
+
8
static inline void push_item(struct spa_pod_builder *b, const struct spa_dict_item *item)
9
{
10
const char *str;
11
12
return 0;
13
}
14
15
-static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict)
16
-{
17
- uint32_t i;
18
- int res;
19
- for (i = 0; i < dict->n_items; i++) {
20
- if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0)
21
- return res;
22
- }
23
- return 0;
24
-}
25
+#define parse_dict(prs,d) \
26
+do { \
27
+ uint32_t i; \
28
+ if (spa_pod_parser_get(prs, \
29
+ SPA_POD_Int(&(d)->n_items), NULL) < 0) \
30
+ return -EINVAL; \
31
+ if ((d)->n_items > 0) { \
32
+ if ((d)->n_items > MAX_DICT) \
33
+ return -ENOSPC; \
34
+ (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \
35
+ for (i = 0; i < (d)->n_items; i++) { \
36
+ if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \
37
+ return -EINVAL; \
38
+ } \
39
+ } \
40
+} while(0)
41
+
42
+#define parse_param_info(prs,n_params,params) \
43
+do { \
44
+ uint32_t i; \
45
+ if (spa_pod_parser_get(prs, \
46
+ SPA_POD_Int(&(n_params)), NULL) < 0) \
47
+ return -EINVAL; \
48
+ if (n_params > 0) { \
49
+ if (n_params > MAX_PARAM_INFO) \
50
+ return -ENOSPC; \
51
+ params = alloca(n_params * sizeof(struct spa_param_info)); \
52
+ for (i = 0; i < n_params; i++) { \
53
+ if (spa_pod_parser_get(prs, \
54
+ SPA_POD_Id(&(params[i]).id), \
55
+ SPA_POD_Int(&(params[i]).flags), NULL) < 0) \
56
+ return -EINVAL; \
57
+ } \
58
+ } \
59
+} while(0)
60
61
static int device_marshal_add_listener(void *object,
62
struct spa_hook *listener,
63
64
struct spa_pod *ipod;
65
struct spa_device_info info = SPA_DEVICE_INFO_INIT(), *infop;
66
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
67
- uint32_t i;
68
69
spa_pod_parser_init(&prs, msg->data, msg->size);
70
71
72
if (spa_pod_parser_push_struct(&p2, &f2) < 0 ||
73
spa_pod_parser_get(&p2,
74
SPA_POD_Long(&info.change_mask),
75
- SPA_POD_Long(&info.flags),
76
- SPA_POD_Int(&props.n_items), NULL) < 0)
77
+ SPA_POD_Long(&info.flags), NULL) < 0)
78
return -EINVAL;
79
80
info.change_mask &= SPA_DEVICE_CHANGE_MASK_FLAGS |
81
SPA_DEVICE_CHANGE_MASK_PROPS |
82
SPA_DEVICE_CHANGE_MASK_PARAMS;
83
84
- if (props.n_items > 0) {
85
+ parse_dict(&p2, &props);
86
+ if (props.n_items > 0)
87
info.props = &props;
88
89
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
90
- if (parse_dict(&p2, &props) < 0)
91
- return -EINVAL;
92
- }
93
- if (spa_pod_parser_get(&p2,
94
- SPA_POD_Int(&info.n_params), NULL) < 0)
95
- return -EINVAL;
96
-
97
- if (info.n_params > 0) {
98
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
99
- for (i = 0; i < info.n_params; i++) {
100
- if (spa_pod_parser_get(&p2,
101
- SPA_POD_Id(&info.params[i].id),
102
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
103
- return -EINVAL;
104
- }
105
- }
106
+ parse_param_info(&p2, info.n_params, info.params);
107
}
108
else {
109
infop = NULL;
110
111
spa_pod_parser_get(&p2,
112
SPA_POD_String(&info.type),
113
SPA_POD_Long(&info.change_mask),
114
- SPA_POD_Long(&info.flags),
115
- SPA_POD_Int(&props.n_items), NULL) < 0)
116
+ SPA_POD_Long(&info.flags), NULL) < 0)
117
return -EINVAL;
118
119
info.change_mask &= SPA_DEVICE_OBJECT_CHANGE_MASK_FLAGS |
120
SPA_DEVICE_CHANGE_MASK_PROPS;
121
122
- if (props.n_items > 0) {
123
+ parse_dict(&p2, &props);
124
+ if (props.n_items > 0)
125
info.props = &props;
126
-
127
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
128
- if (parse_dict(&p2, &props) < 0)
129
- return -EINVAL;
130
- }
131
} else {
132
infop = NULL;
133
}
134
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
11
1
2
if (!CHECK_PORT(this, direction, port_id))
3
return n_buffers == 0 ? 0 : -EINVAL;
4
5
+ if (n_buffers > MAX_BUFFERS)
6
+ return -ENOSPC;
7
+
8
p = GET_PORT(this, direction, port_id);
9
10
spa_log_debug(this->log, "%p: %s port %d.%d use buffers %p %u flags:%08x", this,
11
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
314
1
2
#include <pipewire/extensions/protocol-native.h>
3
#include <pipewire/extensions/client-node.h>
4
5
+#define MAX_DICT 256
6
+#define MAX_PARAMS 128
7
+#define MAX_PARAM_INFO 128
8
+#define MAX_BUFFERS 64
9
+#define MAX_METAS 16u
10
+#define MAX_DATAS 64u
11
+
12
PW_LOG_TOPIC_EXTERN(mod_topic);
13
#define PW_LOG_TOPIC_DEFAULT mod_topic
14
15
16
return 0;
17
}
18
19
-static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict)
20
-{
21
- uint32_t i;
22
- int res;
23
- for (i = 0; i < dict->n_items; i++) {
24
- if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0)
25
- return res;
26
- }
27
- return 0;
28
-}
29
+#define parse_dict(prs,d) \
30
+do { \
31
+ uint32_t i; \
32
+ if (spa_pod_parser_get(prs, \
33
+ SPA_POD_Int(&(d)->n_items), NULL) < 0) \
34
+ return -EINVAL; \
35
+ (d)->items = NULL; \
36
+ if ((d)->n_items > 0) { \
37
+ if ((d)->n_items > MAX_DICT) \
38
+ return -ENOSPC; \
39
+ (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \
40
+ for (i = 0; i < (d)->n_items; i++) { \
41
+ if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \
42
+ return -EINVAL; \
43
+ } \
44
+ } \
45
+} while(0)
46
+
47
+#define parse_dict_struct(prs,f,dict) \
48
+do { \
49
+ if (spa_pod_parser_push_struct(prs, f) < 0) \
50
+ return -EINVAL; \
51
+ parse_dict(prs, dict); \
52
+ spa_pod_parser_pop(prs, f); \
53
+} while(0)
54
+
55
+#define parse_params(prs,n_params,params) \
56
+do { \
57
+ uint32_t i; \
58
+ if (spa_pod_parser_get(prs, \
59
+ SPA_POD_Int(&n_params), NULL) < 0) \
60
+ return -EINVAL; \
61
+ params = NULL; \
62
+ if (n_params > 0) { \
63
+ if (n_params > MAX_PARAMS) \
64
+ return -ENOSPC; \
65
+ params = alloca(n_params * sizeof(struct spa_pod *)); \
66
+ for (i = 0; i < n_params; i++) { \
67
+ if (spa_pod_parser_get(prs, \
68
+ SPA_POD_PodObject(¶ms[i]), NULL) < 0) \
69
+ return -EINVAL; \
70
+ } \
71
+ } \
72
+} while(0)
73
+
74
+#define parse_param_info(prs,n_params,params) \
75
+do { \
76
+ uint32_t i; \
77
+ if (spa_pod_parser_get(prs, \
78
+ SPA_POD_Int(&(n_params)), NULL) < 0) \
79
+ return -EINVAL; \
80
+ params = NULL; \
81
+ if (n_params > 0) { \
82
+ if (n_params > MAX_PARAM_INFO) \
83
+ return -ENOSPC; \
84
+ params = alloca(n_params * sizeof(struct spa_param_info)); \
85
+ for (i = 0; i < n_params; i++) { \
86
+ if (spa_pod_parser_get(prs, \
87
+ SPA_POD_Id(&(params[i]).id), \
88
+ SPA_POD_Int(&(params[i]).flags), NULL) < 0) \
89
+ return -EINVAL; \
90
+ } \
91
+ } \
92
+} while(0)
93
94
static int client_node_marshal_add_listener(void *object,
95
struct spa_hook *listener,
96
97
SPA_POD_Int(&port_id), NULL) < 0)
98
return -EINVAL;
99
100
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0)
101
- return -EINVAL;
102
- if (spa_pod_parser_get(&prs,
103
- SPA_POD_Int(&props.n_items), NULL) < 0)
104
- return -EINVAL;
105
-
106
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
107
- if (parse_dict(&prs, &props) < 0)
108
- return -EINVAL;
109
+ parse_dict_struct(&prs, &f[1], &props);
110
111
pw_proxy_notify(proxy, struct pw_client_node_events, add_port, 0, direction, port_id,
112
props.n_items ? &props : NULL);
113
114
SPA_POD_Int(&n_buffers), NULL) < 0)
115
return -EINVAL;
116
117
+ if (n_buffers > MAX_BUFFERS)
118
+ return -ENOSPC;
119
+
120
buffers = alloca(sizeof(struct pw_client_node_buffer) * n_buffers);
121
for (i = 0; i < n_buffers; i++) {
122
struct spa_buffer *buf = buffers[i].buffer = alloca(sizeof(struct spa_buffer));
123
124
SPA_POD_Int(&buf->n_metas), NULL) < 0)
125
return -EINVAL;
126
127
+ if (buf->n_metas > MAX_METAS)
128
+ return -ENOSPC;
129
+
130
buf->metas = alloca(sizeof(struct spa_meta) * buf->n_metas);
131
for (j = 0; j < buf->n_metas; j++) {
132
struct spa_meta *m = &buf->metas[j];
133
134
SPA_POD_Int(&buf->n_datas), NULL) < 0)
135
return -EINVAL;
136
137
+ if (buf->n_datas > MAX_DATAS)
138
+ return -ENOSPC;
139
+
140
buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas);
141
for (j = 0; j < buf->n_datas; j++) {
142
struct spa_data *d = &buf->datas[j];
143
144
SPA_POD_Int(&peer_id), NULL) < 0)
145
return -EINVAL;
146
147
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0)
148
- return -EINVAL;
149
- if (spa_pod_parser_get(&prs,
150
- SPA_POD_Int(&props.n_items), NULL) < 0)
151
- return -EINVAL;
152
-
153
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
154
- if (parse_dict(&prs, &props) < 0)
155
- return -EINVAL;
156
+ parse_dict_struct(&prs, &f[1], &props);
157
158
pw_proxy_notify(proxy, struct pw_client_node_events, port_set_mix_info, 1,
159
direction, port_id, mix_id,
160
161
struct spa_pod_parser prs;
162
struct spa_pod_frame f[2];
163
uint32_t change_mask, n_params;
164
- const struct spa_pod **params;
165
+ const struct spa_pod **params = NULL;
166
struct spa_node_info info = SPA_NODE_INFO_INIT(), *infop = NULL;
167
struct spa_pod *ipod;
168
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
169
- uint32_t i;
170
171
spa_pod_parser_init(&prs, msg->data, msg->size);
172
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
173
spa_pod_parser_get(&prs,
174
- SPA_POD_Int(&change_mask),
175
- SPA_POD_Int(&n_params), NULL) < 0)
176
+ SPA_POD_Int(&change_mask), NULL) < 0)
177
return -EINVAL;
178
179
- params = alloca(n_params * sizeof(struct spa_pod *));
180
- for (i = 0; i < n_params; i++)
181
- if (spa_pod_parser_get(&prs,
182
- SPA_POD_PodObject(¶ms[i]), NULL) < 0)
183
- return -EINVAL;
184
+ parse_params(&prs, n_params, params);
185
186
if (spa_pod_parser_get(&prs,
187
SPA_POD_PodStruct(&ipod), NULL) < 0)
188
189
SPA_POD_Int(&info.max_input_ports),
190
SPA_POD_Int(&info.max_output_ports),
191
SPA_POD_Long(&info.change_mask),
192
- SPA_POD_Long(&info.flags),
193
- SPA_POD_Int(&props.n_items), NULL) < 0)
194
+ SPA_POD_Long(&info.flags), NULL) < 0)
195
return -EINVAL;
196
197
info.change_mask &= SPA_NODE_CHANGE_MASK_FLAGS |
198
SPA_NODE_CHANGE_MASK_PROPS |
199
SPA_NODE_CHANGE_MASK_PARAMS;
200
201
- if (props.n_items > 0) {
202
+ parse_dict(&p2, &props);
203
+ if (props.n_items > 0)
204
info.props = &props;
205
206
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
207
- if (parse_dict(&p2, &props) < 0)
208
- return -EINVAL;
209
- }
210
- if (spa_pod_parser_get(&p2,
211
- SPA_POD_Int(&info.n_params), NULL) < 0)
212
- return -EINVAL;
213
-
214
- if (info.n_params > 0) {
215
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
216
- for (i = 0; i < info.n_params; i++) {
217
- if (spa_pod_parser_get(&p2,
218
- SPA_POD_Id(&info.params[i].id),
219
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
220
- return -EINVAL;
221
- }
222
- }
223
+ parse_param_info(&p2, info.n_params, info.params);
224
}
225
226
pw_resource_notify(resource, struct pw_client_node_methods, update, 0, change_mask,
227
228
struct pw_resource *resource = object;
229
struct spa_pod_parser prs;
230
struct spa_pod_frame f;
231
- uint32_t i, direction, port_id, change_mask, n_params;
232
+ uint32_t direction, port_id, change_mask, n_params;
233
const struct spa_pod **params = NULL;
234
struct spa_port_info info = SPA_PORT_INFO_INIT(), *infop = NULL;
235
struct spa_pod *ipod;
236
237
spa_pod_parser_get(&prs,
238
SPA_POD_Int(&direction),
239
SPA_POD_Int(&port_id),
240
- SPA_POD_Int(&change_mask),
241
- SPA_POD_Int(&n_params), NULL) < 0)
242
+ SPA_POD_Int(&change_mask), NULL) < 0)
243
return -EINVAL;
244
245
- params = alloca(n_params * sizeof(struct spa_pod *));
246
- for (i = 0; i < n_params; i++)
247
- if (spa_pod_parser_get(&prs,
248
- SPA_POD_PodObject(¶ms[i]), NULL) < 0)
249
- return -EINVAL;
250
+ parse_params(&prs, n_params, params);
251
252
if (spa_pod_parser_get(&prs,
253
SPA_POD_PodStruct(&ipod), NULL) < 0)
254
255
SPA_POD_Long(&info.change_mask),
256
SPA_POD_Long(&info.flags),
257
SPA_POD_Int(&info.rate.num),
258
- SPA_POD_Int(&info.rate.denom),
259
- SPA_POD_Int(&props.n_items), NULL) < 0)
260
+ SPA_POD_Int(&info.rate.denom), NULL) < 0)
261
return -EINVAL;
262
263
info.change_mask &= SPA_PORT_CHANGE_MASK_FLAGS |
264
265
SPA_PORT_CHANGE_MASK_PROPS |
266
SPA_PORT_CHANGE_MASK_PARAMS;
267
268
- if (props.n_items > 0) {
269
+ parse_dict(&p2, &props);
270
+ if (props.n_items > 0)
271
info.props = &props;
272
273
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
274
- if (parse_dict(&p2, &props) < 0)
275
- return -EINVAL;
276
- }
277
- if (spa_pod_parser_get(&p2,
278
- SPA_POD_Int(&info.n_params), NULL) < 0)
279
- return -EINVAL;
280
-
281
- if (info.n_params > 0) {
282
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
283
- for (i = 0; i < info.n_params; i++) {
284
- if (spa_pod_parser_get(&p2,
285
- SPA_POD_Id(&info.params[i].id),
286
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
287
- return -EINVAL;
288
- }
289
- }
290
+ parse_param_info(&p2, info.n_params, info.params);
291
}
292
293
pw_resource_notify(resource, struct pw_client_node_methods, port_update, 0, direction,
294
295
SPA_POD_Int(&n_buffers), NULL) < 0)
296
return -EINVAL;
297
298
+ if (n_buffers > MAX_BUFFERS)
299
+ return -ENOSPC;
300
+
301
buffers = alloca(sizeof(struct spa_buffer*) * n_buffers);
302
for (i = 0; i < n_buffers; i++) {
303
struct spa_buffer *buf = buffers[i] = alloca(sizeof(struct spa_buffer));
304
305
SPA_POD_Int(&buf->n_datas), NULL) < 0)
306
return -EINVAL;
307
308
+ if (buf->n_datas > MAX_DATAS)
309
+ return -ENOSPC;
310
+
311
buf->datas = alloca(sizeof(struct spa_data) * buf->n_datas);
312
for (j = 0; j < buf->n_datas; j++) {
313
struct spa_data *d = &buf->datas[j];
314
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
21
1
2
#include "pipewire/extensions/protocol-native.h"
3
#include "pipewire/extensions/client-node.h"
4
5
-#define MAX_MIX 4096
6
+#define MAX_BUFFERS 64
7
+#define MAX_MIX 4096
8
9
PW_LOG_TOPIC_EXTERN(mod_topic);
10
#define PW_LOG_TOPIC_DEFAULT mod_topic
11
12
goto error_exit;
13
}
14
15
+ if (n_buffers > MAX_BUFFERS)
16
+ return -ENOSPC;
17
+
18
prot = PW_MEMMAP_FLAG_READWRITE;
19
20
/* clear previous buffers */
21
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
62
1
2
3
struct factory_data {
4
struct pw_impl_module *module;
5
+ struct pw_context *context;
6
struct pw_impl_factory *this;
7
8
struct spa_list link_list;
9
10
static void link_initialized(void *data)
11
{
12
struct link_data *ld = data;
13
- struct pw_impl_client *client = pw_resource_get_client(ld->factory_resource);
14
+ struct pw_impl_client *client;
15
int res;
16
17
+ if (ld->factory_resource == NULL)
18
+ return;
19
+
20
+ client = pw_resource_get_client(ld->factory_resource);
21
ld->global = pw_impl_link_get_global(ld->link);
22
pw_global_add_listener(ld->global, &ld->global_listener, &global_events, ld);
23
24
25
struct pw_impl_client *client = NULL;
26
struct pw_impl_node *output_node, *input_node;
27
struct pw_impl_port *outport = NULL, *inport = NULL;
28
- struct pw_context *context;
29
+ struct pw_context *context = d->context;
30
struct pw_impl_link *link;
31
const char *output_node_str, *input_node_str;
32
const char *output_port_str, *input_port_str;
33
34
int res;
35
bool linger;
36
37
- client = pw_resource_get_client(resource);
38
- context = pw_impl_client_get_context(client);
39
-
40
if (properties == NULL)
41
goto error_properties;
42
43
44
45
pw_properties_setf(properties, PW_KEY_FACTORY_ID, "%d",
46
pw_impl_factory_get_info(d->this)->id);
47
- if (!linger)
48
+
49
+ client = resource ? pw_resource_get_client(resource) : NULL;
50
+ if (client && !linger)
51
pw_properties_setf(properties, PW_KEY_CLIENT_ID, "%d",
52
pw_impl_client_get_info(client)->id);
53
54
55
data = pw_impl_factory_get_user_data(factory);
56
data->this = factory;
57
data->module = module;
58
+ data->context = context;
59
data->work = pw_context_get_work_queue(context);
60
if (data->work == NULL) {
61
res = -errno;
62
pipewire-0.3.44.tar.gz/src/modules/module-metadata.c -> pipewire-0.3.45.tar.gz/src/modules/module-metadata.c
Changed
19
1
2
return result;
3
4
error_resource:
5
- pw_log_error("can't create resource: %s", spa_strerror(res));
6
- if (resource)
7
- pw_resource_errorf_id(resource, new_id, res,
8
+ pw_resource_errorf_id(resource, new_id, res,
9
"can't create resource: %s", spa_strerror(res));
10
goto error_exit;
11
error_node:
12
- pw_log_error("can't create metadata: %s", spa_strerror(res));
13
- if (resource)
14
- pw_resource_errorf_id(resource, new_id, res,
15
+ pw_resource_errorf_id(resource, new_id, res,
16
"can't create metadata: %s", spa_strerror(res));
17
goto error_exit_free;
18
19
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
11
1
2
return res;
3
4
error:
5
- if (client->core_resource)
6
- pw_resource_errorf(client->core_resource, res, "client error %d (%s)",
7
+ pw_resource_errorf(client->core_resource, res, "client error %d (%s)",
8
res, spa_strerror(res));
9
goto done;
10
}
11
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
478
1
2
3
#include "connection.h"
4
5
+#define MAX_DICT 256
6
+#define MAX_PARAM_INFO 128
7
+#define MAX_PERMISSIONS 1024
8
+
9
PW_LOG_TOPIC_EXTERN(mod_topic);
10
#define PW_LOG_TOPIC_DEFAULT mod_topic
11
12
13
return 0;
14
}
15
16
-static inline int parse_dict(struct spa_pod_parser *prs, struct spa_dict *dict)
17
-{
18
- uint32_t i;
19
- int res;
20
- for (i = 0; i < dict->n_items; i++) {
21
- if ((res = parse_item(prs, (struct spa_dict_item *) &dict->items[i])) < 0)
22
- return res;
23
- }
24
- return 0;
25
-}
26
+#define parse_dict(prs,d) \
27
+do { \
28
+ if (spa_pod_parser_get(prs, \
29
+ SPA_POD_Int(&(d)->n_items), NULL) < 0) \
30
+ return -EINVAL; \
31
+ (d)->items = NULL; \
32
+ if ((d)->n_items > 0) { \
33
+ uint32_t i; \
34
+ if ((d)->n_items > MAX_DICT) \
35
+ return -ENOSPC; \
36
+ (d)->items = alloca((d)->n_items * sizeof(struct spa_dict_item)); \
37
+ for (i = 0; i < (d)->n_items; i++) { \
38
+ if (parse_item(prs, (struct spa_dict_item *) &(d)->items[i]) < 0) \
39
+ return -EINVAL; \
40
+ } \
41
+ } \
42
+} while(0)
43
+
44
+#define parse_dict_struct(prs,f,dict) \
45
+do { \
46
+ if (spa_pod_parser_push_struct(prs, f) < 0) \
47
+ return -EINVAL; \
48
+ parse_dict(prs, dict); \
49
+ spa_pod_parser_pop(prs, f); \
50
+} while(0)
51
52
static void push_params(struct spa_pod_builder *b, uint32_t n_params,
53
const struct spa_param_info *params)
54
55
spa_pod_builder_pop(b, &f);
56
}
57
58
+
59
+#define parse_params_struct(prs,f,params,n_params) \
60
+do { \
61
+ if (spa_pod_parser_push_struct(prs, f) < 0 || \
62
+ spa_pod_parser_get(prs, \
63
+ SPA_POD_Int(&(n_params)), NULL) < 0) \
64
+ return -EINVAL; \
65
+ params = NULL; \
66
+ if (n_params > 0) { \
67
+ uint32_t i; \
68
+ if (n_params > MAX_PARAM_INFO) \
69
+ return -ENOSPC; \
70
+ params = alloca(n_params * sizeof(struct spa_param_info)); \
71
+ for (i = 0; i < n_params; i++) { \
72
+ if (spa_pod_parser_get(prs, \
73
+ SPA_POD_Id(&(params)[i].id), \
74
+ SPA_POD_Int(&(params)[i].flags), NULL) < 0) \
75
+ return -EINVAL; \
76
+ } \
77
+ } \
78
+ spa_pod_parser_pop(prs, f); \
79
+} while(0)
80
+
81
+
82
+#define parse_permissions_struct(prs,f,n_permissions,permissions) \
83
+do { \
84
+ if (spa_pod_parser_push_struct(prs, f) < 0 || \
85
+ spa_pod_parser_get(prs, \
86
+ SPA_POD_Int(&n_permissions), NULL) < 0) \
87
+ return -EINVAL; \
88
+ permissions = NULL; \
89
+ if (n_permissions > 0) { \
90
+ uint32_t i; \
91
+ if (n_permissions > MAX_PERMISSIONS) \
92
+ return -ENOSPC; \
93
+ permissions = alloca(n_permissions * sizeof(struct pw_permission)); \
94
+ for (i = 0; i < n_permissions; i++) { \
95
+ if (spa_pod_parser_get(prs, \
96
+ SPA_POD_Int(&permissions[i].id), \
97
+ SPA_POD_Int(&permissions[i].permissions), NULL) < 0) \
98
+ return -EINVAL; \
99
+ } \
100
+ } \
101
+ spa_pod_parser_pop(prs, f); \
102
+} while(0)
103
+
104
static void *
105
core_method_marshal_create_object(void *object,
106
const char *factory_name,
107
108
{
109
struct pw_proxy *proxy = object;
110
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
111
+ struct pw_core_info info = { .props = &props };
112
struct spa_pod_frame f[2];
113
- struct pw_core_info info;
114
struct spa_pod_parser prs;
115
116
spa_pod_parser_init(&prs, msg->data, msg->size);
117
118
SPA_POD_Long(&info.change_mask), NULL) < 0)
119
return -EINVAL;
120
121
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0)
122
- return -EINVAL;
123
- if (spa_pod_parser_get(&prs,
124
- SPA_POD_Int(&props.n_items), NULL) < 0)
125
- return -EINVAL;
126
127
- info.props = &props;
128
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
129
- if (parse_dict(&prs, &props) < 0)
130
- return -EINVAL;
131
+ parse_dict_struct(&prs, &f[1], &props);
132
133
return pw_proxy_notify(proxy, struct pw_core_events, info, 0, &info);
134
}
135
136
NULL) < 0)
137
return -EINVAL;
138
139
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
140
- spa_pod_parser_get(&prs,
141
- SPA_POD_Int(&props.n_items), NULL) < 0)
142
- return -EINVAL;
143
-
144
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
145
- if (parse_dict(&prs, &props) < 0)
146
- return -EINVAL;
147
- spa_pod_parser_pop(&prs, &f[1]);
148
+ parse_dict_struct(&prs, &f[1], &props);
149
150
if (spa_pod_parser_get(&prs,
151
SPA_POD_Int(&new_id), NULL) < 0)
152
153
struct spa_pod_parser prs;
154
struct spa_pod_frame f[2];
155
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
156
- struct pw_module_info info;
157
+ struct pw_module_info info = { .props = &props };
158
159
spa_pod_parser_init(&prs, msg->data, msg->size);
160
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
161
162
SPA_POD_Long(&info.change_mask), NULL) < 0)
163
return -EINVAL;
164
165
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
166
- spa_pod_parser_get(&prs,
167
- SPA_POD_Int(&props.n_items), NULL) < 0)
168
- return -EINVAL;
169
-
170
- info.props = &props;
171
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
172
- if (parse_dict(&prs, &props) < 0)
173
- return -EINVAL;
174
+ parse_dict_struct(&prs, &f[1], &props);
175
176
return pw_proxy_notify(proxy, struct pw_module_events, info, 0, &info);
177
}
178
179
struct spa_pod_parser prs;
180
struct spa_pod_frame f[2];
181
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
182
- struct pw_device_info info;
183
- uint32_t i;
184
+ struct pw_device_info info = { .props = &props };
185
186
spa_pod_parser_init(&prs, msg->data, msg->size);
187
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
188
189
SPA_POD_Long(&info.change_mask), NULL) < 0)
190
return -EINVAL;
191
192
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
193
- spa_pod_parser_get(&prs,
194
- SPA_POD_Int(&props.n_items), NULL) < 0)
195
- return -EINVAL;
196
-
197
- info.props = &props;
198
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
199
- if (parse_dict(&prs, &props) < 0)
200
- return -EINVAL;
201
- spa_pod_parser_pop(&prs, &f[1]);
202
-
203
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
204
- spa_pod_parser_get(&prs,
205
- SPA_POD_Int(&info.n_params),
206
- NULL) < 0)
207
- return -EINVAL;
208
-
209
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
210
- for (i = 0; i < info.n_params; i++) {
211
- if (spa_pod_parser_get(&prs,
212
- SPA_POD_Id(&info.params[i].id),
213
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
214
- return -EINVAL;
215
- }
216
+ parse_dict_struct(&prs, &f[1], &props);
217
+ parse_params_struct(&prs, &f[1], info.params, info.n_params);
218
219
return pw_proxy_notify(proxy, struct pw_device_events, info, 0, &info);
220
}
221
222
struct spa_pod_parser prs;
223
struct spa_pod_frame f[2];
224
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
225
- struct pw_factory_info info;
226
+ struct pw_factory_info info = { .props = &props };
227
228
spa_pod_parser_init(&prs, msg->data, msg->size);
229
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
230
231
SPA_POD_Long(&info.change_mask), NULL) < 0)
232
return -EINVAL;
233
234
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
235
- spa_pod_parser_get(&prs,
236
- SPA_POD_Int(&props.n_items), NULL) < 0)
237
- return -EINVAL;
238
-
239
- info.props = &props;
240
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
241
- if (parse_dict(&prs, &props) < 0)
242
- return -EINVAL;
243
+ parse_dict_struct(&prs, &f[1], &props);
244
245
return pw_proxy_notify(proxy, struct pw_factory_events, info, 0, &info);
246
}
247
248
struct spa_pod_parser prs;
249
struct spa_pod_frame f[2];
250
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
251
- struct pw_node_info info;
252
- uint32_t i;
253
+ struct pw_node_info info = { .props = &props };
254
255
spa_pod_parser_init(&prs, msg->data, msg->size);
256
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
257
258
SPA_POD_String(&info.error), NULL) < 0)
259
return -EINVAL;
260
261
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
262
- spa_pod_parser_get(&prs,
263
- SPA_POD_Int(&props.n_items), NULL) < 0)
264
- return -EINVAL;
265
-
266
- info.props = &props;
267
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
268
- if (parse_dict(&prs, &props) < 0)
269
- return -EINVAL;
270
- spa_pod_parser_pop(&prs, &f[1]);
271
-
272
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
273
- spa_pod_parser_get(&prs,
274
- SPA_POD_Int(&info.n_params),
275
- NULL) < 0)
276
- return -EINVAL;
277
-
278
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
279
- for (i = 0; i < info.n_params; i++) {
280
- if (spa_pod_parser_get(&prs,
281
- SPA_POD_Id(&info.params[i].id),
282
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
283
- return -EINVAL;
284
- }
285
+ parse_dict_struct(&prs, &f[1], &props);
286
+ parse_params_struct(&prs, &f[1], info.params, info.n_params);
287
288
return pw_proxy_notify(proxy, struct pw_node_events, info, 0, &info);
289
}
290
291
struct spa_pod_parser prs;
292
struct spa_pod_frame f[2];
293
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
294
- struct pw_port_info info;
295
- uint32_t i;
296
+ struct pw_port_info info = { .props = &props };
297
298
spa_pod_parser_init(&prs, msg->data, msg->size);
299
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
300
301
SPA_POD_Long(&info.change_mask), NULL) < 0)
302
return -EINVAL;
303
304
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
305
- spa_pod_parser_get(&prs,
306
- SPA_POD_Int(&props.n_items), NULL) < 0)
307
- return -EINVAL;
308
-
309
- info.props = &props;
310
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
311
- if (parse_dict(&prs, &props) < 0)
312
- return -EINVAL;
313
- spa_pod_parser_pop(&prs, &f[1]);
314
-
315
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
316
- spa_pod_parser_get(&prs,
317
- SPA_POD_Int(&info.n_params),
318
- NULL) < 0)
319
- return -EINVAL;
320
+ parse_dict_struct(&prs, &f[1], &props);
321
+ parse_params_struct(&prs, &f[1], info.params, info.n_params);
322
323
- info.params = alloca(info.n_params * sizeof(struct spa_param_info));
324
- for (i = 0; i < info.n_params; i++) {
325
- if (spa_pod_parser_get(&prs,
326
- SPA_POD_Id(&info.params[i].id),
327
- SPA_POD_Int(&info.params[i].flags), NULL) < 0)
328
- return -EINVAL;
329
- }
330
return pw_proxy_notify(proxy, struct pw_port_events, info, 0, &info);
331
}
332
333
334
struct spa_pod_parser prs;
335
struct spa_pod_frame f[2];
336
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
337
- struct pw_client_info info;
338
+ struct pw_client_info info = { .props = &props };
339
340
spa_pod_parser_init(&prs, msg->data, msg->size);
341
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
342
343
SPA_POD_Long(&info.change_mask), NULL) < 0)
344
return -EINVAL;
345
346
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
347
- spa_pod_parser_get(&prs,
348
- SPA_POD_Int(&props.n_items), NULL) < 0)
349
- return -EINVAL;
350
-
351
- info.props = &props;
352
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
353
- if (parse_dict(&prs, &props) < 0)
354
- return -EINVAL;
355
+ parse_dict_struct(&prs, &f[1], &props);
356
357
return pw_proxy_notify(proxy, struct pw_client_events, info, 0, &info);
358
}
359
360
struct pw_permission *permissions;
361
struct spa_pod_parser prs;
362
struct spa_pod_frame f[2];
363
- uint32_t i, index, n_permissions;
364
+ uint32_t index, n_permissions;
365
366
spa_pod_parser_init(&prs, msg->data, msg->size);
367
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
368
369
SPA_POD_Int(&index), NULL) < 0)
370
return -EINVAL;
371
372
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
373
- spa_pod_parser_get(&prs,
374
- SPA_POD_Int(&n_permissions), NULL) < 0)
375
- return -EINVAL;
376
+ parse_permissions_struct(&prs, &f[1], n_permissions, permissions);
377
378
- permissions = alloca(n_permissions * sizeof(struct pw_permission));
379
- for (i = 0; i < n_permissions; i++) {
380
- if (spa_pod_parser_get(&prs,
381
- SPA_POD_Int(&permissions[i].id),
382
- SPA_POD_Int(&permissions[i].permissions), NULL) < 0)
383
- return -EINVAL;
384
- }
385
return pw_proxy_notify(proxy, struct pw_client_events, permissions, 0, index, n_permissions, permissions);
386
}
387
388
389
struct spa_pod_frame f[2];
390
391
spa_pod_parser_init(&prs, msg->data, msg->size);
392
- if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
393
- spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
394
- spa_pod_parser_get(&prs,
395
- SPA_POD_Int(&props.n_items), NULL) < 0)
396
+ if (spa_pod_parser_push_struct(&prs, &f[0]) < 0)
397
return -EINVAL;
398
399
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
400
- if (parse_dict(&prs, &props) < 0)
401
- return -EINVAL;
402
+ parse_dict_struct(&prs, &f[1], &props);
403
404
return pw_resource_notify(resource, struct pw_client_methods, update_properties, 0,
405
&props);
406
407
struct pw_permission *permissions;
408
struct spa_pod_parser prs;
409
struct spa_pod_frame f[1];
410
- uint32_t i, n_permissions;
411
+ uint32_t n_permissions;
412
413
spa_pod_parser_init(&prs, msg->data, msg->size);
414
- if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
415
- spa_pod_parser_get(&prs,
416
- SPA_POD_Int(&n_permissions), NULL) < 0)
417
- return -EINVAL;
418
419
- permissions = alloca(n_permissions * sizeof(struct pw_permission));
420
- for (i = 0; i < n_permissions; i++) {
421
- if (spa_pod_parser_get(&prs,
422
- SPA_POD_Int(&permissions[i].id),
423
- SPA_POD_Int(&permissions[i].permissions), NULL) < 0)
424
- return -EINVAL;
425
- }
426
+ parse_permissions_struct(&prs, &f[0], n_permissions, permissions);
427
+
428
return pw_resource_notify(resource, struct pw_client_methods, update_permissions, 0,
429
n_permissions, permissions);
430
}
431
432
struct spa_pod_parser prs;
433
struct spa_pod_frame f[2];
434
struct spa_dict props = SPA_DICT_INIT(NULL, 0);
435
- struct pw_link_info info = { 0, };
436
+ struct pw_link_info info = { .props = &props };
437
438
spa_pod_parser_init(&prs, msg->data, msg->size);
439
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
440
441
SPA_POD_Pod(&info.format), NULL) < 0)
442
return -EINVAL;
443
444
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
445
- spa_pod_parser_get(&prs,
446
- SPA_POD_Int(&props.n_items), NULL) < 0)
447
- return -EINVAL;
448
-
449
- info.props = &props;
450
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
451
- if (parse_dict(&prs, &props) < 0)
452
- return -EINVAL;
453
+ parse_dict_struct(&prs, &f[1], &props);
454
455
return pw_proxy_notify(proxy, struct pw_link_events, info, 0, &info);
456
}
457
458
SPA_POD_Int(&version), NULL) < 0)
459
return -EINVAL;
460
461
- if (spa_pod_parser_push_struct(&prs, &f[1]) < 0 ||
462
- spa_pod_parser_get(&prs,
463
- SPA_POD_Int(&props.n_items), NULL) < 0)
464
- return -EINVAL;
465
-
466
- props.items = alloca(props.n_items * sizeof(struct spa_dict_item));
467
- if (parse_dict(&prs, &props) < 0)
468
- return -EINVAL;
469
+ parse_dict_struct(&prs, &f[1], &props);
470
471
return pw_proxy_notify(proxy, struct pw_registry_events,
472
- global, 0, id, permissions, type, version,
473
- props.n_items > 0 ? &props : NULL);
474
+ global, 0, id, permissions, type, version, &props);
475
}
476
477
static int registry_demarshal_global_remove(void *object, const struct pw_protocol_native_message *msg)
478
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
48
1
2
3
/* remove from the `server->clients` list */
4
spa_list_remove(&client->link);
5
+ spa_list_append(&impl->cleanup_clients, &client->link);
6
7
server->n_clients--;
8
if (server->wait_clients > 0 && --server->wait_clients == 0) {
9
10
spa_assert(client->server == NULL);
11
12
client->disconnect = true;
13
- spa_list_append(&impl->cleanup_clients, &client->link);
14
15
pw_map_for_each(&client->streams, client_free_stream, client);
16
17
- if (client->source)
18
+ if (client->source) {
19
pw_loop_destroy_source(impl->loop, client->source);
20
+ client->source = NULL;
21
+ }
22
23
- if (client->manager)
24
+ if (client->manager) {
25
pw_manager_destroy(client->manager);
26
+ client->manager = NULL;
27
+ }
28
}
29
30
void client_free(struct client *client)
31
32
spa_list_consume(o, &client->operations, link)
33
operation_free(o);
34
35
- if (client->core) {
36
- client->disconnecting = true;
37
+ if (client->core)
38
pw_core_disconnect(client->core);
39
- }
40
41
pw_map_clear(&client->streams);
42
43
+ pw_work_queue_cancel(impl->work_queue, client, SPA_ID_INVALID);
44
+
45
free(client->default_sink);
46
free(client->default_source);
47
48
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
9
1
2
struct spa_list pending_streams;
3
4
unsigned int disconnect:1;
5
- unsigned int disconnecting:1;
6
unsigned int new_msg_since_last_flush:1;
7
unsigned int authenticated:1;
8
9
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
10
1
2
#define MIN_BUFFERS 1u
3
#define MAX_BUFFERS 4u
4
5
-#define MAXLENGTH (4*1024*1024) /* 4MB */
6
+#define MAXLENGTH (4u*1024*1024) /* 4MB */
7
8
#define SCACHE_ENTRY_SIZE_MAX (1024*1024*16)
9
10
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
27
1
2
return -ENOTSUP;
3
4
info.info.raw.format = SPA_AUDIO_FORMAT_S16;
5
- info.info.raw.channels = 2;
6
info.info.raw.rate = iec.rate;
7
- info.info.raw.position[0] = SPA_AUDIO_CHANNEL_FL;
8
- info.info.raw.position[1] = SPA_AUDIO_CHANNEL_FR;
9
break;
10
}
11
default:
12
13
ss->channels = info.info.raw.channels;
14
}
15
if (map) {
16
- map->channels = info.info.raw.channels;
17
- for (i = 0; i < map->channels; i++)
18
- map->map[i] = info.info.raw.position[i];
19
+ if (info.info.raw.channels) {
20
+ map->channels = info.info.raw.channels;
21
+ for (i = 0; i < map->channels; i++)
22
+ map->map[i] = info.info.raw.position[i];
23
+ }
24
}
25
return 0;
26
}
27
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
37
1
2
static void on_module_unload(void *obj, void *data, int res, uint32_t index)
3
{
4
struct module *module = obj;
5
- module_unload(NULL, module);
6
+ module_unload(module);
7
}
8
9
void module_schedule_unload(struct module *module)
10
11
free(module);
12
}
13
14
-int module_unload(struct client *client, struct module *module)
15
+int module_unload(struct module *module)
16
{
17
struct impl *impl = module->impl;
18
int res = 0;
19
20
pw_log_info("unload module index:%u name:%s", module->index, module->name);
21
22
if (module->methods->unload)
23
- res = module->methods->unload(client, module);
24
+ res = module->methods->unload(module);
25
26
if (module->loaded)
27
broadcast_subscribe_event(impl,
28
29
30
module->index = pw_map_insert_new(&impl->modules, module);
31
if (module->index == SPA_ID_INVALID) {
32
- module_unload(client, module);
33
+ module_unload(module);
34
return NULL;
35
}
36
module->name = strdup(name);
37
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
19
1
2
uint32_t version;
3
4
int (*load) (struct client *client, struct module *module);
5
- int (*unload) (struct client *client, struct module *module);
6
+ int (*unload) (struct module *module);
7
};
8
9
struct module {
10
11
void module_free(struct module *module);
12
struct module *module_new(struct impl *impl, const struct module_methods *methods, size_t user_data);
13
int module_load(struct client *client, struct module *module);
14
-int module_unload(struct client *client, struct module *module);
15
+int module_unload(struct module *module);
16
void module_schedule_unload(struct module *module);
17
18
void module_add_listener(struct module *module,
19
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
10
1
2
return 0;
3
}
4
5
-static int module_combine_sink_unload(struct client *client, struct module *module)
6
+static int module_combine_sink_unload(struct module *module)
7
{
8
struct module_combine_sink_data *d = module->user_data;
9
int i;
10
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
10
1
2
return 0;
3
}
4
5
-static int module_echo_cancel_unload(struct client *client, struct module *module)
6
+static int module_echo_cancel_unload(struct module *module)
7
{
8
struct module_echo_cancel_data *d = module->user_data;
9
10
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
19
1
2
return 0;
3
}
4
5
-static int module_ladspa_sink_unload(struct client *client, struct module *module)
6
+static int module_ladspa_sink_unload(struct module *module)
7
{
8
struct module_ladspa_sink_data *d = module->user_data;
9
10
11
}
12
if (pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS) == NULL)
13
pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
14
+ if (pw_properties_get(capture_props, PW_KEY_DEVICE_CLASS) == NULL)
15
+ pw_properties_set(capture_props, PW_KEY_DEVICE_CLASS, "filter");
16
17
if ((str = pw_properties_get(props, "master")) != NULL ||
18
(str = pw_properties_get(props, "sink_master")) != NULL) {
19
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
19
1
2
return 0;
3
}
4
5
-static int module_ladspa_source_unload(struct client *client, struct module *module)
6
+static int module_ladspa_source_unload(struct module *module)
7
{
8
struct module_ladspa_source_data *d = module->user_data;
9
10
11
}
12
if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL)
13
pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source");
14
+ if (pw_properties_get(playback_props, PW_KEY_DEVICE_CLASS) == NULL)
15
+ pw_properties_set(playback_props, PW_KEY_DEVICE_CLASS, "filter");
16
17
if ((str = pw_properties_get(props, "master")) != NULL ||
18
(str = pw_properties_get(props, "source_master")) != NULL) {
19
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
10
1
2
return 0;
3
}
4
5
-static int module_loopback_unload(struct client *client, struct module *module)
6
+static int module_loopback_unload(struct module *module)
7
{
8
struct module_loopback_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_native_protocol_tcp_unload(struct client *client, struct module *module)
6
+static int module_native_protocol_tcp_unload(struct module *module)
7
{
8
struct module_native_protocol_tcp_data *d = module->user_data;
9
struct server **s;
10
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
10
1
2
return SPA_RESULT_RETURN_ASYNC(0);
3
}
4
5
-static int module_null_sink_unload(struct client *client, struct module *module)
6
+static int module_null_sink_unload(struct module *module)
7
{
8
struct module_null_sink_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_pipesink_unload(struct client *client, struct module *module)
6
+static int module_pipesink_unload(struct module *module)
7
{
8
struct module_pipesink_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_pipesource_unload(struct client *client, struct module *module)
6
+static int module_pipesource_unload(struct module *module)
7
{
8
struct module_pipesrc_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_raop_discover_unload(struct client *client, struct module *module)
6
+static int module_raop_discover_unload(struct module *module)
7
{
8
struct module_raop_discover_data *d = module->user_data;
9
10
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
62
1
2
return 0;
3
}
4
5
-static int module_remap_sink_unload(struct client *client, struct module *module)
6
+static int module_remap_sink_unload(struct module *module)
7
{
8
struct module_remap_sink_data *d = module->user_data;
9
10
11
struct module *module;
12
struct module_remap_sink_data *d;
13
struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
14
- const char *str;
15
+ const char *str, *master;
16
struct spa_audio_info_raw capture_info = { 0 };
17
struct spa_audio_info_raw playback_info = { 0 };
18
int res;
19
20
if (argument)
21
module_args_add_props(props, argument);
22
23
+ master = pw_properties_get(props, "master");
24
+ if (pw_properties_get(props, "sink_name") == NULL) {
25
+ pw_properties_setf(props, "sink_name", "%s.remapped",
26
+ master ? master : "default");
27
+ }
28
if ((str = pw_properties_get(props, "sink_name")) != NULL) {
29
pw_properties_set(capture_props, PW_KEY_NODE_NAME, str);
30
+ pw_properties_setf(playback_props, PW_KEY_NODE_NAME, "output.%s", str);
31
pw_properties_set(props, "sink_name", NULL);
32
}
33
if ((str = pw_properties_get(props, "sink_properties")) != NULL) {
34
module_args_add_props(capture_props, str);
35
pw_properties_set(props, "sink_properties", NULL);
36
}
37
- pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
38
-
39
+ if (pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS) == NULL)
40
+ pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink");
41
+ if (pw_properties_get(capture_props, PW_KEY_DEVICE_CLASS) == NULL)
42
+ pw_properties_set(capture_props, PW_KEY_DEVICE_CLASS, "filter");
43
+
44
+ if ((str = pw_properties_get(capture_props, PW_KEY_MEDIA_NAME)) != NULL)
45
+ pw_properties_set(props, PW_KEY_MEDIA_NAME, str);
46
+ if ((str = pw_properties_get(capture_props, PW_KEY_NODE_DESCRIPTION)) != NULL) {
47
+ pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
48
+ } else {
49
+ str = pw_properties_get(capture_props, PW_KEY_NODE_NAME);
50
+ if (master != NULL || str == NULL) {
51
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
52
+ "Remapped %s sink",
53
+ master ? master : "default");
54
+ } else {
55
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
56
+ "%s sink", str);
57
+ }
58
+ }
59
if ((str = pw_properties_get(props, "master")) != NULL) {
60
pw_properties_set(playback_props, PW_KEY_NODE_TARGET, str);
61
pw_properties_set(props, "master", NULL);
62
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
62
1
2
return 0;
3
}
4
5
-static int module_remap_source_unload(struct client *client, struct module *module)
6
+static int module_remap_source_unload(struct module *module)
7
{
8
struct module_remap_source_data *d = module->user_data;
9
10
11
struct module *module;
12
struct module_remap_source_data *d;
13
struct pw_properties *props = NULL, *playback_props = NULL, *capture_props = NULL;
14
- const char *str;
15
+ const char *str, *master;
16
struct spa_audio_info_raw capture_info = { 0 };
17
struct spa_audio_info_raw playback_info = { 0 };
18
int res;
19
20
if (argument)
21
module_args_add_props(props, argument);
22
23
+ master = pw_properties_get(props, "master");
24
+ if (pw_properties_get(props, "source_name") == NULL) {
25
+ pw_properties_setf(props, "source_name", "%s.remapped",
26
+ master ? master : "default");
27
+ }
28
if ((str = pw_properties_get(props, "source_name")) != NULL) {
29
pw_properties_set(playback_props, PW_KEY_NODE_NAME, str);
30
+ pw_properties_setf(capture_props, PW_KEY_NODE_NAME, "input.%s", str);
31
pw_properties_set(props, "source_name", NULL);
32
}
33
if ((str = pw_properties_get(props, "source_properties")) != NULL) {
34
module_args_add_props(playback_props, str);
35
pw_properties_set(props, "source_properties", NULL);
36
}
37
- pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source");
38
-
39
+ if (pw_properties_get(playback_props, PW_KEY_MEDIA_CLASS) == NULL)
40
+ pw_properties_set(playback_props, PW_KEY_MEDIA_CLASS, "Audio/Source");
41
+ if (pw_properties_get(playback_props, PW_KEY_DEVICE_CLASS) == NULL)
42
+ pw_properties_set(playback_props, PW_KEY_DEVICE_CLASS, "filter");
43
+
44
+ if ((str = pw_properties_get(playback_props, PW_KEY_MEDIA_NAME)) != NULL)
45
+ pw_properties_set(props, PW_KEY_MEDIA_NAME, str);
46
+ if ((str = pw_properties_get(playback_props, PW_KEY_NODE_DESCRIPTION)) != NULL) {
47
+ pw_properties_set(props, PW_KEY_NODE_DESCRIPTION, str);
48
+ } else {
49
+ str = pw_properties_get(playback_props, PW_KEY_NODE_NAME);
50
+ if (master != NULL || str == NULL) {
51
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
52
+ "Remapped %s source",
53
+ master ? master : "default");
54
+ } else {
55
+ pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
56
+ "%s source", str);
57
+ }
58
+ }
59
if ((str = pw_properties_get(props, "master")) != NULL) {
60
pw_properties_set(capture_props, PW_KEY_NODE_TARGET, str);
61
pw_properties_set(props, "master", NULL);
62
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
10
1
2
return 0;
3
}
4
5
-static int module_roc_sink_unload(struct client *client, struct module *module)
6
+static int module_roc_sink_unload(struct module *module)
7
{
8
struct module_roc_sink_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_roc_source_unload(struct client *client, struct module *module)
6
+static int module_roc_source_unload(struct module *module)
7
{
8
struct module_roc_source_data *d = module->user_data;
9
10
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
117
1
2
3
struct module_simple_protocol_tcp_data {
4
struct module *module;
5
- struct pw_properties *module_props;
6
struct pw_impl_module *mod;
7
struct spa_hook mod_listener;
8
+
9
+ struct pw_properties *module_props;
10
+
11
+ struct spa_audio_info_raw info;
12
};
13
14
static void module_destroy(void *data)
15
16
struct module_simple_protocol_tcp_data *data = module->user_data;
17
struct impl *impl = client->impl;
18
char *args;
19
- const char *str;
20
size_t size;
21
+ uint32_t i;
22
FILE *f;
23
24
f = open_memstream(&args, &size);
25
- if ((str = pw_properties_get(data->module_props, "audio.format")) != NULL)
26
- fprintf(f, "audio.format=%s ", str);
27
- if ((str = pw_properties_get(data->module_props, "audio.rate")) != NULL)
28
- fprintf(f, "audio.rate=%s ", str);
29
- if ((str = pw_properties_get(data->module_props, "audio.channels")) != NULL)
30
- fprintf(f, "audio.channels=%s ", str);
31
- if ((str = pw_properties_get(data->module_props, "server.address")) != NULL)
32
- fprintf(f, "server.address=%s ", str);
33
- if ((str = pw_properties_get(data->module_props, "capture")) != NULL)
34
- fprintf(f, "capture=%s ", str);
35
- if ((str = pw_properties_get(data->module_props, "playback")) != NULL)
36
- fprintf(f, "playback=%s ", str);
37
- if ((str = pw_properties_get(data->module_props, "capture.node")) != NULL)
38
- fprintf(f, "capture.node=\"%s\" ", str);
39
- if ((str = pw_properties_get(data->module_props, "playback.node")) != NULL)
40
- fprintf(f, "playback.node=\"%s\" ", str);
41
- if ((str = pw_properties_get(data->module_props, PW_KEY_STREAM_CAPTURE_SINK)) != NULL)
42
- fprintf(f, PW_KEY_STREAM_CAPTURE_SINK"=\"%s\" ", str);
43
+ fprintf(f, "{");
44
+ if (data->info.rate != 0)
45
+ fprintf(f, " \"audio.rate\": %u,", data->info.rate);
46
+ if (data->info.channels != 0) {
47
+ fprintf(f, " \"audio.channels\": %u,", data->info.channels);
48
+ if (!(data->info.flags & SPA_AUDIO_FLAG_UNPOSITIONED)) {
49
+ fprintf(f, " \"audio.position\": [ ");
50
+ for (i = 0; i < data->info.channels; i++)
51
+ fprintf(f, "%s\"%s\"", i == 0 ? "" : ",",
52
+ channel_id2name(data->info.position[i]));
53
+ fprintf(f, " ],");
54
+ }
55
+ }
56
+ pw_properties_serialize_dict(f, &data->module_props->dict, 0);
57
+ fprintf(f, "}");
58
fclose(f);
59
60
data->mod = pw_context_load_module(impl->context,
61
62
return 0;
63
}
64
65
-static int module_simple_protocol_tcp_unload(struct client *client, struct module *module)
66
+static int module_simple_protocol_tcp_unload(struct module *module)
67
{
68
struct module_simple_protocol_tcp_data *d = module->user_data;
69
70
71
{ PW_KEY_MODULE_USAGE, "rate=<sample rate> "
72
"format=<sample format> "
73
"channels=<number of channels> "
74
+ "channel_map=<number of channels> "
75
"sink=<sink to connect to> "
76
"source=<source to connect to> "
77
"playback=<enable playback?> "
78
79
struct module_simple_protocol_tcp_data *d;
80
struct pw_properties *props = NULL, *module_props = NULL;
81
const char *str, *port, *listen;
82
+ struct spa_audio_info_raw info = { 0 };
83
int res;
84
85
PW_LOG_TOPIC_INIT(mod_topic);
86
87
goto out;
88
}
89
90
- if ((str = pw_properties_get(props, "rate")) != NULL) {
91
- pw_properties_set(module_props, "audio.rate", str);
92
- pw_properties_set(props, "rate", NULL);
93
- }
94
if ((str = pw_properties_get(props, "format")) != NULL) {
95
- pw_properties_set(module_props, "audio.format", format_id2name(format_paname2id(str, strlen(str))));
96
+ pw_properties_set(module_props, "audio.format",
97
+ format_id2name(format_paname2id(str, strlen(str))));
98
pw_properties_set(props, "format", NULL);
99
}
100
- if ((str = pw_properties_get(props, "channels")) != NULL) {
101
- pw_properties_set(module_props, "audio.channels", str);
102
- pw_properties_set(props, "channels", NULL);
103
+ if (module_args_to_audioinfo(impl, props, &info) < 0) {
104
+ res = -EINVAL;
105
+ goto out;
106
}
107
if ((str = pw_properties_get(props, "playback")) != NULL) {
108
pw_properties_set(module_props, "playback", str);
109
110
d = module->user_data;
111
d->module = module;
112
d->module_props = module_props;
113
+ d->info = info;
114
115
return module;
116
out:
117
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
10
1
2
return res;
3
}
4
5
-static int module_switch_on_connect_unload(struct client *client, struct module *module)
6
+static int module_switch_on_connect_unload(struct module *module)
7
{
8
struct module_switch_on_connect_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_tunnel_sink_unload(struct client *client, struct module *module)
6
+static int module_tunnel_sink_unload(struct module *module)
7
{
8
struct module_tunnel_sink_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_tunnel_source_unload(struct client *client, struct module *module)
6
+static int module_tunnel_source_unload(struct module *module)
7
{
8
struct module_tunnel_source_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_x11_bell_unload(struct client *client, struct module *module)
6
+static int module_x11_bell_unload(struct module *module)
7
{
8
struct module_x11_bell_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_zeroconf_discover_unload(struct client *client, struct module *module)
6
+static int module_zeroconf_discover_unload(struct module *module)
7
{
8
struct module_zeroconf_discover_data *d = module->user_data;
9
10
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
10
1
2
return 0;
3
}
4
5
-static int module_zeroconf_publish_unload(struct client *client, struct module *module)
6
+static int module_zeroconf_publish_unload(struct module *module)
7
{
8
struct module_zeroconf_publish_data *d = module->user_data;
9
struct service *s;
10
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
9
1
2
spa_hook_remove(&ps->listener);
3
pw_work_queue_cancel(impl->work_queue, ps, SPA_ID_INVALID);
4
5
- client->ref--;
6
-
7
sample_play_destroy(ps->play);
8
}
9
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
9
1
2
struct sample_play *play;
3
struct spa_hook listener;
4
uint32_t tag;
5
- unsigned int done:1;
6
};
7
8
void pending_sample_free(struct pending_sample *ps);
9
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
479
1
2
* DEALINGS IN THE SOFTWARE.
3
*/
4
5
-#include "pipewire/core.h"
6
-
7
#include "config.h"
8
9
#include <errno.h>
10
11
return latency / frame_size;
12
}
13
14
-static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer)
15
+static uint64_t set_playback_buffer_attr(struct stream *s, struct buffer_attr *attr)
16
{
17
- struct client *client = stream->client;
18
- struct pw_manager *manager = client->manager;
19
- struct message *reply;
20
- uint32_t missing, peer_index;
21
+ struct spa_fraction lat;
22
+ uint64_t lat_usec;
23
struct spa_dict_item items[5];
24
char latency[32];
25
char attr_maxlength[32];
26
char attr_tlength[32];
27
char attr_prebuf[32];
28
char attr_minreq[32];
29
- const char *peer_name;
30
- struct spa_fraction lat;
31
- uint64_t lat_usec;
32
33
- lat.denom = stream->ss.rate;
34
- lat.num = fix_playback_buffer_attr(stream, &stream->attr);
35
+ lat.denom = s->ss.rate;
36
+ lat.num = fix_playback_buffer_attr(s, attr);
37
38
- stream->buffer = calloc(1, stream->attr.maxlength);
39
- if (stream->buffer == NULL)
40
- return -errno;
41
+ s->attr = *attr;
42
43
- if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num)
44
- lat.num = (stream->min_quantum.num * lat.denom +
45
- (stream->min_quantum.denom -1)) / stream->min_quantum.denom;
46
+ if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num)
47
+ lat.num = (s->min_quantum.num * lat.denom +
48
+ (s->min_quantum.denom -1)) / s->min_quantum.denom;
49
lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
50
51
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
52
- snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", stream->attr.maxlength);
53
- snprintf(attr_tlength, sizeof(attr_tlength), "%u", stream->attr.tlength);
54
- snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", stream->attr.prebuf);
55
- snprintf(attr_minreq, sizeof(attr_minreq), "%u", stream->attr.minreq);
56
+ snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength);
57
+ snprintf(attr_tlength, sizeof(attr_tlength), "%u", s->attr.tlength);
58
+ snprintf(attr_prebuf, sizeof(attr_prebuf), "%u", s->attr.prebuf);
59
+ snprintf(attr_minreq, sizeof(attr_minreq), "%u", s->attr.minreq);
60
61
items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency);
62
items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
63
items[2] = SPA_DICT_ITEM_INIT("pulse.attr.tlength", attr_tlength);
64
items[3] = SPA_DICT_ITEM_INIT("pulse.attr.prebuf", attr_prebuf);
65
items[4] = SPA_DICT_ITEM_INIT("pulse.attr.minreq", attr_minreq);
66
- pw_stream_update_properties(stream->stream, &SPA_DICT_INIT(items, 5));
67
+ pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 5));
68
69
- if (stream->attr.prebuf > 0)
70
- stream->in_prebuf = true;
71
+ if (s->attr.prebuf > 0)
72
+ s->in_prebuf = true;
73
+
74
+ return lat_usec;
75
+}
76
+
77
+static int reply_create_playback_stream(struct stream *stream, struct pw_manager_object *peer)
78
+{
79
+ struct client *client = stream->client;
80
+ struct pw_manager *manager = client->manager;
81
+ struct message *reply;
82
+ uint32_t missing, peer_index;
83
+ const char *peer_name;
84
+ uint64_t lat_usec;
85
+
86
+ stream->buffer = calloc(1, MAXLENGTH);
87
+ if (stream->buffer == NULL)
88
+ return -errno;
89
+
90
+ lat_usec = set_playback_buffer_attr(stream, &stream->attr);
91
92
missing = stream_pop_missing(stream);
93
stream->index = id_to_index(manager, stream->id);
94
95
- pw_log_info("[%s] reply CREATE_PLAYBACK_STREAM tag:%u index:%u missing:%u latency:%s",
96
- client->name, stream->create_tag, stream->index, missing, latency);
97
+ pw_log_info("[%s] reply CREATE_PLAYBACK_STREAM tag:%u index:%u missing:%u lat:%"PRIu64,
98
+ client->name, stream->create_tag, stream->index, missing, lat_usec);
99
100
reply = reply_new(client, stream->create_tag);
101
message_put(reply,
102
103
return latency / frame_size;
104
}
105
106
-static int reply_create_record_stream(struct stream *stream, struct pw_manager_object *peer)
107
+static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr)
108
{
109
- struct client *client = stream->client;
110
- struct pw_manager *manager = client->manager;
111
- struct message *reply;
112
struct spa_dict_item items[3];
113
- char latency[32], *tmp;
114
+ char latency[32];
115
char attr_maxlength[32];
116
char attr_fragsize[32];
117
- const char *peer_name, *name;
118
- uint32_t peer_index;
119
struct spa_fraction lat;
120
uint64_t lat_usec;
121
122
- lat.denom = stream->ss.rate;
123
- lat.num = fix_record_buffer_attr(stream, &stream->attr);
124
-
125
- stream->buffer = calloc(1, stream->attr.maxlength);
126
- if (stream->buffer == NULL)
127
- return -errno;
128
+ lat.denom = s->ss.rate;
129
+ lat.num = fix_record_buffer_attr(s, &s->attr);
130
131
- if (lat.num * stream->min_quantum.denom / lat.denom < stream->min_quantum.num)
132
- lat.num = (stream->min_quantum.num * lat.denom +
133
- (stream->min_quantum.denom -1)) / stream->min_quantum.denom;
134
+ if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num)
135
+ lat.num = (s->min_quantum.num * lat.denom +
136
+ (s->min_quantum.denom -1)) / s->min_quantum.denom;
137
lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom;
138
139
snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom);
140
141
- snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", stream->attr.maxlength);
142
- snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", stream->attr.fragsize);
143
+ snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength);
144
+ snprintf(attr_fragsize, sizeof(attr_fragsize), "%u", s->attr.fragsize);
145
146
items[0] = SPA_DICT_ITEM_INIT(PW_KEY_NODE_LATENCY, latency);
147
items[1] = SPA_DICT_ITEM_INIT("pulse.attr.maxlength", attr_maxlength);
148
items[2] = SPA_DICT_ITEM_INIT("pulse.attr.fragsize", attr_fragsize);
149
- pw_stream_update_properties(stream->stream,
150
- &SPA_DICT_INIT(items, 3));
151
+ pw_stream_update_properties(s->stream, &SPA_DICT_INIT(items, 3));
152
+
153
+ return lat_usec;
154
+}
155
+
156
+static int reply_create_record_stream(struct stream *stream, struct pw_manager_object *peer)
157
+{
158
+ struct client *client = stream->client;
159
+ struct pw_manager *manager = client->manager;
160
+ char *tmp;
161
+ struct message *reply;
162
+ const char *peer_name, *name;
163
+ uint32_t peer_index;
164
+ uint64_t lat_usec;
165
+
166
+ stream->buffer = calloc(1, MAXLENGTH);
167
+ if (stream->buffer == NULL)
168
+ return -errno;
169
+
170
+ lat_usec = set_record_buffer_attr(stream, &stream->attr);
171
172
stream->index = id_to_index(manager, stream->id);
173
174
- pw_log_info("[%s] reply CREATE_RECORD_STREAM tag:%u index:%u latency:%s",
175
- client->name, stream->create_tag, stream->index, latency);
176
+ pw_log_info("[%s] reply CREATE_RECORD_STREAM tag:%u index:%u latency:%"PRIu64,
177
+ client->name, stream->create_tag, stream->index, lat_usec);
178
179
reply = reply_new(client, stream->create_tag);
180
message_put(reply,
181
182
183
static void do_free_client(void *obj, void *data, int res, uint32_t id)
184
{
185
- struct client *client = data;
186
+ struct client *client = obj;
187
client_free(client);
188
}
189
190
191
{
192
struct client *client = data;
193
pw_log_debug("manager_disconnect()");
194
- pw_work_queue_add(client->impl->work_queue, NULL, 0,
195
- do_free_client, client);
196
+ pw_work_queue_add(client->impl->work_queue, client, 0,
197
+ do_free_client, NULL);
198
}
199
200
static const struct pw_manager_events manager_events = {
201
202
}
203
}
204
205
-static void on_stream_cleanup(void *obj, void *data, int res, uint32_t id)
206
+static void do_destroy_stream(void *obj, void *data, int res, uint32_t id)
207
{
208
struct stream *stream = obj;
209
- struct client *client = stream->client;
210
+
211
stream_free(stream);
212
- if (client->ref <= 0)
213
- client_free(client);
214
}
215
216
static void stream_state_changed(void *data, enum pw_stream_state old,
217
218
struct stream *stream = data;
219
struct client *client = stream->client;
220
struct impl *impl = client->impl;
221
+ bool destroy_stream = false;
222
223
switch (state) {
224
case PW_STREAM_STATE_ERROR:
225
reply_error(client, -1, stream->create_tag, -EIO);
226
- stream->done = true;
227
+ destroy_stream = true;
228
break;
229
case PW_STREAM_STATE_UNCONNECTED:
230
if (stream->create_tag != SPA_ID_INVALID)
231
reply_error(client, -1, stream->create_tag, -ENOENT);
232
- else if (!client->disconnecting)
233
+ else
234
stream->killed = true;
235
- stream->done = true;
236
+ destroy_stream = true;
237
break;
238
case PW_STREAM_STATE_CONNECTING:
239
case PW_STREAM_STATE_PAUSED:
240
case PW_STREAM_STATE_STREAMING:
241
break;
242
}
243
- if (stream->done) {
244
+
245
+ if (destroy_stream) {
246
pw_work_queue_add(impl->work_queue, stream, 0,
247
- on_stream_cleanup, client);
248
+ do_destroy_stream, NULL);
249
}
250
}
251
252
253
return -errno;
254
255
spa_ringbuffer_read_data(&stream->ring,
256
- stream->buffer, stream->attr.maxlength,
257
- index % stream->attr.maxlength,
258
+ stream->buffer, MAXLENGTH,
259
+ index % MAXLENGTH,
260
msg->data, towrite);
261
262
client_queue_message(client, msg);
263
264
if ((stream->attr.prebuf == 0 || do_flush) && !stream->corked) {
265
if (avail > 0) {
266
spa_ringbuffer_read_data(&stream->ring,
267
- stream->buffer, stream->attr.maxlength,
268
- index % stream->attr.maxlength,
269
+ stream->buffer, MAXLENGTH,
270
+ index % MAXLENGTH,
271
p, avail);
272
}
273
pd.playing_for = size;
274
275
size = SPA_MIN(size, minreq);
276
277
spa_ringbuffer_read_data(&stream->ring,
278
- stream->buffer, stream->attr.maxlength,
279
- index % stream->attr.maxlength,
280
+ stream->buffer, MAXLENGTH,
281
+ index % MAXLENGTH,
282
p, size);
283
284
index += size;
285
286
}
287
288
spa_ringbuffer_write_data(&stream->ring,
289
- stream->buffer, stream->attr.maxlength,
290
- index % stream->attr.maxlength,
291
+ stream->buffer, MAXLENGTH,
292
+ index % MAXLENGTH,
293
SPA_PTROFF(p, buf->datas[0].chunk->offset, void),
294
- SPA_MIN(size, stream->attr.maxlength));
295
+ SPA_MIN(size, MAXLENGTH));
296
297
index += size;
298
pd.write_inc = size;
299
300
301
stream->props = props;
302
303
- stream->buffer = calloc(1, stream->attr.maxlength);
304
+ stream->buffer = calloc(1, MAXLENGTH);
305
if (stream->buffer == NULL)
306
goto error_errno;
307
308
309
channel, name);
310
311
struct sample *old = find_sample(impl, SPA_ID_INVALID, name);
312
- if (old == NULL || (old != NULL && old->ref > 1)) {
313
+ if (old == NULL || old->ref > 1) {
314
sample = calloc(1, sizeof(*sample));
315
if (sample == NULL)
316
goto error_errno;
317
318
{
319
struct pending_sample *ps = obj;
320
struct client *client = ps->client;
321
+
322
pending_sample_free(ps);
323
- if (client->ref <= 0)
324
- client_free(client);
325
+ client_unref(client);
326
}
327
328
static void sample_play_done(void *data, int res)
329
330
else
331
pw_log_info("[%s] PLAY_SAMPLE done tag:%u", client->name, ps->tag);
332
333
- ps->done = true;
334
pw_work_queue_add(impl->work_queue, ps, 0,
335
on_sample_done, client);
336
}
337
338
struct message *reply;
339
struct buffer_attr attr;
340
bool adjust_latency = false, early_requests = false;
341
+ uint64_t lat_usec;
342
343
if (message_get(m,
344
TAG_U32, &channel,
345
346
347
reply = reply_new(client, tag);
348
349
+ stream->adjust_latency = adjust_latency;
350
+ stream->early_requests = early_requests;
351
+
352
if (command == COMMAND_SET_PLAYBACK_STREAM_BUFFER_ATTR) {
353
+ lat_usec = set_playback_buffer_attr(stream, &attr);
354
+
355
message_put(reply,
356
TAG_U32, stream->attr.maxlength,
357
TAG_U32, stream->attr.tlength,
358
359
TAG_INVALID);
360
if (client->version >= 13) {
361
message_put(reply,
362
- TAG_USEC, 0LL, /* configured_sink_latency */
363
+ TAG_USEC, lat_usec, /* configured_sink_latency */
364
TAG_INVALID);
365
}
366
} else {
367
+ lat_usec = set_record_buffer_attr(stream, &attr);
368
+
369
message_put(reply,
370
TAG_U32, stream->attr.maxlength,
371
TAG_U32, stream->attr.fragsize,
372
TAG_INVALID);
373
if (client->version >= 13) {
374
message_put(reply,
375
- TAG_USEC, 0LL, /* configured_source_latency */
376
+ TAG_USEC, lat_usec, /* configured_source_latency */
377
TAG_INVALID);
378
}
379
}
380
381
if (module == NULL)
382
return -ENOENT;
383
384
- module_unload(client, module);
385
+ module_unload(module);
386
387
return reply_simple_ack(client, tag);
388
}
389
390
static int impl_free_sample(void *item, void *data)
391
{
392
struct sample *s = item;
393
- sample_free(s);
394
+
395
+ spa_assert(s->ref == 1);
396
+ sample_unref(s);
397
+
398
return 0;
399
}
400
401
-static int impl_free_module(void *item, void *data)
402
+static int impl_unload_module(void *item, void *data)
403
{
404
struct module *m = item;
405
- module_free(m);
406
+ module_unload(m);
407
return 0;
408
}
409
410
-static void impl_free(struct impl *impl)
411
+static void impl_clear(struct impl *impl)
412
{
413
+ struct message *msg;
414
struct server *s;
415
struct client *c;
416
- struct message *msg;
417
-
418
-#if HAVE_DBUS
419
- if (impl->dbus_name)
420
- dbus_release_name(impl->dbus_name);
421
-#endif
422
423
- spa_list_consume(msg, &impl->free_messages, link)
424
- message_free(impl, msg, true, true);
425
+ spa_list_consume(s, &impl->servers, link)
426
+ server_free(s);
427
428
- if (impl->context != NULL)
429
- spa_hook_remove(&impl->context_listener);
430
spa_list_consume(c, &impl->cleanup_clients, link)
431
client_free(c);
432
- spa_list_consume(s, &impl->servers, link)
433
- server_free(s);
434
+
435
+ spa_list_consume(msg, &impl->free_messages, link)
436
+ message_free(impl, msg, true, true);
437
438
pw_map_for_each(&impl->samples, impl_free_sample, impl);
439
pw_map_clear(&impl->samples);
440
- pw_map_for_each(&impl->modules, impl_free_module, impl);
441
+
442
+ pw_map_for_each(&impl->modules, impl_unload_module, impl);
443
pw_map_clear(&impl->modules);
444
445
+#if HAVE_DBUS
446
+ if (impl->dbus_name) {
447
+ dbus_release_name(impl->dbus_name);
448
+ impl->dbus_name = NULL;
449
+ }
450
+#endif
451
+
452
+ if (impl->context) {
453
+ spa_hook_remove(&impl->context_listener);
454
+ impl->context = NULL;
455
+ }
456
+
457
pw_properties_free(impl->props);
458
+ impl->props = NULL;
459
+}
460
+
461
+static void impl_free(struct impl *impl)
462
+{
463
+ impl_clear(impl);
464
free(impl);
465
}
466
467
static void context_destroy(void *data)
468
{
469
- struct impl *impl = data;
470
- struct server *s;
471
- spa_list_consume(s, &impl->servers, link)
472
- server_free(s);
473
- spa_hook_remove(&impl->context_listener);
474
- impl->context = NULL;
475
+ impl_clear(data);
476
}
477
478
static const struct pw_context_events context_events = {
479
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
28
1
2
return 0;
3
}
4
5
+static int apply_pulse_rules(void *data, const char *location, const char *section,
6
+ const char *str, size_t len)
7
+{
8
+ struct client *client = data;
9
+ pw_conf_match_rules(str, len, &client->props->dict,
10
+ client_rule_matched, client);
11
+ return 0;
12
+}
13
+
14
int client_update_quirks(struct client *client)
15
{
16
struct impl *impl = client->impl;
17
struct pw_context *context = impl->context;
18
- const char *rules;
19
-
20
- if ((rules = pw_context_get_conf_section(context, "pulse.rules")) == NULL)
21
- return 0;
22
-
23
- return pw_conf_match_rules(rules, strlen(rules), &client->props->dict,
24
- client_rule_matched, client);
25
+ return pw_context_conf_section_for_each(context, "pulse.rules",
26
+ apply_pulse_rules, client);
27
}
28
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
15
1
2
/* always write data to ringbuffer, we expect the other side
3
* to recover */
4
spa_ringbuffer_write_data(&stream->ring,
5
- stream->buffer, stream->attr.maxlength,
6
- index % stream->attr.maxlength,
7
+ stream->buffer, MAXLENGTH,
8
+ index % MAXLENGTH,
9
msg->data,
10
- SPA_MIN(msg->length, stream->attr.maxlength));
11
+ SPA_MIN(msg->length, MAXLENGTH));
12
index += msg->length;
13
stream->write_index += msg->length;
14
spa_ringbuffer_write_update(&stream->ring, index);
15
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
22
1
2
3
#include "client.h"
4
#include "commands.h"
5
+#include "defs.h"
6
#include "internal.h"
7
#include "log.h"
8
#include "message.h"
9
10
if (new_tlength <= old_tlength)
11
return 0;
12
13
+ if (new_tlength > MAXLENGTH)
14
+ new_tlength = MAXLENGTH;
15
+
16
stream->attr.tlength = new_tlength;
17
+ if (stream->attr.tlength > stream->attr.maxlength)
18
+ stream->attr.maxlength = stream->attr.tlength;
19
20
if (client->version >= 15) {
21
struct message *msg;
22
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
9
1
2
unsigned int adjust_latency:1;
3
unsigned int is_underrun:1;
4
unsigned int in_prebuf:1;
5
- unsigned int done:1;
6
unsigned int killed:1;
7
unsigned int pending:1;
8
};
9
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
48
1
2
#define DEFAULT_RATE "44100"
3
#define DEFAULT_CHANNELS 2
4
#define DEFAULT_POSITION "[ FL FR ]"
5
-#define DEFAULT_LATENCY "1024/48000"
6
+#define DEFAULT_LATENCY "1024/44100"
7
8
#define MAX_CLIENTS 10
9
10
#define MODULE_USAGE "[ capture=<bool> ] " \
11
"[ playback=<bool> ] " \
12
- "[ capture.node=<source-target> ] " \
13
+ "[ node.latency=<num/denom, default:"DEFAULT_LATENCY"> ] " \
14
+ "[ node.rate=<1/rate, default:1/"DEFAULT_RATE"> ] " \
15
+ "[ capture.node=<source-target> [ stream.capture.sink=true ]] " \
16
"[ playback.node=<sink-target> ] " \
17
"[ audio.rate=<sample-rate, default:"DEFAULT_RATE"> ] " \
18
"[ audio.format=<format, default:"DEFAULT_FORMAT"> ] " \
19
20
uint8_t buffer[1024];
21
struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
22
struct pw_properties *props;
23
+ const char *latency;
24
int res;
25
26
+ if ((latency = pw_properties_get(impl->props, PW_KEY_NODE_LATENCY)) == NULL)
27
+ latency = DEFAULT_LATENCY;
28
+
29
if (impl->capture) {
30
props = pw_properties_new(
31
PW_KEY_NODE_GROUP, "pipewire.dummy",
32
- PW_KEY_NODE_LATENCY, DEFAULT_LATENCY,
33
+ PW_KEY_NODE_LATENCY, latency,
34
+ PW_KEY_NODE_RATE, pw_properties_get(impl->props, PW_KEY_NODE_RATE),
35
PW_KEY_NODE_TARGET, pw_properties_get(impl->props, "capture.node"),
36
PW_KEY_STREAM_CAPTURE_SINK, pw_properties_get(impl->props,
37
PW_KEY_STREAM_CAPTURE_SINK),
38
39
if (impl->playback) {
40
props = pw_properties_new(
41
PW_KEY_NODE_GROUP, "pipewire.dummy",
42
- PW_KEY_NODE_LATENCY, DEFAULT_LATENCY,
43
+ PW_KEY_NODE_LATENCY, latency,
44
+ PW_KEY_NODE_RATE, pw_properties_get(impl->props, PW_KEY_NODE_RATE),
45
PW_KEY_NODE_TARGET, pw_properties_get(impl->props, "playback.node"),
46
PW_KEY_NODE_NETWORK, "true",
47
NULL);
48
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
66
1
2
#include <pipewire/extensions/session-manager.h>
3
#include <pipewire/extensions/protocol-native.h>
4
5
+#define MAX_DICT 256
6
+#define MAX_PARAMS 128
7
+#define MAX_PARAM_INFO 128
8
+
9
static void push_dict(struct spa_pod_builder *b, const struct spa_dict *dict)
10
{
11
struct spa_pod_frame f;
12
13
return -EINVAL; \
14
\
15
if ((dict)->n_items > 0) { \
16
+ if ((dict)->n_items > MAX_DICT) \
17
+ return -ENOSPC; \
18
(dict)->items = alloca((dict)->n_items * sizeof(struct spa_dict_item)); \
19
for (i = 0; i < (dict)->n_items; i++) { \
20
if (spa_pod_parser_get(p, \
21
22
return -EINVAL; \
23
\
24
if (*(n_params_p) > 0) { \
25
+ if (*(n_params_p) > MAX_PARAM_INFO) \
26
+ return -ENOSPC; \
27
*(params_p) = alloca(*(n_params_p) * sizeof(struct spa_param_info)); \
28
for (i = 0; i < *(n_params_p); i++) { \
29
if (spa_pod_parser_get(p, \
30
31
SPA_POD_Int(&n_params), NULL) < 0)
32
return -EINVAL;
33
34
+ if (n_params > MAX_PARAMS)
35
+ return -ENOSPC;
36
if (n_params > 0)
37
params = alloca(n_params * sizeof(struct spa_pod *));
38
for (i = 0; i < n_params; i++)
39
40
SPA_POD_Int(&n_params), NULL) < 0)
41
return -EINVAL;
42
43
+ if (n_params > MAX_PARAMS)
44
+ return -ENOSPC;
45
if (n_params > 0)
46
params = alloca(n_params * sizeof(struct spa_pod *));
47
for (i = 0; i < n_params; i++)
48
49
SPA_POD_Int(&n_params), NULL) < 0)
50
return -EINVAL;
51
52
+ if (n_params > MAX_PARAMS)
53
+ return -ENOSPC;
54
if (n_params > 0)
55
params = alloca(n_params * sizeof(struct spa_pod *));
56
for (i = 0; i < n_params; i++)
57
58
SPA_POD_Int(&n_params), NULL) < 0)
59
return -EINVAL;
60
61
+ if (n_params > MAX_PARAMS)
62
+ return -ENOSPC;
63
if (n_params > 0)
64
params = alloca(n_params * sizeof(struct spa_pod *));
65
for (i = 0; i < n_params; i++)
66
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
19
1
2
3
error_properties:
4
res = -EINVAL;
5
- pw_log_error("factory %p: usage: " FACTORY_USAGE, data->this);
6
- if (resource)
7
- pw_resource_errorf_id(resource, new_id, res,
8
- "usage: "FACTORY_USAGE);
9
+ pw_resource_errorf_id(resource, new_id, res, "usage: "FACTORY_USAGE);
10
goto error_exit_cleanup;
11
error_device:
12
- pw_log_debug("can't create device %s: %s", factory_name, spa_strerror(res));
13
- if (resource)
14
- pw_resource_errorf_id(resource, new_id, res,
15
+ pw_resource_errorf_id(resource, new_id, res,
16
"can't create device %s: %s", factory_name,
17
spa_strerror(res));
18
goto error_exit;
19
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
20
1
2
3
error_properties:
4
res = -EINVAL;
5
- pw_log_error("factory %p: usage: " FACTORY_USAGE, data->this);
6
- if (resource)
7
- pw_resource_errorf_id(resource, new_id, res,
8
- "usage: "FACTORY_USAGE);
9
+ pw_resource_errorf_id(resource, new_id, res, "usage: "FACTORY_USAGE);
10
goto error_exit_cleanup;
11
error_create_node:
12
res = -errno;
13
- pw_log_error("can't create node: %m");
14
- if (resource)
15
- pw_resource_errorf_id(resource, new_id, res,
16
+ pw_resource_errorf_id(resource, new_id, res,
17
"can't create node: %s", spa_strerror(res));
18
goto error_exit;
19
error_bind:
20
pipewire-0.3.44.tar.gz/src/pipewire/conf.c -> pipewire-0.3.45.tar.gz/src/pipewire/conf.c
Changed
599
1
2
#include <fcntl.h>
3
#include <unistd.h>
4
#include <sys/wait.h>
5
+#include <dirent.h>
6
#if HAVE_PWD_H
7
#include <pwd.h>
8
#endif
9
10
#include <spa/utils/json.h>
11
12
#include <pipewire/impl.h>
13
+#include <pipewire/private.h>
14
15
PW_LOG_TOPIC_EXTERN(log_conf);
16
#define PW_LOG_TOPIC_DEFAULT log_conf
17
18
return 0;
19
}
20
21
-static int get_config_path(char *path, size_t size, const char *prefix, const char *name)
22
+static int get_abs_path(char *path, size_t size, const char *prefix, const char *name)
23
{
24
- const char *dir;
25
- char buffer[4096];
26
-
27
- if (name[0] == '/') {
28
- const char *paths[] = { name, NULL };
29
- if (make_path(path, size, paths) == 0 &&
30
- access(path, R_OK) == 0)
31
- return 1;
32
- return -ENOENT;
33
- }
34
-
35
- if (prefix && prefix[0] == '/') {
36
+ if (prefix[0] == '/') {
37
const char *paths[] = { prefix, name, NULL };
38
if (make_path(path, size, paths) == 0 &&
39
access(path, R_OK) == 0)
40
return 1;
41
return -ENOENT;
42
}
43
+ return 0;
44
+}
45
46
- if (prefix == NULL) {
47
- prefix = name;
48
- name = NULL;
49
- }
50
-
51
- if (pw_check_option("no-config", "true"))
52
- goto no_config;
53
+static int get_envconf_path(char *path, size_t size, const char *prefix, const char *name)
54
+{
55
+ const char *dir;
56
57
dir = getenv("PIPEWIRE_CONFIG_DIR");
58
if (dir != NULL) {
59
60
if (make_path(path, size, paths) == 0 &&
61
access(path, R_OK) == 0)
62
return 1;
63
+ return -ENOENT;
64
}
65
+ return 0;
66
+}
67
+
68
+static int get_homeconf_path(char *path, size_t size, const char *prefix, const char *name)
69
+{
70
+ char buffer[4096];
71
+ const char *dir;
72
73
dir = getenv("XDG_CONFIG_HOME");
74
if (dir != NULL) {
75
76
access(path, R_OK) == 0)
77
return 1;
78
}
79
+ return 0;
80
+}
81
82
+static int get_configdir_path(char *path, size_t size, const char *prefix, const char *name)
83
+{
84
+ const char *dir;
85
dir = PIPEWIRE_CONFIG_DIR;
86
if (dir != NULL) {
87
const char *paths[] = { dir, prefix, name, NULL };
88
89
access(path, R_OK) == 0)
90
return 1;
91
}
92
-no_config:
93
+ return 0;
94
+}
95
+
96
+static int get_confdata_path(char *path, size_t size, const char *prefix, const char *name)
97
+{
98
+ const char *dir;
99
dir = PIPEWIRE_CONFDATADIR;
100
if (dir != NULL) {
101
const char *paths[] = { dir, prefix, name, NULL };
102
103
return 0;
104
}
105
106
-static int get_state_path(char *path, size_t size, const char *prefix, const char *name)
107
+static int get_config_path(char *path, size_t size, const char *prefix, const char *name)
108
{
109
- const char *dir;
110
- char buffer[4096];
111
+ int res;
112
113
- if (name[0] == '/') {
114
- const char *paths[] = { name, NULL };
115
- if (make_path(path, size, paths) == 0 &&
116
- access(path, R_OK) == 0)
117
- return 1;
118
- return -ENOENT;
119
+ if (prefix == NULL) {
120
+ prefix = name;
121
+ name = NULL;
122
}
123
+ if ((res = get_abs_path(path, size, prefix, name)) != 0)
124
+ return res;
125
126
- if (prefix && prefix[0] == '/') {
127
- const char *paths[] = { prefix, name, NULL };
128
- if (make_path(path, size, paths) == 0 &&
129
- access(path, R_OK) == 0)
130
- return 1;
131
- return -ENOENT;
132
- }
133
+ if (pw_check_option("no-config", "true"))
134
+ goto no_config;
135
+
136
+ if ((res = get_envconf_path(path, size, prefix, name)) != 0)
137
+ return res;
138
+
139
+ if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
140
+ return res;
141
+
142
+ if ((res = get_configdir_path(path, size, prefix, name)) != 0)
143
+ return res;
144
+no_config:
145
+ if ((res = get_confdata_path(path, size, prefix, name)) != 0)
146
+ return res;
147
+ return 0;
148
+}
149
+
150
+static int get_config_dir(char *path, size_t size, const char *prefix, const char *name, int *level)
151
+{
152
+ int res;
153
154
if (prefix == NULL) {
155
prefix = name;
156
name = NULL;
157
}
158
+ if ((res = get_abs_path(path, size, prefix, name)) != 0) {
159
+ if ((*level)++ == 0)
160
+ return res;
161
+ return -ENOENT;
162
+ }
163
+
164
+ if ((res = get_envconf_path(path, size, prefix, name)) != 0) {
165
+ if ((*level)++ == 0)
166
+ return res;
167
+ return -ENOENT;
168
+ }
169
+
170
+ if (*level == 0) {
171
+ (*level)++;
172
+ if ((res = get_confdata_path(path, size, prefix, name)) != 0)
173
+ return res;
174
+ }
175
+ if (pw_check_option("no-config", "true"))
176
+ return 0;
177
178
+ if (*level == 1) {
179
+ (*level)++;
180
+ if ((res = get_configdir_path(path, size, prefix, name)) != 0)
181
+ return res;
182
+ }
183
+ if (*level == 2) {
184
+ (*level)++;
185
+ if ((res = get_homeconf_path(path, size, prefix, name)) != 0)
186
+ return res;
187
+ }
188
+ return 0;
189
+}
190
+
191
+static int get_envstate_path(char *path, size_t size, const char *prefix, const char *name)
192
+{
193
+ const char *dir;
194
dir = getenv("PIPEWIRE_STATE_DIR");
195
if (dir != NULL) {
196
const char *paths[] = { dir, prefix, name, NULL };
197
if (make_path(path, size, paths) == 0 &&
198
access(path, R_OK) == 0)
199
return 1;
200
+ return -ENOENT;
201
}
202
+ return 0;
203
+}
204
+
205
+static int get_homestate_path(char *path, size_t size, const char *prefix, const char *name)
206
+{
207
+ const char *dir;
208
+ char buffer[4096];
209
210
dir = getenv("XDG_STATE_HOME");
211
if (dir != NULL) {
212
213
access(path, R_OK) == 0)
214
return 1;
215
}
216
+ return 0;
217
+}
218
+
219
+static int get_state_path(char *path, size_t size, const char *prefix, const char *name)
220
+{
221
+ int res;
222
+
223
+ if (prefix == NULL) {
224
+ prefix = name;
225
+ name = NULL;
226
+ }
227
+ if ((res = get_abs_path(path, size, prefix, name)) != 0)
228
+ return res;
229
+
230
+ if ((res = get_envstate_path(path, size, prefix, name)) != 0)
231
+ return res;
232
+
233
+ if ((res = get_homestate_path(path, size, prefix, name)) != 0)
234
+ return res;
235
236
return 0;
237
}
238
239
{
240
char *data;
241
struct stat sbuf;
242
- int fd;
243
+ int fd, count;
244
245
- if ((fd = open(path, O_CLOEXEC | O_RDONLY)) < 0) {
246
- pw_log_warn("%p: error loading config '%s': %m", conf, path);
247
- return -errno;
248
- }
249
+ if ((fd = open(path, O_CLOEXEC | O_RDONLY)) < 0)
250
+ goto error;
251
252
- pw_log_info("%p: loading config '%s'", conf, path);
253
if (fstat(fd, &sbuf) < 0)
254
goto error_close;
255
if ((data = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
256
goto error_close;
257
close(fd);
258
259
- pw_properties_update_string(conf, data, sbuf.st_size);
260
+ count = pw_properties_update_string(conf, data, sbuf.st_size);
261
munmap(data, sbuf.st_size);
262
263
+ pw_log_info("%p: loaded config '%s' with %d items", conf, path, count);
264
+
265
return 0;
266
267
error_close:
268
close(fd);
269
+error:
270
+ pw_log_warn("%p: error loading config '%s': %m", conf, path);
271
return -errno;
272
}
273
274
+static void add_override(struct pw_properties *conf, struct pw_properties *override,
275
+ const char *path, int level, int index)
276
+{
277
+ const struct spa_dict_item *it;
278
+ char key[1024];
279
+ snprintf(key, sizeof(key), "override.%d.%d.config.path", level, index);
280
+ pw_properties_set(conf, key, path);
281
+ spa_dict_for_each(it, &override->dict) {
282
+ snprintf(key, sizeof(key), "override.%d.%d.%s", level, index, it->key);
283
+ pw_properties_set(conf, key, it->value);
284
+ }
285
+}
286
+
287
+static int conf_filter(const struct dirent *entry)
288
+{
289
+ return spa_strendswith(entry->d_name, ".conf");
290
+}
291
+
292
SPA_EXPORT
293
int pw_conf_load_conf(const char *prefix, const char *name, struct pw_properties *conf)
294
{
295
char path[PATH_MAX];
296
+ char fname[PATH_MAX + 256];
297
+ int i, res, level = 0;
298
+ struct pw_properties *override = NULL;
299
+ const char *dname;
300
301
if (name == NULL) {
302
pw_log_debug("%p: config name must not be NULL", conf);
303
304
pw_log_debug("%p: can't load config '%s': %m", conf, path);
305
return -ENOENT;
306
}
307
+ pw_properties_set(conf, "config.prefix", prefix);
308
+ pw_properties_set(conf, "config.name", name);
309
+ pw_properties_set(conf, "config.path", path);
310
311
- return conf_load(path, conf);
312
+ if ((res = conf_load(path, conf)) < 0)
313
+ return res;
314
+
315
+ pw_properties_setf(conf, "config.name.d", "%s.d", name);
316
+ dname = pw_properties_get(conf, "config.name.d");
317
+
318
+ while (true) {
319
+ struct dirent **entries = NULL;
320
+ int n;
321
+
322
+ if (get_config_dir(path, sizeof(path), prefix, dname, &level) <= 0)
323
+ break;
324
+
325
+ n = scandir(path, &entries, conf_filter, alphasort);
326
+ if (n == 0)
327
+ continue;
328
+ if (n < 0) {
329
+ pw_log_warn("scandir %s failed: %m", path);
330
+ continue;
331
+ }
332
+ if (override == NULL &&
333
+ (override = pw_properties_new(NULL, NULL)) == NULL)
334
+ return -errno;
335
+
336
+ for (i = 0; i < n; i++) {
337
+ snprintf(fname, sizeof(fname), "%s/%s", path, entries[i]->d_name);
338
+ if (conf_load(fname, override) >= 0)
339
+ add_override(conf, override, fname, level, i);
340
+ pw_properties_clear(override);
341
+ free(entries[i]);
342
+ }
343
+ free(entries);
344
+ }
345
+ pw_properties_free(override);
346
+ return 0;
347
}
348
349
SPA_EXPORT
350
351
pw_log_debug("%p: can't load config '%s': %m", conf, path);
352
return -ENOENT;
353
}
354
-
355
return conf_load(path, conf);
356
}
357
358
+struct data {
359
+ struct pw_context *context;
360
+ struct pw_properties *props;
361
+ int count;
362
+};
363
+
364
/* context.spa-libs = {
365
* <factory-name regex> = <library-name>
366
* }
367
*/
368
-static int parse_spa_libs(struct pw_context *context, char *str)
369
+static int parse_spa_libs(void *user_data, const char *location,
370
+ const char *section, const char *str, size_t len)
371
{
372
+ struct data *d = user_data;
373
+ struct pw_context *context = d->context;
374
struct spa_json it[2];
375
char key[512], value[512];
376
- int count = 0;
377
378
- spa_json_init(&it[0], str, strlen(str));
379
+ spa_json_init(&it[0], str, len);
380
if (spa_json_enter_object(&it[0], &it[1]) < 0) {
381
pw_log_error("config file error: context.spa-libs is not an object");
382
return -EINVAL;
383
384
while (spa_json_get_string(&it[1], key, sizeof(key)) > 0) {
385
if (spa_json_get_string(&it[1], value, sizeof(value)) > 0) {
386
pw_context_add_spa_lib(context, key, value);
387
- count++;
388
+ d->count++;
389
}
390
}
391
- return count;
392
+ return 0;
393
}
394
395
static int load_module(struct pw_context *context, const char *key, const char *args, const char *flags)
396
397
* }
398
* ]
399
*/
400
-static int parse_modules(struct pw_context *context, char *str)
401
+static int parse_modules(void *user_data, const char *location,
402
+ const char *section, const char *str, size_t len)
403
{
404
+ struct data *d = user_data;
405
+ struct pw_context *context = d->context;
406
struct spa_json it[3];
407
- char key[512];
408
- int res = 0, count = 0;
409
+ char key[512], *s;
410
+ int res = 0;
411
412
- spa_json_init(&it[0], str, strlen(str));
413
+ s = strndup(str, len);
414
+ spa_json_init(&it[0], s, len);
415
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
416
pw_log_error("config file error: context.modules is not an array");
417
- return -EINVAL;
418
+ res = -EINVAL;
419
+ goto exit;
420
}
421
422
while (spa_json_enter_object(&it[1], &it[2]) > 0) {
423
424
if (res < 0)
425
break;
426
427
- res = ++count;
428
+ d->count++;
429
}
430
+exit:
431
+ free(s);
432
return res;
433
}
434
435
436
* }
437
* ]
438
*/
439
-static int parse_objects(struct pw_context *context, char *str)
440
+static int parse_objects(void *user_data, const char *location,
441
+ const char *section, const char *str, size_t len)
442
{
443
+ struct data *d = user_data;
444
+ struct pw_context *context = d->context;
445
struct spa_json it[3];
446
- char key[512];
447
- int res = 0, count = 0;
448
+ char key[512], *s;
449
+ int res = 0;
450
451
- spa_json_init(&it[0], str, strlen(str));
452
+ s = strndup(str, len);
453
+ spa_json_init(&it[0], s, len);
454
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
455
pw_log_error("config file error: context.objects is not an array");
456
- return -EINVAL;
457
+ res = -EINVAL;
458
+ goto exit;
459
}
460
461
while (spa_json_enter_object(&it[1], &it[2]) > 0) {
462
463
464
if (res < 0)
465
break;
466
- res = ++count;
467
+ d->count++;
468
}
469
+exit:
470
+ free(s);
471
return res;
472
}
473
474
475
* }
476
* ]
477
*/
478
-static int parse_exec(struct pw_context *context, char *str)
479
+static int parse_exec(void *user_data, const char *location,
480
+ const char *section, const char *str, size_t len)
481
{
482
+ struct data *d = user_data;
483
+ struct pw_context *context = d->context;
484
struct spa_json it[3];
485
- char key[512];
486
- int res = 0, count = 0;
487
+ char key[512], *s;
488
+ int res = 0;
489
490
- spa_json_init(&it[0], str, strlen(str));
491
+ s = strndup(str, len);
492
+ spa_json_init(&it[0], s, len);
493
if (spa_json_enter_array(&it[0], &it[1]) < 0) {
494
pw_log_error("config file error: context.exec is not an array");
495
- return -EINVAL;
496
+ res = -EINVAL;
497
+ goto exit;
498
}
499
500
while (spa_json_enter_object(&it[1], &it[2]) > 0) {
501
502
if (res < 0)
503
break;
504
505
- res = ++count;
506
+ d->count++;
507
}
508
+exit:
509
+ free(s);
510
return res;
511
}
512
513
SPA_EXPORT
514
-int pw_context_parse_conf_section(struct pw_context *context,
515
- struct pw_properties *conf, const char *section)
516
+int pw_context_conf_section_for_each(struct pw_context *context, const char *section,
517
+ int (*callback) (void *data, const char *location, const char *section,
518
+ const char *str, size_t len),
519
+ void *data)
520
{
521
- const char *str;
522
- char *s;
523
+ struct pw_properties *conf = context->conf;
524
+ const char *path = NULL;
525
+ const struct spa_dict_item *it;
526
int res;
527
528
- if ((str = pw_properties_get(conf, section)) == NULL)
529
- return 0;
530
+ spa_dict_for_each(it, &conf->dict) {
531
+ if (spa_strendswith(it->key, "config.path")) {
532
+ path = it->value;
533
+ continue;
534
+
535
+ } else if (spa_streq(it->key, section)) {
536
+ pw_log_info("handle config '%s' section '%s'", path, section);
537
+ } else if (spa_strstartswith(it->key, "override.") &&
538
+ spa_strendswith(it->key, section)) {
539
+ pw_log_info("handle override '%s' section '%s'", path, section);
540
+ } else
541
+ continue;
542
+
543
+ res = callback(data, path, section, it->value, strlen(it->value));
544
+ if (res != 0)
545
+ break;
546
+ }
547
+ return res;
548
+}
549
550
- s = strdup(str);
551
+SPA_EXPORT
552
+int pw_context_parse_conf_section(struct pw_context *context,
553
+ struct pw_properties *conf, const char *section)
554
+{
555
+ struct data data = { .context = context };
556
557
if (spa_streq(section, "context.spa-libs"))
558
- res = parse_spa_libs(context, s);
559
+ pw_context_conf_section_for_each(context, section,
560
+ parse_spa_libs, &data);
561
else if (spa_streq(section, "context.modules"))
562
- res = parse_modules(context, s);
563
+ pw_context_conf_section_for_each(context, section,
564
+ parse_modules, &data);
565
else if (spa_streq(section, "context.objects"))
566
- res = parse_objects(context, s);
567
+ pw_context_conf_section_for_each(context, section,
568
+ parse_objects, &data);
569
else if (spa_streq(section, "context.exec"))
570
- res = parse_exec(context, s);
571
+ pw_context_conf_section_for_each(context, section,
572
+ parse_exec, &data);
573
else
574
- res = -EINVAL;
575
+ data.count = -EINVAL;
576
577
- free(s);
578
+ return data.count;
579
+}
580
581
- return res;
582
+static int update_props(void *user_data, const char *location, const char *key,
583
+ const char *val, size_t len)
584
+{
585
+ struct data *data = user_data;
586
+ data->count += pw_properties_update_string(data->props, val, len);
587
+ return 0;
588
+}
589
+
590
+SPA_EXPORT
591
+int pw_context_conf_update_props(struct pw_context *context,
592
+ const char *section, struct pw_properties *props)
593
+{
594
+ struct data data = { .context = context, .props = props };
595
+ pw_context_conf_section_for_each(context, section,
596
+ update_props, &data);
597
+ return data.count;
598
}
599
pipewire-0.3.44.tar.gz/src/pipewire/conf.h -> pipewire-0.3.45.tar.gz/src/pipewire/conf.h
Changed
10
1
2
int pw_conf_load_state(const char *prefix, const char *name, struct pw_properties *conf);
3
int pw_conf_save_state(const char *prefix, const char *name, const struct pw_properties *conf);
4
5
-int pw_context_parse_conf_section(struct pw_context *context,
6
- struct pw_properties *conf, const char *section);
7
8
/**
9
* \}
10
pipewire-0.3.44.tar.gz/src/pipewire/context.c -> pipewire-0.3.45.tar.gz/src/pipewire/context.c
Changed
86
1
2
n_support = pw_get_support(this->support, SPA_N_ELEMENTS(this->support) - 6);
3
cpu = spa_support_find(this->support, n_support, SPA_TYPE_INTERFACE_CPU);
4
5
- if ((str = pw_properties_get(conf, "context.properties")) != NULL) {
6
- pw_properties_update_string(properties, str, strlen(str));
7
- pw_log_info("%p: parsed context.properties section", this);
8
- }
9
+ res = pw_context_conf_update_props(this, "context.properties", properties);
10
+ pw_log_info("%p: parsed %d context.properties items", this, res);
11
12
if ((str = getenv("PIPEWIRE_CORE"))) {
13
pw_log_info("using core.name from environment: %s", str);
14
15
int pw_context_recalc_graph(struct pw_context *context, const char *reason)
16
{
17
struct impl *impl = SPA_CONTAINER_OF(context, struct impl, this);
18
+ struct settings *settings = &context->settings;
19
struct pw_impl_node *n, *s, *target, *fallback;
20
uint32_t max_quantum, min_quantum, def_quantum, lim_quantum, rate_quantum;
21
uint32_t *rates, n_rates, def_rate;
22
- bool freewheel = false, force_rate;
23
+ bool freewheel = false, global_force_rate, force_rate, global_force_quantum;
24
25
pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason);
26
27
28
impl->recalc = true;
29
30
get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &lim_quantum, &rate_quantum);
31
- rates = get_rates(context, &def_rate, &n_rates, &force_rate);
32
+ rates = get_rates(context, &def_rate, &n_rates, &global_force_rate);
33
+
34
+ global_force_quantum = rate_quantum == 0;
35
+ force_rate = global_force_rate;
36
37
/* start from all drivers and group all nodes that are linked
38
* to it. Some nodes are not (yet) linked to anything and they
39
40
struct spa_fraction max_latency = SPA_FRACTION(0, 0);
41
struct spa_fraction rate = SPA_FRACTION(0, 0);
42
uint32_t quantum, target_rate, current_rate;
43
+ uint64_t quantum_stamp = 0, rate_stamp = 0;
44
45
if (!n->driving || n->exported)
46
continue;
47
48
lock_quantum |= s->lock_quantum;
49
lock_rate |= s->lock_rate;
50
}
51
+ if (!global_force_quantum && s->force_quantum > 0 &&
52
+ s->stamp > quantum_stamp) {
53
+ def_quantum = min_quantum = max_quantum = s->force_quantum;
54
+ rate_quantum = 0;
55
+ quantum_stamp = s->stamp;
56
+ }
57
+ if (!global_force_rate && s->force_rate > 0 &&
58
+ s->stamp > rate_stamp) {
59
+ def_rate = s->force_rate;
60
+ force_rate = true;
61
+ n_rates = 1;
62
+ rates = &s->force_rate;
63
+ rate_stamp = s->stamp;
64
+ }
65
66
/* smallest latencies */
67
if (latency.denom == 0 ||
68
69
target_rate);
70
71
if (force_rate) {
72
- if (context->settings.clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD)
73
+ if (settings->clock_rate_update_mode == CLOCK_RATE_UPDATE_MODE_HARD)
74
suspend_driver(context, n);
75
} else {
76
if (n->info.state >= PW_NODE_STATE_IDLE)
77
78
quantum = SPA_CLAMP(quantum, min_quantum, max_quantum);
79
quantum = SPA_MIN(quantum, lim_quantum);
80
81
- if (context->settings.clock_power_of_two_quantum)
82
+ if (settings->clock_power_of_two_quantum)
83
quantum = flp2(quantum);
84
85
if (running && quantum != n->current_quantum && !lock_quantum) {
86
pipewire-0.3.44.tar.gz/src/pipewire/context.h -> pipewire-0.3.45.tar.gz/src/pipewire/context.h
Changed
24
1
2
/** Update the context properties */
3
int pw_context_update_properties(struct pw_context *context, const struct spa_dict *dict);
4
5
-/** Get a config section for this context. Since 0.3.22 */
6
+/** Get a config section for this context. Since 0.3.22, deprecated,
7
+ * use pw_context_conf_section_for_each(). */
8
const char *pw_context_get_conf_section(struct pw_context *context, const char *section);
9
+/** Parse a standard config section for this context. Since 0.3.22 */
10
+int pw_context_parse_conf_section(struct pw_context *context,
11
+ struct pw_properties *conf, const char *section);
12
+
13
+/** update properties from a section into props. Since 0.3.45 */
14
+int pw_context_conf_update_props(struct pw_context *context, const char *section,
15
+ struct pw_properties *props);
16
+/** emit callback for all config sections. Since 0.3.45 */
17
+int pw_context_conf_section_for_each(struct pw_context *context, const char *section,
18
+ int (*callback) (void *data, const char *location, const char *section,
19
+ const char *str, size_t len),
20
+ void *data);
21
22
/** Get the context support objects */
23
const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support);
24
pipewire-0.3.44.tar.gz/src/pipewire/data-loop.c -> pipewire-0.3.45.tar.gz/src/pipewire/data-loop.c
Changed
71
1
2
return NULL;
3
}
4
5
-static void do_stop(void *data, uint64_t count)
6
+static int do_stop(struct spa_loop *loop, bool async, uint32_t seq,
7
+ const void *data, size_t size, void *user_data)
8
{
9
- struct pw_data_loop *this = data;
10
+ struct pw_data_loop *this = user_data;
11
pw_log_debug("%p: stopping", this);
12
this->running = false;
13
+ return 0;
14
}
15
16
static struct pw_data_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props)
17
18
}
19
this->loop = loop;
20
21
- if (props == NULL ||
22
- (str = spa_dict_lookup(props, "loop.cancel")) == NULL ||
23
- pw_properties_parse_bool(str) == false) {
24
- this->event = pw_loop_add_event(this->loop, do_stop, this);
25
- if (this->event == NULL) {
26
- res = -errno;
27
- pw_log_error("%p: can't add event: %m", this);
28
- goto error_loop_destroy;
29
- }
30
- }
31
+ if (props != NULL &&
32
+ (str = spa_dict_lookup(props, "loop.cancel")) != NULL)
33
+ this->cancel = pw_properties_parse_bool(str);
34
+
35
spa_hook_list_init(&this->listener_list);
36
37
return this;
38
39
-error_loop_destroy:
40
- if (this->created && this->loop)
41
- pw_loop_destroy(this->loop);
42
error_free:
43
free(this);
44
error_cleanup:
45
46
47
pw_data_loop_stop(loop);
48
49
- if (loop->event)
50
- pw_loop_destroy_source(loop->loop, loop->event);
51
if (loop->created)
52
pw_loop_destroy(loop->loop);
53
54
55
{
56
pw_log_debug("%p stopping", loop);
57
if (loop->running) {
58
- if (loop->event) {
59
- pw_log_debug("%p signal", loop);
60
- pw_loop_signal_event(loop->loop, loop->event);
61
- } else {
62
+ if (loop->cancel) {
63
pw_log_debug("%p cancel", loop);
64
pthread_cancel(loop->thread);
65
+ } else {
66
+ pw_log_debug("%p signal", loop);
67
+ pw_loop_invoke(loop->loop, do_stop, 1, NULL, 0, false, loop);
68
}
69
pw_log_debug("%p join", loop);
70
pw_thread_utils_join((struct spa_thread*)loop->thread, NULL);
71
pipewire-0.3.44.tar.gz/src/pipewire/filter.c -> pipewire-0.3.45.tar.gz/src/pipewire/filter.c
Changed
11
1
2
res = -errno;
3
goto error_properties;
4
}
5
- if ((str = pw_context_get_conf_section(context, "filter.properties")) != NULL)
6
- pw_properties_update_string(props, str, strlen(str));
7
+ pw_context_conf_update_props(context, "filter.properties", props);
8
9
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) {
10
str = pw_properties_get(extra, PW_KEY_APP_NAME);
11
pipewire-0.3.44.tar.gz/src/pipewire/global.c -> pipewire-0.3.45.tar.gz/src/pipewire/global.c
Changed
25
1
2
PW_LOG_TOPIC_EXTERN(log_global);
3
#define PW_LOG_TOPIC_DEFAULT log_global
4
5
-static uint64_t serial = 0;
6
-
7
/** \cond */
8
struct impl {
9
struct pw_global this;
10
11
SPA_EXPORT
12
uint64_t pw_global_get_serial(struct pw_global *global)
13
{
14
+ struct pw_context *context = global->context;
15
if (global->serial == SPA_ID_INVALID)
16
- global->serial = serial++;
17
- if ((uint32_t)serial == SPA_ID_INVALID)
18
- serial++;
19
+ global->serial = context->serial++;
20
+ if ((uint32_t)context->serial == SPA_ID_INVALID)
21
+ context->serial++;
22
return global->serial;
23
}
24
25
pipewire-0.3.44.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.45.tar.gz/src/pipewire/impl-node.c
Changed
67
1
2
struct pw_context *context = node->context;
3
const char *str, *recalc_reason = NULL;
4
struct spa_fraction frac;
5
+ uint32_t value;
6
bool driver;
7
8
if ((str = pw_properties_get(node->properties, PW_KEY_PRIORITY_DRIVER))) {
9
10
}
11
node->lock_quantum = pw_properties_get_bool(node->properties, PW_KEY_NODE_LOCK_QUANTUM, false);
12
13
+ if ((str = pw_properties_get(node->properties, PW_KEY_NODE_FORCE_QUANTUM))) {
14
+ if (spa_atou32(str, &value, 0) &&
15
+ node->force_quantum != value) {
16
+ node->force_quantum = value;
17
+ node->stamp = ++context->stamp;
18
+ recalc_reason = "force quantum changed";
19
+ }
20
+ }
21
+
22
if ((str = pw_properties_get(node->properties, PW_KEY_NODE_RATE))) {
23
if (sscanf(str, "%u/%u", &frac.num, &frac.denom) == 2 && frac.denom != 0) {
24
if (node->rate.num != frac.num || node->rate.denom != frac.denom) {
25
26
}
27
node->lock_rate = pw_properties_get_bool(node->properties, PW_KEY_NODE_LOCK_RATE, false);
28
29
+ if ((str = pw_properties_get(node->properties, PW_KEY_NODE_FORCE_RATE))) {
30
+ if (spa_atou32(str, &value, 0) &&
31
+ node->force_rate != value) {
32
+ node->force_rate = value;
33
+ node->stamp = ++context->stamp;
34
+ recalc_reason = "force rate changed";
35
+ }
36
+ }
37
+
38
pw_log_debug("%p: driver:%d recalc:%s active:%d", node, node->driver,
39
recalc_reason, node->active);
40
41
42
struct impl *impl = SPA_CONTAINER_OF(node, struct impl, this);
43
struct pw_impl_port *port;
44
struct pw_impl_node *follower;
45
+ struct pw_context *context = node->context;
46
bool active, had_driver;
47
48
active = node->active;
49
50
}
51
52
if (active || had_driver)
53
- pw_context_recalc_graph(node->context,
54
+ pw_context_recalc_graph(context,
55
"active node destroy");
56
57
pw_log_debug("%p: free", node);
58
59
60
clear_info(node);
61
62
- spa_system_close(node->context->data_system, node->source.fd);
63
+ spa_system_close(context->data_system, node->source.fd);
64
free(impl);
65
}
66
67
pipewire-0.3.44.tar.gz/src/pipewire/keys.h -> pipewire-0.3.45.tar.gz/src/pipewire/keys.h
Changed
16
1
2
* node as a fraction. Ex: 1024/48000 */
3
#define PW_KEY_NODE_LOCK_QUANTUM "node.lock-quantum" /**< don't change quantum when this node
4
* is active */
5
+#define PW_KEY_NODE_FORCE_QUANTUM "node.force-quantum" /**< force a quantum while the node is
6
+ * active */
7
#define PW_KEY_NODE_RATE "node.rate" /**< the requested rate of the graph as
8
* a fraction. Ex: 1/48000 */
9
#define PW_KEY_NODE_LOCK_RATE "node.lock-rate" /**< don't change rate when this node
10
* is active */
11
+#define PW_KEY_NODE_FORCE_RATE "node.force-rate" /**< force a rate while the node is
12
+ * active */
13
14
#define PW_KEY_NODE_DONT_RECONNECT "node.dont-reconnect" /**< don't reconnect this node */
15
#define PW_KEY_NODE_ALWAYS_PROCESS "node.always-process" /**< process even when unlinked */
16
pipewire-0.3.44.tar.gz/src/pipewire/log.h -> pipewire-0.3.45.tar.gz/src/pipewire/log.h
Changed
13
1
2
#define pw_log_level_enabled(lev) (pw_log_level >= (lev))
3
#define pw_log_topic_enabled(lev,t) ((t) && (t)->has_custom_level ? (t)->level >= (lev) : pw_log_level_enabled((lev)))
4
5
+#define pw_logtv(lev,topic,fmt,ap) \
6
+({ \
7
+ if (SPA_UNLIKELY(pw_log_topic_enabled(lev,topic))) \
8
+ pw_log_logtv(lev,topic,__FILE__,__LINE__,__func__,fmt,ap); \
9
+})
10
11
#define pw_logt(lev,topic,...) \
12
({ \
13
pipewire-0.3.44.tar.gz/src/pipewire/main-loop.c -> pipewire-0.3.45.tar.gz/src/pipewire/main-loop.c
Changed
46
1
2
PW_LOG_TOPIC_EXTERN(log_main_loop);
3
#define PW_LOG_TOPIC_DEFAULT log_main_loop
4
5
-static void do_stop(void *data, uint64_t count)
6
+static int do_stop(struct spa_loop *loop, bool async, uint32_t seq,
7
+ const void *data, size_t size, void *user_data)
8
{
9
- struct pw_main_loop *this = data;
10
+ struct pw_main_loop *this = user_data;
11
pw_log_debug("%p: do stop", this);
12
this->running = false;
13
+ return 0;
14
}
15
16
static struct pw_main_loop *loop_new(struct pw_loop *loop, const struct spa_dict *props)
17
18
}
19
this->loop = loop;
20
21
- this->event = pw_loop_add_event(this->loop, do_stop, this);
22
- if (this->event == NULL) {
23
- res = -errno;
24
- goto error_free_loop;
25
- }
26
-
27
spa_hook_list_init(&this->listener_list);
28
29
return this;
30
31
-error_free_loop:
32
- if (this->created && this->loop)
33
- pw_loop_destroy(this->loop);
34
error_free:
35
free(this);
36
error_cleanup:
37
38
int pw_main_loop_quit(struct pw_main_loop *loop)
39
{
40
pw_log_debug("%p: quit", loop);
41
- return pw_loop_signal_event(loop->loop, loop->event);
42
+ return pw_loop_invoke(loop->loop, do_stop, 1, NULL, 0, false, loop);
43
}
44
45
/** Start a main loop
46
pipewire-0.3.44.tar.gz/src/pipewire/mem.c -> pipewire-0.3.45.tar.gz/src/pipewire/mem.c
Changed
19
1
2
}
3
unlink(filename);
4
#endif
5
+ pw_log_debug("%p: new fd:%d", pool, b->this.fd);
6
7
if (ftruncate(b->this.fd, size) < 0) {
8
res = -errno;
9
10
11
b->this.id = pw_map_insert_new(&impl->map, b);
12
spa_list_append(&impl->blocks, &b->link);
13
- pw_log_debug("%p: block:%p id:%d type:%u size:%zu", pool, &b->this, b->this.id, type, size);
14
+ pw_log_debug("%p: block:%p id:%d type:%u size:%zu", pool,
15
+ &b->this, b->this.id, type, size);
16
17
if (!SPA_FLAG_IS_SET(flags, PW_MEMBLOCK_FLAG_DONT_NOTIFY))
18
pw_mempool_emit_added(impl, &b->this);
19
pipewire-0.3.44.tar.gz/src/pipewire/private.h -> pipewire-0.3.45.tar.gz/src/pipewire/private.h
Changed
52
1
2
buffer[1023] = '\0';
3
pw_log_debug("resource %p: id:%d seq:%d res:%d (%s) msg:\"%s\"",
4
resource, id, seq, res, spa_strerror(res), buffer);
5
- pw_core_resource_error(resource, id, seq, res, buffer);
6
+ if (resource)
7
+ pw_core_resource_error(resource, id, seq, res, buffer);
8
+ else
9
+ pw_log_error("id:%d seq:%d res:%d (%s) msg:\"%s\"",
10
+ id, seq, res, spa_strerror(res), buffer);
11
}
12
13
static inline SPA_PRINTF_FUNC(5,6) void
14
15
16
struct pw_mempool *pool; /**< global memory pool */
17
18
+ uint64_t stamp;
19
+ uint64_t serial;
20
struct pw_map globals; /**< map of globals */
21
22
struct spa_list core_impl_list; /**< list of core_imp */
23
24
struct pw_loop *loop;
25
26
struct spa_hook_list listener_list;
27
- struct spa_source *event;
28
29
pthread_t thread;
30
+ unsigned int cancel:1;
31
unsigned int created:1;
32
unsigned int running:1;
33
};
34
35
struct pw_loop *loop;
36
37
struct spa_hook_list listener_list;
38
- struct spa_source *event;
39
40
unsigned int created:1;
41
unsigned int running:1;
42
43
struct spa_fraction latency; /**< requested latency */
44
struct spa_fraction max_latency; /**< maximum latency */
45
struct spa_fraction rate; /**< requested rate */
46
+ uint32_t force_quantum; /**< forced quantum */
47
+ uint32_t force_rate; /**< forced rate */
48
+ uint32_t stamp; /**< stamp of last update */
49
struct spa_source source; /**< source to remotely trigger this node */
50
struct pw_memblock *activation;
51
struct {
52
pipewire-0.3.44.tar.gz/src/pipewire/resource.c -> pipewire-0.3.45.tar.gz/src/pipewire/resource.c
Changed
76
1
2
3
#include <spa/debug/types.h>
4
5
-PW_LOG_TOPIC_EXTERN(log_device);
6
-#define PW_LOG_TOPIC_DEFAULT log_device
7
+PW_LOG_TOPIC_EXTERN(log_resource);
8
+#define PW_LOG_TOPIC_DEFAULT log_resource
9
10
/** \cond */
11
struct impl {
12
13
static void SPA_PRINTF_FUNC(4, 0)
14
pw_resource_errorv_id(struct pw_resource *resource, uint32_t id, int res, const char *error, va_list ap)
15
{
16
- struct pw_impl_client *client = resource->client;
17
- if (client->core_resource != NULL)
18
- pw_core_resource_errorv(client->core_resource,
19
- id, client->recv_seq, res, error, ap);
20
+ struct pw_impl_client *client;
21
+
22
+ if (resource) {
23
+ client = resource->client;
24
+ if (client->core_resource != NULL)
25
+ pw_core_resource_errorv(client->core_resource,
26
+ id, client->recv_seq, res, error, ap);
27
+ } else {
28
+ pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap);
29
+ }
30
}
31
32
SPA_EXPORT
33
34
{
35
va_list ap;
36
va_start(ap, error);
37
- pw_resource_errorv_id(resource, resource->id, res, error, ap);
38
+ if (resource)
39
+ pw_resource_errorv_id(resource, resource->id, res, error, ap);
40
+ else
41
+ pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap);
42
va_end(ap);
43
}
44
45
46
{
47
va_list ap;
48
va_start(ap, error);
49
- pw_resource_errorv_id(resource, id, res, error, ap);
50
+ if (resource)
51
+ pw_resource_errorv_id(resource, id, res, error, ap);
52
+ else
53
+ pw_logtv(SPA_LOG_LEVEL_ERROR, PW_LOG_TOPIC_DEFAULT, error, ap);
54
va_end(ap);
55
}
56
57
SPA_EXPORT
58
void pw_resource_error(struct pw_resource *resource, int res, const char *error)
59
{
60
- struct pw_impl_client *client = resource->client;
61
- if (client->core_resource != NULL)
62
- pw_core_resource_error(client->core_resource,
63
- resource->id, client->recv_seq, res, error);
64
+ struct pw_impl_client *client;
65
+ if (resource) {
66
+ client = resource->client;
67
+ if (client->core_resource != NULL)
68
+ pw_core_resource_error(client->core_resource,
69
+ resource->id, client->recv_seq, res, error);
70
+ } else {
71
+ pw_log_error("%s: %s", error, spa_strerror(res));
72
+ }
73
}
74
75
SPA_EXPORT
76
pipewire-0.3.44.tar.gz/src/pipewire/stream.c -> pipewire-0.3.45.tar.gz/src/pipewire/stream.c
Changed
11
1
2
res = -errno;
3
goto error_properties;
4
}
5
- if ((str = pw_context_get_conf_section(context, "stream.properties")) != NULL)
6
- pw_properties_update_string(props, str, strlen(str));
7
+ pw_context_conf_update_props(context, "stream.properties", props);
8
9
if (pw_properties_get(props, PW_KEY_STREAM_IS_LIVE) == NULL)
10
pw_properties_set(props, PW_KEY_STREAM_IS_LIVE, "true");
11
pipewire-0.3.44.tar.gz/src/tools/pw-cli.c -> pipewire-0.3.45.tar.gz/src/tools/pw-cli.c
Changed
88
1
2
#include <readline/readline.h>
3
#include <readline/history.h>
4
5
+#if !defined(FNM_EXTMATCH)
6
+#define FNM_EXTMATCH 0
7
+#endif
8
+
9
#define spa_debug(...) fprintf(stdout,__VA_ARGS__);fputc('\n', stdout)
10
11
#include <spa/utils/result.h>
12
13
static bool do_set_param(struct data *data, const char *cmd, char *args, char **error);
14
static bool do_permissions(struct data *data, const char *cmd, char *args, char **error);
15
static bool do_get_permissions(struct data *data, const char *cmd, char *args, char **error);
16
+static bool do_send_command(struct data *data, const char *cmd, char *args, char **error);
17
static bool do_dump(struct data *data, const char *cmd, char *args, char **error);
18
static bool do_quit(struct data *data, const char *cmd, char *args, char **error);
19
20
21
{ "set-param", "s", "Set param of an object <object-id> <param-id> <param-json>", do_set_param },
22
{ "permissions", "sp", "Set permissions for a client <client-id> <object> <permission>", do_permissions },
23
{ "get-permissions", "gp", "Get permissions of a client <client-id>", do_get_permissions },
24
+ { "send-command", "c", "Send a command <object-id>", do_send_command },
25
{ "dump", "D", "Dump objects in ways that are cleaner for humans to understand "
26
"[short|deep|resolve|notype] [-sdrt] [all|"DUMP_NAMES"|<id>]", do_dump },
27
{ "quit", "q", "Quit", do_quit },
28
29
return true;
30
}
31
32
+static bool do_send_command(struct data *data, const char *cmd, char *args, char **error)
33
+{
34
+ struct remote_data *rd = data->current;
35
+ char *a[3];
36
+ int res, n;
37
+ struct global *global;
38
+ uint8_t buffer[1024];
39
+ struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer));
40
+ const struct spa_type_info *ti;
41
+ struct spa_pod *pod;
42
+
43
+ n = pw_split_ip(args, WHITESPACE, 3, a);
44
+ if (n < 3) {
45
+ *error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd);
46
+ return false;
47
+ }
48
+
49
+ global = find_global(rd, a[0]);
50
+ if (global == NULL) {
51
+ *error = spa_aprintf("%s: unknown global '%s'", cmd, a[0]);
52
+ return false;
53
+ }
54
+ if (global->proxy == NULL) {
55
+ if (!bind_global(rd, global, error))
56
+ return false;
57
+ }
58
+
59
+ if (spa_streq(global->type, PW_TYPE_INTERFACE_Node)) {
60
+ ti = spa_debug_type_find_short(spa_type_node_command_id, a[1]);
61
+ } else {
62
+ *error = spa_aprintf("send-command not implemented on object %d type:%s",
63
+ atoi(a[0]), global->type);
64
+ return false;
65
+ }
66
+
67
+ if (ti == NULL) {
68
+ *error = spa_aprintf("%s: unknown node command type: %s", cmd, a[1]);
69
+ return false;
70
+ }
71
+ if ((res = spa_json_to_pod(&b, 0, ti, a[2], strlen(a[2]))) < 0) {
72
+ *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res));
73
+ return false;
74
+ }
75
+ if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) {
76
+ *error = spa_aprintf("%s: can't make pod", cmd);
77
+ return false;
78
+ }
79
+ spa_debug_pod(0, NULL, pod);
80
+
81
+ pw_node_send_command((struct pw_node*)global->proxy, (struct spa_command*)pod);
82
+ return true;
83
+}
84
+
85
static const char *
86
pw_interface_short(const char *type)
87
{
88
pipewire-0.3.44.tar.gz/src/tools/pw-dump.c -> pipewire-0.3.45.tar.gz/src/tools/pw-dump.c
Changed
12
1
2
#include <math.h>
3
#include <fnmatch.h>
4
5
+#if !defined(FNM_EXTMATCH)
6
+#define FNM_EXTMATCH 0
7
+#endif
8
+
9
#include <spa/utils/result.h>
10
#include <spa/utils/string.h>
11
#include <spa/pod/iter.h>
12
pipewire-0.3.44.tar.gz/test/test-config.c -> pipewire-0.3.45.tar.gz/test/test-config.c
Changed
17
1
2
pwtest_str_eq(pw_properties_get(props, "data"), "x");
3
pw_properties_free(props);
4
5
+#if 0
6
/* Load with non-NULL abs prefix and abs path */
7
props = pw_properties_new("ignore", "me", NULL);
8
r = pw_conf_load_conf("/dummy", path, props);
9
10
pwtest_neg_errno_ok(r);
11
pwtest_str_eq(pw_properties_get(props, "data"), "x");
12
pw_properties_free(props);
13
+#endif
14
15
/* Load with non-NULL abs prefix and relative path */
16
basename = rindex(path, '/'); /* basename(3) and dirname(3) are terrible */
17
Refresh
No build results available
Refresh
No rpmlint results available
Login required, please
login
or
signup
in order to comment
Request History
zaitor created request about 3 years ago
New upstream release
zaitor accepted request about 3 years ago
Xin