Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Problem getting expanded diff: bad link: Essentials/vlc-beta: package 'vlc-beta' does not exist
×
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 31
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Mon Jul 31 19:02:32 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.76 + +------------------------------------------------------------------- Wed Jul 26 14:05:18 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.74
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.74 +Version: 0.3.76 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.74.tar.gz/NEWS -> pipewire-0.3.76.tar.gz/NEWS
Changed
@@ -1,3 +1,94 @@ +# PipeWire 0.3.76 (2023-07-28) + +This is a quick bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a regression that would cause the MPV pipewire backend to fail because + of a spurious thread-loop signal. + - Fix a crash when DBus is not found. + - ALSA hires timestamps are now disabled by default. + - Some more fixes and improvements. + +## PipeWire + - A new option was added to pw-thread-loop to signal when the thread starts. + This is only used in module-rt to avoid regressions in mpv. (#3374) + - Fix a compilation problem. + - Stream flags now only set the properties when not already set. This fixes + a regression with node autoconnect. (#3382) + +## Tools + - pw-cat will now stop when the stream is disconnected. (#2731) + - Improve the pw-cat man page, mention that stdin/stdout handling is only + on raw data. + +## modules + - module-rt will now not crash when dbus is not available but error out as + before. + - A new VBAN (vb-audio.com) sender and receiver was added. (#3380) + +## SPA + - Add an option in audioconvert to disable volume updates. (#3361) + - ALSA hires timestamps are disabled by default because many drivers seem to + give wrong timestamps and cause extra delay. + +## bluetooth + - LE Audio support is now enabled by default when liblc3 is available now that + bluez has support for detecting the hardware features. + +Older versions: + + +# PipeWire 0.3.75 (2023-07-21) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Link permissions between nodes are now enforced. This avoids potential portal + managed screencast nodes to link to the camera even though it was not assigned + permissions to do so by the session manager. + - Libcamera and v4l2 devices now have properties so that duplicates can be + filtered out by the session manager. + - A bug with draining was fixed where a buffer would be marked EMPTY and would not + play when it contained drained samples. (#3365) + - Many fixes and improvements. + + +## PipeWire + - Permissions for links between nodes are now enforced. The link will now check + that the owner clients of the nodes can see eachother before allowing the link. + This avoids screensharing clients to accidentally being linked to the camera + nodes by the session manager. A side effect is that patchbay tools will no longer + be able to link portal managed screencast nodes to the camera, for this we need + a new permission for those patchbay clients. (wireplumber#218) + - The stream.rules/filter.rules are now evaluated when connecting the stream/filter + so that more properties can be matched. (#3355) + - Move some internal events from the context to the nodes to better handle per-node + threads in the future. + - The thread-loop will now signal when the thread is started. + +## modules + - A timestamp workaround in module-raop was reverted because it does not work + in all cases. Instead latency was increased to 1.5 seconds, which also makes + the problematic device in question work. (#3247) + - The profiler module was reworked a bit to use the new node realtime events. It + should now also handle dynamically added and removed drivers. + - The module-rt now does the rtkit calls from a separate thread so that it does + not block the main thread. This could cause deadlocks during startup in some + cases. (#3357) + +## SPA + - Atomic operation macros were move from internal pipewire API to public API. + - The video-info structure now has a new SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED + flag to instruct the application to fixate the modifiers. This simplifies some + logic in applications a lot. + - The libcamera and v4l2 nodes now have properties to enumerate the device id + they are using. This can be used to match v4l2 devices and libcamera devices + and filter out duplicates. + - A bug with draining was fixed where a buffer would be marked EMPTY and would not + play when it contained drained samples. (#3365) + # PipeWire 0.3.74 (2023-07-12) This is a quick bugfix release that is API and ABI compatible with previous @@ -33,9 +124,6 @@ - Merge scope based cleanup macros. - Add ratelimit function. -Older versions: - - # PipeWire 0.3.73 (2023-07-06) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.74.tar.gz/doc/pipewire-modules.dox -> pipewire-0.3.76.tar.gz/doc/pipewire-modules.dox
Changed
@@ -86,6 +86,8 @@ - \subpage page_module_rtp_session - \subpage page_module_rt - \subpage page_module_session_manager +- \subpage page_module_vban_recv +- \subpage page_module_vban_send - \subpage page_module_x11_bell - \subpage page_module_zeroconf_discover
View file
pipewire-0.3.74.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.76.tar.gz/man/pw-cat.1.rst.in
Changed
@@ -24,7 +24,9 @@ **pw-cat** is a simple tool for playing back or capturing raw or encoded media files on a PipeWire server. It understands all audio file formats supported by -``libsndfile`` for PCM capture and playback. +``libsndfile`` for PCM capture and playback. When capturing PCM, the filename +extension is used to guess the file format with the WAV file format as +the default. It understands standard MIDI files for playback and recording. This tool will not render MIDI files, it will simply make the MIDI events available @@ -35,7 +37,7 @@ with native DSD capable hardware and will produce an error when no such hardware was found. -When the *FILE* is - input and output will be from STDIN and +When the *FILE* is - input and output will be raw data from STDIN and STDOUT respectively. OPTIONS
View file
pipewire-0.3.74.tar.gz/meson.build -> pipewire-0.3.76.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.74', + version : '0.3.76', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3',
View file
pipewire-0.3.74.tar.gz/meson_options.txt -> pipewire-0.3.76.tar.gz/meson_options.txt
Changed
@@ -127,7 +127,7 @@ option('bluez5-codec-lc3', description: 'Enable LC3 open source codec implementation', type: 'feature', - value: 'disabled') + value: 'auto') option('control', description: 'Enable control spa plugin integration', type: 'feature',
View file
pipewire-0.3.74.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.76.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -19,20 +19,12 @@ #include <spa/param/audio/format-utils.h> #include <spa/debug/types.h> #include <spa/param/props.h> +#include <spa/utils/atomic.h> #include <spa/utils/result.h> #include <spa/utils/string.h> #include <pipewire/pipewire.h> -#define ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST) -#define ATOMIC_LOAD(s) __atomic_load_n(&(s), __ATOMIC_SEQ_CST) - -#define SEQ_WRITE(s) ATOMIC_INC(s) -#define SEQ_WRITE_SUCCESS(s1,s2) ((s1) + 1 == (s2) && ((s2) & 1) == 0) - -#define SEQ_READ(s) ATOMIC_LOAD(s) -#define SEQ_READ_SUCCESS(s1,s2) ((s1) == (s2) && ((s2) & 1) == 0) - PW_LOG_TOPIC_STATIC(alsa_log_topic, "alsa.pcm"); #define PW_LOG_TOPIC_DEFAULT alsa_log_topic @@ -223,7 +215,7 @@ int64_t diff; do { - seq1 = SEQ_READ(pw->seq); + seq1 = SPA_SEQ_READ(pw->seq); delay = pw->delay + pw->transfered; now = pw->now; @@ -232,8 +224,8 @@ else avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr); - seq2 = SEQ_READ(pw->seq); - } while (!SEQ_READ_SUCCESS(seq1, seq2)); + seq2 = SPA_SEQ_READ(pw->seq); + } while (!SPA_SEQ_READ_SUCCESS(seq1, seq2)); if (now != 0 && (io->state == SND_PCM_STATE_RUNNING || io->state == SND_PCM_STATE_DRAINING)) { @@ -437,7 +429,7 @@ want = b->requested ? b->requested : hw_avail; - SEQ_WRITE(pw->seq); + SPA_SEQ_WRITE(pw->seq); if (pw->now != pwt.now) { pw->transfered = pw->buffered; @@ -455,7 +447,7 @@ pw->buffered = (want == 0 || pw->transfered < want) ? 0 : (pw->transfered % want); pw->now = pwt.now; - SEQ_WRITE(pw->seq); + SPA_SEQ_WRITE(pw->seq); pw_log_trace("%p: avail-before:%lu avail:%lu want:%lu xfer:%lu hw:%lu appl:%lu", pw, before, hw_avail, want, xfer, pw->hw_ptr, io->appl_ptr);
View file
pipewire-0.3.74.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.76.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -1737,7 +1737,7 @@ pw_log_trace_fp("%p: link %p %p %d/%d", c, l, state, state->pending, state->required); - if (pw_node_activation_state_dec(state, 1)) { + if (pw_node_activation_state_dec(state)) { l->activation->status = PW_NODE_ACTIVATION_TRIGGERED; l->activation->signal_time = nsec; @@ -1898,18 +1898,18 @@ pw_log_debug("%p: activation %p", c, a); /* was ok */ - owner = ATOMIC_LOAD(a->segment_owner0); + owner = SPA_ATOMIC_LOAD(a->segment_owner0); if (owner == c->node_id) return 0; /* try to become owner */ if (c->timeowner_conditional) { - if (!ATOMIC_CAS(a->segment_owner0, 0, c->node_id)) { + if (!SPA_ATOMIC_CAS(a->segment_owner0, 0, c->node_id)) { pw_log_debug("%p: owner:%u id:%u", c, owner, c->node_id); return -EBUSY; } } else { - ATOMIC_STORE(a->segment_owner0, c->node_id); + SPA_ATOMIC_STORE(a->segment_owner0, c->node_id); } pw_log_debug("%p: timebase installed for id:%u", c, c->node_id); @@ -3536,6 +3536,7 @@ uint32_t n_support; const char *str; struct spa_cpu *cpu_iface; + const struct pw_properties *props; va_list ap; if (getenv("PIPEWIRE_NOJACK") != NULL || @@ -3607,14 +3608,16 @@ client->notify_buffer = calloc(1, NOTIFY_BUFFER_SIZE + sizeof(struct notify)); spa_ringbuffer_init(&client->notify_ring); - client->allow_mlock = client->context.context->settings.mem_allow_mlock; - client->warn_mlock = client->context.context->settings.mem_warn_mlock; - pw_context_conf_update_props(client->context.context, "jack.properties", client->props); + props = pw_context_get_properties(client->context.context); + + client->allow_mlock = pw_properties_get_bool(props, "mem.allow-mlock", true); + client->warn_mlock = pw_properties_get_bool(props, "mem.warn-mlock", false); + pw_context_conf_section_match_rules(client->context.context, "jack.rules", - &client->context.context->properties->dict, execute_match, client); + &props->dict, execute_match, client); support = pw_context_get_support(client->context.context, &n_support); @@ -6192,7 +6195,7 @@ if ((a = c->driver_activation) == NULL) return -EIO; - if (!ATOMIC_CAS(a->segment_owner0, c->node_id, 0)) + if (!SPA_ATOMIC_CAS(a->segment_owner0, c->node_id, 0)) return -EINVAL; c->timebase_callback = NULL; @@ -6364,7 +6367,7 @@ na->reposition.duration = 0; na->reposition.position = pos->frame; na->reposition.rate = 1.0; - ATOMIC_STORE(a->reposition_owner, c->node_id); + SPA_ATOMIC_STORE(a->reposition_owner, c->node_id); return 0; } @@ -6374,7 +6377,7 @@ struct pw_node_activation *a = c->rt.driver_activation; if (!a) return; - ATOMIC_STORE(a->command, command); + SPA_ATOMIC_STORE(a->command, command); } SPA_EXPORT
View file
pipewire-0.3.74.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c -> pipewire-0.3.76.tar.gz/pipewire-v4l2/src/pipewire-v4l2.c
Changed
@@ -19,6 +19,7 @@ #include "pipewire-v4l2.h" +#include <spa/utils/atomic.h> #include <spa/utils/result.h> #include <spa/pod/iter.h> #include <spa/pod/parser.h> @@ -248,8 +249,6 @@ } } } -#define ATOMIC_DEC(s) __atomic_sub_fetch(&(s), 1, __ATOMIC_SEQ_CST) -#define ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST) static struct file *make_file(void) { @@ -301,7 +300,7 @@ static void unref_file(struct file *file) { pw_log_debug("file:%d ref:%d", file->fd, file->ref); - if (ATOMIC_DEC(file->ref) <= 0) + if (SPA_ATOMIC_DEC(file->ref) <= 0) free_file(file); } @@ -314,7 +313,7 @@ map->fd = fd; map->flags = flags; map->file = file; - ATOMIC_INC(file->ref); + SPA_ATOMIC_INC(file->ref); pw_log_debug("fd:%d -> file:%d ref:%d", fd, file->fd, file->ref); } pthread_mutex_unlock(&globals.lock); @@ -349,7 +348,7 @@ struct fd_map *map; pw_array_for_each(map, &globals.fd_maps) { if (map->fd == fd) { - ATOMIC_INC(map->file->ref); + SPA_ATOMIC_INC(map->file->ref); pw_log_debug("fd:%d find:%d ref:%d", map->fd, fd, map->file->ref); return map; } @@ -384,7 +383,7 @@ if (tmp->file->dev_id == dev) { if (tmp->file->closed) tmp->file->fd = tmp->fd; - ATOMIC_INC(tmp->file->ref); + SPA_ATOMIC_INC(tmp->file->ref); map = tmp; pw_log_debug("dev:%d find:%d ref:%d", tmp->file->dev_id, dev, tmp->file->ref);
View file
pipewire-0.3.74.tar.gz/spa/include/spa/graph/graph.h -> pipewire-0.3.76.tar.gz/spa/include/spa/graph/graph.h
Changed
@@ -18,6 +18,7 @@ * \{ */ +#include <spa/utils/atomic.h> #include <spa/utils/defs.h> #include <spa/utils/list.h> #include <spa/utils/hook.h> @@ -53,7 +54,7 @@ #define spa_graph_link_signal(l) ((l)->signal((l)->signal_data)) -#define spa_graph_state_dec(s,c) (__atomic_sub_fetch(&(s)->pending, c, __ATOMIC_SEQ_CST) == 0) +#define spa_graph_state_dec(s) (SPA_ATOMIC_DEC(s->pending) == 0) static inline int spa_graph_link_trigger(struct spa_graph_link *link) { @@ -62,7 +63,7 @@ spa_debug("link %p: state %p: pending %d/%d", link, state, state->pending, state->required); - if (spa_graph_state_dec(state, 1)) + if (spa_graph_state_dec(state)) spa_graph_link_signal(link); return state->status;
View file
pipewire-0.3.74.tar.gz/spa/include/spa/monitor/device.h -> pipewire-0.3.76.tar.gz/spa/include/spa/monitor/device.h
Changed
@@ -275,7 +275,8 @@ #define SPA_KEY_DEVICE_PROFILE_SET "device.profile-set" /**< profile set for the device */ #define SPA_KEY_DEVICE_STRING "device.string" /**< device string in the underlying * layer's format. E.g. "surround51:0" */ - +#define SPA_KEY_DEVICE_DEVIDS "device.devids" /**< space separated list of device ids (dev_t) of the + * underlying device(s) if applicable */ /** * \} */
View file
pipewire-0.3.74.tar.gz/spa/include/spa/param/props.h -> pipewire-0.3.76.tar.gz/spa/include/spa/param/props.h
Changed
@@ -59,13 +59,16 @@ SPA_PROP_START_Audio = 0x10000, /**< audio related properties */ SPA_PROP_waveType, SPA_PROP_frequency, - SPA_PROP_volume, /**< a volume (Float), 0.0 silence, 1.0 normal */ + SPA_PROP_volume, /**< a volume (Float), 0.0 silence, 1.0 no attenutation */ SPA_PROP_mute, /**< mute (Bool) */ SPA_PROP_patternType, SPA_PROP_ditherType, SPA_PROP_truncate, - SPA_PROP_channelVolumes, /**< a volume array, one volume per - * channel (Array of Float) */ + SPA_PROP_channelVolumes, /**< a volume array, one volume per channel + * (Array of Float). 0.0 is silence, 1.0 is + * without attenuation. This is the effective volume + * that is applied. It can result in a hardware volume + * and software volume (see softVolumes) */ SPA_PROP_volumeBase, /**< a volume base (Float) */ SPA_PROP_volumeStep, /**< a volume step (Float) */ SPA_PROP_channelMap, /**< a channelmap array @@ -74,9 +77,11 @@ SPA_PROP_monitorVolumes, /**< a volume array, one volume per * channel (Array of Float) */ SPA_PROP_latencyOffsetNsec, /**< delay adjustment */ - SPA_PROP_softMute, /**< mute (Bool) */ - SPA_PROP_softVolumes, /**< a volume array, one volume per - * channel (Array of Float) */ + SPA_PROP_softMute, /**< mute (Bool) applied in software */ + SPA_PROP_softVolumes, /**< a volume array, one volume per channel + * (Array of Float). 0.0 is silence, 1.0 is without + * attenuation. This is the volume applied in software, + * there might be a part applied in hardware. */ SPA_PROP_iec958Codecs, /**< enabled IEC958 (S/PDIF) codecs, * (Array (Id enum spa_audio_iec958_codec) */
View file
pipewire-0.3.74.tar.gz/spa/include/spa/param/video/dsp-utils.h -> pipewire-0.3.76.tar.gz/spa/include/spa/param/video/dsp-utils.h
Changed
@@ -23,8 +23,11 @@ struct spa_video_info_dsp *info) { info->flags = SPA_VIDEO_FLAG_NONE; - if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) { + const struct spa_pod_prop *mod_prop; + if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) { info->flags |= SPA_VIDEO_FLAG_MODIFIER; + if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE) + info->flags |= SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED; } return spa_pod_parse_object(format,
View file
pipewire-0.3.74.tar.gz/spa/include/spa/param/video/raw-utils.h -> pipewire-0.3.76.tar.gz/spa/include/spa/param/video/raw-utils.h
Changed
@@ -23,8 +23,11 @@ struct spa_video_info_raw *info) { info->flags = SPA_VIDEO_FLAG_NONE; - if (spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) { + const struct spa_pod_prop *mod_prop; + if ((mod_prop = spa_pod_find_prop (format, NULL, SPA_FORMAT_VIDEO_modifier)) != NULL) { info->flags |= SPA_VIDEO_FLAG_MODIFIER; + if ((mod_prop->flags & SPA_POD_PROP_FLAG_DONT_FIXATE) == SPA_POD_PROP_FLAG_DONT_FIXATE) + info->flags |= SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED; } return spa_pod_parse_object(format,
View file
pipewire-0.3.74.tar.gz/spa/include/spa/param/video/raw.h -> pipewire-0.3.76.tar.gz/spa/include/spa/param/video/raw.h
Changed
@@ -134,11 +134,12 @@ * Extra video flags */ enum spa_video_flags { - SPA_VIDEO_FLAG_NONE = 0, /**< no flags */ - SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0), /**< a variable fps is selected, fps_n and fps_d - * denote the maximum fps of the video */ - SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1), /**< Each color has been scaled by the alpha value. */ - SPA_VIDEO_FLAG_MODIFIER = (1 << 2), /**< use the format modifier */ + SPA_VIDEO_FLAG_NONE = 0, /**< no flags */ + SPA_VIDEO_FLAG_VARIABLE_FPS = (1 << 0), /**< a variable fps is selected, fps_n and fps_d + * denote the maximum fps of the video */ + SPA_VIDEO_FLAG_PREMULTIPLIED_ALPHA = (1 << 1), /**< Each color has been scaled by the alpha value. */ + SPA_VIDEO_FLAG_MODIFIER = (1 << 2), /**< use the format modifier */ + SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED = (1 << 3), /**< format modifier was not fixated yet */ }; /**
View file
pipewire-0.3.76.tar.gz/spa/include/spa/utils/atomic.h
Added
@@ -0,0 +1,35 @@ +/* Atomic operations */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_ATOMIC_H +#define SPA_ATOMIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define SPA_ATOMIC_CAS(v,ov,nv) \ +({ \ + __typeof__(v) __ov = (ov); \ + __atomic_compare_exchange_n(&(v), &__ov, (nv), \ + 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ +}) + +#define SPA_ATOMIC_DEC(s) __atomic_sub_fetch(&(s), 1, __ATOMIC_SEQ_CST) +#define SPA_ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST) +#define SPA_ATOMIC_LOAD(s) __atomic_load_n(&(s), __ATOMIC_SEQ_CST) +#define SPA_ATOMIC_STORE(s,v) __atomic_store_n(&(s), (v), __ATOMIC_SEQ_CST) +#define SPA_ATOMIC_XCHG(s,v) __atomic_exchange_n(&(s), (v), __ATOMIC_SEQ_CST) + +#define SPA_SEQ_WRITE(s) SPA_ATOMIC_INC(s) +#define SPA_SEQ_WRITE_SUCCESS(s1,s2) ((s1) + 1 == (s2) && ((s2) & 1) == 0) + +#define SPA_SEQ_READ(s) SPA_ATOMIC_LOAD(s) +#define SPA_SEQ_READ_SUCCESS(s1,s2) ((s1) == (s2) && ((s2) & 1) == 0) + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_ATOMIC_H */
View file
pipewire-0.3.74.tar.gz/spa/meson.build -> pipewire-0.3.76.tar.gz/spa/meson.build
Changed
@@ -80,7 +80,6 @@ summary({'Opus': opus_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') lc3_dep = dependency('lc3', required : get_option('bluez5-codec-lc3')) summary({'LC3': lc3_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') - cdata.set('HAVE_BLUETOOTH_BAP', get_option('bluez5-codec-lc3').allowed() and lc3_dep.found()) if get_option('bluez5-backend-hsp-native').allowed() or get_option('bluez5-backend-hfp-native').allowed() mm_dep = dependency('ModemManager', version : '>= 1.10.0', required : get_option('bluez5-backend-native-mm')) summary({'ModemManager': mm_dep.found()}, bool_yn: true, section: 'Bluetooth backends') @@ -94,6 +93,7 @@ libcamera_dep = dependency('libcamera', required: get_option('libcamera')) summary({'libcamera': libcamera_dep.found()}, bool_yn: true, section: 'Backend') + cdata.set('HAVE_LIBCAMERA_SYSTEM_DEVICES', libcamera_dep.version().version_compare('>= 0.1.0')) compress_offload_option = get_option('compress-offload') summary({'Compress-Offload': compress_offload_option.allowed()}, bool_yn: true, section: 'Backend')
View file
pipewire-0.3.74.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.76.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -503,7 +503,7 @@ snd_config_update_free_global(); state->multi_rate = true; - state->htimestamp = true; + state->htimestamp = false; for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; const char *s = info->itemsi.value;
View file
pipewire-0.3.74.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.76.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -89,6 +89,7 @@ unsigned int resample_quality; double rate; char wav_path512; + unsigned int lock_volumes:1; }; static void props_reset(struct props *props) @@ -109,6 +110,7 @@ props->resample_quality = RESAMPLE_DEFAULT_QUALITY; props->rate = 1.0; spa_zero(props->wav_path); + props->lock_volumes = false; } struct buffer { @@ -695,6 +697,14 @@ SPA_PROP_INFO_type, SPA_POD_String(p->wav_path), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; + case 27: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_name, SPA_POD_String("channelmix.lock-volumes"), + SPA_PROP_INFO_description, SPA_POD_String("Disable volume updates"), + SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->lock_volumes), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; default: return 0; } @@ -773,6 +783,8 @@ spa_pod_builder_string(&b, dither_method_infothis->dir1.conv.method.label); spa_pod_builder_string(&b, "debug.wav-path"); spa_pod_builder_string(&b, p->wav_path); + spa_pod_builder_string(&b, "channelmix.lock-volumes"); + spa_pod_builder_bool(&b, p->lock_volumes); spa_pod_builder_pop(&b, &f1); param = spa_pod_builder_pop(&b, &f0); break; @@ -854,6 +866,8 @@ spa_scnprintf(this->props.wav_path, sizeof(this->props.wav_path), "%s", s ? s : ""); } + else if (spa_streq(k, "channelmix.lock-volumes")) + this->props.lock_volumes = spa_atob(s); else return 0; return 1; @@ -1049,13 +1063,15 @@ case SPA_PROP_volume: p->prev_volume = p->volume; - if (spa_pod_get_float(&prop->value, &p->volume) == 0) { + if (!p->lock_volumes && + spa_pod_get_float(&prop->value, &p->volume) == 0) { spa_log_debug(this->log, "%p new volume %f", this, p->volume); changed++; } break; case SPA_PROP_mute: - if (spa_pod_get_bool(&prop->value, &p->channel.mute) == 0) { + if (!p->lock_volumes && + spa_pod_get_bool(&prop->value, &p->channel.mute) == 0) { have_channel_volume = true; changed++; } @@ -1124,7 +1140,8 @@ } break; case SPA_PROP_channelVolumes: - if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, + if (!p->lock_volumes && + (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, p->channel.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { have_channel_volume = true; p->channel.n_volumes = n; @@ -1139,13 +1156,15 @@ } break; case SPA_PROP_softMute: - if (spa_pod_get_bool(&prop->value, &p->soft.mute) == 0) { + if (!p->lock_volumes && + spa_pod_get_bool(&prop->value, &p->soft.mute) == 0) { have_soft_volume = true; changed++; } break; case SPA_PROP_softVolumes: - if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, + if (!p->lock_volumes && + (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, p->soft.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { have_soft_volume = true; p->soft.n_volumes = n; @@ -1187,7 +1206,7 @@ set_volume(this); } - if (vol_ramp_params_changed) { + if (!p->lock_volumes && vol_ramp_params_changed) { void *sequence = NULL; if (p->volume == p->prev_volume) spa_log_error(this->log, "no change in volume, cannot ramp volume"); @@ -2609,7 +2628,8 @@ struct dir *dir; int tmp = 0, res = 0; bool in_passthrough, mix_passthrough, resample_passthrough, out_passthrough; - bool in_avail = false, flush_in = false, flush_out = false, draining = false, in_empty = true; + bool in_avail = false, flush_in = false, flush_out = false; + bool draining = false, in_empty = this->out_offset == 0; struct spa_io_buffers *io, *ctrlio = NULL; const struct spa_pod_sequence *ctrl = NULL;
View file
pipewire-0.3.74.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.76.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
@@ -709,9 +709,10 @@ size = SPA_MIN(bd->maxsize - offs, bd->chunk->size); maxsize = SPA_MIN(maxsize, size); - spa_log_trace_fp(this->log, "%p: mix input %d %p->%p %d %d %d:%d/%d", this, + spa_log_trace_fp(this->log, "%p: mix input %d %p->%p %d %d %d:%d/%d %u", this, i, inio, outio, inio->status, inio->buffer_id, - offs, size, (int)sizeof(float)); + offs, size, (int)sizeof(float), + bd->chunk->flags); if (!SPA_FLAG_IS_SET(bd->chunk->flags, SPA_CHUNK_FLAG_EMPTY)) { datasn_buffers = SPA_PTROFF(bd->data, offs, void);
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/backend-hsphfpd.c
Changed
@@ -18,6 +18,7 @@ #include <spa/param/audio/raw.h> #include "defs.h" +#include "dbus-helpers.h" static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.bluez5.hsphfpd"); #undef SPA_LOG_TOPIC_DEFAULT @@ -764,7 +765,6 @@ { const char *interface_name = HSPHFPD_AUDIO_AGENT_INTERFACE; DBusMessageIter object, array, entry, dict, codec, data; - char *str = "AgentCodec"; dbus_message_iter_open_container(iter, DBUS_TYPE_DICT_ENTRY, NULL, &object); dbus_message_iter_append_basic(&object, DBUS_TYPE_OBJECT_PATH, &endpoint); @@ -777,7 +777,7 @@ dbus_message_iter_open_container(&entry, DBUS_TYPE_ARRAY, "{sv}", &dict); dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &codec); - dbus_message_iter_append_basic(&codec, DBUS_TYPE_STRING, &str); + dbus_message_iter_append_basic(&codec, DBUS_TYPE_STRING, &(const char *) { "AgentCodec" }); dbus_message_iter_open_container(&codec, DBUS_TYPE_VARIANT, "s", &data); dbus_message_iter_append_basic(&data, DBUS_TYPE_STRING, &agent_codec); dbus_message_iter_close_container(&codec, &data); @@ -847,7 +847,7 @@ backend->acquire_in_progress = false; - r = dbus_pending_call_steal_reply(pending); + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -890,7 +890,6 @@ finish: dbus_message_unref(r); - dbus_pending_call_unref(pending); if (ret < 0) spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ERROR); @@ -906,7 +905,6 @@ const char *air_codec = HSPHFP_AIR_CODEC_CVSD; const char *agent_codec = HSPHFP_AGENT_CODEC_PCM; DBusPendingCall *call; - DBusError err; spa_log_debug(backend->log, "transport %p: Acquire %s", transport, transport->path); @@ -927,8 +925,6 @@ return -ENOMEM; dbus_message_append_args(m, DBUS_TYPE_STRING, &air_codec, DBUS_TYPE_STRING, &agent_codec, DBUS_TYPE_INVALID); - dbus_error_init(&err); - dbus_connection_send_with_reply(backend->conn, m, &call, -1); dbus_pending_call_set_notify(call, hsphfpd_audio_acquire_reply, transport, NULL); dbus_message_unref(m); @@ -1183,7 +1179,7 @@ DBusMessage *r; DBusMessageIter i, array_i; - r = dbus_pending_call_steal_reply(pending); + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -1216,7 +1212,6 @@ finish: dbus_message_unref(r); - dbus_pending_call_unref(pending); } static int backend_hsphfpd_register(void *data) @@ -1303,9 +1298,6 @@ { const char *sender; struct impl *backend = user_data; - DBusError err; - - dbus_error_init(&err); sender = dbus_message_get_sender(m);
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/backend-native.c
Changed
@@ -33,6 +33,7 @@ #include <libusb.h> #endif +#include "dbus-helpers.h" #include "modemmanager.h" #include "upower.h" @@ -1163,10 +1164,9 @@ return true; } } else if (spa_strstartswith(buf, "AT+VTS=")) { - char *dtmf; + char dtmf2; enum cmee_error error; - dtmf = calloc(1, 2); if (sscanf(buf, "AT+VTS=%1s", dtmf) != 1) { spa_log_debug(backend->log, "Failed to parse AT+VTS: \"%s\"", buf); rfcomm_send_error(rfcomm, CMEE_AG_FAILURE); @@ -2196,7 +2196,7 @@ { struct impl *backend = userdata; DBusMessage *r; - DBusMessageIter it5; + DBusMessageIter it; const char *handler, *path; enum spa_bt_profile profile; struct rfcomm *rfcomm; @@ -2216,8 +2216,8 @@ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } - dbus_message_iter_init(m, &it0); - dbus_message_iter_get_basic(&it0, &path); + dbus_message_iter_init(m, &it); + dbus_message_iter_get_basic(&it, &path); d = spa_bt_device_find(backend->monitor, path); if (d == NULL || d->adapter == NULL) { @@ -2226,8 +2226,8 @@ } spa_bt_device_add_profile(d, profile); - dbus_message_iter_next(&it0); - dbus_message_iter_get_basic(&it0, &fd); + dbus_message_iter_next(&it); + dbus_message_iter_get_basic(&it, &fd); spa_log_debug(backend->log, "NewConnection path=%s, fd=%d, profile %s", path, fd, handler); @@ -2414,7 +2414,7 @@ struct impl *backend = user_data; DBusMessage *r; - r = dbus_pending_call_steal_reply(pending); + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -2432,9 +2432,8 @@ goto finish; } - finish: +finish: dbus_message_unref(r); - dbus_pending_call_unref(pending); } static int register_profile(struct impl *backend, const char *profile, const char *uuid)
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/backend-ofono.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/backend-ofono.c
Changed
@@ -22,6 +22,7 @@ #include <spa/param/audio/raw.h> #include "defs.h" +#include "dbus-helpers.h" #define INITIAL_INTERVAL_NSEC (500 * SPA_NSEC_PER_MSEC) #define ACTION_INTERVAL_NSEC (3000 * SPA_NSEC_PER_MSEC) @@ -633,7 +634,7 @@ DBusMessage *r; DBusMessageIter i, array_i, struct_i, props_i; - r = dbus_pending_call_steal_reply(pending); + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -665,7 +666,6 @@ finish: dbus_message_unref(r); - dbus_pending_call_unref(pending); } static int backend_ofono_register(void *data)
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -35,6 +35,7 @@ #include "config.h" #include "codec-loader.h" +#include "dbus-helpers.h" #include "player.h" #include "iso-io.h" #include "defs.h" @@ -225,12 +226,7 @@ DBusMessage *m; const char *interface; - if (device->battery_pending_call) { - spa_log_debug(device->monitor->log, "Cancelling and freeing pending battery provider register call"); - dbus_pending_call_cancel(device->battery_pending_call); - dbus_pending_call_unref(device->battery_pending_call); - device->battery_pending_call = NULL; - } + cancel_and_unref(&device->battery_pending_call); if (!device->adapter || !device->adapter->has_battery_provider || !device->has_battery) return; @@ -355,10 +351,8 @@ DBusMessage *reply; struct spa_bt_device *device = data; - reply = dbus_pending_call_steal_reply(pending_call); - dbus_pending_call_unref(pending_call); - - device->battery_pending_call = NULL; + spa_assert(device->battery_pending_call == pending_call); + reply = steal_reply_and_unref(&device->battery_pending_call); if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR) { spa_log_error(device->monitor->log, "Failed to register battery provider. Error: %s", dbus_message_get_error_name(reply)); @@ -422,9 +416,7 @@ device->battery_pending_call, on_battery_provider_registered, device, NULL)) { spa_log_error(device->monitor->log, "Failed to register battery provider"); - dbus_pending_call_cancel(device->battery_pending_call); - dbus_pending_call_unref(device->battery_pending_call); - device->battery_pending_call = NULL; + cancel_and_unref(&device->battery_pending_call); } } @@ -2340,7 +2332,7 @@ if (j >= size) { const struct media_codec **p; size = size * 2; -#ifdef HAVE_REALLOCARRRAY +#ifdef HAVE_REALLOCARRAY p = reallocarray(supported_codecs, size, sizeof(const struct media_codec *)); #else p = realloc(supported_codecs, size * sizeof(const struct media_codec *)); @@ -2634,17 +2626,8 @@ spa_bt_transport_destroy(transport); - if (transport->acquire_call) { - dbus_pending_call_cancel(transport->acquire_call); - dbus_pending_call_unref(transport->acquire_call); - transport->acquire_call = NULL; - } - - if (transport->volume_call) { - dbus_pending_call_cancel(transport->volume_call); - dbus_pending_call_unref(transport->volume_call); - transport->volume_call = NULL; - } + cancel_and_unref(&transport->acquire_call); + cancel_and_unref(&transport->volume_call); if (transport->fd >= 0) { spa_bt_player_set_state(transport->device->adapter->dummy_player, SPA_BT_PLAYER_STOPPED); @@ -2669,6 +2652,7 @@ spa_list_remove(&transport->bap_transport_linked); + free(transport->configuration); free(transport->endpoint_path); free(transport->path); free(transport); @@ -3242,11 +3226,8 @@ DBusError err = DBUS_ERROR_INIT; DBusMessage *r; - r = dbus_pending_call_steal_reply(pending); - spa_assert(transport->volume_call == pending); - dbus_pending_call_unref(pending); - transport->volume_call = NULL; + r = steal_reply_and_unref(&transport->volume_call); if (dbus_set_error_from_message(&err, r)) { spa_log_info(monitor->log, "transport %p: set volume failed for transport %s: %s", @@ -3270,11 +3251,7 @@ int res = 0; dbus_bool_t ret; - if (transport->volume_call) { - dbus_pending_call_cancel(transport->volume_call); - dbus_pending_call_unref(transport->volume_call); - transport->volume_call = NULL; - } + cancel_and_unref(&transport->volume_call); m = dbus_message_new_method_call(BLUEZ_SERVICE, transport->path, @@ -3400,11 +3377,8 @@ DBusMessage *r; struct spa_bt_transport *t, *t_linked; - r = dbus_pending_call_steal_reply(pending); - spa_assert(transport->acquire_call == pending); - dbus_pending_call_unref(pending); - transport->acquire_call = NULL; + r = steal_reply_and_unref(&transport->acquire_call); spa_bt_device_update_last_bluez_action_time(device); @@ -3613,11 +3587,7 @@ spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_IDLE); - if (transport->acquire_call) { - dbus_pending_call_cancel(transport->acquire_call); - dbus_pending_call_unref(transport->acquire_call); - transport->acquire_call = NULL; - } + cancel_and_unref(&transport->acquire_call); if (transport->iso_io) { spa_log_debug(monitor->log, "transport %p: remove ISO IO", transport); @@ -3742,10 +3712,7 @@ media_codec_switch_stop_timer(sw); - if (sw->pending != NULL) { - dbus_pending_call_cancel(sw->pending); - dbus_pending_call_unref(sw->pending); - } + cancel_and_unref(&sw->pending); if (sw->device != NULL) spa_list_remove(&sw->device_link); @@ -3992,11 +3959,8 @@ struct spa_bt_device *device = sw->device; DBusMessage *r; - r = dbus_pending_call_steal_reply(pending); - spa_assert(sw->pending == pending); - dbus_pending_call_unref(pending); - sw->pending = NULL; + r = steal_reply_and_unref(&sw->pending); spa_bt_device_update_last_bluez_action_time(device); @@ -4475,9 +4439,7 @@ struct spa_bt_monitor *monitor = adapter->monitor; DBusMessage *r; - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -4776,9 +4738,7 @@ DBusMessage *r; bool fallback = true; - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -4809,9 +4769,7 @@ struct spa_bt_monitor *monitor = adapter->monitor; DBusMessage *r; - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); - + r = steal_reply_and_unref(&pending); if (r == NULL) return; @@ -5225,12 +5183,8 @@ DBusMessage *r; DBusMessageIter it6; - spa_assert(pending == monitor->get_managed_objects_call); - monitor->get_managed_objects_call = NULL; -
View file
pipewire-0.3.76.tar.gz/spa/plugins/bluez5/dbus-helpers.h
Added
@@ -0,0 +1,32 @@ +/* Spa Bluez5 DBus helpers */ +/* SPDX-FileCopyrightText: Copyright © 2023 PipeWire authors */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_BLUEZ5_DBUS_HELPERS_H +#define SPA_BLUEZ5_DBUS_HELPERS_H + +#include <dbus/dbus.h> + +#include <spa/utils/cleanup.h> + +static inline void cancel_and_unref(DBusPendingCall **pp) +{ + DBusPendingCall *pending_call = spa_steal_ptr(*pp); + + if (pending_call) { + dbus_pending_call_cancel(pending_call); + dbus_pending_call_unref(pending_call); + } +} + +static inline DBusMessage *steal_reply_and_unref(DBusPendingCall **pp) +{ + DBusPendingCall *pending_call = spa_steal_ptr(*pp); + + DBusMessage *reply = dbus_pending_call_steal_reply(pending_call); + dbus_pending_call_unref(pending_call); + + return reply; +} + +#endif /* SPA_BLUEZ5_DBUS_HELPERS_H */
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/modemmanager.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/modemmanager.c
Changed
@@ -7,6 +7,7 @@ #include <ModemManager.h> +#include "dbus-helpers.h" #include "modemmanager.h" #define DBUS_INTERFACE_OBJECTMANAGER "org.freedesktop.DBus.ObjectManager" @@ -56,8 +57,7 @@ ret = dbus_pending_call_set_notify(pending_call, function, user_data, NULL); if (!ret) { spa_log_debug(this->log, "dbus set notify failure"); - dbus_pending_call_cancel(pending_call); - dbus_pending_call_unref(pending_call); + cancel_and_unref(&pending_call); goto out; } @@ -125,10 +125,7 @@ MMCallState state; spa_assert(call->pending == pending); - call->pending = NULL; - - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + r = steal_reply_and_unref(&call->pending); if (r == NULL) return; @@ -424,10 +421,7 @@ DBusMessageIter i, array_i; spa_assert(this->pending == pending); - this->pending = NULL; - - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + r = steal_reply_and_unref(&this->pending); if (r == NULL) return; @@ -455,13 +449,11 @@ dbus_message_unref(r); } -static void call_free(struct call *call) { +static void call_free(struct call *call) +{ spa_list_remove(&call->link); - if (call->pending != NULL) { - dbus_pending_call_cancel(call->pending); - dbus_pending_call_unref(call->pending); - } + cancel_and_unref(&call->pending); if (call->number) free(call->number); @@ -477,10 +469,7 @@ spa_list_consume(call, &this->call_list, link) call_free(call); - if (this->voice_pending != NULL) { - dbus_pending_call_cancel(this->voice_pending); - dbus_pending_call_unref(this->voice_pending); - } + cancel_and_unref(&this->voice_pending); if (this->ops->set_call_setup) this->ops->set_call_setup(CIND_CALLSETUP_NONE, this->user_data); @@ -787,10 +776,7 @@ free(data); spa_assert(call->pending == pending); - call->pending = NULL; - - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + r = steal_reply_and_unref(&call->pending); if (r == NULL) return; @@ -820,10 +806,7 @@ free(data); spa_assert(this->voice_pending == pending); - this->voice_pending = NULL; - - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + r = steal_reply_and_unref(&this->voice_pending); if (r == NULL) return; @@ -1158,10 +1141,7 @@ { struct impl *this = data; - if (this->pending != NULL) { - dbus_pending_call_cancel(this->pending); - dbus_pending_call_unref(this->pending); - } + cancel_and_unref(&this->pending); mm_clean_voice(this); mm_clean_modem3gpp(this);
View file
pipewire-0.3.74.tar.gz/spa/plugins/bluez5/upower.c -> pipewire-0.3.76.tar.gz/spa/plugins/bluez5/upower.c
Changed
@@ -5,6 +5,7 @@ #include <errno.h> #include <spa/utils/string.h> +#include "dbus-helpers.h" #include "upower.h" #define UPOWER_SERVICE "org.freedesktop.UPower" @@ -17,6 +18,8 @@ struct spa_log *log; DBusConnection *conn; + DBusPendingCall *pending_get_call; + bool filters_added; void *user_data; @@ -43,8 +46,8 @@ DBusMessage *r; DBusMessageIter i, variant_i; - r = dbus_pending_call_steal_reply(pending); - dbus_pending_call_unref(pending); + spa_assert(backend->pending_get_call == pending); + r = steal_reply_and_unref(&backend->pending_get_call); if (r == NULL) return; @@ -66,6 +69,31 @@ dbus_message_unref(r); } +static int update_battery_percentage(struct impl *this) +{ + cancel_and_unref(&this->pending_get_call); + + DBusMessage *m = dbus_message_new_method_call(UPOWER_SERVICE, + UPOWER_DISPLAY_DEVICE_OBJECT, + DBUS_INTERFACE_PROPERTIES, + "Get"); + if (!m) + return -ENOMEM; + + dbus_message_append_args(m, + DBUS_TYPE_STRING, &(const char *){ UPOWER_DEVICE_INTERFACE }, + DBUS_TYPE_STRING, &(const char *){ "Percentage" }, + DBUS_TYPE_INVALID); + dbus_message_set_auto_start(m, false); + + dbus_connection_send_with_reply(this->conn, m, &this->pending_get_call, -1); + dbus_pending_call_set_notify(this->pending_get_call, upower_get_percentage_properties_reply, this, NULL); + + dbus_message_unref(m); + + return 0; +} + static void upower_clean(struct impl *this) { this->set_battery_level(0, this->user_data); @@ -99,20 +127,8 @@ } if (new_owner && *new_owner) { - DBusPendingCall *call; - static const char* upower_device_interface = UPOWER_DEVICE_INTERFACE; - static const char* percentage_property = "Percentage"; - spa_log_debug(this->log, "UPower daemon appeared (%s)", new_owner); - - m = dbus_message_new_method_call(UPOWER_SERVICE, UPOWER_DISPLAY_DEVICE_OBJECT, DBUS_INTERFACE_PROPERTIES, "Get"); - if (m == NULL) - goto finish; - dbus_message_append_args(m, DBUS_TYPE_STRING, &upower_device_interface, - DBUS_TYPE_STRING, &percentage_property, DBUS_TYPE_INVALID); - dbus_connection_send_with_reply(this->conn, m, &call, -1); - dbus_pending_call_set_notify(call, upower_get_percentage_properties_reply, this, NULL); - dbus_message_unref(m); + update_battery_percentage(this); } } } else if (dbus_message_is_signal(m, DBUS_INTERFACE_PROPERTIES, DBUS_SIGNAL_PROPERTIES_CHANGED)) { @@ -210,26 +226,12 @@ this->set_battery_level = set_battery_level; this->user_data = user_data; - if (add_filters(this) < 0) { + if (add_filters(this) < 0) goto fail4; - } - - DBusMessage *m; - DBusPendingCall *call; - m = dbus_message_new_method_call(UPOWER_SERVICE, UPOWER_DISPLAY_DEVICE_OBJECT, DBUS_INTERFACE_PROPERTIES, "Get"); - if (m == NULL) + if (update_battery_percentage(this) < 0) goto fail4; - dbus_message_append_args(m, - DBUS_TYPE_STRING, &(const char *){ UPOWER_DEVICE_INTERFACE }, - DBUS_TYPE_STRING, &(const char *){ "Percentage" }, - DBUS_TYPE_INVALID); - dbus_message_set_auto_start(m, false); - dbus_connection_send_with_reply(this->conn, m, &call, -1); - dbus_pending_call_set_notify(call, upower_get_percentage_properties_reply, this, NULL); - dbus_message_unref(m); - return this; fail4: @@ -241,6 +243,8 @@ { struct impl *this = data; + cancel_and_unref(&this->pending_get_call); + if (this->filters_added) { dbus_connection_remove_filter(this->conn, upower_filter_cb, this); this->filters_added = false;
View file
pipewire-0.3.74.tar.gz/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-0.3.76.tar.gz/spa/plugins/libcamera/libcamera-device.cpp
Changed
@@ -4,6 +4,8 @@ /* SPDX-FileCopyrightText: Copyright © 2021 Wim Taymans <wim.taymans@gmail.com> */ /* SPDX-License-Identifier: MIT */ +#include "config.h" + #include <stddef.h> #include <sys/types.h> #include <sys/stat.h> @@ -29,6 +31,7 @@ #include <libcamera/camera.h> #include <libcamera/property_ids.h> +#include <libcamera/base/span.h> using namespace libcamera; @@ -55,6 +58,19 @@ } +static const libcamera::Span<const int64_t> cameraDevice( + const Camera *camera) +{ +#ifdef HAVE_LIBCAMERA_SYSTEM_DEVICES + const ControlList &props = camera->properties(); + + if (auto devices = props.get(properties::SystemDevices)) + return devices.value(); +#endif + + return {}; +} + static std::string cameraModel(const Camera *camera) { const ControlList &props = camera->properties(); @@ -90,7 +106,8 @@ uint32_t n_items = 0; struct spa_device_info info; struct spa_param_info params2; - char path256, model256, name256; + char path256, model256, name256, devices_str128; + struct spa_strbuf buf; info = SPA_DEVICE_INFO_INIT(); @@ -111,6 +128,19 @@ ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, model); snprintf(name, sizeof(name), "libcamera_device.%s", impl->device_id.c_str()); ADD_ITEM(SPA_KEY_DEVICE_NAME, name); + + auto device_numbers = cameraDevice(impl->camera.get()); + + if (!device_numbers.empty()) { + spa_strbuf_init(&buf, devices_str, sizeof(devices_str)); + + /* created a space separated string of all the device numbers */ + for (int64_t device_number : device_numbers) + spa_strbuf_append(&buf, "%" PRId64 " ", device_number); + + ADD_ITEM(SPA_KEY_DEVICE_DEVIDS, devices_str); + } + #undef ADD_ITEM dict = SPA_DICT_INIT(items, n_items);
View file
pipewire-0.3.74.tar.gz/spa/plugins/libcamera/meson.build -> pipewire-0.3.76.tar.gz/spa/plugins/libcamera/meson.build
Changed
@@ -7,6 +7,7 @@ libcameralib = shared_library('spa-libcamera', libcamera_sources, + include_directories : configinc , dependencies : spa_dep, libudev_dep, libcamera_dep, pthread_lib , install : true, install_dir : spa_plugindir / 'libcamera')
View file
pipewire-0.3.74.tar.gz/spa/plugins/support/dbus.c -> pipewire-0.3.76.tar.gz/spa/plugins/support/dbus.c
Changed
@@ -73,6 +73,7 @@ struct connection *conn = userdata; struct impl *impl = conn->impl; + spa_log_debug(impl->log, "impl:%p", impl); if (dbus_connection_dispatch(conn->conn) == DBUS_DISPATCH_COMPLETE) spa_loop_utils_enable_idle(impl->utils, conn->dispatch_event, false); } @@ -82,6 +83,7 @@ struct connection *c = userdata; struct impl *impl = c->impl; + spa_log_debug(impl->log, "impl:%p %d", impl, status); spa_loop_utils_enable_idle(impl->utils, c->dispatch_event, status == DBUS_DISPATCH_COMPLETE ? false : true); } @@ -268,6 +270,7 @@ struct connection *this = userdata; struct impl *impl = this->impl; + spa_log_debug(impl->log, "wakeup main impl:%p", impl); spa_loop_utils_enable_idle(impl->utils, this->dispatch_event, true); }
View file
pipewire-0.3.74.tar.gz/spa/plugins/v4l2/v4l2-device.c -> pipewire-0.3.76.tar.gz/spa/plugins/v4l2/v4l2-device.c
Changed
@@ -29,6 +29,7 @@ struct props { char device64; + char devnum32; char product_id6; char vendor_id6; int device_fd; @@ -55,11 +56,11 @@ static int emit_info(struct impl *this, bool full) { int res; - struct spa_dict_item items12; + struct spa_dict_item items13; uint32_t n_items = 0; struct spa_device_info info; struct spa_param_info params2; - char path128, version16, capabilities16, device_caps16; + char path128, version16, capabilities16, device_caps16; if ((res = spa_v4l2_open(&this->dev, this->props.device)) < 0) return res; @@ -78,6 +79,7 @@ if (this->props.vendor_id0) ADD_ITEM(SPA_KEY_DEVICE_VENDOR_ID, this->props.vendor_id); ADD_ITEM(SPA_KEY_API_V4L2_PATH, (char *)this->props.device); + ADD_ITEM(SPA_KEY_DEVICE_DEVIDS, (char *)this->props.devnum); ADD_ITEM(SPA_KEY_API_V4L2_CAP_DRIVER, (char *)this->dev.cap.driver); ADD_ITEM(SPA_KEY_API_V4L2_CAP_CARD, (char *)this->dev.cap.card); ADD_ITEM(SPA_KEY_API_V4L2_CAP_BUS_INFO, (char *)this->dev.cap.bus_info); @@ -233,6 +235,8 @@ if (info && (str = spa_dict_lookup(info, SPA_KEY_API_V4L2_PATH))) strncpy(this->props.device, str, 63); + if (info && (str = spa_dict_lookup(info, SPA_KEY_DEVICE_DEVIDS))) + strncpy(this->props.devnum, str, 31); if (info && (str = spa_dict_lookup(info, SPA_KEY_DEVICE_PRODUCT_ID))) strncpy(this->props.product_id, str, 5); if (info && (str = spa_dict_lookup(info, SPA_KEY_DEVICE_VENDOR_ID)))
View file
pipewire-0.3.74.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.76.tar.gz/spa/plugins/v4l2/v4l2-udev.c
Changed
@@ -220,8 +220,9 @@ uint32_t id = device->id; struct udev_device *dev = device->dev; const char *str; - struct spa_dict_item items20; + struct spa_dict_item items21; uint32_t n_items = 0; + char devnum32; info = SPA_DEVICE_OBJECT_INFO_INIT(); @@ -236,6 +237,8 @@ itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Video/Device"); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_API_V4L2_PATH, udev_device_get_devnode(dev)); + snprintf(devnum, sizeof(devnum), "%" PRId64, (int64_t)udev_device_get_devnum(dev)); + itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_DEVIDS, devnum); if ((str = udev_device_get_property_value(dev, "USEC_INITIALIZED")) && *str) itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PLUGGED_USEC, str);
View file
pipewire-0.3.74.tar.gz/src/modules/meson.build -> pipewire-0.3.76.tar.gz/src/modules/meson.build
Changed
@@ -38,6 +38,8 @@ 'module-rtp-session.c', 'module-rtp-source.c', 'module-rtp-sink.c', + 'module-vban-recv.c', + 'module-vban-send.c', 'module-session-manager.c', 'module-zeroconf-discover.c', 'module-roc-source.c', @@ -659,6 +661,26 @@ dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, ) +pipewire_module_vban_send = shared_library('pipewire-module-vban-send', + 'module-vban-send.c', + 'module-vban/stream.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, +) + +pipewire_module_vban_recv = shared_library('pipewire-module-vban-recv', + 'module-vban-recv.c', + 'module-vban/stream.c' , + include_directories : configinc, + install : true, + install_dir : modules_install_dir, + install_rpath: modules_install_dir, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, +) + build_module_roc = roc_dep.found() if build_module_roc pipewire_module_roc_sink = shared_library('pipewire-module-roc-sink',
View file
pipewire-0.3.74.tar.gz/src/modules/module-client-node/client-node.c -> pipewire-0.3.76.tar.gz/src/modules/module-client-node/client-node.c
Changed
@@ -1092,7 +1092,7 @@ spa_node_call_ready(&impl->callbacks, status); } else { spa_log_trace_fp(impl->log, "%p: got complete", impl); - pw_context_driver_emit_complete(node->context, node); + pw_impl_node_rt_emit_complete(node); } } }
View file
pipewire-0.3.74.tar.gz/src/modules/module-client-node/remote-node.c -> pipewire-0.3.76.tar.gz/src/modules/module-client-node/remote-node.c
Changed
@@ -45,7 +45,6 @@ struct node_data { struct pw_context *context; - struct spa_hook context_listener; struct pw_loop *data_loop; struct spa_system *data_system; @@ -61,6 +60,7 @@ struct pw_impl_node *node; struct spa_hook node_listener; + struct spa_hook node_rt_listener; unsigned int do_free:1; unsigned int have_transport:1; unsigned int allow_mlock:1; @@ -889,8 +889,9 @@ { pw_log_debug("port %p: mix clear %d.%d", mix->port, mix->port->port_id, mix->mix.id); - spa_node_port_set_io(mix->port->mix, mix->mix.port.direction, - mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0); + if (mix->mix.id != SPA_ID_INVALID) + spa_node_port_set_io(mix->port->mix, mix->mix.port.direction, + mix->mix.port.port_id, SPA_IO_Buffers, NULL, 0); spa_list_remove(&mix->link); @@ -1129,11 +1130,10 @@ spa_hook_remove(&data->proxy_client_node_listener); spa_hook_remove(&data->client_node_listener); - pw_context_driver_remove_listener(data->context, - &data->context_listener); - if (data->node) { spa_hook_remove(&data->node_listener); + pw_impl_node_remove_rt_listener(data->node, + &data->node_rt_listener); pw_impl_node_set_state(data->node, PW_NODE_STATE_SUSPENDED); clean_node(data); @@ -1168,12 +1168,13 @@ .bound_props = client_node_bound_props, }; -static void context_complete(void *data, struct pw_impl_node *node) +static void node_rt_complete(void *data) { struct node_data *d = data; + struct pw_impl_node *node = d->node; struct spa_system *data_system = d->data_system; - if (node != d->node || !node->driving || + if (!node->driving || !SPA_FLAG_IS_SET(node->rt.target.activation->flags, PW_NODE_ACTIVATION_FLAG_PROFILER)) return; @@ -1181,9 +1182,9 @@ pw_log_warn("node %p: write failed %m", node); } -static const struct pw_context_driver_events context_events = { - PW_VERSION_CONTEXT_DRIVER_EVENTS, - .complete = context_complete, +static const struct pw_impl_node_rt_events node_rt_events = { + PW_VERSION_IMPL_NODE_RT_EVENTS, + .complete = node_rt_complete, }; static struct pw_proxy *node_export(struct pw_core *core, void *object, bool do_free, @@ -1238,14 +1239,13 @@ &proxy_client_node_events, data); pw_impl_node_add_listener(node, &data->node_listener, &node_events, data); + pw_impl_node_add_rt_listener(node, &data->node_rt_listener, + &node_rt_events, data); pw_client_node_add_listener(data->client_node, &data->client_node_listener, &client_node_events, data); - pw_context_driver_add_listener(data->context, - &data->context_listener, - &context_events, data); do_node_init(data);
View file
pipewire-0.3.74.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.76.tar.gz/src/modules/module-profiler.c
Changed
@@ -52,10 +52,8 @@ #define PW_LOG_TOPIC_DEFAULT mod_topic #define TMP_BUFFER (16 * 1024) -#define MAX_BUFFER (8 * 1024 * 1024) -#define MIN_FLUSH (16 * 1024) -#define DEFAULT_IDLE 5 -#define DEFAULT_INTERVAL 1 +#define DATA_BUFFER (32 * 1024) +#define FLUSH_BUFFER (8 * 1024 * 1024) int pw_protocol_native_ext_profiler_init(struct pw_context *context); @@ -71,6 +69,21 @@ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; +struct node { + struct spa_list link; + struct impl *impl; + + struct pw_impl_node *node; + struct spa_hook node_rt_listener; + + int64_t count; + struct spa_ringbuffer buffer; + uint8_t tmpTMP_BUFFER; + uint8_t dataDATA_BUFFER; + + unsigned enabled:1; +}; + struct impl { struct pw_context *context; struct pw_properties *properties; @@ -84,18 +97,13 @@ struct pw_global *global; struct spa_hook global_listener; - int64_t count; + struct spa_list node_list; + uint32_t busy; - uint32_t empty; - struct spa_source *flush_timeout; - unsigned int flushing:1; + struct spa_source *flush_event; unsigned int listening:1; - struct spa_ringbuffer buffer; - uint8_t tmpTMP_BUFFER; - uint8_t dataMAX_BUFFER; - - uint8_t flushMAX_BUFFER + sizeof(struct spa_pod_struct); + uint8_t flushFLUSH_BUFFER + sizeof(struct spa_pod_struct); }; struct resource_data { @@ -105,69 +113,45 @@ struct spa_hook resource_listener; }; -static void start_flush(struct impl *impl) -{ - struct timespec value, interval; - - value.tv_sec = 0; - value.tv_nsec = 1; - interval.tv_sec = DEFAULT_INTERVAL; - interval.tv_nsec = 0; - pw_loop_update_timer(impl->main_loop, - impl->flush_timeout, &value, &interval, false); - impl->flushing = true; -} - -static void stop_flush(struct impl *impl) -{ - struct timespec value, interval; - - if (!impl->flushing) - return; - - value.tv_sec = 0; - value.tv_nsec = 0; - interval.tv_sec = 0; - interval.tv_nsec = 0; - pw_loop_update_timer(impl->main_loop, - impl->flush_timeout, &value, &interval, false); - impl->flushing = false; -} - -static void flush_timeout(void *data, uint64_t expirations) +static void do_flush_event(void *data, uint64_t count) { struct impl *impl = data; - int32_t avail; - uint32_t idx; - struct spa_pod_struct *p; struct pw_resource *resource; + struct node *n; + uint32_t total = 0; + struct spa_pod_struct *p; - avail = spa_ringbuffer_get_read_index(&impl->buffer, &idx); + p = (struct spa_pod_struct *)impl->flush; - pw_log_trace("%p avail %d", impl, avail); + spa_list_for_each(n, &impl->node_list, link) { + int32_t avail; + uint32_t idx; - if (avail <= 0) { - if (++impl->empty == DEFAULT_IDLE) - stop_flush(impl); - return; - } - impl->empty = 0; + avail = spa_ringbuffer_get_read_index(&n->buffer, &idx); - p = (struct spa_pod_struct *)impl->flush; - *p = SPA_POD_INIT_Struct(avail); + pw_log_trace("%p avail %d", impl, avail); + + if (avail > 0) { + spa_ringbuffer_read_data(&n->buffer, n->data, DATA_BUFFER, + idx % DATA_BUFFER, + SPA_PTROFF(p, sizeof(struct spa_pod_struct) + total, void), + avail); + spa_ringbuffer_read_update(&n->buffer, idx + avail); + total += avail; + } + } - spa_ringbuffer_read_data(&impl->buffer, impl->data, MAX_BUFFER, - idx % MAX_BUFFER, - SPA_PTROFF(p, sizeof(struct spa_pod_struct), void), avail); - spa_ringbuffer_read_update(&impl->buffer, idx + avail); + *p = SPA_POD_INIT_Struct(total); spa_list_for_each(resource, &impl->global->resource_list, link) pw_profiler_resource_profile(resource, &p->pod); } -static void context_do_profile(void *data, struct pw_impl_node *node) +static void context_do_profile(void *data) { - struct impl *impl = data; + struct node *n = data; + struct pw_impl_node *node = n->node; + struct impl *impl = n->impl; struct spa_pod_builder b; struct spa_pod_frame f2; uint32_t id = node->info.id; @@ -180,13 +164,13 @@ if (SPA_FLAG_IS_SET(pos->clock.flags, SPA_IO_CLOCK_FLAG_FREEWHEEL)) return; - spa_pod_builder_init(&b, impl->tmp, sizeof(impl->tmp)); + spa_pod_builder_init(&b, n->tmp, sizeof(n->tmp)); spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_Profiler, 0); spa_pod_builder_prop(&b, SPA_PROFILER_info, 0); spa_pod_builder_add_struct(&b, - SPA_POD_Long(impl->count), + SPA_POD_Long(n->count), SPA_POD_Float(a->cpu_load0), SPA_POD_Float(a->cpu_load1), SPA_POD_Float(a->cpu_load2), @@ -253,42 +237,107 @@ } spa_pod_builder_pop(&b, &f0); - if (b.state.offset > sizeof(impl->tmp)) + if (b.state.offset > sizeof(n->tmp)) goto done; - filled = spa_ringbuffer_get_write_index(&impl->buffer, &idx); - if (filled < 0 || filled > MAX_BUFFER) { + filled = spa_ringbuffer_get_write_index(&n->buffer, &idx); + if (filled < 0 || filled > DATA_BUFFER) { pw_log_warn("%p: queue xrun %d", impl, filled); goto done; } - avail = MAX_BUFFER - filled; + avail = DATA_BUFFER - filled; if (avail < b.state.offset) { pw_log_warn("%p: queue full %d < %d", impl, avail, b.state.offset); goto done; } - spa_ringbuffer_write_data(&impl->buffer, - impl->data, MAX_BUFFER, - idx % MAX_BUFFER, + spa_ringbuffer_write_data(&n->buffer, + n->data, DATA_BUFFER, + idx % DATA_BUFFER, b.data, b.state.offset); - spa_ringbuffer_write_update(&impl->buffer, idx + b.state.offset); + spa_ringbuffer_write_update(&n->buffer, idx + b.state.offset);
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse.c -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse.c
Changed
@@ -281,6 +281,9 @@ * * `remove-capture-dont-move` Removes the DONT_MOVE flag on capture streams. Some applications * set this flag so that the stream can't be moved anymore with tools such as * pavucontrol. + * * `block-source-volume` blocks the client from updating any source volumes. This can be used + * to disable things like automatic gain control. + * * `block-sink-volume` blocks the client from updating any sink volumes. * * ### update-props *
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse/manager.c
Changed
@@ -974,6 +974,16 @@ pw_properties_parse_bool(str); } +bool pw_manager_object_is_network(struct pw_manager_object *o) +{ + const char *str; + struct pw_node_info *info; + return spa_streq(o->type, PW_TYPE_INTERFACE_Node) && + (info = o->info) != NULL && info->props != NULL && + (str = spa_dict_lookup(info->props, PW_KEY_NODE_NETWORK)) != NULL && + pw_properties_parse_bool(str); +} + bool pw_manager_object_is_source_or_monitor(struct pw_manager_object *o) { return pw_manager_object_is_source(o) || pw_manager_object_is_monitor(o);
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse/manager.h
Changed
@@ -112,6 +112,7 @@ bool pw_manager_object_is_source(struct pw_manager_object *o); bool pw_manager_object_is_monitor(struct pw_manager_object *o); bool pw_manager_object_is_virtual(struct pw_manager_object *o); +bool pw_manager_object_is_network(struct pw_manager_object *o); bool pw_manager_object_is_source_or_monitor(struct pw_manager_object *o); bool pw_manager_object_is_sink_input(struct pw_manager_object *o); bool pw_manager_object_is_source_output(struct pw_manager_object *o);
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse/modules/module-switch-on-connect.c
Changed
@@ -107,7 +107,7 @@ return; } - if (d->ignore_virtual && spa_dict_lookup(info->props, PW_KEY_DEVICE_API) == NULL) { + if (d->ignore_virtual && pw_manager_object_is_virtual(o)) { pw_log_debug("not switching to virtual device"); return; }
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c
Changed
@@ -215,7 +215,7 @@ collect_device_info(o, card, &dev_info, false, &impl->defs); - if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)) != NULL) { + if (!pw_manager_object_is_virtual(o)) { if (is_sink) flags |= SINK_HARDWARE; else if (is_source) @@ -574,7 +574,6 @@ { struct service *s; struct pw_node_info *info; - const char *str; if (!pw_manager_object_is_sink(o) && !pw_manager_object_is_source(o)) return; @@ -583,8 +582,7 @@ if (info == NULL || info->props == NULL) return; - if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_NETWORK)) != NULL && - spa_atob(str)) + if (pw_manager_object_is_network(o)) return; s = create_service(d, o);
View file
pipewire-0.3.74.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.76.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -3715,9 +3715,9 @@ } flags = SINK_LATENCY | SINK_DYNAMIC_LATENCY | SINK_DECIBEL_VOLUME; - if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)) != NULL) + if (!pw_manager_object_is_virtual(o)) flags |= SINK_HARDWARE; - if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_NETWORK)) != NULL) + if (pw_manager_object_is_network(o)) flags |= SINK_NETWORK; if (SPA_FLAG_IS_SET(dev_info.volume_info.flags, VOLUME_HW_VOLUME)) flags |= SINK_HW_VOLUME_CTRL; @@ -3927,9 +3927,9 @@ } flags = SOURCE_LATENCY | SOURCE_DYNAMIC_LATENCY | SOURCE_DECIBEL_VOLUME; - if ((str = spa_dict_lookup(info->props, PW_KEY_DEVICE_API)) != NULL) + if (!pw_manager_object_is_virtual(o)) flags |= SOURCE_HARDWARE; - if ((str = spa_dict_lookup(info->props, PW_KEY_NODE_NETWORK)) != NULL) + if (pw_manager_object_is_network(o)) flags |= SOURCE_NETWORK; if (SPA_FLAG_IS_SET(dev_info.volume_info.flags, VOLUME_HW_VOLUME)) flags |= SOURCE_HW_VOLUME_CTRL;
View file
pipewire-0.3.74.tar.gz/src/modules/module-raop-discover.c -> pipewire-0.3.76.tar.gz/src/modules/module-raop-discover.c
Changed
@@ -229,12 +229,12 @@ value = "tcp"; pw_properties_set(props, "raop.transport", value); } else if (spa_streq(key, "et")) { - /* Supported encryption types: + /* RAOP encryption types: * 0 = none, * 1 = RSA, - * 2 = FairPlay, - * 3 = MFiSAP, - * 4 = FairPlay SAPv2.5. */ + * 3 = FairPlay, + * 4 = MFiSAP (/auth-setup), + * 5 = FairPlay SAPv2.5 */ if (str_in_list(value, ",", "1")) value = "RSA"; else if (str_in_list(value, ",", "4")) @@ -254,7 +254,7 @@ value = "ALAC"; else if (str_in_list(value, ",", "2")) value = "AAC"; - else if (str_in_list(value, ",", "2")) + else if (str_in_list(value, ",", "3")) value = "AAC-ELD"; else value = "unknown";
View file
pipewire-0.3.74.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.76.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -124,7 +124,7 @@ #define FRAMES_PER_UDP_PACKET 352 #define RAOP_LATENCY_MIN 11025u -#define DEFAULT_LATENCY_MS "1000" +#define DEFAULT_LATENCY_MS "1500" #define DEFAULT_TCP_AUDIO_PORT 6000 #define DEFAULT_UDP_AUDIO_PORT 6000 @@ -318,7 +318,7 @@ pkt0 |= htonl(0x10000000); pkt1 = htonl(rtptime - latency); transmitted = ntp_now(); - pkt2 = htonl((transmitted >> 32) & 0x0000ffff); + pkt2 = htonl(transmitted >> 32); pkt3 = htonl(transmitted & 0xffffffff); pkt4 = htonl(rtptime); @@ -827,7 +827,7 @@ static int rtsp_send(struct impl *impl, const char *method, const char *content_type, const char *content, - int (*reply) (void *data, int status, const struct spa_dict *headers)) + int (*reply) (void *data, int status, const struct spa_dict *headers, const struct pw_array *content)) { int res; @@ -838,9 +838,9 @@ return res; } -static int rtsp_flush_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_log_reply_status(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { - pw_log_info("reply %d", status); + pw_log_info("reply status: %d", status); return 0; } @@ -857,7 +857,7 @@ impl->recording = false; - res = rtsp_send(impl, "FLUSH", NULL, NULL, rtsp_flush_reply); + res = rtsp_send(impl, "FLUSH", NULL, NULL, rtsp_log_reply_status); pw_properties_set(impl->headers, "Range", NULL); pw_properties_set(impl->headers, "RTP-Info", NULL); @@ -873,10 +873,10 @@ char header128, volstr64; snprintf(header, sizeof(header), "volume: %s\r\n", spa_dtoa(volstr, sizeof(volstr), impl->volume)); - return rtsp_send(impl, "SET_PARAMETER", "text/parameters", header, NULL); + return rtsp_send(impl, "SET_PARAMETER", "text/parameters", header, rtsp_log_reply_status); } -static int rtsp_record_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_record_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; const char *str; @@ -887,7 +887,7 @@ struct spa_latency_info latency; char progress128; - pw_log_info("reply %d", status); + pw_log_info("record status: %d", status); if ((str = spa_dict_lookup(headers, "Audio-Latency")) != NULL) { uint32_t l; @@ -913,7 +913,7 @@ rtsp_send_volume(impl); snprintf(progress, sizeof(progress), "progress: %s/%s/%s\r\n", "0", "0", "0"); - return rtsp_send(impl, "SET_PARAMETER", "text/parameters", progress, NULL); + return rtsp_send(impl, "SET_PARAMETER", "text/parameters", progress, rtsp_log_reply_status); } static int rtsp_do_record(struct impl *impl) @@ -966,7 +966,7 @@ pw_loop_update_io(impl->loop, impl->server_source, 0); } -static int rtsp_setup_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_setup_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; const char *str, *state = NULL, *s; @@ -975,7 +975,7 @@ uint16_t control_port, timing_port; int res; - pw_log_info("reply %d", status); + pw_log_info("setup status: %d", status); if ((str = spa_dict_lookup(headers, "Session")) == NULL) { pw_log_error("missing Session header"); @@ -1105,11 +1105,11 @@ return -EIO; } -static int rtsp_announce_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_announce_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; - pw_log_info("reply %d", status); + pw_log_info("announce status: %d", status); pw_properties_set(impl->headers, "Apple-Challenge", NULL); @@ -1294,11 +1294,11 @@ return rtsp_send(impl, "ANNOUNCE", "application/sdp", sdp, rtsp_announce_reply); } -static int rtsp_auth_setup_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_auth_setup_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; - pw_log_info("reply %d", status); + pw_log_info("auth-setup status: %d", status); return rtsp_do_announce(impl); } @@ -1315,12 +1315,12 @@ rtsp_auth_setup_reply, impl); } -static int rtsp_auth_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_auth_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; int res = 0; - pw_log_info("auth %d", status); + pw_log_info("auth status: %d", status); switch (status) { case 200: @@ -1385,12 +1385,12 @@ return rtsp_send(impl, "OPTIONS", NULL, NULL, rtsp_auth_reply); } -static int rtsp_options_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_options_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; int res = 0; - pw_log_info("options %d", status); + pw_log_info("options status: %d", status); switch (status) { case 401: @@ -1547,12 +1547,12 @@ return pw_rtsp_client_connect(impl->rtsp, hostname, atoi(port), impl->session_id); } -static int rtsp_teardown_reply(void *data, int status, const struct spa_dict *headers) +static int rtsp_teardown_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; const char *str; - pw_log_info("reply"); + pw_log_info("teardown status: %d", status); connection_cleanup(impl);
View file
pipewire-0.3.74.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.76.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
@@ -25,7 +25,7 @@ size_t len; size_t offset; uint32_t cseq; - int (*reply) (void *user_data, int status, const struct spa_dict *headers); + int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content); void *user_data; }; @@ -60,6 +60,7 @@ char line_buf1024; size_t line_pos; struct pw_properties *headers; + struct pw_array content; size_t content_length; uint32_t cseq; @@ -89,6 +90,7 @@ spa_list_init(&client->pending); spa_hook_list_init(&client->listener_list); client->headers = pw_properties_new(NULL, NULL); + pw_array_init(&client->content, 4096); client->recv_state = CLIENT_RECV_NONE; pw_log_info("new client %p", client); @@ -105,6 +107,7 @@ pw_properties_free(client->headers); pw_properties_free(client->props); spa_hook_list_clean(&client->listener_list); + pw_array_clear(&client->content); free(client); } @@ -277,7 +280,7 @@ msg = find_pending(client, cseq); if (msg) { - res = msg->reply(msg->user_data, client->status, &client->headers->dict); + res = msg->reply(msg->user_data, client->status, &client->headers->dict, &client->content); spa_list_remove(&msg->link); free(msg); @@ -288,6 +291,8 @@ else { pw_rtsp_client_emit_message(client, client->status, &client->headers->dict); } + + pw_array_reset(&client->content); } static void process_received_message(struct pw_rtsp_client *client) @@ -328,7 +333,7 @@ static int process_content(struct pw_rtsp_client *client) { - char buf1024; + uint8_t buf4096; while (client->content_length > 0) { const size_t max_recv = SPA_MIN(sizeof(buf), client->content_length); @@ -345,6 +350,9 @@ return res; } + void *p = pw_array_add(&client->content, res); + memcpy(p, buf, res); + spa_assert((size_t) res <= client->content_length); client->content_length -= res; } @@ -556,7 +564,7 @@ int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url, const char *cmd, const struct spa_dict *headers, const char *content_type, const void *content, size_t content_length, - int (*reply) (void *user_data, int status, const struct spa_dict *headers), + int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content), void *user_data) { FILE *f; @@ -610,7 +618,7 @@ int pw_rtsp_client_send(struct pw_rtsp_client *client, const char *cmd, const struct spa_dict *headers, const char *content_type, const char *content, - int (*reply) (void *user_data, int status, const struct spa_dict *headers), + int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content), void *user_data) { const size_t content_length = content ? strlen(content) : 0;
View file
pipewire-0.3.74.tar.gz/src/modules/module-raop/rtsp-client.h -> pipewire-0.3.76.tar.gz/src/modules/module-raop/rtsp-client.h
Changed
@@ -55,13 +55,13 @@ int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url, const char *cmd, const struct spa_dict *headers, const char *content_type, const void *content, size_t content_length, - int (*reply) (void *user_data, int status, const struct spa_dict *headers), + int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content), void *user_data); int pw_rtsp_client_send(struct pw_rtsp_client *client, const char *cmd, const struct spa_dict *headers, const char *content_type, const char *content, - int (*reply) (void *user_data, int status, const struct spa_dict *headers), + int (*reply) (void *user_data, int status, const struct spa_dict *headers, const struct pw_array *content), void *user_data);
View file
pipewire-0.3.74.tar.gz/src/modules/module-rt.c -> pipewire-0.3.76.tar.gz/src/modules/module-rt.c
Changed
@@ -173,6 +173,8 @@ struct spa_thread_utils thread_utils; + pid_t main_pid; + struct rlimit rl; int nice_level; int rt_prio; rlim_t rt_time_soft; @@ -191,6 +193,10 @@ const char* object_path; const char* interface; struct pw_rtkit_bus *rtkit_bus; + struct pw_thread_loop *thread_loop; + int max_rtprio; + int min_nice_level; + rlim_t rttime_max; /* These are only for the RTKit implementation to fill in the `thread` * struct. Since there's barely any overhead here we'll do this @@ -383,41 +389,12 @@ return ret; } -static int pw_rtkit_get_max_realtime_priority(struct impl *impl) -{ - long long retval; - int err; - - err = rtkit_get_int_property(impl, "MaxRealtimePriority", &retval); - return err < 0 ? err : retval; -} - -static int pw_rtkit_get_min_nice_level(struct impl *impl, int *min_nice_level) -{ - long long retval; - int err; - - err = rtkit_get_int_property(impl, "MinNiceLevel", &retval); - if (err >= 0) - *min_nice_level = retval; - return err; -} - -static long long pw_rtkit_get_rttime_usec_max(struct impl *impl) -{ - long long retval; - int err; - - err = rtkit_get_int_property(impl, "RTTimeUSecMax", &retval); - return err < 0 ? err : retval; -} - static int pw_rtkit_make_realtime(struct impl *impl, pid_t thread, int priority) { - DBusMessage *m = NULL, *r = NULL; + DBusMessage *m = NULL; dbus_uint64_t pid; dbus_uint64_t u64; - dbus_uint32_t u32; + dbus_uint32_t u32, serial; DBusError error; int ret; struct pw_rtkit_bus *connection = impl->rtkit_bus; @@ -446,17 +423,10 @@ goto finish; } - if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) { + if (!dbus_connection_send(connection->bus, m, &serial)) { ret = translate_error(error.name); goto finish; } - - - if (dbus_set_error_from_message(&error, r)) { - ret = translate_error(error.name); - goto finish; - } - ret = 0; finish: @@ -464,26 +434,20 @@ if (m) dbus_message_unref(m); - if (r) - dbus_message_unref(r); - - dbus_error_free(&error); - return ret; } + static int pw_rtkit_make_high_priority(struct impl *impl, pid_t thread, int nice_level) { - DBusMessage *m = NULL, *r = NULL; + DBusMessage *m = NULL; dbus_uint64_t pid; dbus_uint64_t u64; dbus_int32_t s32; - DBusError error; + dbus_uint32_t serial; int ret; struct pw_rtkit_bus *connection = impl->rtkit_bus; - dbus_error_init(&error); - if (thread == 0) thread = _gettid(); @@ -505,20 +469,10 @@ ret = -ENOMEM; goto finish; } - - - - if (!(r = dbus_connection_send_with_reply_and_block(connection->bus, m, -1, &error))) { - ret = translate_error(error.name); - goto finish; - } - - - if (dbus_set_error_from_message(&error, r)) { - ret = translate_error(error.name); + if (!dbus_connection_send(connection->bus, m, &serial)) { + ret = -EIO; goto finish; } - ret = 0; finish: @@ -526,11 +480,6 @@ if (m) dbus_message_unref(m); - if (r) - dbus_message_unref(r); - - dbus_error_free(&error); - return ret; } #endif /* HAVE_DBUS */ @@ -542,6 +491,8 @@ spa_hook_remove(&impl->module_listener); #ifdef HAVE_DBUS + if (impl->thread_loop) + pw_thread_loop_destroy(impl->thread_loop); if (impl->rtkit_bus) pw_rtkit_bus_free(impl->rtkit_bus); #endif @@ -637,9 +588,9 @@ return false; } -static int sched_set_nice(int nice_level) +static int sched_set_nice(pid_t pid, int nice_level) { - if (setpriority(PRIO_PROCESS, _gettid(), nice_level) == 0) + if (setpriority(PRIO_PROCESS, pid, nice_level) == 0) return 0; else return -errno; @@ -651,30 +602,27 @@ #ifdef HAVE_DBUS if (impl->use_rtkit) { - int min_nice = nice_level; - pw_rtkit_get_min_nice_level(impl, &min_nice); - if (nice_level < min_nice) { + if (nice_level < impl->min_nice_level) { pw_log_info("clamped nice level %d to %d", - nice_level, min_nice); - nice_level = min_nice; + nice_level, impl->min_nice_level); + nice_level = impl->min_nice_level; } - res = pw_rtkit_make_high_priority(impl, 0, nice_level); + res = pw_rtkit_make_high_priority(impl, impl->main_pid, nice_level); } - else if (impl->rlimits_enabled) - res = sched_set_nice(nice_level); else - res = -ENOTSUP; -#else +#endif if (impl->rlimits_enabled) - res = sched_set_nice(nice_level); + res = sched_set_nice(impl->main_pid, nice_level); else res = -ENOTSUP; -#endif if (res < 0) {
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban
Added
+(directory)
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban-recv.c
Added
@@ -0,0 +1,572 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#include "config.h" + +#include <limits.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <net/if.h> +#include <ctype.h> + +#include <spa/utils/hook.h> +#include <spa/utils/result.h> +#include <spa/utils/ringbuffer.h> +#include <spa/utils/defs.h> +#include <spa/utils/dll.h> +#include <spa/utils/json.h> +#include <spa/param/audio/format-utils.h> +#include <spa/control/control.h> +#include <spa/debug/types.h> +#include <spa/debug/mem.h> + +#include <pipewire/pipewire.h> +#include <pipewire/impl.h> + +#include <module-vban/stream.h> + +#ifdef __FreeBSD__ +#define ifr_ifindex ifr_index +#endif + +/** \page page_module_vban_recv PipeWire Module: VBAN receiver + * + * The `vban-recv` module creates a PipeWire source that receives audio + * and midi VBAN(https://vb-audio.com) packets. + * + * ## Module Options + * + * Options specific to the behavior of this module + * + * - `local.ifname = <str>`: interface name to use + * - `source.ip = <str>`: the source ip address, default 127.0.0.1 + * - `source.port = <int>`: the source port + * - `node.always-process = <bool>`: true to receive even when not running + * - `sess.latency.msec = <str>`: target network latency in milliseconds, default 100 + * - `sess.ignore-ssrc = <bool>`: ignore SSRC, default false + * - `sess.media = <string>`: the media type audio|midi|opus, default audio + * - `stream.props = {}`: properties to be passed to the stream + * + * ## General options + * + * Options with well-known behavior: + * + * - \ref PW_KEY_REMOTE_NAME + * - \ref PW_KEY_AUDIO_FORMAT + * - \ref PW_KEY_AUDIO_RATE + * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_POSITION + * - \ref PW_KEY_MEDIA_NAME + * - \ref PW_KEY_MEDIA_CLASS + * - \ref PW_KEY_NODE_NAME + * - \ref PW_KEY_NODE_DESCRIPTION + * - \ref PW_KEY_NODE_GROUP + * - \ref PW_KEY_NODE_LATENCY + * - \ref PW_KEY_NODE_VIRTUAL + * + * ## Example configuration + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-vban-recv + * args = { + * #local.ifname = eth0 + * #source.ip = 127.0.0.1 + * #source.port = 6980 + * sess.latency.msec = 100 + * #sess.ignore-ssrc = false + * #node.always-process = false + * #sess.media = "audio" + * #audio.format = "S16LE" + * #audio.rate = 44100 + * #audio.channels = 2 + * #audio.position = FL FR + * stream.props = { + * #media.class = "Audio/Source" + * node.name = "vban-receiver" + * } + * } + * } + * + *\endcode + * + * \since 0.3.76 + */ + +#define NAME "vban-recv" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +#define DEFAULT_CLEANUP_SEC 60 +#define DEFAULT_SOURCE_IP "127.0.0.1" +#define DEFAULT_SOURCE_PORT 6980 + +#define USAGE "( local.ifname=<local interface name to use> ) " \ + "( source.ip=<source IP address, default:"DEFAULT_SOURCE_IP"> ) " \ + "( source.port=<int, source port, default:"SPA_STRINGIFY(DEFAULT_SOURCE_PORT)"> " \ + "( sess.latency.msec=<target network latency, default "SPA_STRINGIFY(DEFAULT_SESS_LATENCY)"> ) "\ + "( sess.media=<string, the media type audio|midi, default audio> ) " \ + "( audio.format=<format, default:"DEFAULT_FORMAT"> ) " \ + "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ + "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \ + "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ + "( stream.props= { key=value ... } ) " + +static const struct spa_dict_item module_info = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "VBAN Receiver" }, + { PW_KEY_MODULE_USAGE, USAGE }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +struct impl { + struct pw_impl_module *module; + struct spa_hook module_listener; + struct pw_properties *props; + struct pw_context *context; + + struct pw_loop *loop; + struct pw_loop *data_loop; + + struct pw_core *core; + struct spa_hook core_listener; + struct spa_hook core_proxy_listener; + unsigned int do_disconnect:1; + + char *ifname; + bool always_process; + uint32_t cleanup_interval; + + struct spa_source *timer; + + struct pw_properties *stream_props; + struct vban_stream *stream; + + uint16_t src_port; + struct sockaddr_storage src_addr; + socklen_t src_len; + struct spa_source *source; + + unsigned receiving:1; +}; + +static void +on_vban_io(void *data, int fd, uint32_t mask) +{ + struct impl *impl = data; + ssize_t len; + uint8_t buffer2048; + + if (mask & SPA_IO_IN) { + if ((len = recv(fd, buffer, sizeof(buffer), 0)) < 0) + goto receive_error; + + if (len < 12) + goto short_packet; + + if (SPA_LIKELY(impl->stream)) + vban_stream_receive_packet(impl->stream, buffer, len); + + impl->receiving = true; + } + return; + +receive_error: + pw_log_warn("recv error: %m"); + return; +short_packet: + pw_log_warn("short packet received"); + return; +} + +static int parse_address(const char *address, uint16_t port, + struct sockaddr_storage *addr, socklen_t *len) +{ + struct sockaddr_in *sa4 = (struct sockaddr_in*)addr; + struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)addr; + + if (inet_pton(AF_INET, address, &sa4->sin_addr) > 0) { + sa4->sin_family = AF_INET; + sa4->sin_port = htons(port); + *len = sizeof(*sa4); + } else if (inet_pton(AF_INET6, address, &sa6->sin6_addr) > 0) { + sa6->sin6_family = AF_INET6;
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban-send.c
Added
@@ -0,0 +1,534 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#include "config.h" + +#include <limits.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <netinet/ip.h> +#include <netinet/in.h> +#include <net/if.h> +#include <ctype.h> + +#include <spa/utils/hook.h> +#include <spa/utils/result.h> +#include <spa/utils/ringbuffer.h> +#include <spa/utils/json.h> +#include <spa/param/audio/format-utils.h> +#include <spa/debug/types.h> + +#include <pipewire/pipewire.h> +#include <pipewire/impl.h> + +#include <module-vban/stream.h> + +#ifndef IPTOS_DSCP +#define IPTOS_DSCP_MASK 0xfc +#define IPTOS_DSCP(x) ((x) & IPTOS_DSCP_MASK) +#endif + +/** \page page_module_vban_send PipeWire Module: VBAN sender + * + * The `vban-send` module creates a PipeWire sink that sends + * audio and midi VBAN(https://vb-audio.com) packets. + * + * ## Module Options + * + * Options specific to the behavior of this module + * + * - `source.ip =<str>`: source IP address, default "0.0.0.0" + * - `destination.ip =<str>`: destination IP address, default "127.0.0.1" + * - `destination.port =<int>`: destination port, default 6980 + * - `local.ifname = <str>`: interface name to use + * - `net.mtu = <int>`: MTU to use, default 1500 + * - `net.ttl = <int>`: TTL to use, default 1 + * - `net.loop = <bool>`: loopback multicast, default false + * - `sess.min-ptime = <int>`: minimum packet time in milliseconds, default 2 + * - `sess.max-ptime = <int>`: maximum packet time in milliseconds, default 20 + * - `sess.name = <str>`: a session name + * - `sess.media = <string>`: the media type audio|midi, default audio + * - `stream.props = {}`: properties to be passed to the stream + * + * ## General options + * + * Options with well-known behavior: + * + * - \ref PW_KEY_REMOTE_NAME + * - \ref PW_KEY_AUDIO_FORMAT + * - \ref PW_KEY_AUDIO_RATE + * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_POSITION + * - \ref PW_KEY_NODE_NAME + * - \ref PW_KEY_NODE_DESCRIPTION + * - \ref PW_KEY_MEDIA_NAME + * - \ref PW_KEY_NODE_GROUP + * - \ref PW_KEY_NODE_LATENCY + * - \ref PW_KEY_NODE_VIRTUAL + * - \ref PW_KEY_MEDIA_CLASS + * + * ## Example configuration + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-vban-send + * args = { + * #local.ifname = "eth0" + * #source.ip = "0.0.0.0" + * #destination.ip = "127.0.0.1" + * #destination.port = 6980 + * #net.mtu = 1500 + * #net.ttl = 1 + * #net.loop = false + * #sess.min-ptime = 2 + * #sess.max-ptime = 20 + * #sess.name = "PipeWire VBAN stream" + * #sess.media = "audio" + * #audio.format = "S16LE" + * #audio.rate = 44100 + * #audio.channels = 2 + * #audio.position = FL FR + * stream.props = { + * node.name = "vban-sender" + * } + * } + *} + * + *\endcode + * + * \since 0.3.76 + */ + +#define NAME "vban-send" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +#define DEFAULT_PORT 6980 +#define DEFAULT_SOURCE_IP "0.0.0.0" +#define DEFAULT_DESTINATION_IP "127.0.0.1" +#define DEFAULT_TTL 1 +#define DEFAULT_LOOP false +#define DEFAULT_DSCP 34 /* Default to AES-67 AF41 (34) */ + +#define USAGE "( source.ip=<source IP address, default:"DEFAULT_SOURCE_IP"> ) " \ + "( destination.ip=<destination IP address, default:"DEFAULT_DESTINATION_IP"> ) " \ + "( destination.port=<int, default:"SPA_STRINGIFY(DEFAULT_PORT)"> ) " \ + "( local.ifname=<local interface name to use> ) " \ + "( net.mtu=<desired MTU, default:"SPA_STRINGIFY(DEFAULT_MTU)"> ) " \ + "( net.ttl=<desired TTL, default:"SPA_STRINGIFY(DEFAULT_TTL)"> ) " \ + "( net.loop=<desired loopback, default:"SPA_STRINGIFY(DEFAULT_LOOP)"> ) " \ + "( net.dscp=<desired DSCP, default:"SPA_STRINGIFY(DEFAULT_DSCP)"> ) " \ + "( sess.name=<a name for the session> ) " \ + "( sess.min-ptime=<minimum packet time in milliseconds, default:2> ) " \ + "( sess.max-ptime=<maximum packet time in milliseconds, default:20> ) " \ + "( sess.media=<string, the media type audio|midi, default audio> ) " \ + "( audio.format=<format, default:"DEFAULT_FORMAT"> ) " \ + "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ + "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \ + "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ + "( stream.props= { key=value ... } ) " + +static const struct spa_dict_item module_info = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "VBAN Sender" }, + { PW_KEY_MODULE_USAGE, USAGE }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +struct impl { + struct pw_context *context; + + struct pw_impl_module *module; + struct spa_hook module_listener; + struct pw_properties *props; + + struct pw_loop *loop; + + struct pw_core *core; + struct spa_hook core_listener; + struct spa_hook core_proxy_listener; + + struct pw_properties *stream_props; + struct vban_stream *stream; + + unsigned int do_disconnect:1; + + char *ifname; + char *session_name; + uint32_t ttl; + bool mcast_loop; + uint32_t dscp; + + struct sockaddr_storage src_addr; + socklen_t src_len; + + uint16_t dst_port; + struct sockaddr_storage dst_addr; + socklen_t dst_len; + + int vban_fd; +}; + +static void stream_destroy(void *d) +{ + struct impl *impl = d; + impl->stream = NULL; +} + +static void stream_send_packet(void *data, struct iovec *iov, size_t iovlen) +{ + struct impl *impl = data; + struct msghdr msg; + ssize_t n; + + spa_zero(msg); + msg.msg_iov = iov; + msg.msg_iovlen = iovlen; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + + n = sendmsg(impl->vban_fd, &msg, MSG_NOSIGNAL); + if (n < 0) + pw_log_debug("sendmsg() failed: %m"); +} +
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban/audio.c
Added
@@ -0,0 +1,281 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2022 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +static void vban_audio_process_playback(void *data) +{ + struct impl *impl = data; + struct pw_buffer *buf; + struct spa_data *d; + uint32_t wanted, timestamp, target_buffer, stride, maxsize; + int32_t avail; + + if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) { + pw_log_debug("Out of stream buffers: %m"); + return; + } + d = buf->buffer->datas; + + stride = impl->stride; + + maxsize = d0.maxsize / stride; + wanted = buf->requested ? SPA_MIN(buf->requested, maxsize) : maxsize; + + avail = spa_ringbuffer_get_read_index(&impl->ring, ×tamp); + + target_buffer = impl->target_buffer; + + if (avail < (int32_t)wanted) { + enum spa_log_level level; + memset(d0.data, 0, wanted * stride); + if (impl->have_sync) { + impl->have_sync = false; + level = SPA_LOG_LEVEL_WARN; + } else { + level = SPA_LOG_LEVEL_DEBUG; + } + pw_log(level, "underrun %d/%u < %u", + avail, target_buffer, wanted); + } else { + float error, corr; + if (impl->first) { + if ((uint32_t)avail > target_buffer) { + uint32_t skip = avail - target_buffer; + pw_log_debug("first: avail:%d skip:%u target:%u", + avail, skip, target_buffer); + timestamp += skip; + avail = target_buffer; + } + impl->first = false; + } else if (avail > (int32_t)SPA_MIN(target_buffer * 8, BUFFER_SIZE / stride)) { + pw_log_warn("overrun %u > %u", avail, target_buffer * 8); + timestamp += avail - target_buffer; + avail = target_buffer; + } + /* try to adjust our playback rate to keep the + * requested target_buffer bytes in the ringbuffer */ + error = (float)target_buffer - (float)avail; + error = SPA_CLAMP(error, -impl->max_error, impl->max_error); + + corr = spa_dll_update(&impl->dll, error); + + pw_log_debug("avail:%u target:%u error:%f corr:%f", avail, + target_buffer, error, corr); + + if (impl->io_rate_match) { + SPA_FLAG_SET(impl->io_rate_match->flags, + SPA_IO_RATE_MATCH_FLAG_ACTIVE); + impl->io_rate_match->rate = 1.0f / corr; + } + spa_ringbuffer_read_data(&impl->ring, + impl->buffer, + BUFFER_SIZE, + (timestamp * stride) & BUFFER_MASK, + d0.data, wanted * stride); + + timestamp += wanted; + spa_ringbuffer_read_update(&impl->ring, timestamp); + } + d0.chunk->size = wanted * stride; + d0.chunk->stride = stride; + d0.chunk->offset = 0; + buf->size = wanted; + + pw_stream_queue_buffer(impl->stream, buf); +} + +static int vban_audio_receive(struct impl *impl, uint8_t *buffer, ssize_t len) +{ + struct vban_header *hdr; + ssize_t hlen, plen; + uint32_t n_frames, timestamp, samples, write, expected_write; + uint32_t stride = impl->stride; + int32_t filled; + + if (len < VBAN_HEADER_SIZE) + goto short_packet; + + hdr = (struct vban_header*)buffer; + if (strncmp(hdr->vban, "VBAN", 3)) + goto invalid_version; + + impl->receiving = true; + + hlen = VBAN_HEADER_SIZE; + plen = len - hlen; + samples = SPA_MIN(hdr->format_nbs, plen / stride); + + n_frames = hdr->n_frames; + if (impl->have_sync && impl->n_frames != n_frames) { + pw_log_info("unexpected frame (%d != %d)", + n_frames, impl->n_frames); + impl->have_sync = false; + } + impl->n_frames = n_frames + 1; + + timestamp = impl->timestamp; + impl->timestamp += samples; + + filled = spa_ringbuffer_get_write_index(&impl->ring, &expected_write); + + /* we always write to timestamp + delay */ + write = timestamp + impl->target_buffer; + + if (!impl->have_sync) { + pw_log_info("sync to timestamp:%u target:%u", + timestamp, impl->target_buffer); + + /* we read from timestamp, keeping target_buffer of data + * in the ringbuffer. */ + impl->ring.readindex = timestamp; + impl->ring.writeindex = write; + filled = impl->target_buffer; + + spa_dll_init(&impl->dll); + spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 128, impl->rate); + memset(impl->buffer, 0, BUFFER_SIZE); + impl->have_sync = true; + } else if (expected_write != write) { + pw_log_debug("unexpected write (%u != %u)", + write, expected_write); + } + + if (filled + samples > BUFFER_SIZE / stride) { + pw_log_debug("capture overrun %u + %u > %u", filled, samples, + BUFFER_SIZE / stride); + impl->have_sync = false; + } else { + pw_log_debug("got samples:%u", samples); + spa_ringbuffer_write_data(&impl->ring, + impl->buffer, + BUFFER_SIZE, + (write * stride) & BUFFER_MASK, + &bufferhlen, (samples * stride)); + write += samples; + spa_ringbuffer_write_update(&impl->ring, write); + } + return 0; + +short_packet: + pw_log_warn("short packet received"); + return -EINVAL; +invalid_version: + pw_log_warn("invalid VBAN version"); + spa_debug_mem(0, buffer, len); + return -EPROTO; +} + +static inline void +set_iovec(struct spa_ringbuffer *rbuf, void *buffer, uint32_t size, + uint32_t offset, struct iovec *iov, uint32_t len) +{ + iov0.iov_len = SPA_MIN(len, size - offset); + iov0.iov_base = SPA_PTROFF(buffer, offset, void); + iov1.iov_len = len - iov0.iov_len; + iov1.iov_base = buffer; +} + +static void vban_audio_flush_packets(struct impl *impl) +{ + int32_t avail, tosend; + uint32_t stride, timestamp; + struct iovec iov3; + struct vban_header header; + + avail = spa_ringbuffer_get_read_index(&impl->ring, ×tamp); + tosend = impl->psamples; + + if (avail < tosend) + return; + + stride = impl->stride; + + header = impl->header; + header.format_nbs = tosend - 1; + header.format_nbc = impl->stream_info.info.raw.channels - 1; + + iov0.iov_base = &header; + iov0.iov_len = sizeof(header); +
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban/stream.c
Added
@@ -0,0 +1,479 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#include <sys/socket.h> +#include <arpa/inet.h> + +#include <spa/utils/result.h> +#include <spa/utils/json.h> +#include <spa/utils/ringbuffer.h> +#include <spa/utils/dll.h> +#include <spa/param/audio/format-utils.h> +#include <spa/control/control.h> +#include <spa/debug/types.h> +#include <spa/debug/mem.h> + +#include "config.h" + +#include <pipewire/pipewire.h> +#include <pipewire/impl.h> + +#include <module-vban/vban.h> +#include <module-vban/stream.h> + +#define BUFFER_SIZE (1u<<22) +#define BUFFER_MASK (BUFFER_SIZE-1) +#define BUFFER_SIZE2 (BUFFER_SIZE>>1) +#define BUFFER_MASK2 (BUFFER_SIZE2-1) + +#define vban_stream_emit(s,m,v,...) spa_hook_list_call(&s->listener_list, \ + struct vban_stream_events, m, v, ##__VA_ARGS__) +#define vban_stream_emit_destroy(s) vban_stream_emit(s, destroy, 0) +#define vban_stream_emit_state_changed(s,n,e) vban_stream_emit(s, state_changed,0,n,e) +#define vban_stream_emit_send_packet(s,i,l) vban_stream_emit(s, send_packet,0,i,l) +#define vban_stream_emit_send_feedback(s,seq) vban_stream_emit(s, send_feedback,0,seq) + +struct impl { + struct spa_audio_info info; + struct spa_audio_info stream_info; + + struct pw_stream *stream; + struct spa_hook stream_listener; + struct pw_stream_events stream_events; + + struct spa_hook_list listener_list; + struct spa_hook listener; + + const struct format_info *format_info; + + void *stream_data; + + uint32_t rate; + uint32_t stride; + uint32_t psamples; + uint32_t mtu; + + struct vban_header header; + uint32_t timestamp; + uint32_t n_frames; + + struct spa_ringbuffer ring; + uint8_t bufferBUFFER_SIZE; + + struct spa_io_rate_match *io_rate_match; + struct spa_io_position *io_position; + struct spa_dll dll; + double corr; + uint32_t target_buffer; + float max_error; + + float last_timestamp; + float last_time; + + unsigned always_process:1; + unsigned started:1; + unsigned have_sync:1; + unsigned receiving:1; + unsigned first:1; + + int (*receive_vban)(struct impl *impl, uint8_t *buffer, ssize_t len); +}; + +#include "module-vban/audio.c" +//#include "module-vban/midi.c" + +struct format_info { + uint32_t media_subtype; + uint32_t format; + uint32_t size; + uint8_t format_bit; +}; + +static const struct format_info audio_format_info = { + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_U8, 1, VBAN_DATATYPE_U8, }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S16_LE, 2, VBAN_DATATYPE_INT16, }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S24_LE, 3, VBAN_DATATYPE_INT24, }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S32_LE, 4, VBAN_DATATYPE_INT32, }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_F32_LE, 4, VBAN_DATATYPE_FLOAT32, }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_F64_LE, 8, VBAN_DATATYPE_FLOAT64, }, + { SPA_MEDIA_SUBTYPE_control, 0, 1, }, +}; + +static void stream_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + switch (id) { + case SPA_IO_RateMatch: + impl->io_rate_match = area; + break; + case SPA_IO_Position: + impl->io_position = area; + break; + } +} + +static void stream_destroy(void *d) +{ + struct impl *impl = d; + spa_hook_remove(&impl->stream_listener); + impl->stream = NULL; +} + +static int stream_start(struct impl *impl) +{ + if (impl->started) + return 0; + + vban_stream_emit_state_changed(impl, true, NULL); + + impl->started = true; + return 0; +} + +static int stream_stop(struct impl *impl) +{ + if (!impl->started) + return 0; + + vban_stream_emit_state_changed(impl, false, NULL); + + impl->started = false; + return 0; +} + +static void on_stream_state_changed(void *d, enum pw_stream_state old, + enum pw_stream_state state, const char *error) +{ + struct impl *impl = d; + + switch (state) { + case PW_STREAM_STATE_UNCONNECTED: + pw_log_info("stream disconnected"); + break; + case PW_STREAM_STATE_ERROR: + pw_log_error("stream error: %s", error); + vban_stream_emit_state_changed(impl, false, error); + break; + case PW_STREAM_STATE_STREAMING: + if ((errno = -stream_start(impl)) < 0) + pw_log_error("failed to start RTP stream: %m"); + break; + case PW_STREAM_STATE_PAUSED: + if (!impl->always_process) + stream_stop(impl); + impl->have_sync = false; + break; + default: + break; + } +} + +static const struct pw_stream_events stream_events = { + PW_VERSION_STREAM_EVENTS, + .destroy = stream_destroy, + .state_changed = on_stream_state_changed, + .io_changed = stream_io_changed, +}; + +static const struct format_info *find_audio_format_info(const struct spa_audio_info *info) +{ + SPA_FOR_EACH_ELEMENT_VAR(audio_format_info, f) + if (f->media_subtype == info->media_subtype && + (f->format == 0 || f->format == info->info.raw.format)) + return f; + return NULL; +} + +static inline uint32_t format_from_name(const char *name, size_t len) +{ + int i; + for (i = 0; spa_type_audio_formati.name; i++) { + if (strncmp(name, spa_debug_type_short_name(spa_type_audio_formati.name), len) == 0) + return spa_type_audio_formati.type; + } + return SPA_AUDIO_FORMAT_UNKNOWN; +} + +static uint32_t channel_from_name(const char *name) +{
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban/stream.h
Added
@@ -0,0 +1,54 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#ifndef PIPEWIRE_VBAN_STREAM_H +#define PIPEWIRE_VBAN_STREAM_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct vban_stream; + +#define DEFAULT_FORMAT "S16LE" +#define DEFAULT_RATE 44100 +#define DEFAULT_CHANNELS 2 +#define DEFAULT_POSITION " FL FR " + +#define ERROR_MSEC 2 +#define DEFAULT_SESS_LATENCY 100 + +#define DEFAULT_MTU VBAN_PROTOCOL_MAX_SIZE +#define DEFAULT_MIN_PTIME 2 +#define DEFAULT_MAX_PTIME 20 + +struct vban_stream_events { +#define VBAN_VERSION_STREAM_EVENTS 0 + uint32_t version; + + void (*destroy) (void *data); + + void (*state_changed) (void *data, bool started, const char *error); + + void (*send_packet) (void *data, struct iovec *iov, size_t iovlen); + + void (*send_feedback) (void *data, uint32_t senum); +}; + +struct vban_stream *vban_stream_new(struct pw_core *core, + enum pw_direction direction, struct pw_properties *props, + const struct vban_stream_events *events, void *data); + +void vban_stream_destroy(struct vban_stream *s); + +int vban_stream_receive_packet(struct vban_stream *s, uint8_t *buffer, size_t len); + +uint64_t vban_stream_get_time(struct vban_stream *s, uint64_t *rate); + + +#ifdef __cplusplus +} +#endif + +#endif /* PIPEWIRE_VBAN_STREAM_H */
View file
pipewire-0.3.76.tar.gz/src/modules/module-vban/vban.h
Added
@@ -0,0 +1,60 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#ifndef PIPEWIRE_VBAN_H +#define PIPEWIRE_VBAN_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define VBAN_HEADER_SIZE (4 + 4 + 16 + 4) +#define VBAN_STREAM_NAME_SIZE 16 +#define VBAN_PROTOCOL_MAX_SIZE 1464 +#define VBAN_DATA_MAX_SIZE (VBAN_PROTOCOL_MAX_SIZE - VBAN_HEADER_SIZE) +#define VBAN_CHANNELS_MAX_NB 256 +#define VBAN_SAMPLES_MAX_NB 256 + +struct vban_header { + char vban4; /* contains 'V' 'B', 'A', 'N' */ + uint8_t format_SR; /* SR index */ + uint8_t format_nbs; /* nb sample per frame (1 to 256) */ + uint8_t format_nbc; /* nb channel (1 to 256) */ + uint8_t format_bit; /* bit format */ + char stream_nameVBAN_STREAM_NAME_SIZE; /* stream name */ + uint32_t n_frames; /* growing frame number. */ +} __attribute__ ((packed)); + +#define VBAN_SR_MAXNUMBER 21 + +static uint32_t const vban_SRVBAN_SR_MAXNUMBER = { + 6000, 12000, 24000, 48000, 96000, 192000, 384000, + 8000, 16000, 32000, 64000, 128000, 256000, 512000, + 11025, 22050, 44100, 88200, 176400, 352800, 705600 +}; + +static inline uint8_t vban_sr_index(uint32_t rate) +{ + uint8_t i; + for (i = 0; i < SPA_N_ELEMENTS(vban_SR); i++) { + if (vban_SRi == rate) + return i; + } + return VBAN_SR_MAXNUMBER; +} + +#define VBAN_DATATYPE_U8 0x00 +#define VBAN_DATATYPE_INT16 0x01 +#define VBAN_DATATYPE_INT24 0x02 +#define VBAN_DATATYPE_INT32 0x03 +#define VBAN_DATATYPE_FLOAT32 0x04 +#define VBAN_DATATYPE_FLOAT64 0x05 +#define VBAN_DATATYPE_12BITS 0x06 +#define VBAN_DATATYPE_10BITS 0x07 + +#ifdef __cplusplus +} +#endif + +#endif /* PIPEWIRE_VBAN_H */
View file
pipewire-0.3.74.tar.gz/src/pipewire/context.c -> pipewire-0.3.76.tar.gz/src/pipewire/context.c
Changed
@@ -17,6 +17,7 @@ #include <spa/support/plugin.h> #include <spa/support/plugin-loader.h> #include <spa/node/utils.h> +#include <spa/utils/atomic.h> #include <spa/utils/names.h> #include <spa/utils/string.h> #include <spa/debug/types.h> @@ -478,61 +479,6 @@ spa_hook_list_append(&context->listener_list, listener, events, data); } -struct listener_data { - struct spa_hook *listener; - const struct pw_context_driver_events *events; - void *data; -}; - -static int -do_add_listener(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct pw_context *context = user_data; - const struct listener_data *d = data; - spa_hook_list_append(&context->driver_listener_list, - d->listener, d->events, d->data); - return 0; -} - -SPA_EXPORT -void pw_context_driver_add_listener(struct pw_context *context, - struct spa_hook *listener, - const struct pw_context_driver_events *events, - void *data) -{ - struct listener_data d = { - .listener = listener, - .events = events, - .data = data }; - struct pw_impl_node *n; - spa_list_for_each(n, &context->driver_list, driver_link) { - SPA_FLAG_SET(n->rt.target.activation->flags, PW_NODE_ACTIVATION_FLAG_PROFILER); - } - pw_loop_invoke(context->data_loop, - do_add_listener, SPA_ID_INVALID, &d, sizeof(d), false, context); -} - -static int do_remove_listener(struct spa_loop *loop, - bool async, uint32_t seq, const void *data, size_t size, void *user_data) -{ - struct spa_hook *listener = user_data; - spa_hook_remove(listener); - return 0; -} - -SPA_EXPORT -void pw_context_driver_remove_listener(struct pw_context *context, - struct spa_hook *listener) -{ - struct pw_impl_node *n; - spa_list_for_each(n, &context->driver_list, driver_link) { - SPA_FLAG_CLEAR(n->rt.target.activation->flags, PW_NODE_ACTIVATION_FLAG_PROFILER); - } - pw_loop_invoke(context->data_loop, - do_remove_listener, SPA_ID_INVALID, NULL, 0, true, listener); -} - SPA_EXPORT const struct spa_support *pw_context_get_support(struct pw_context *context, uint32_t *n_support) { @@ -1534,10 +1480,10 @@ pw_log_debug("%p: apply duration:%"PRIu64" rate:%u/%u", context, n->target_quantum, n->target_rate.num, n->target_rate.denom); - SEQ_WRITE(n->rt.position->clock.target_seq); + SPA_SEQ_WRITE(n->rt.position->clock.target_seq); n->rt.position->clock.target_duration = n->target_quantum; n->rt.position->clock.target_rate = n->target_rate; - SEQ_WRITE(n->rt.position->clock.target_seq); + SPA_SEQ_WRITE(n->rt.position->clock.target_seq); if (n->info.state < PW_NODE_STATE_RUNNING) { n->rt.position->clock.duration = n->target_quantum;
View file
pipewire-0.3.74.tar.gz/src/pipewire/context.h -> pipewire-0.3.76.tar.gz/src/pipewire/context.h
Changed
@@ -43,6 +43,7 @@ struct pw_global; struct pw_impl_client; +struct pw_impl_node; #include <pipewire/core.h> #include <pipewire/loop.h> @@ -50,7 +51,7 @@ /** context events emitted by the context object added with \ref pw_context_add_listener */ struct pw_context_events { -#define PW_VERSION_CONTEXT_EVENTS 0 +#define PW_VERSION_CONTEXT_EVENTS 1 uint32_t version; /** The context is being destroyed */ @@ -63,6 +64,11 @@ void (*global_added) (void *data, struct pw_global *global); /** a global object was removed */ void (*global_removed) (void *data, struct pw_global *global); + + /** a driver was added, since 0.3.75 version:1 */ + void (*driver_added) (void *data, struct pw_impl_node *node); + /** a driver was removed, since 0.3.75 version:1 */ + void (*driver_removed) (void *data, struct pw_impl_node *node); }; /** Make a new context object for a given main_loop. Ownership of the properties is taken */
View file
pipewire-0.3.74.tar.gz/src/pipewire/filter.c -> pipewire-0.3.76.tar.gz/src/pipewire/filter.c
Changed
@@ -1222,7 +1222,6 @@ struct filter *impl; struct pw_filter *this; const char *str; - struct match match; int res; ensure_loop(context->main_loop, return NULL); @@ -1250,28 +1249,6 @@ spa_hook_list_init(&impl->hooks); this->properties = props; - pw_context_conf_update_props(context, "filter.properties", props); - - match = MATCH_INIT(this); - pw_context_conf_section_match_rules(context, "filter.rules", - &this->properties->dict, execute_match, &match); - - if ((str = getenv("PIPEWIRE_PROPS")) != NULL) - pw_properties_update_string(props, str, strlen(str)); - if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) { - struct spa_fraction q; - if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) { - pw_properties_setf(props, PW_KEY_NODE_RATE, - "1/%u", q.denom); - pw_properties_setf(props, PW_KEY_NODE_LATENCY, - "%u/%u", q.num, q.denom); - } - } - if ((str = getenv("PIPEWIRE_LATENCY")) != NULL) - pw_properties_set(props, PW_KEY_NODE_LATENCY, str); - if ((str = getenv("PIPEWIRE_RATE")) != NULL) - pw_properties_set(props, PW_KEY_NODE_RATE, str); - if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) { str = pw_properties_get(extra, PW_KEY_APP_NAME); if (str == NULL) @@ -1281,6 +1258,11 @@ pw_properties_set(props, PW_KEY_NODE_NAME, str); } + if ((pw_properties_get(props, PW_KEY_NODE_WANT_DRIVER) == NULL)) + pw_properties_set(props, PW_KEY_NODE_WANT_DRIVER, "true"); + + pw_context_conf_update_props(context, "filter.properties", props); + this->name = name ? strdup(name) : NULL; this->node_id = SPA_ID_INVALID; @@ -1605,6 +1587,8 @@ { struct filter *impl = SPA_CONTAINER_OF(filter, struct filter, this); struct pw_properties *props = NULL; + const char *str; + struct match match; int res; uint32_t i; @@ -1658,13 +1642,31 @@ if (flags & PW_FILTER_FLAG_DRIVER) pw_properties_set(filter->properties, PW_KEY_NODE_DRIVER, "true"); - if ((pw_properties_get(filter->properties, PW_KEY_NODE_WANT_DRIVER) == NULL)) - pw_properties_set(filter->properties, PW_KEY_NODE_WANT_DRIVER, "true"); if (flags & PW_FILTER_FLAG_TRIGGER) { pw_properties_set(filter->properties, PW_KEY_NODE_TRIGGER, "true"); impl->trigger = true; } + match = MATCH_INIT(filter); + pw_context_conf_section_match_rules(impl->context, "filter.rules", + &filter->properties->dict, execute_match, &match); + + if ((str = getenv("PIPEWIRE_PROPS")) != NULL) + pw_properties_update_string(filter->properties, str, strlen(str)); + if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) { + struct spa_fraction q; + if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) { + pw_properties_setf(filter->properties, PW_KEY_NODE_RATE, + "1/%u", q.denom); + pw_properties_setf(filter->properties, PW_KEY_NODE_LATENCY, + "%u/%u", q.num, q.denom); + } + } + if ((str = getenv("PIPEWIRE_LATENCY")) != NULL) + pw_properties_set(filter->properties, PW_KEY_NODE_LATENCY, str); + if ((str = getenv("PIPEWIRE_RATE")) != NULL) + pw_properties_set(filter->properties, PW_KEY_NODE_RATE, str); + if (filter->core == NULL) { filter->core = pw_context_connect(impl->context, pw_properties_copy(filter->properties), 0);
View file
pipewire-0.3.74.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.76.tar.gz/src/pipewire/impl-client.c
Changed
@@ -713,7 +713,7 @@ if (context->current_client == client) new_perm &= old_perm; - pw_log_debug("%p: set default permissions %08x -> %08x", + pw_log_info("%p: set default permissions %08x -> %08x", client, old_perm, new_perm); def->permissions = new_perm; @@ -748,7 +748,7 @@ if (context->current_client == client) new_perm &= old_perm; - pw_log_debug("%p: set global %d permissions %08x -> %08x", + pw_log_info("%p: set global %d permissions %08x -> %08x", client, global->id, old_perm, new_perm); p->permissions = new_perm;
View file
pipewire-0.3.74.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.76.tar.gz/src/pipewire/impl-link.c
Changed
@@ -1130,18 +1130,63 @@ } } +static int check_owner_permissions(struct pw_context *context, + struct pw_impl_node *node, uint32_t id, uint32_t permissions) +{ + const char *str; + struct pw_impl_client *client; + struct pw_global *global; + uint32_t perms; + uint32_t client_id; + + str = pw_properties_get(node->properties, PW_KEY_CLIENT_ID); + if (str == NULL) + /* node not owned by client */ + return 0; + + if (!spa_atou32(str, &client_id, 0)) + /* invalid client_id, something is wrong */ + return -EIO; + if ((global = pw_context_find_global(context, client_id)) == NULL) + /* current client can't see the owner client */ + return -errno; + if (!pw_global_is_type(global, PW_TYPE_INTERFACE_Client) || + (client = global->object) == NULL) + /* not the right object, something wrong */ + return -EIO; + + if ((global = pw_context_find_global(context, id)) == NULL) + /* current client can't see node id */ + return -errno; + + perms = pw_global_get_permissions(global, client); + if ((perms & permissions) != permissions) + /* owner client can't see other node */ + return -EPERM; + + return 0; +} + static int check_permission(struct pw_context *context, struct pw_impl_port *output, struct pw_impl_port *input, struct pw_properties *properties) { + int res; + if ((res = check_owner_permissions(context, output->node, + input->node->info.id, PW_PERM_R)) < 0) + return res; + if ((res = check_owner_permissions(context, input->node, + output->node->info.id, PW_PERM_R)) < 0) + return res; return 0; } static void permissions_changed(struct pw_impl_link *this, struct pw_impl_port *other, struct pw_impl_client *client, uint32_t old, uint32_t new) { + int res; uint32_t perm; perm = pw_global_get_permissions(other->global, client); @@ -1149,17 +1194,36 @@ new &= perm; pw_log_debug("%p: permissions changed %08x -> %08x", this, old, new); - if (check_permission(this->context, this->output, this->input, this->properties) < 0) { + if ((res = check_permission(this->context, this->output, this->input, this->properties)) < 0) { + pw_log_info("%p: link permissions removed: %s", this, spa_strerror(res)); pw_impl_link_destroy(this); } else if (this->global != NULL) { pw_global_update_permissions(this->global, client, old, new); } } +static bool is_port_owner(struct pw_impl_client *client, struct pw_impl_port *port) +{ + const char *str; + uint32_t client_id; + + str = pw_properties_get(port->node->properties, PW_KEY_CLIENT_ID); + if (str == NULL) + return false; + + if (!spa_atou32(str, &client_id, 0)) + return false; + + return client_id == client->info.id; +} + static void output_permissions_changed(void *data, struct pw_impl_client *client, uint32_t old, uint32_t new) { struct pw_impl_link *this = data; + if (!is_port_owner(client, this->output) && + !is_port_owner(client, this->input)) + return; permissions_changed(this, this->input, client, old, new); } @@ -1172,6 +1236,9 @@ struct pw_impl_client *client, uint32_t old, uint32_t new) { struct pw_impl_link *this = data; + if (!is_port_owner(client, this->output) && + !is_port_owner(client, this->input)) + return; permissions_changed(this, this->output, client, old, new); }
View file
pipewire-0.3.74.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.76.tar.gz/src/pipewire/impl-node.c
Changed
@@ -698,6 +698,13 @@ break; } spa_list_append(&n->driver_link, &node->driver_link); + pw_context_emit_driver_added(context, node); +} + +static inline void remove_driver(struct pw_context *context, struct pw_impl_node *node) +{ + spa_list_remove(&node->driver_link); + pw_context_emit_driver_removed(context, node); } static void update_io(struct pw_impl_node *node) @@ -846,8 +853,8 @@ static void remove_segment_owner(struct pw_impl_node *driver, uint32_t node_id) { struct pw_node_activation *a = driver->rt.target.activation; - ATOMIC_CAS(a->segment_owner0, node_id, 0); - ATOMIC_CAS(a->segment_owner1, node_id, 0); + SPA_ATOMIC_CAS(a->segment_owner0, node_id, 0); + SPA_ATOMIC_CAS(a->segment_owner1, node_id, 0); } SPA_EXPORT @@ -941,8 +948,9 @@ if (node->registered) { if (driver) insert_driver(context, node); - else - spa_list_remove(&node->driver_link); + else { + remove_driver(context, node); + } } if (driver && node->driver_node == node) node->driving = true; @@ -1158,7 +1166,7 @@ pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node, t->name, t->id, state, state->pending, state->required); - if (pw_node_activation_state_dec(state, 1)) { + if (pw_node_activation_state_dec(state)) { a->status = PW_NODE_ACTIVATION_TRIGGERED; a->signal_time = nsec; if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0)) @@ -1249,11 +1257,12 @@ /* calculate CPU time when finished */ a->signal_time = this->driver_start; calculate_stats(this, a); - pw_context_driver_emit_complete(this->context, this); + pw_impl_node_rt_emit_complete(this); +// pw_context_driver_emit_complete(this->context, this); } if (SPA_UNLIKELY(status & SPA_STATUS_DRAINED)) - pw_context_driver_emit_drained(this->context, this); + pw_impl_node_rt_emit_drained(this); return status; } @@ -1263,7 +1272,7 @@ struct pw_node_activation *a = node->rt.target.activation; struct pw_node_activation_state *state = &a->state0; - if (pw_node_activation_state_dec(state, 1)) { + if (pw_node_activation_state_dec(state)) { uint64_t nsec = get_time_ns(node->data_system); a->status = PW_NODE_ACTIVATION_TRIGGERED; a->signal_time = nsec; @@ -1394,6 +1403,7 @@ spa_list_init(&this->peer_list); spa_hook_list_init(&this->listener_list); + spa_hook_list_init(&this->rt_listener_list); this->info.state = PW_NODE_STATE_CREATING; this->info.props = &this->properties->dict; @@ -1661,8 +1671,8 @@ if (SPA_UNLIKELY(a->position.offset == INT64_MIN)) a->position.offset = a->position.clock.position; - command = ATOMIC_XCHG(a->command, PW_NODE_ACTIVATION_COMMAND_NONE); - *reposition_owner = ATOMIC_XCHG(a->reposition_owner, 0); + command = SPA_ATOMIC_XCHG(a->command, PW_NODE_ACTIVATION_COMMAND_NONE); + *reposition_owner = SPA_ATOMIC_XCHG(a->reposition_owner, 0); if (SPA_UNLIKELY(command != PW_NODE_ACTIVATION_COMMAND_NONE)) { pw_log_debug("%p: update command:%u", node, command); @@ -1726,7 +1736,7 @@ pw_log_warn("(%s-%u) sync timeout, going to RUNNING", node->name, node->info.id); check_states(node, nsec); - pw_context_driver_emit_timeout(node->context, node); + pw_impl_node_rt_emit_timeout(node); all_ready = true; } if (all_ready) @@ -1775,7 +1785,7 @@ state, a->position.clock.duration, state->pending, state->required); check_states(node, nsec); - pw_context_driver_emit_incomplete(node->context, node); + pw_impl_node_rt_emit_incomplete(node); } /* This update is done too late, the driver should do this @@ -1790,8 +1800,8 @@ } sync_type = check_updates(node, &reposition_owner); - owner0 = ATOMIC_LOAD(a->segment_owner0); - owner1 = ATOMIC_LOAD(a->segment_owner1); + owner0 = SPA_ATOMIC_LOAD(a->segment_owner0); + owner1 = SPA_ATOMIC_LOAD(a->segment_owner1); again: all_ready = sync_type == SYNC_CHECK; update_sync = !all_ready; @@ -1841,7 +1851,7 @@ update_position(node, all_ready, nsec); - pw_context_driver_emit_start(node->context, node); + pw_impl_node_rt_emit_start(node); } /* this should not happen, driver nodes that are not currently driving * should not emit the ready callback */ @@ -1904,7 +1914,7 @@ missed); } - pw_context_driver_emit_xrun(this->context, this); + pw_impl_node_rt_emit_xrun(this); return 0; } @@ -1954,6 +1964,50 @@ spa_hook_list_append(&node->listener_list, listener, events, data); } +struct listener_data { + struct spa_hook *listener; + const struct pw_impl_node_rt_events *events; + void *data; +}; + +static int +do_add_rt_listener(struct spa_loop *loop, + bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct pw_impl_node *node = user_data; + const struct listener_data *d = data; + spa_hook_list_append(&node->rt_listener_list, + d->listener, d->events, d->data); + return 0; +} + +SPA_EXPORT +void pw_impl_node_add_rt_listener(struct pw_impl_node *node, + struct spa_hook *listener, + const struct pw_impl_node_rt_events *events, + void *data) +{ + struct listener_data d = { .listener = listener, .events = events, .data = data }; + pw_loop_invoke(node->data_loop, + do_add_rt_listener, SPA_ID_INVALID, &d, sizeof(d), false, node); +} + +static int do_remove_listener(struct spa_loop *loop, + bool async, uint32_t seq, const void *data, size_t size, void *user_data) +{ + struct spa_hook *listener = user_data; + spa_hook_remove(listener); + return 0; +} + +SPA_EXPORT +void pw_impl_node_remove_rt_listener(struct pw_impl_node *node, + struct spa_hook *listener) +{ + pw_loop_invoke(node->data_loop, + do_remove_listener, SPA_ID_INVALID, NULL, 0, true, listener); +} + /** Destroy a node * \param node a node to destroy * @@ -1998,7 +2052,7 @@ if (node->registered) { spa_list_remove(&node->link); if (node->driver) - spa_list_remove(&node->driver_link); + remove_driver(context, node); } if (node->node) {
View file
pipewire-0.3.74.tar.gz/src/pipewire/impl-node.h -> pipewire-0.3.76.tar.gz/src/pipewire/impl-node.h
Changed
@@ -75,6 +75,23 @@ void (*peer_removed) (void *data, struct pw_impl_node *peer); }; +struct pw_impl_node_rt_events { +#define PW_VERSION_IMPL_NODE_RT_EVENTS 0 + uint32_t version; + /** the node is drained */ + void (*drained) (void *data); + /** the node had an xrun */ + void (*xrun) (void *data); + /** the driver node starts processing */ + void (*start) (void *data); + /** the driver node completed processing */ + void (*complete) (void *data); + /** the driver node did not complete processing */ + void (*incomplete) (void *data); + /** the node had */ + void (*timeout) (void *data); +}; + /** Create a new node */ struct pw_impl_node * pw_context_create_node(struct pw_context *context, /**< the context */ @@ -118,6 +135,14 @@ const struct pw_impl_node_events *events, void *data); +/** Add an rt_event listener */ +void pw_impl_node_add_rt_listener(struct pw_impl_node *node, + struct spa_hook *listener, + const struct pw_impl_node_rt_events *events, + void *data); +void pw_impl_node_remove_rt_listener(struct pw_impl_node *node, + struct spa_hook *listener); + /** Iterate the ports in the given direction. The callback should return * 0 to fetch the next item, any other value stops the iteration and returns * the value. When all callbacks return 0, this function returns 0 when all
View file
pipewire-0.3.74.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.76.tar.gz/src/pipewire/pipewire.c
Changed
@@ -838,6 +838,12 @@ return pw_get_headers_version(); } +SPA_EXPORT +bool pw_check_library_version(int major, int minor, int micro) +{ + return PW_CHECK_VERSION(major, minor, micro); +} + static const struct spa_type_info type_info = { { SPA_ID_INVALID, SPA_ID_INVALID, "spa_types", spa_types }, { 0, 0, NULL, NULL },
View file
pipewire-0.3.74.tar.gz/src/pipewire/private.h -> pipewire-0.3.76.tar.gz/src/pipewire/private.h
Changed
@@ -17,6 +17,7 @@ #include <spa/support/plugin.h> #include <spa/pod/builder.h> #include <spa/param/latency-utils.h> +#include <spa/utils/atomic.h> #include <spa/utils/ratelimit.h> #include <spa/utils/result.h> #include <spa/utils/type-info.h> @@ -359,39 +360,6 @@ } \ }) -#define pw_context_driver_emit(c,m,v,...) spa_hook_list_call_simple(&c->driver_listener_list, struct pw_context_driver_events, m, v, ##__VA_ARGS__) -#define pw_context_driver_emit_start(c,n) pw_context_driver_emit(c, start, 0, n) -#define pw_context_driver_emit_xrun(c,n) pw_context_driver_emit(c, xrun, 0, n) -#define pw_context_driver_emit_incomplete(c,n) pw_context_driver_emit(c, incomplete, 0, n) -#define pw_context_driver_emit_timeout(c,n) pw_context_driver_emit(c, timeout, 0, n) -#define pw_context_driver_emit_drained(c,n) pw_context_driver_emit(c, drained, 0, n) -#define pw_context_driver_emit_complete(c,n) pw_context_driver_emit(c, complete, 0, n) - -struct pw_context_driver_events { -#define PW_VERSION_CONTEXT_DRIVER_EVENTS 0 - uint32_t version; - - /** The driver graph is started */ - void (*start) (void *data, struct pw_impl_node *node); - /** The driver under/overruns */ - void (*xrun) (void *data, struct pw_impl_node *node); - /** The driver could not complete the graph */ - void (*incomplete) (void *data, struct pw_impl_node *node); - /** The driver got a sync timeout */ - void (*timeout) (void *data, struct pw_impl_node *node); - /** a node drained */ - void (*drained) (void *data, struct pw_impl_node *node); - /** The driver completed the graph */ - void (*complete) (void *data, struct pw_impl_node *node); -}; - -void pw_context_driver_add_listener(struct pw_context *context, - struct spa_hook *listener, - const struct pw_context_driver_events *events, - void *data); -void pw_context_driver_remove_listener(struct pw_context *context, - struct spa_hook *listener); - #define pw_registry_resource(r,m,v,...) pw_resource_call(r, struct pw_registry_events,m,v,##__VA_ARGS__) #define pw_registry_resource_global(r,...) pw_registry_resource(r,global,0,__VA_ARGS__) #define pw_registry_resource_global_remove(r,...) pw_registry_resource(r,global_remove,0,__VA_ARGS__) @@ -403,6 +371,8 @@ #define pw_context_emit_check_access(c,cl) pw_context_emit(c, check_access, 0, cl) #define pw_context_emit_global_added(c,g) pw_context_emit(c, global_added, 0, g) #define pw_context_emit_global_removed(c,g) pw_context_emit(c, global_removed, 0, g) +#define pw_context_emit_driver_added(c,n) pw_context_emit(c, driver_added, 1, n) +#define pw_context_emit_driver_removed(c,n) pw_context_emit(c, driver_removed, 1, n) struct pw_context { struct pw_impl_core *core; /**< core object */ @@ -549,7 +519,7 @@ state->pending = state->required; } -#define pw_node_activation_state_dec(s,c) (__atomic_sub_fetch(&(s)->pending, c, __ATOMIC_SEQ_CST) == 0) +#define pw_node_activation_state_dec(s) (SPA_ATOMIC_DEC(s->pending) == 0) struct pw_node_target { struct spa_list link; @@ -631,25 +601,6 @@ * to update wins */ }; -#define ATOMIC_CAS(v,ov,nv) \ -({ \ - __typeof__(v) __ov = (ov); \ - __atomic_compare_exchange_n(&(v), &__ov, (nv), \ - 0, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST); \ -}) - -#define ATOMIC_DEC(s) __atomic_sub_fetch(&(s), 1, __ATOMIC_SEQ_CST) -#define ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST) -#define ATOMIC_LOAD(s) __atomic_load_n(&(s), __ATOMIC_SEQ_CST) -#define ATOMIC_STORE(s,v) __atomic_store_n(&(s), (v), __ATOMIC_SEQ_CST) -#define ATOMIC_XCHG(s,v) __atomic_exchange_n(&(s), (v), __ATOMIC_SEQ_CST) - -#define SEQ_WRITE(s) ATOMIC_INC(s) -#define SEQ_WRITE_SUCCESS(s1,s2) ((s1) + 1 == (s2) && ((s2) & 1) == 0) - -#define SEQ_READ(s) ATOMIC_LOAD(s) -#define SEQ_READ_SUCCESS(s1,s2) ((s1) == (s2) && ((s2) & 1) == 0) - #define pw_impl_node_emit(o,m,v,...) spa_hook_list_call(&o->listener_list, struct pw_impl_node_events, m, v, ##__VA_ARGS__) #define pw_impl_node_emit_destroy(n) pw_impl_node_emit(n, destroy, 0) #define pw_impl_node_emit_free(n) pw_impl_node_emit(n, free, 0) @@ -669,6 +620,14 @@ #define pw_impl_node_emit_peer_added(n,p) pw_impl_node_emit(n, peer_added, 0, p) #define pw_impl_node_emit_peer_removed(n,p) pw_impl_node_emit(n, peer_removed, 0, p) +#define pw_impl_node_rt_emit(o,m,v,...) spa_hook_list_call(&o->rt_listener_list, struct pw_impl_node_rt_events, m, v, ##__VA_ARGS__) +#define pw_impl_node_rt_emit_drained(n) pw_impl_node_rt_emit(n, drained, 0) +#define pw_impl_node_rt_emit_xrun(n) pw_impl_node_rt_emit(n, xrun, 0) +#define pw_impl_node_rt_emit_start(n) pw_impl_node_rt_emit(n, start, 0) +#define pw_impl_node_rt_emit_complete(n) pw_impl_node_rt_emit(n, complete, 0) +#define pw_impl_node_rt_emit_incomplete(n) pw_impl_node_rt_emit(n, incomplete, 0) +#define pw_impl_node_rt_emit_timeout(n) pw_impl_node_rt_emit(n, timeout, 0) + struct pw_impl_node { struct pw_context *context; /**< context object */ struct spa_list link; /**< link in context node_list */ @@ -737,6 +696,7 @@ struct pw_map output_port_map; /**< map from port_id to port */ struct spa_hook_list listener_list; + struct spa_hook_list rt_listener_list; struct pw_loop *data_loop; /**< the data loop for this node */ struct spa_system *data_system; @@ -1085,6 +1045,7 @@ struct pw_impl_node *node; struct spa_hook node_listener; + struct spa_hook node_rt_listener; struct spa_list controls; }; @@ -1321,8 +1282,6 @@ int pw_settings_expose(struct pw_context *context); void pw_settings_clean(struct pw_context *context); -pthread_attr_t *pw_thread_fill_attr(const struct spa_dict *props, pthread_attr_t *attr); - /** \endcond */ #ifdef __cplusplus
View file
pipewire-0.3.74.tar.gz/src/pipewire/stream.c -> pipewire-0.3.76.tar.gz/src/pipewire/stream.c
Changed
@@ -17,7 +17,6 @@ #include <spa/pod/filter.h> #include <spa/pod/dynamic.h> #include <spa/debug/types.h> -#include <spa/debug/dict.h> #define PW_ENABLE_DEPRECATED @@ -84,7 +83,6 @@ const char *path; struct pw_context *context; - struct spa_hook context_listener; struct pw_loop *main_loop; struct pw_loop *data_loop; @@ -436,7 +434,7 @@ buffer->this.requested = impl->quantum; res = 1; } - pw_log_trace_fp("%p: update buffer:%u size:%"PRIu64, impl, id, buffer->this.requested); + pw_log_trace_fp("%p: update buffer:%u req:%"PRIu64, impl, id, buffer->this.requested); return res; } @@ -480,6 +478,7 @@ static void call_drained(struct stream *impl) { + pw_log_info("%p: drained", impl); pw_loop_invoke(impl->main_loop, do_call_drained, 1, NULL, 0, false, impl); } @@ -621,7 +620,7 @@ { struct spa_io_position *p = impl->rt.position; - SEQ_WRITE(impl->seq); + SPA_SEQ_WRITE(impl->seq); if (SPA_LIKELY(p != NULL)) { impl->time.now = p->clock.nsec; impl->time.rate = p->clock.rate; @@ -636,7 +635,7 @@ } if (SPA_LIKELY(impl->rate_match != NULL)) impl->rate_queued = impl->rate_match->delay; - SEQ_WRITE(impl->seq); + SPA_SEQ_WRITE(impl->seq); } static int impl_send_command(void *object, const struct spa_command *command) @@ -859,7 +858,7 @@ while ((b = queue_pop(impl, &impl->dequeued))) { if (b->busy) - ATOMIC_DEC(b->busy->count); + SPA_ATOMIC_DEC(b->busy->count); } } else clear_queue(impl, &impl->dequeued); @@ -1039,7 +1038,7 @@ pw_log_trace_fp("%p: push %d %p", stream, b->id, io); if (queue_push(impl, &impl->dequeued, b) == 0) { if (b->busy) - ATOMIC_INC(b->busy->count); + SPA_ATOMIC_INC(b->busy->count); } } if (!queue_is_empty(impl, &impl->dequeued)) { @@ -1389,6 +1388,7 @@ struct pw_stream *stream = data; struct stream *impl = SPA_CONTAINER_OF(stream, struct stream, this); spa_hook_remove(&stream->node_listener); + pw_impl_node_remove_rt_listener(stream->node, &stream->node_rt_listener); stream->node = NULL; impl->data_loop = NULL; } @@ -1440,11 +1440,9 @@ .error = on_core_error, }; -static void context_drained(void *data, struct pw_impl_node *node) +static void node_drained(void *data) { struct stream *impl = data; - if (impl->this.node != node) - return; if (impl->draining && impl->drained) { impl->draining = false; if (impl->io != NULL) @@ -1453,9 +1451,9 @@ } } -static const struct pw_context_driver_events context_events = { - PW_VERSION_CONTEXT_DRIVER_EVENTS, - .drained = context_drained, +static const struct pw_impl_node_rt_events node_rt_events = { + PW_VERSION_IMPL_NODE_RT_EVENTS, + .drained = node_drained, }; struct match { @@ -1481,7 +1479,6 @@ struct stream *impl; struct pw_stream *this; const char *str; - struct match match; int res; ensure_loop(context->main_loop, return NULL); @@ -1513,28 +1510,6 @@ spa_hook_list_init(&impl->hooks); this->properties = props; - pw_context_conf_update_props(context, "stream.properties", props); - - match = MATCH_INIT(this); - pw_context_conf_section_match_rules(context, "stream.rules", - &this->properties->dict, execute_match, &match); - - if ((str = getenv("PIPEWIRE_PROPS")) != NULL) - pw_properties_update_string(props, str, strlen(str)); - if ((str = getenv("PIPEWIRE_QUANTUM")) != NULL) { - struct spa_fraction q; - if (sscanf(str, "%u/%u", &q.num, &q.denom) == 2 && q.denom != 0) { - pw_properties_setf(props, PW_KEY_NODE_RATE, - "1/%u", q.denom); - pw_properties_setf(props, PW_KEY_NODE_LATENCY, - "%u/%u", q.num, q.denom); - } - } - if ((str = getenv("PIPEWIRE_LATENCY")) != NULL) - pw_properties_set(props, PW_KEY_NODE_LATENCY, str); - if ((str = getenv("PIPEWIRE_RATE")) != NULL) - pw_properties_set(props, PW_KEY_NODE_RATE, str); - if (pw_properties_get(props, PW_KEY_STREAM_IS_LIVE) == NULL) pw_properties_set(props, PW_KEY_STREAM_IS_LIVE, "true"); if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL && extra) { @@ -1545,6 +1520,10 @@ str = name; pw_properties_set(props, PW_KEY_NODE_NAME, str); } + if ((pw_properties_get(props, PW_KEY_NODE_WANT_DRIVER) == NULL)) + pw_properties_set(props, PW_KEY_NODE_WANT_DRIVER, "true"); + + pw_context_conf_update_props(context, "stream.properties", props); this->name = name ? strdup(name) : NULL; this->node_id = SPA_ID_INVALID; @@ -1562,9 +1541,6 @@ impl->allow_mlock = context->settings.mem_allow_mlock; impl->warn_mlock = context->settings.mem_warn_mlock; - pw_context_driver_add_listener(impl->context, - &impl->context_listener, - &context_events, impl); return impl; error_properties: @@ -1730,9 +1706,6 @@ spa_hook_list_clean(&impl->hooks); spa_hook_list_clean(&stream->listener_list); - pw_context_driver_remove_listener(impl->context, - &impl->context_listener); - if (impl->data.context) pw_context_destroy(impl->data.context); @@ -1914,6 +1887,7 @@ struct pw_impl_factory *factory; struct pw_properties *props = NULL; const char *str; + struct match match; uint32_t i; int res; @@ -2007,49 +1981,69 @@ impl->using_trigger = false; stream_set_state(stream, PW_STREAM_STATE_CONNECTING, 0, NULL); - if ((str = getenv("PIPEWIRE_NODE")) != NULL) - pw_properties_set(stream->properties, PW_KEY_TARGET_OBJECT, str); - else if (target_id != PW_ID_ANY) + if (target_id != PW_ID_ANY) /* XXX this is deprecated but still used by the portal and its apps */ - pw_properties_setf(stream->properties, PW_KEY_NODE_TARGET, "%d", target_id); + if (pw_properties_get(stream->properties, PW_KEY_NODE_TARGET) == NULL) + pw_properties_setf(stream->properties, PW_KEY_NODE_TARGET, "%d", target_id); + if (flags & PW_STREAM_FLAG_AUTOCONNECT) + if (pw_properties_get(stream->properties, PW_KEY_NODE_AUTOCONNECT) == NULL) + pw_properties_set(stream->properties, PW_KEY_NODE_AUTOCONNECT, "true"); + if (flags & PW_STREAM_FLAG_EXCLUSIVE) + if (pw_properties_get(stream->properties, PW_KEY_NODE_EXCLUSIVE) == NULL) + pw_properties_set(stream->properties, PW_KEY_NODE_EXCLUSIVE, "true"); + if (flags & PW_STREAM_FLAG_DONT_RECONNECT) + if (pw_properties_get(stream->properties, PW_KEY_NODE_DONT_RECONNECT) == NULL) + pw_properties_set(stream->properties, PW_KEY_NODE_DONT_RECONNECT, "true");
View file
pipewire-0.3.74.tar.gz/src/pipewire/thread-loop.c -> pipewire-0.3.76.tar.gz/src/pipewire/thread-loop.c
Changed
@@ -43,6 +43,7 @@ int n_waiting_for_accept; unsigned int created:1; unsigned int running:1; + unsigned int start_signal:1; }; /** \endcond */ @@ -143,6 +144,11 @@ return NULL; pw_log_debug("%p: new name:%s", this, name); + if (props != NULL) { + const char *str = spa_dict_lookup(props, "thread-loop.start-signal"); + if (str != NULL) + this->start_signal = spa_atob(str); + } if (loop == NULL) { loop = pw_loop_new(props); @@ -282,6 +288,9 @@ pw_log_debug("%p: enter thread", this); pw_loop_enter(this->loop); + if (this->start_signal) + pw_thread_loop_signal(this, false); + while (this->running) { if ((res = pw_loop_iterate(this->loop, -1)) < 0) { if (res == -EINTR)
View file
pipewire-0.3.74.tar.gz/src/pipewire/thread.c -> pipewire-0.3.76.tar.gz/src/pipewire/thread.c
Changed
@@ -25,8 +25,9 @@ } while(false); SPA_EXPORT -pthread_attr_t *pw_thread_fill_attr(const struct spa_dict *props, pthread_attr_t *attr) +void *pw_thread_fill_attr(const struct spa_dict *props, void *_attr) { + pthread_attr_t *attr = _attr; const char *str; int res;
View file
pipewire-0.3.74.tar.gz/src/pipewire/thread.h -> pipewire-0.3.76.tar.gz/src/pipewire/thread.h
Changed
@@ -27,6 +27,7 @@ SPA_DEPRECATED void pw_thread_utils_set(struct spa_thread_utils *impl); struct spa_thread_utils *pw_thread_utils_get(void); +void *pw_thread_fill_attr(const struct spa_dict *props, void *attr); #define pw_thread_utils_create(...) spa_thread_utils_create(pw_thread_utils_get(), ##__VA_ARGS__) #define pw_thread_utils_join(...) spa_thread_utils_join(pw_thread_utils_get(), ##__VA_ARGS__)
View file
pipewire-0.3.74.tar.gz/src/pipewire/version.h.in -> pipewire-0.3.76.tar.gz/src/pipewire/version.h.in
Changed
@@ -11,6 +11,8 @@ extern "C" { #endif +#include <stdbool.h> + /** Return the version of the header files. Keep in mind that this is a macro and not a function, so it is impossible to get the pointer of it. */ @@ -20,6 +22,10 @@ * linked to. */ const char* pw_get_library_version(void); +/** Return TRUE if the currently linked PipeWire library version is equal + * or newer than the specified version. Since 0.3.75 */ +bool pw_check_library_version(int major, int minor, int micro); + /** The current API version. Versions prior to 0.2.0 have * PW_API_VERSION undefined. Please note that this is only ever * increased on incompatible API changes! */
View file
pipewire-0.3.74.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.76.tar.gz/src/tools/pw-cat.c
Changed
@@ -745,6 +745,11 @@ error); pw_main_loop_quit(data->loop); break; + case PW_STREAM_STATE_UNCONNECTED: + printf("stream node %"PRIu32" unconnected\n", + pw_stream_get_node_id(data->stream)); + pw_main_loop_quit(data->loop); + break; default: break; }
View file
pipewire-0.3.74.tar.gz/test/test-context.c -> pipewire-0.3.76.tar.gz/test/test-context.c
Changed
@@ -27,6 +27,8 @@ void (*check_access) (void *data, struct pw_impl_client *client); void (*global_added) (void *data, struct pw_global *global); void (*global_removed) (void *data, struct pw_global *global); + void (*driver_added) (void *data, struct pw_impl_node *node); + void (*driver_removed) (void *data, struct pw_impl_node *node); } test = { PW_VERSION_CONTEXT_EVENTS, NULL }; pw_init(0, NULL); @@ -36,8 +38,10 @@ TEST_FUNC(ev, test, check_access); TEST_FUNC(ev, test, global_added); TEST_FUNC(ev, test, global_removed); + TEST_FUNC(ev, test, driver_added); + TEST_FUNC(ev, test, driver_removed); - pwtest_int_eq(PW_VERSION_CONTEXT_EVENTS, 0); + pwtest_int_eq(PW_VERSION_CONTEXT_EVENTS, 1); pwtest_int_eq(sizeof(ev), sizeof(test)); pw_deinit(); @@ -65,7 +69,14 @@ { pwtest_fail_if_reached(); } - +static void context_driver_added_error(void *data, struct pw_impl_node *node) +{ + pwtest_fail_if_reached(); +} +static void context_driver_removed_error(void *data, struct pw_impl_node *node) +{ + pwtest_fail_if_reached(); +} static const struct pw_context_events context_events_error = { PW_VERSION_CONTEXT_EVENTS, @@ -74,6 +85,8 @@ .check_access = context_check_access_error, .global_added = context_global_added_error, .global_removed = context_global_removed_error, + .driver_added = context_driver_added_error, + .driver_removed = context_driver_removed_error, }; static int destroy_count = 0;
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.