Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 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
.