Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 36
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed Oct 18 08:54:11 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.82 + +------------------------------------------------------------------- Sun Oct 8 16:26:36 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.81
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.81 +Version: 0.3.82 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.81.tar.gz/.gitlab/ci/check_missing_headers.sh -> pipewire-0.3.82.tar.gz/.gitlab/ci/check_missing_headers.sh
Changed
@@ -5,7 +5,7 @@ LIST="" -for i in $(find spa/include -name '*.h' -a -not -path 'spa/include/spa/utils/cleanup.h' | sed s#spa/include/##); +for i in $(find spa/include -name '*.h' | sed s#spa/include/##); do -f "$PREFIX/include/spa-0.2/$i" || LIST="$i $LIST" done
View file
pipewire-0.3.81.tar.gz/NEWS -> pipewire-0.3.82.tar.gz/NEWS
Changed
@@ -1,3 +1,68 @@ +# PipeWire 0.3.82 (2023-10-13) + +This is the second 1.0 release candidate that is API and ABI compatible +with previous 0.3.x releases. + +## Highlights + - Fix a regression in some devices when the Pro-Audio profile was selected. + Only enable the IRQ based scheduling and device linking in specific + safe cases. (#3556) + - Improve rate switching. In some cases the graph rate would not switch + correctly. (#2929) + - Fix regression in alsa wakeups that would cause silence in VMs. + - Fix a leak in the SBC codecs for SCO. + - More improvements to the RAOP module. + - Other small improvements and fixes. + + +## PipeWire + - Improve client property checks. + - Allow non-power-of-2 quantums when forced. + - Improve rate switching. In some cases the graph rate would not switch + correctly. (#2929) + - The PIPEWIRE_QUANTUM env variable now forces the size and rate in the + graph for the duration of the application. The softer PIPEWIRE_LATENCY + and PIPEWIRE_RATE can still be used to merely suggest a maximum latency + and a rate. + +## modules + - Remove the RTSP FLUSH request in RAOP because it does not seem necessary. + - The RAOP module now uses the common RTP stream functions. + - Add sockets option to protocol-native to make pipewire listen on multiple + sockets. + +## SPA + - Clean up some of the log functions. + - Add an option in ALSA to disable linking devices together. + - Only link pcms together when 1 capture and 1 playback pcm. For more complex + devices we can't be sure which ones can be linked. (#3556) + - disable tsched only when using linked devices. + - Add some extra checks in ALSA to avoid segfaults. (#3554) + - Add Tag support to alsa-sink and alsa-source. + - Use dynamic pod builder when we can. + - Set priority.driver on midi-bridge to allow it as a fallback driver. (#3562) + - Fix regression in alsa wakeups. (#3565) + - The PTP clock can now be found from the interface in node-driver. + +## pulse-server + - Some small cleanups and internal improvements. + - Add some memory debugging messages. + - Add Tag messages to streams. + +## Bluetooth + - Fix a leak in the SBC codecs for SCO. + +## JACK + - Patch up midi events in the destination buffer instead of writing to the + source buffer. (#3580) + - Group all jack clients together to avoid transport issues. (#3562) + +## ALSA-plugins + - Add also.deny option to block alsa clients from opening the PCM. + +Older versions: + + # PipeWire 0.3.81 (2023-10-06) This is the first 1.0 release candidate that is API and ABI compatible @@ -80,9 +145,6 @@ - jack_property now always manages to actually change the metadata because it waits for a roundtrip before exiting. -Older versions: - - # PipeWire 0.3.80 (2023-09-14) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.81.tar.gz/README.md -> pipewire-0.3.82.tar.gz/README.md
Changed
@@ -52,9 +52,8 @@ the samplerate. * `PIPEWIRE_RATE=<num/denom>` to configure a rate for the graph. * `PIPEWIRE_QUANTUM=<num/denom>` to configure latency as a fraction and a - samplerate. This function will attempt to change - the graph samplerate to `denom` and use the - specified `num` as the buffer size. + samplerate. This function will force the graph samplerate to + `denom` and force the specified `num` as the buffer size. * `PIPEWIRE_NODE=<id>` to request a link to the specified node. The id can be a node.name or object.serial of the target node.
View file
pipewire-0.3.81.tar.gz/meson.build -> pipewire-0.3.82.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.81', + version : '0.3.82', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -232,6 +232,7 @@ 'sys/random.h', 'HAVE_SYS_RANDOM_H', 'sys/vfs.h', 'HAVE_SYS_VFS_H', 'pwd.h', 'HAVE_PWD_H', + 'grp.h', 'HAVE_GRP_H', foreach h : check_headers @@ -247,6 +248,10 @@ summary({'libsystemd': systemd_dep.found()}, bool_yn: true) cdata.set('HAVE_SYSTEMD', systemd.found() and systemd_dep.found()) +selinux_dep = dependency('libselinux', required: get_option('selinux')) +summary({'libselinux': selinux_dep.found()}, bool_yn: true) +cdata.set('HAVE_SELINUX', selinux_dep.found()) + configinc = include_directories('.') includes_inc = include_directories('include') pipewire_inc = include_directories('src') @@ -436,6 +441,7 @@ 'sigabbrev_np', '#include <string.h>', '-D_GNU_SOURCE', , 'XSetIOErrorExitHandler', '#include <X11/Xlib.h>', , x11_dep, 'malloc_trim', '#include <malloc.h>', , , + 'malloc_info', '#include <malloc.h>', , , foreach f : check_functions
View file
pipewire-0.3.81.tar.gz/meson_options.txt -> pipewire-0.3.82.tar.gz/meson_options.txt
Changed
@@ -42,6 +42,10 @@ description: 'Install systemd user service file (ignored without systemd)', type: 'feature', value: 'enabled') +option('selinux', + description: 'Enable SELinux integration', + type: 'feature', + value: 'auto') option('pipewire-alsa', description: 'Enable pipewire-alsa integration', type: 'feature',
View file
pipewire-0.3.81.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.82.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -1238,6 +1238,12 @@ if (str != NULL) pw_properties_update_string(pw->props, str, strlen(str)); + if ((str = pw_properties_get(pw->props, "alsa.deny")) != NULL && + spa_atob(str)) { + err = -EACCES; + goto error; + } + str = getenv("PIPEWIRE_NODE"); if (str != NULL && str0) pw_properties_set(pw->props, PW_KEY_TARGET_OBJECT, str);
View file
pipewire-0.3.81.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.82.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -1332,15 +1332,6 @@ return b.state.offset; } -static inline void fix_midi_event(uint8_t *data, size_t size) -{ - /* fixup NoteOn with vel 0 */ - if (size > 2 && (data0 & 0xF0) == 0x90 && data2 == 0x00) { - data0 = 0x80 + (data0 & 0x0F); - data2 = 0x40; - } -} - static inline int event_sort(struct spa_pod_control *a, struct spa_pod_control *b) { if (a->offset < b->offset) @@ -1373,6 +1364,29 @@ } } +static inline void fix_midi_event(uint8_t *data, size_t size) +{ + /* fixup NoteOn with vel 0 */ + if (size > 2 && (data0 & 0xF0) == 0x90 && data2 == 0x00) { + data0 = 0x80 + (data0 & 0x0F); + data2 = 0x40; + } +} + +static inline int midi_event_write(void *port_buffer, + jack_nframes_t time, + const jack_midi_data_t *data, + size_t data_size, bool fix) +{ + jack_midi_data_t *retbuf = jack_midi_event_reserve (port_buffer, time, data_size); + if (SPA_UNLIKELY(retbuf == NULL)) + return -ENOBUFS; + memcpy (retbuf, data, data_size); + if (fix) + fix_midi_event(retbuf, data_size); + return 0; +} + static void convert_to_midi(struct spa_pod_sequence **seq, uint32_t n_seq, void *midi, bool fix) { struct spa_pod_control *cn_seq; @@ -1405,10 +1419,7 @@ uint8_t *data = SPA_POD_BODY(&next->value); size_t size = SPA_POD_BODY_SIZE(&next->value); - if (fix) - fix_midi_event(data, size); - - if ((res = jack_midi_event_write(midi, next->offset, data, size)) < 0) + if ((res = midi_event_write(midi, next->offset, data, size, fix)) < 0) pw_log_warn("midi %p: can't write event: %s", midi, spa_strerror(res)); break; @@ -3804,10 +3815,10 @@ 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(client->props, PW_KEY_NODE_RATE, + pw_properties_setf(client->props, PW_KEY_NODE_FORCE_RATE, "1/%u", q.denom); - pw_properties_setf(client->props, PW_KEY_NODE_LATENCY, - "%u/%u", q.num, q.denom); + pw_properties_setf(client->props, PW_KEY_NODE_FORCE_QUANTUM, + "%u", q.num); } else { pw_log_warn("invalid PIPEWIRE_QUANTUM: %s", str); } @@ -3828,7 +3839,7 @@ if (pw_properties_get(client->props, PW_KEY_NODE_NAME) == NULL) pw_properties_set(client->props, PW_KEY_NODE_NAME, client_name); if (pw_properties_get(client->props, PW_KEY_NODE_GROUP) == NULL) - pw_properties_setf(client->props, PW_KEY_NODE_GROUP, "jack-%d", getpid()); + pw_properties_setf(client->props, PW_KEY_NODE_GROUP, "group.dsp.0"); if (pw_properties_get(client->props, PW_KEY_NODE_DESCRIPTION) == NULL) pw_properties_set(client->props, PW_KEY_NODE_DESCRIPTION, client_name); if (pw_properties_get(client->props, PW_KEY_MEDIA_TYPE) == NULL) @@ -6924,11 +6935,7 @@ const jack_midi_data_t *data, size_t data_size) { - jack_midi_data_t *retbuf = jack_midi_event_reserve (port_buffer, time, data_size); - if (SPA_UNLIKELY(retbuf == NULL)) - return -ENOBUFS; - memcpy (retbuf, data, data_size); - return 0; + return midi_event_write(port_buffer, time, data, data_size, false); } SPA_EXPORT
View file
pipewire-0.3.81.tar.gz/spa/include/meson.build -> pipewire-0.3.82.tar.gz/spa/include/meson.build
Changed
@@ -15,7 +15,4 @@ spa_headers = 'spa' # used by doxygen install_subdir('spa', install_dir : get_option('includedir') / spa_name, - exclude_files : - 'utils/cleanup.h', - , )
View file
pipewire-0.3.81.tar.gz/spa/include/spa/pod/dynamic.h -> pipewire-0.3.82.tar.gz/spa/include/spa/pod/dynamic.h
Changed
@@ -10,6 +10,7 @@ #endif #include <spa/pod/builder.h> +#include <spa/utils/cleanup.h> struct spa_pod_dynamic_builder { struct spa_pod_builder b; @@ -23,14 +24,15 @@ struct spa_pod_dynamic_builder *d = (struct spa_pod_dynamic_builder*)data; int32_t old_size = d->b.size; int32_t new_size = SPA_ROUND_UP_N(size, d->extend); - void *old_data = d->b.data; + void *old_data = d->b.data, *new_data; if (old_data == d->data) d->b.data = NULL; - if ((d->b.data = realloc(d->b.data, new_size)) == NULL) + if ((new_data = realloc(d->b.data, new_size)) == NULL) return -errno; - if (old_data == d->data && d->b.data != old_data && old_size > 0) - memcpy(d->b.data, old_data, old_size); + if (old_data == d->data && new_data != old_data && old_size > 0) + memcpy(new_data, old_data, old_size); + d->b.data = new_data; d->b.size = new_size; return 0; } @@ -54,6 +56,10 @@ free(builder->b.data); } +SPA_DEFINE_AUTO_CLEANUP(spa_pod_dynamic_builder, struct spa_pod_dynamic_builder, { + spa_pod_dynamic_builder_clean(thing); +}) + #ifdef __cplusplus } /* extern "C" */ #endif
View file
pipewire-0.3.81.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.82.tar.gz/spa/include/spa/support/log.h
Changed
@@ -194,28 +194,29 @@ #define SPA_LOG_TOPIC(v, t) \ (struct spa_log_topic){ .version = (v), .topic = (t)} -#define spa_log_topic_init(l, topic) \ -do { \ - struct spa_log *_l = l; \ - if (SPA_LIKELY(_l)) { \ - struct spa_interface *_if = &_l->iface; \ - spa_interface_call(_if, struct spa_log_methods, \ - topic_init, 1, topic); \ - } \ -} while(0) - -/* Unused, left for backwards compat */ -#define spa_log_level_enabled(l,lev) ((l) && (l)->level >= (lev)) - -#define spa_log_level_topic_enabled(l,topic,lev) \ -({ \ - struct spa_log *_log = l; \ - enum spa_log_level _lev = _log ? _log->level : SPA_LOG_LEVEL_NONE; \ - struct spa_log_topic *_t = (struct spa_log_topic *)(topic); \ - if (_t && _t->has_custom_level) \ - _lev = _t->level; \ - _lev >= (lev); \ -}) +static inline void spa_log_topic_init(struct spa_log *log, struct spa_log_topic *topic) +{ + if (SPA_UNLIKELY(!log)) + return; + + spa_interface_call(&log->iface, struct spa_log_methods, topic_init, 1, topic); +} + +static inline bool spa_log_level_topic_enabled(const struct spa_log *log, + const struct spa_log_topic *topic, + enum spa_log_level level) +{ + enum spa_log_level max_level; + + if (topic && topic->has_custom_level) + max_level = topic->level; + else if (log) + max_level = log->level; + else + max_level = SPA_LOG_LEVEL_NONE; + + return level <= max_level; +} /* Transparently calls to version 0 log if v1 is not supported */ #define spa_log_logt(l,lev,topic,...) \
View file
pipewire-0.3.81.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-0.3.82.tar.gz/spa/include/spa/utils/cleanup.h
Changed
@@ -5,10 +5,48 @@ #ifndef SPA_UTILS_CLEANUP_H #define SPA_UTILS_CLEANUP_H -#if !defined(__has_attribute) || !__has_attribute(__cleanup__) -#error "attribute `cleanup` is required" +#define spa_exchange(var, new_value) \ +__extension__ ({ \ + __typeof__(var) *_ptr = &(var); \ + __typeof__(var) _old_value = *_ptr; \ + *_ptr = (new_value); \ + _old_value; \ +}) + +/* ========================================================================== */ + +#if __GNUC__ >= 10 || defined(__clang__) +#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL)) +#else +#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL) #endif +#define spa_clear_ptr(ptr, destructor) \ +__extension__ ({ \ + __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \ + if (_old_value) \ + destructor(_old_value); \ + (void) 0; \ +}) + +/* ========================================================================== */ + +#include <unistd.h> + +#define spa_steal_fd(fd) spa_exchange((fd), -1) + +#define spa_clear_fd(fd) \ +__extension__ ({ \ + int _old_value = spa_steal_fd(fd), _res = 0; \ + if (_old_value >= 0) \ + _res = close(_old_value); \ + _res; \ +}) + +/* ========================================================================== */ + +#if defined(__has_attribute) && __has_attribute(__cleanup__) + #define spa_cleanup(func) __attribute__((__cleanup__(func))) #define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \ @@ -33,34 +71,10 @@ spa_cleanup(_spa_autoptr_cleanup_func_ ## name) \ _spa_autoptr_cleanup_type_ ## name -#define spa_exchange(var, new_value) \ -__extension__ ({ \ - __typeof__(var) *_ptr = &(var); \ - __typeof__(var) _old_value = *_ptr; \ - *_ptr = (new_value); \ - _old_value; \ -}) - -#if __GNUC__ >= 10 || defined(__clang__) -#define spa_steal_ptr(ptr) ((__typeof__(*(ptr)) *) spa_exchange((ptr), NULL)) -#else -#define spa_steal_ptr(ptr) spa_exchange((ptr), NULL) -#endif - -#define spa_steal_fd(fd) spa_exchange((fd), -1) - /* ========================================================================== */ #include <stdlib.h> -#define spa_clear_ptr(ptr, destructor) \ -__extension__ ({ \ - __typeof__(ptr) _old_value = spa_steal_ptr(ptr); \ - if (_old_value) \ - destructor(_old_value); \ - (void) 0; \ -}) - static inline void _spa_autofree_cleanup_func(void *p) { free(*(void **) p); @@ -69,16 +83,6 @@ /* ========================================================================== */ -#include <unistd.h> - -#define spa_clear_fd(fd) \ -__extension__ ({ \ - int _old_value = spa_steal_fd(fd), _res = 0; \ - if (_old_value >= 0) \ - _res = close(_old_value); \ - _res; \ -}) - static inline void _spa_autoclose_cleanup_func(int *fd) { spa_clear_fd(*fd); @@ -101,4 +105,11 @@ spa_clear_ptr(*thing, closedir); }) +#else + +#define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) +#define SPA_DEFINE_AUTOPTR_CLEANUP(name, type, ...) + +#endif + #endif /* SPA_UTILS_CLEANUP_H */
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -296,7 +296,7 @@ static int add_pro_profile(pa_card *impl, uint32_t index) { snd_ctl_t *ctl_hndl; - int err, dev, count = 0; + int err, dev, count = 0, n_capture = 0, n_playback = 0; pa_alsa_profile *ap; pa_alsa_profile_set *ps = impl->profile_set; pa_alsa_mapping *m; @@ -304,6 +304,7 @@ snd_pcm_info_t *pcminfo; pa_sample_spec ss; snd_pcm_uframes_t try_period_size, try_buffer_size; + uint32_t idx; if (impl->use_ucm) { const char *verb = find_best_verb(impl); @@ -388,11 +389,10 @@ pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm); pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index); pa_proplist_setf(m->output_proplist, "device.profile.pro", "true"); - pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index); - pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index); pa_alsa_close(&m->output_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX); + n_playback++; } pa_idxset_put(ap->output_mappings, m, NULL); free(name); @@ -421,11 +421,10 @@ pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm); pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index); pa_proplist_setf(m->input_proplist, "device.profile.pro", "true"); - pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index); - pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index); pa_alsa_close(&m->input_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX); + n_capture++; } pa_idxset_put(ap->input_mappings, m, NULL); free(name); @@ -433,6 +432,20 @@ } snd_ctl_close(ctl_hndl); + if (n_capture == 1 && n_playback == 1) { + PA_IDXSET_FOREACH(m, ap->output_mappings, idx) { + pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index); + pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index); + pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true"); + pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true"); + } + PA_IDXSET_FOREACH(m, ap->input_mappings, idx) { + pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index); + pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index); + pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true"); + pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true"); + } + } return 0; }
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-acp-device.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-acp-device.c
Changed
@@ -26,6 +26,7 @@ #include <spa/param/param.h> #include <spa/pod/filter.h> #include <spa/pod/parser.h> +#include <spa/pod/dynamic.h> #include <spa/debug/pod.h> #include <spa/debug/log.h> @@ -484,7 +485,8 @@ { struct impl *this = object; struct spa_pod *param; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; uint8_t buffer4096; struct spa_result_device_params result; uint32_t count = 0; @@ -496,6 +498,9 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + card = this->card; result.id = id; @@ -503,7 +508,7 @@ next: result.index = result.next++; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_EnumProfile: @@ -511,7 +516,7 @@ return 0; pr = card->profilesresult.index; - param = build_profile(&b, id, pr, false); + param = build_profile(&b.b, id, pr, false); break; case SPA_PARAM_Profile: @@ -519,7 +524,7 @@ return 0; pr = card->profilescard->active_profile_index; - param = build_profile(&b, id, pr, true); + param = build_profile(&b.b, id, pr, true); break; case SPA_PARAM_EnumRoute: @@ -527,7 +532,7 @@ return 0; p = card->portsresult.index; - param = build_route(&b, id, p, NULL, SPA_ID_INVALID); + param = build_route(&b.b, id, p, NULL, SPA_ID_INVALID); break; case SPA_PARAM_Route: @@ -543,7 +548,7 @@ result.index++; } result.next = result.index + 1; - param = build_route(&b, id, p, dev, card->active_profile_index); + param = build_route(&b.b, id, p, dev, card->active_profile_index); if (param == NULL) return -errno; break; @@ -552,7 +557,7 @@ return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) + if (spa_pod_filter(&b.b, &result.param, param, filter) < 0) goto next; spa_device_emit_result(&this->hooks, seq, 0,
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -15,6 +15,7 @@ #include <spa/utils/string.h> #include <spa/param/audio/format.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include <spa/debug/log.h> #include <spa/debug/pod.h> @@ -100,7 +101,8 @@ { struct state *this = object; struct spa_pod *param; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; uint8_t buffer4096; struct spa_result_node_params result; uint32_t count = 0; @@ -108,12 +110,15 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = id; result.next = start; - next: +next: result.index = result.next++; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_PropInfo: @@ -122,7 +127,7 @@ switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device), SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH), @@ -130,21 +135,21 @@ SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName), SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name))); break; case 2: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName), SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name))); break; case 3: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), @@ -153,7 +158,7 @@ case 4: if (!this->is_iec958 && !this->is_hdmi) goto next; - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_iec958Codecs), SPA_PROP_INFO_name, SPA_POD_String("iec958.codecs"), @@ -163,7 +168,7 @@ SPA_PROP_INFO_container, SPA_POD_Id(SPA_TYPE_Array)); break; default: - param = spa_alsa_enum_propinfo(this, result.index - 5, &b); + param = spa_alsa_enum_propinfo(this, result.index - 5, &b.b); if (param == NULL) return 0; } @@ -177,9 +182,9 @@ switch (result.index) { case 0: - spa_pod_builder_push_object(&b, &f, + spa_pod_builder_push_object(&b.b, &f, SPA_TYPE_OBJECT_Props, id); - spa_pod_builder_add(&b, + spa_pod_builder_add(&b.b, SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)), SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)), SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), @@ -188,12 +193,12 @@ if (this->is_iec958 || this->is_hdmi) { n_codecs = spa_alsa_get_iec958_codecs(this, codecs, SPA_N_ELEMENTS(codecs)); - spa_pod_builder_prop(&b, SPA_PROP_iec958Codecs, 0); - spa_pod_builder_array(&b, sizeof(uint32_t), SPA_TYPE_Id, + spa_pod_builder_prop(&b.b, SPA_PROP_iec958Codecs, 0); + spa_pod_builder_array(&b.b, sizeof(uint32_t), SPA_TYPE_Id, n_codecs, codecs); } - spa_alsa_add_prop_params(this, &b); - param = spa_pod_builder_pop(&b, &f); + spa_alsa_add_prop_params(this, &b.b); + param = spa_pod_builder_pop(&b.b, &f); break; default: return 0; @@ -203,13 +208,13 @@ case SPA_PARAM_IO: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Clock), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_clock))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Position), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_position))); @@ -222,7 +227,7 @@ case SPA_PARAM_ProcessLatency: switch (result.index) { case 0: - param = spa_process_latency_build(&b, id, &this->process_latency); + param = spa_process_latency_build(&b.b, id, &this->process_latency); break; default: return 0; @@ -233,7 +238,7 @@ return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) + if (spa_pod_filter(&b.b, &result.param, param, filter) < 0) goto next; spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); @@ -469,7 +474,8 @@ struct state *this = object; struct spa_pod *param; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; uint8_t buffer1024; struct spa_result_node_params result; uint32_t count = 0; @@ -479,12 +485,15 @@ spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = id; result.next = start; next: result.index = result.next++; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_EnumFormat: @@ -498,15 +507,15 @@ switch (this->current_format.media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - param = spa_format_audio_raw_build(&b, id, + param = spa_format_audio_raw_build(&b.b, id, &this->current_format.info.raw); break; case SPA_MEDIA_SUBTYPE_iec958: - param = spa_format_audio_iec958_build(&b, id, + param = spa_format_audio_iec958_build(&b.b, id, &this->current_format.info.iec958); break; case SPA_MEDIA_SUBTYPE_dsd: - param = spa_format_audio_dsd_build(&b, id, + param = spa_format_audio_dsd_build(&b.b, id, &this->current_format.info.dsd); break; default: @@ -520,7 +529,7 @@ if (result.index > 0) return 0; - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamBuffers, id, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks), @@ -534,7 +543,7 @@ case SPA_PARAM_Meta: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamMeta, id, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); @@ -547,13 +556,13 @@ case SPA_PARAM_IO: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Buffers), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_buffers))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_RateMatch), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_rate_match))); @@ -570,19 +579,28 @@ struct spa_latency_info latency = this->latencyresult.index; if (latency.direction == SPA_DIRECTION_INPUT) spa_process_latency_info_add(&this->process_latency, &latency); - param = spa_latency_build(&b, id, &latency); + param = spa_latency_build(&b.b, id, &latency); break; } default: return 0; } break; - + case SPA_PARAM_Tag: + switch (result.index) { + case 0: case 1: + if ((param = this->tagresult.index) == NULL) + goto next; + break; + default: + return 0; + } + break; default: return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) + if (spa_pod_filter(&b.b, &result.param, param, filter) < 0) goto next; spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); @@ -687,12 +705,13 @@ break; case SPA_PARAM_Latency: { + enum spa_direction other = SPA_DIRECTION_REVERSE(direction); struct spa_latency_info info; if (param == NULL) - info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction)); + info = SPA_LATENCY_INFO(other); else if ((res = spa_latency_parse(param, &info)) < 0) return res; - if (direction == info.direction) + if (info.direction != other) return -EINVAL; this->latencyinfo.direction = info; @@ -702,9 +721,25 @@ break; } case SPA_PARAM_Tag: - if (param != NULL) - spa_debug_log_pod(this->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, param); + { + enum spa_direction other = SPA_DIRECTION_REVERSE(direction); + if (param != NULL) { + struct spa_tag_info info; + void *state = NULL; + if (spa_tag_parse(param, &info, &state) < 0 || + info.direction != other) + return -EINVAL; + } + if (spa_tag_compare(param, this->tagother) != 0) { + free(this->tagother); + this->tagother = param ? spa_pod_copy(param) : NULL; + + this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; + this->port_paramsPORT_Tag.user++; + emit_port_info(this, false); + } break; + } default: res = -ENOENT; break; @@ -956,6 +991,7 @@ this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); this->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE); + this->port_paramsPORT_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE); this->port_info.params = this->port_params; this->port_info.n_params = N_PORT_PARAMS;
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -16,6 +16,7 @@ #include <spa/monitor/device.h> #include <spa/param/audio/format.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> #include "alsa.h" @@ -100,7 +101,8 @@ struct state *this = object; struct spa_pod *param; uint8_t buffer4096; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; struct props *p; struct spa_result_node_params result; uint32_t count = 0; @@ -108,6 +110,9 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + p = &this->props; result.id = id; @@ -115,13 +120,13 @@ next: result.index = result.next++; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_PropInfo: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_device), SPA_PROP_INFO_name, SPA_POD_String(SPA_KEY_API_ALSA_PATH), @@ -129,28 +134,28 @@ SPA_PROP_INFO_type, SPA_POD_Stringn(p->device, sizeof(p->device))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_deviceName), SPA_PROP_INFO_description, SPA_POD_String("The ALSA device name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->device_name, sizeof(p->device_name))); break; case 2: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_cardName), SPA_PROP_INFO_description, SPA_POD_String("The ALSA card name"), SPA_PROP_INFO_type, SPA_POD_Stringn(p->card_name, sizeof(p->card_name))); break; case 3: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, id, SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_latencyOffsetNsec), SPA_PROP_INFO_description, SPA_POD_String("Latency offset (ns)"), SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Long(0LL, 0LL, 2 * SPA_NSEC_PER_SEC)); break; default: - param = spa_alsa_enum_propinfo(this, result.index - 4, &b); + param = spa_alsa_enum_propinfo(this, result.index - 4, &b.b); if (param == NULL) return 0; } @@ -162,16 +167,16 @@ switch (result.index) { case 0: - spa_pod_builder_push_object(&b, &f, + spa_pod_builder_push_object(&b.b, &f, SPA_TYPE_OBJECT_Props, id); - spa_pod_builder_add(&b, + spa_pod_builder_add(&b.b, SPA_PROP_device, SPA_POD_Stringn(p->device, sizeof(p->device)), SPA_PROP_deviceName, SPA_POD_Stringn(p->device_name, sizeof(p->device_name)), SPA_PROP_cardName, SPA_POD_Stringn(p->card_name, sizeof(p->card_name)), SPA_PROP_latencyOffsetNsec, SPA_POD_Long(this->process_latency.ns), 0); - spa_alsa_add_prop_params(this, &b); - param = spa_pod_builder_pop(&b, &f); + spa_alsa_add_prop_params(this, &b.b); + param = spa_pod_builder_pop(&b.b, &f); break; default: return 0; @@ -181,13 +186,13 @@ case SPA_PARAM_IO: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Clock), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_clock))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Position), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_position))); @@ -200,7 +205,7 @@ case SPA_PARAM_ProcessLatency: switch (result.index) { case 0: - param = spa_process_latency_build(&b, id, &this->process_latency); + param = spa_process_latency_build(&b.b, id, &this->process_latency); break; default: return 0; @@ -211,7 +216,7 @@ return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) + if (spa_pod_filter(&b.b, &result.param, param, filter) < 0) goto next; spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); @@ -431,22 +436,25 @@ { struct state *this = object; struct spa_pod *param; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; uint8_t buffer1024; struct spa_result_node_params result; uint32_t count = 0; spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); - spa_return_val_if_fail(CHECK_PORT(this, direction, port_id), -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = id; result.next = start; next: result.index = result.next++; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_EnumFormat: @@ -458,7 +466,7 @@ if (result.index > 0) return 0; - param = spa_format_audio_raw_build(&b, id, &this->current_format.info.raw); + param = spa_format_audio_raw_build(&b.b, id, &this->current_format.info.raw); break; case SPA_PARAM_Buffers: @@ -467,7 +475,7 @@ if (result.index > 0) return 0; - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamBuffers, id, SPA_PARAM_BUFFERS_buffers, SPA_POD_CHOICE_RANGE_Int(2, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(this->blocks), @@ -481,7 +489,7 @@ case SPA_PARAM_Meta: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamMeta, id, SPA_PARAM_META_type, SPA_POD_Id(SPA_META_Header), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_header))); @@ -494,13 +502,13 @@ case SPA_PARAM_IO: switch (result.index) { case 0: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_Buffers), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_buffers))); break; case 1: - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_ParamIO, id, SPA_PARAM_IO_id, SPA_POD_Id(SPA_IO_RateMatch), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_rate_match))); @@ -517,19 +525,29 @@ struct spa_latency_info latency = this->latencyresult.index; if (latency.direction == SPA_DIRECTION_OUTPUT) spa_process_latency_info_add(&this->process_latency, &latency); - param = spa_latency_build(&b, id, &latency); + param = spa_latency_build(&b.b, id, &latency); break; } default: return 0; } break; + case SPA_PARAM_Tag: + switch (result.index) { + case 0: case 1: + if ((param = this->tagresult.index) == NULL) + goto next; + break; + default: + return 0; + } + break; default: return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) + if (spa_pod_filter(&b.b, &result.param, param, filter) < 0) goto next; spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); @@ -609,7 +627,7 @@ const struct spa_pod *param) { struct state *this = object; - int res; + int res = 0; spa_return_val_if_fail(this != NULL, -EINVAL); @@ -621,19 +639,39 @@ break; case SPA_PARAM_Latency: { + enum spa_direction other = SPA_DIRECTION_REVERSE(direction); struct spa_latency_info info; if (param == NULL) - info = SPA_LATENCY_INFO(SPA_DIRECTION_REVERSE(direction)); + info = SPA_LATENCY_INFO(other); else if ((res = spa_latency_parse(param, &info)) < 0) return res; - if (direction == info.direction) + if (info.direction != other) return -EINVAL; this->latencyinfo.direction = info; this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Latency.user++; emit_port_info(this, false); - res = 0; + break; + } + case SPA_PARAM_Tag: + { + enum spa_direction other = SPA_DIRECTION_REVERSE(direction); + if (param != NULL) { + struct spa_tag_info info; + void *state = NULL; + if (spa_tag_parse(param, &info, &state) < 0 || + info.direction != other) + return -EINVAL; + } + if (spa_tag_compare(param, this->tagother) != 0) { + free(this->tagother); + this->tagother = param ? spa_pod_copy(param) : NULL; + + this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; + this->port_paramsPORT_Tag.user++; + emit_port_info(this, false); + } break; } default: @@ -901,6 +939,7 @@ this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); this->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_READWRITE); + this->port_paramsPORT_Tag = SPA_PARAM_INFO(SPA_PARAM_Tag, SPA_PARAM_INFO_READWRITE); this->port_info.params = this->port_params; this->port_info.n_params = N_PORT_PARAMS;
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -131,6 +131,8 @@ state->multi_rate = spa_atob(s); } else if (spa_streq(k, "api.alsa.htimestamp")) { state->htimestamp = spa_atob(s); + } else if (spa_streq(k, "api.alsa.auto-link")) { + state->auto_link = spa_atob(s); } else if (spa_streq(k, "latency.internal.rate")) { state->process_latency.rate = atoi(s); } else if (spa_streq(k, "latency.internal.ns")) { @@ -512,7 +514,6 @@ state->multi_rate = true; state->htimestamp = false; - state->disable_tsched = state->is_pro; for (i = 0; info && i < info->n_items; i++) { const char *k = info->itemsi.key; const char *s = info->itemsi.value; @@ -574,6 +575,9 @@ spa_log_warn(state->log, "output close failed: %s", snd_strerror(err)); fclose(state->log_file); + free(state->tag0); + free(state->tag1); + return err; } @@ -1991,7 +1995,7 @@ CHECK(set_swparams(state), "swparams"); - if ((err = snd_pcm_prepare(state->hndl)) < 0 && err != -EBUSY) { + if ((!state->linked) && (err = snd_pcm_prepare(state->hndl)) < 0 && err != -EBUSY) { spa_log_error(state->log, "%s: snd_pcm_prepare error: %s", state->name, snd_strerror(err)); return err; @@ -2398,10 +2402,13 @@ if (SPA_UNLIKELY((res = check_position_config(state)) < 0)) return res; - if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) + if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) { + spa_log_error(state->log, "get_status error"); + state->next_time += state->threshold * 1e9 / state->rate; return res; + } - if (SPA_UNLIKELY(!following && delay > target + state->max_error)) { + if (SPA_UNLIKELY(!following && state->alsa_started && delay > target + state->max_error)) { spa_log_trace(state->log, "%p: early wakeup %ld %lu %lu", state, avail, delay, target); if (delay > target * 3) @@ -2412,7 +2419,7 @@ if (SPA_UNLIKELY((res = update_time(state, current_time, delay, target, following)) < 0)) return res; - if (following && !state->linked) { + if (following && state->alsa_started && !state->linked) { if (SPA_UNLIKELY(state->alsa_sync)) { enum spa_log_level lev; @@ -2553,11 +2560,9 @@ int spa_alsa_write(struct state *state) { - int res = 0; if (state->following && state->rt.driver == NULL) { uint64_t current_time = state->position->clock.nsec; - if ((res = alsa_write_sync(state, current_time)) < 0) - return res; + alsa_write_sync(state, current_time); } return alsa_write_frames(state); } @@ -2656,8 +2661,11 @@ if (SPA_UNLIKELY((res = check_position_config(state)) < 0)) return res; - if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) + if (SPA_UNLIKELY((res = get_status(state, current_time, &avail, &delay, &target)) < 0)) { + spa_log_error(state->log, "get_status error"); + state->next_time += state->threshold * 1e9 / state->rate; return res; + } if (SPA_UNLIKELY(!following && avail < state->read_size)) { spa_log_trace(state->log, "%p: early wakeup %ld %ld %ld %d", state, @@ -2671,7 +2679,7 @@ return res; max_read = state->buffer_frames; - if (following) { + if (following && !state->linked) { if (state->alsa_sync) { enum spa_log_level lev; @@ -2767,11 +2775,9 @@ int spa_alsa_read(struct state *state) { - int res; if (state->following && state->rt.driver == NULL) { uint64_t current_time = state->position->clock.nsec; - if ((res = alsa_read_sync(state, current_time)) < 0) - return res; + alsa_read_sync(state, current_time); } return alsa_read_frames(state); } @@ -3019,6 +3025,9 @@ struct state *follower; int err; + if (!state->opened) + return -EIO; + spa_alsa_pause(state); if (state->prepared) @@ -3034,7 +3043,7 @@ spa_list_for_each(follower, &state->followers, driver_link) { if (follower != state && !follower->matching) { spa_alsa_prepare(follower); - if (!follower->linked) + if (!follower->linked && state->auto_link) do_link(state, follower); } } @@ -3051,6 +3060,8 @@ if (state->started) return 0; + else if (!state->opened) + return -EIO; spa_alsa_prepare(state);
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -30,6 +30,7 @@ #include <spa/param/param.h> #include <spa/param/latency-utils.h> #include <spa/param/audio/format-utils.h> +#include <spa/param/tag-utils.h> #include "alsa.h" @@ -165,7 +166,8 @@ #define PORT_Format 3 #define PORT_Buffers 4 #define PORT_Latency 5 -#define N_PORT_PARAMS 6 +#define PORT_Tag 6 +#define N_PORT_PARAMS 7 struct spa_param_info port_paramsN_PORT_PARAMS; enum spa_direction port_direction; struct spa_io_buffers *io; @@ -214,6 +216,7 @@ unsigned int htimestamp:1; unsigned int is_pro:1; unsigned int sources_added:1; + unsigned int auto_link:1; unsigned int linked:1; uint64_t iec958_codecs; @@ -233,6 +236,8 @@ struct spa_latency_info latency2; struct spa_process_latency_info process_latency; + struct spa_pod *tag2; + /* Rate match via an ALSA ctl */ snd_ctl_t *ctl; snd_ctl_elem_value_t *pitch_elem;
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c
Changed
@@ -195,6 +195,7 @@ { SPA_KEY_DEVICE_API, "alsa" }, { SPA_KEY_MEDIA_CLASS, "Midi/Bridge" }, { SPA_KEY_NODE_DRIVER, "true" }, + { "priority.driver", "1" }, }; static void emit_node_info(struct seq_state *this, bool full)
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa.c -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa.c
Changed
@@ -9,6 +9,8 @@ #include <spa/support/plugin.h> #include <spa/support/log.h> +#include "alsa.h" + extern const struct spa_handle_factory spa_alsa_source_factory; extern const struct spa_handle_factory spa_alsa_sink_factory; extern const struct spa_handle_factory spa_alsa_udev_factory; @@ -20,8 +22,7 @@ extern const struct spa_handle_factory spa_alsa_compress_offload_device_factory; #endif -struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.alsa"); -struct spa_log_topic *alsa_log_topic = &log_topic; +struct spa_log_topic alsa_log_topic = SPA_LOG_TOPIC(0, "spa.alsa"); SPA_EXPORT int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
View file
pipewire-0.3.81.tar.gz/spa/plugins/alsa/alsa.h -> pipewire-0.3.82.tar.gz/spa/plugins/alsa/alsa.h
Changed
@@ -8,12 +8,12 @@ #include <spa/support/log.h> #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT alsa_log_topic -extern struct spa_log_topic *alsa_log_topic; +#define SPA_LOG_TOPIC_DEFAULT &alsa_log_topic +extern struct spa_log_topic alsa_log_topic; static inline void alsa_log_topic_init(struct spa_log *log) { - spa_log_topic_init(log, alsa_log_topic); + spa_log_topic_init(log, &alsa_log_topic); } #endif /* SPA_ALSA_H */
View file
pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-0.3.82.tar.gz/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -26,8 +26,8 @@ #include <spa/debug/log.h> #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT log_topic -static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audioadapter"); +#define SPA_LOG_TOPIC_DEFAULT &log_topic +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audioadapter"); #define DEFAULT_ALIGN 16 @@ -153,7 +153,8 @@ { struct impl *this = object; uint8_t buffer4096; - struct spa_pod_dynamic_builder b; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; struct spa_result_node_params result; uint32_t count = 0; int res; @@ -161,6 +162,9 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_return_val_if_fail(num != 0, -EINVAL); + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = id; result.next = start; next: @@ -168,7 +172,7 @@ spa_log_debug(this->log, "%p: %d id:%u", this, seq, id); - spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_reset(&b.b, &state); switch (id) { case SPA_PARAM_EnumPortConfig: @@ -215,16 +219,12 @@ default: return -ENOENT; } - - if (res == 1) { - spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); - count++; - } - spa_pod_dynamic_builder_clean(&b); - if (res != 1) return res; + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + if (count != num) goto next; @@ -580,8 +580,9 @@ static int recalc_tag(struct impl *this, struct spa_node *src, enum spa_direction direction, uint32_t port_id, struct spa_node *dst) { - struct spa_pod_builder b = { 0 }; - uint8_t buffer1024; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; + uint8_t buffer2048; struct spa_pod *param; uint32_t index = 0; struct spa_tag_info info; @@ -592,26 +593,25 @@ if (this->target == this->follower) return 0; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 2048); + spa_pod_builder_get_state(&b.b, &state); + while (true) { - void *state = NULL; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + void *tag_state = NULL; + spa_pod_builder_reset(&b.b, &state); if ((res = spa_node_port_enum_params_sync(src, direction, port_id, SPA_PARAM_Tag, - &index, NULL, ¶m, &b)) != 1) { + &index, NULL, ¶m, &b.b)) != 1) { param = NULL; break; } - if ((res = spa_tag_parse(param, &info, &state)) < 0) + if ((res = spa_tag_parse(param, &info, &tag_state)) < 0) return res; if (info.direction == direction) break; } - if ((res = spa_node_port_set_param(dst, - SPA_DIRECTION_REVERSE(direction), 0, - SPA_PARAM_Tag, 0, param)) < 0) - return res; - - return 0; + return spa_node_port_set_param(dst, SPA_DIRECTION_REVERSE(direction), 0, + SPA_PARAM_Tag, 0, param); } @@ -1755,7 +1755,7 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - spa_log_topic_init(this->log, log_topic); + spa_log_topic_init(this->log, &log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
View file
pipewire-0.3.81.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.82.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -36,8 +36,8 @@ #include "wavfile.h" #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT log_topic -static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audioconvert"); +#define SPA_LOG_TOPIC_DEFAULT &log_topic +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audioconvert"); #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 @@ -3354,7 +3354,7 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - spa_log_topic_init(this->log, log_topic); + spa_log_topic_init(this->log, &log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU); if (this->cpu) {
View file
pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.82.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -23,8 +23,8 @@ #include "mix-ops.h" #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT log_topic -static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer"); +#define SPA_LOG_TOPIC_DEFAULT &log_topic +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.audiomixer"); #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 @@ -918,7 +918,7 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - spa_log_topic_init(this->log, log_topic); + spa_log_topic_init(this->log, &log_topic); this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); if (this->data_loop == NULL) {
View file
pipewire-0.3.81.tar.gz/spa/plugins/audiomixer/mixer-dsp.c -> pipewire-0.3.82.tar.gz/spa/plugins/audiomixer/mixer-dsp.c
Changed
@@ -23,8 +23,8 @@ #include "mix-ops.h" #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT log_topic -static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.mixer-dsp"); +#define SPA_LOG_TOPIC_DEFAULT &log_topic +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.mixer-dsp"); #define MAX_BUFFERS 64 #define MAX_PORTS 512 @@ -855,7 +855,7 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - spa_log_topic_init(this->log, log_topic); + spa_log_topic_init(this->log, &log_topic); this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); if (this->data_loop == NULL) {
View file
pipewire-0.3.81.tar.gz/spa/plugins/avb/avb.c -> pipewire-0.3.82.tar.gz/spa/plugins/avb/avb.c
Changed
@@ -7,11 +7,12 @@ #include <spa/support/plugin.h> #include <spa/support/log.h> +#include "avb.h" + extern const struct spa_handle_factory spa_avb_sink_factory; extern const struct spa_handle_factory spa_avb_source_factory; -struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.avb"); -struct spa_log_topic *avb_log_topic = &log_topic; +struct spa_log_topic avb_log_topic = SPA_LOG_TOPIC(0, "spa.avb"); SPA_EXPORT int spa_handle_factory_enum(const struct spa_handle_factory **factory, uint32_t *index)
View file
pipewire-0.3.81.tar.gz/spa/plugins/avb/avb.h -> pipewire-0.3.82.tar.gz/spa/plugins/avb/avb.h
Changed
@@ -8,12 +8,12 @@ #include <spa/support/log.h> #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT avb_log_topic -extern struct spa_log_topic *avb_log_topic; +#define SPA_LOG_TOPIC_DEFAULT &avb_log_topic +extern struct spa_log_topic avb_log_topic; static inline void avb_log_topic_init(struct spa_log *log) { - spa_log_topic_init(log, avb_log_topic); + spa_log_topic_init(log, &avb_log_topic); } #endif /* SPA_AVB_H */
View file
pipewire-0.3.81.tar.gz/spa/plugins/bluez5/sco-sink.c -> pipewire-0.3.82.tar.gz/spa/plugins/bluez5/sco-sink.c
Changed
@@ -662,7 +662,9 @@ /* Init mSBC if needed */ if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) { - sbc_init_msbc(&this->msbc, 0); + res = sbc_init_msbc(&this->msbc, 0); + if (res < 0) + return res; /* Libsbc expects audio samples by default in host endianness, mSBC requires little endian */ this->msbc.endian = SBC_LE; @@ -705,6 +707,7 @@ fail: free(this->buffer); this->buffer = NULL; + sbc_finish(&this->msbc); return res; } @@ -819,6 +822,8 @@ this->buffer = NULL; this->buffer_head = this->buffer_next = this->buffer; } + + sbc_finish(&this->msbc); } static int do_stop(struct impl *this)
View file
pipewire-0.3.81.tar.gz/spa/plugins/bluez5/sco-source.c -> pipewire-0.3.82.tar.gz/spa/plugins/bluez5/sco-source.c
Changed
@@ -687,7 +687,10 @@ /* Init mSBC if needed */ if (this->transport->codec == HFP_AUDIO_CODEC_MSBC) { - sbc_init_msbc(&this->msbc, 0); + res = sbc_init_msbc(&this->msbc, 0); + if (res < 0) + return res; + /* Libsbc expects audio samples by default in host endianness, mSBC requires little endian */ this->msbc.endian = SBC_LE; this->msbc_seq_initialized = false; @@ -708,6 +711,7 @@ return 0; fail: + sbc_finish(&this->msbc); return res; } @@ -798,6 +802,8 @@ spa_loop_invoke(this->data_loop, do_remove_transport_source, 0, NULL, 0, true, this); spa_bt_decode_buffer_clear(&port->buffer); + + sbc_finish(&this->msbc); } static int do_stop(struct impl *this)
View file
pipewire-0.3.81.tar.gz/spa/plugins/libcamera/libcamera.c -> pipewire-0.3.82.tar.gz/spa/plugins/libcamera/libcamera.c
Changed
@@ -9,8 +9,7 @@ #include "libcamera.h" -struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.libcamera"); -struct spa_log_topic *libcamera_log_topic = &log_topic; +struct spa_log_topic libcamera_log_topic = SPA_LOG_TOPIC(0, "spa.libcamera"); SPA_EXPORT int spa_handle_factory_enum(const struct spa_handle_factory **factory,
View file
pipewire-0.3.81.tar.gz/spa/plugins/libcamera/libcamera.h -> pipewire-0.3.82.tar.gz/spa/plugins/libcamera/libcamera.h
Changed
@@ -18,12 +18,12 @@ extern const struct spa_handle_factory spa_libcamera_device_factory; #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT libcamera_log_topic -extern struct spa_log_topic *libcamera_log_topic; +#define SPA_LOG_TOPIC_DEFAULT &libcamera_log_topic +extern struct spa_log_topic libcamera_log_topic; static inline void libcamera_log_topic_init(struct spa_log *log) { - spa_log_topic_init(log, libcamera_log_topic); + spa_log_topic_init(log, &libcamera_log_topic); } #ifdef __cplusplus
View file
pipewire-0.3.81.tar.gz/spa/plugins/support/log-patterns.c -> pipewire-0.3.82.tar.gz/spa/plugins/support/log-patterns.c
Changed
@@ -22,6 +22,7 @@ struct spa_log_topic *t) { enum spa_log_level level = default_level; + bool has_custom_level = false; const char *topic = t->topic; struct support_log_pattern *pattern; @@ -29,10 +30,11 @@ if (fnmatch(pattern->pattern, topic, 0) != 0) continue; level = pattern->level; - t->has_custom_level = true; + has_custom_level = true; } t->level = level; + t->has_custom_level = has_custom_level; } int
View file
pipewire-0.3.81.tar.gz/spa/plugins/support/node-driver.c -> pipewire-0.3.82.tar.gz/spa/plugins/support/node-driver.c
Changed
@@ -8,6 +8,11 @@ #include <string.h> #include <stdio.h> #include <fcntl.h> +#if !defined(__FreeBSD__) && !defined(__MidnightBSD__) +#include <linux/ethtool.h> +#include <linux/sockios.h> +#endif +#include <net/if.h> #include <spa/support/plugin.h> #include <spa/support/log.h> @@ -485,6 +490,33 @@ return sizeof(struct impl); } +int get_phc_index(struct spa_system *s, const char *name) { +#ifdef ETHTOOL_GET_TS_INFO + struct ethtool_ts_info info = {0}; + struct ifreq ifr = {0}; + int fd, err; + + info.cmd = ETHTOOL_GET_TS_INFO; + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) &info; + fd = socket(AF_INET, SOCK_DGRAM, 0); + + if (fd < 0) { + return -1; + } + + err = spa_system_ioctl(s, fd, SIOCETHTOOL, &ifr); + close(fd); + if (err < 0) { + return err; + } + + return info.phc_index; +#else + return -1; +#endif +} + static int impl_init(const struct spa_handle_factory *factory, struct spa_handle *handle, @@ -553,9 +585,28 @@ this->props.clock_id = DEFAULT_CLOCK_ID; } } else if (spa_streq(k, "clock.device")) { + if (this->clock_fd >= 0) { + close(this->clock_fd); + } this->clock_fd = open(s, O_RDWR); + + if (this->clock_fd == -1) { + spa_log_warn(this->log, "failed to open clock device '%s'", s); + } else { + this->props.clock_id = FD_TO_CLOCKID(this->clock_fd); + } + } else if (spa_streq(k, "clock.interface") && this->clock_fd < 0) { + int phc_index = get_phc_index(this->data_system, s); + if (phc_index < 0) { + spa_log_warn(this->log, "failed to get phc device index for interface '%s'", s); + } else { + char dev19; + spa_scnprintf(dev, sizeof(dev), "/dev/ptp%d", phc_index); + this->clock_fd = open(dev, O_RDWR); + } + if (this->clock_fd == -1) { - spa_log_info(this->log, "failed to open clock device '%s'", s); + spa_log_warn(this->log, "failed to open clock device '%s'", s); } else { this->props.clock_id = FD_TO_CLOCKID(this->clock_fd); }
View file
pipewire-0.3.81.tar.gz/spa/plugins/v4l2/v4l2.c -> pipewire-0.3.82.tar.gz/spa/plugins/v4l2/v4l2.c
Changed
@@ -7,12 +7,13 @@ #include <spa/support/plugin.h> #include <spa/support/log.h> +#include "v4l2.h" + extern const struct spa_handle_factory spa_v4l2_source_factory; extern const struct spa_handle_factory spa_v4l2_udev_factory; extern const struct spa_handle_factory spa_v4l2_device_factory; -struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.v4l2"); -struct spa_log_topic *v4l2_log_topic = &log_topic; +struct spa_log_topic v4l2_log_topic = SPA_LOG_TOPIC(0, "spa.v4l2"); SPA_EXPORT int spa_handle_factory_enum(const struct spa_handle_factory **factory,
View file
pipewire-0.3.81.tar.gz/spa/plugins/v4l2/v4l2.h -> pipewire-0.3.82.tar.gz/spa/plugins/v4l2/v4l2.h
Changed
@@ -4,15 +4,17 @@ #include <errno.h> +#include <linux/videodev2.h> + #include <spa/support/log.h> #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT v4l2_log_topic -extern struct spa_log_topic *v4l2_log_topic; +#define SPA_LOG_TOPIC_DEFAULT &v4l2_log_topic +extern struct spa_log_topic v4l2_log_topic; static inline void v4l2_log_topic_init(struct spa_log *log) { - spa_log_topic_init(log, v4l2_log_topic); + spa_log_topic_init(log, &v4l2_log_topic); } struct spa_v4l2_device {
View file
pipewire-0.3.81.tar.gz/spa/plugins/videoconvert/videoadapter.c -> pipewire-0.3.82.tar.gz/spa/plugins/videoconvert/videoadapter.c
Changed
@@ -25,8 +25,8 @@ #include <spa/debug/log.h> #undef SPA_LOG_TOPIC_DEFAULT -#define SPA_LOG_TOPIC_DEFAULT log_topic -static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.videoadapter"); +#define SPA_LOG_TOPIC_DEFAULT &log_topic +static struct spa_log_topic log_topic = SPA_LOG_TOPIC(0, "spa.videoadapter"); #define DEFAULT_ALIGN 16 @@ -1554,7 +1554,7 @@ this = (struct impl *) handle; this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); - spa_log_topic_init(this->log, log_topic); + spa_log_topic_init(this->log, &log_topic); this->cpu = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_CPU);
View file
pipewire-0.3.81.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -111,6 +111,7 @@ alsa.properties = { + #alsa.deny = false # ALSA params take a single value, an array of values # or a range { min=.. max=... } #alsa.access = MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED
View file
pipewire-0.3.81.tar.gz/src/daemon/pipewire-aes67.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/pipewire-aes67.conf.in
Changed
@@ -23,9 +23,11 @@ } context.objects = - # An example clock reading from /dev/ptp0. Another option is to sync the - # ptp clock to CLOCK_TAI and then set clock.id = tai. - # If both device and ID are given and available, device takes precedence + # An example clock reading from /dev/ptp0. You can also specify the network interface name, + # pipewire will query the interface for the current active PHC index. Another option is to + # sync the ptp clock to CLOCK_TAI and then set clock.id = tai, keep in mind that tai may + # also be synced by a NTP client. + # The precedence is: device, interface, id { factory = spa-node-factory args = { factory.name = support.node.driver @@ -34,8 +36,9 @@ # This driver should only be used for network nodes marked with group priority.driver = 0 clock.name = "clock.system.ptp0" + #clock.id = tai clock.device = "/dev/ptp0" - clock.id = tai + #clock.interface = "eth0" object.export = true } }
View file
pipewire-0.3.81.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.82.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -102,7 +102,12 @@ } # The native communication protocol. - { name = libpipewire-module-protocol-native } + { name = libpipewire-module-protocol-native + args = { + # List of server Unix sockets, and optionally permissions + #sockets = { name = "pipewire-0" }, { name = "pipewire-manager-0" } + } + } # The profile module. Allows application to access profiler # and performance data. It provides an interface that is used
View file
pipewire-0.3.81.tar.gz/src/modules/flatpak-utils.h -> pipewire-0.3.82.tar.gz/src/modules/flatpak-utils.h
Changed
@@ -76,20 +76,20 @@ spa_autoclose int root_fd = openat(AT_FDCWD, root_path, O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC | O_NOCTTY); if (root_fd < 0) { res = -errno; + pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res)); + if (res == -EACCES) { - struct statfs buf; - /* Access to the root dir isn't allowed. This can happen if the root is on a fuse - * filesystem, such as in a toolbox container. We will never have a fuse rootfs - * in the flatpak case, so in that case its safe to ignore this and - * continue to detect other types of apps. */ - if (statfs(root_path, &buf) == 0 && - buf.f_type == 0x65735546) /* FUSE_SUPER_MAGIC */ - return 0; + /* If we can't access the root filesystem, consider not sandboxed. + * This should not happen but for now it is a workaround for selinux + * where we can't access the gnome-shell root when it connects for + * screen sharing. + */ + return 0; } + /* Not able to open the root dir shouldn't happen. Probably the app died and * we're failing due to /proc/$pid not existing. In that case fail instead * of treating this as privileged. */ - pw_log_info("failed to open \"%s\": %s", root_path, spa_strerror(res)); return res; }
View file
pipewire-0.3.81.tar.gz/src/modules/meson.build -> pipewire-0.3.82.tar.gz/src/modules/meson.build
Changed
@@ -313,6 +313,10 @@ pipewire_module_protocol_deps += systemd_dep endif +if selinux_dep.found() + pipewire_module_protocol_deps += selinux_dep +endif + pipewire_module_protocol_native = shared_library('pipewire-module-protocol-native', 'module-protocol-native.c', 'module-protocol-native/local-socket.c', @@ -607,12 +611,13 @@ if build_module_raop pipewire_module_raop_sink = shared_library('pipewire-module-raop-sink', 'module-raop-sink.c', - 'module-raop/rtsp-client.c' , + 'module-raop/rtsp-client.c', + 'module-rtp/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, openssl_lib, + dependencies : mathlib, dl_lib, rt_lib, pipewire_dep, opus_dep, openssl_lib, ) endif summary({'raop-sink (requires OpenSSL)': build_module_raop}, bool_yn: true, section: 'Optional Modules')
View file
pipewire-0.3.81.tar.gz/src/modules/module-access.c -> pipewire-0.3.82.tar.gz/src/modules/module-access.c
Changed
@@ -263,17 +263,11 @@ res = pw_check_flatpak(pid, &flatpak_app_id, NULL); if (res != 0) { - if (res < 0) { - if (res == -EACCES) { - access = "unrestricted"; - goto granted; - } + if (res < 0) pw_log_warn("%p: client %p sandbox check failed: %s", impl, client, spa_strerror(res)); - } - else if (res > 0) { + else pw_log_debug(" %p: flatpak client %p added", impl, client); - } access = "flatpak"; itemsnitems++ = SPA_DICT_ITEM_INIT("pipewire.access.portal.app_id", flatpak_app_id);
View file
pipewire-0.3.81.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.82.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -147,7 +147,9 @@ * * Normally the volume of the sink/source is handled by the stream software volume. * With the capture.volumes and playback.volumes properties this can be handled - * by a control port in the graph instead. + * by a control port in the graph instead. Use capture.volumes for the volume of the + * input of the filter (when for example used as a sink). Use playback,volumes for + * the volume of the output of the filter (when for example used as a source). * * The min and max values (defaults 0.0 and 1.0) respectively can be used to scale * and translate the volume min and max values. @@ -1947,7 +1949,7 @@ /** * { * control = name:portname - * min = <float, defaukt 0.0> + * min = <float, default 0.0> * max = <float, default 1.0> * scale = <string, default "linear", options "linear","cubic"> * }
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -15,9 +15,13 @@ #include <fcntl.h> #include <sys/file.h> #include <ctype.h> +#include <limits.h> #ifdef HAVE_PWD_H #include <pwd.h> #endif +#ifdef HAVE_GRP_H +#include <grp.h> +#endif #if defined(__FreeBSD__) || defined(__MidnightBSD__) #include <sys/ucred.h> #endif @@ -27,13 +31,19 @@ #include <spa/pod/builder.h> #include <spa/utils/result.h> #include <spa/utils/string.h> +#include <spa/utils/json.h> #ifdef HAVE_SYSTEMD #include <systemd/sd-daemon.h> #endif +#ifdef HAVE_SELINUX +#include <selinux/selinux.h> +#endif + #include <pipewire/impl.h> #include <pipewire/extensions/protocol-native.h> +#include <pipewire/cleanup.h> #include "pipewire/private.h" @@ -63,7 +73,17 @@ * * ## Module Options * - * The module has no options. + * The module supports the following arguments: + * + * - `sockets`: ` { name = "socket-name", owner = "owner", group = "group", mode = "mode", selinux.context = "context" }, ... ` + * + * Array of Unix socket names and (optionally) owner/permissions to serve, + * if the context is a server. If not absolute paths, the sockets are created + * in the default runtime directory. If not specified, one socket with + * a default name is created. + * + * The permissions have no effect for sockets from Systemd socket activation. + * Those should be configured via the systemd.socket(5) mechanism. * * ## General Options * @@ -107,6 +127,13 @@ { name = libpipewire-module-protocol-native } * *\endcode + * + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-protocol-native, + * args = { sockets = { name = "pipewire-0" }, { name = "pipewire-1" } } } + * + *\endcode */ #ifndef UNIX_PATH_MAX @@ -165,12 +192,23 @@ free(impl); } +struct socket_info { + char *name; + uid_t uid; + gid_t gid; + int mode; + char *selinux_context; + unsigned int has_owner:1; + unsigned int has_mode:1; +}; + struct server { struct pw_protocol_server this; int fd_lock; struct sockaddr_un addr; char lock_addrUNIX_PATH_MAX + LOCK_SUFFIXLEN; + struct socket_info socket_info; struct pw_loop *loop; struct spa_source *source; @@ -540,6 +578,8 @@ if (props == NULL) goto exit; + pw_properties_set(props, PW_KEY_SEC_SOCKET, s->socket_info.name); + #if defined(__linux__) len = sizeof(ucred); if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) < 0) { @@ -789,6 +829,31 @@ return res; } +static int set_socket_permissions(struct server *s) +{ + struct socket_info *info = &s->socket_info; + const char *path = s->addr.sun_path; + + if (info->has_owner) + if (chown(path, info->uid, info->gid) < 0) + return -errno; + + if (info->has_mode) + if (chmod(path, info->mode) < 0) + return -errno; + + if (info->selinux_context) { +#ifdef HAVE_SELINUX + if (setfilecon(path, info->selinux_context) < 0) + return -errno; +#else + return -EOPNOTSUPP; +#endif + } + + return 0; +} + static int add_socket(struct pw_protocol *protocol, struct server *s) { socklen_t size; @@ -836,11 +901,22 @@ goto error_close; } + if ((res = set_socket_permissions(s)) < 0) { + errno = -res; + pw_log_error("server %p: failed to set socket %s permissions: %m", + s, s->socket_info.name); + goto error_close; + } + if (listen(fd, 128) < 0) { res = -errno; pw_log_error("server %p: listen() failed with error: %m", s); goto error_close; } + } else { + if (s->socket_info.has_owner || s->socket_info.has_mode || s->socket_info.selinux_context) + pw_log_info("server %p: permissions ignored for socket %s from systemd", + s, s->socket_info.name); } res = write_socket_address(s); @@ -1250,6 +1326,8 @@ unlink(s->lock_addr); if (s->fd_lock != -1) close(s->fd_lock); + free(s->socket_info.name); + free(s->socket_info.selinux_context); free(s); } @@ -1311,9 +1389,10 @@ } static struct pw_protocol_server * -impl_add_server(struct pw_protocol *protocol, +add_server(struct pw_protocol *protocol, struct pw_impl_core *core, - const struct spa_dict *props) + const struct spa_dict *props, + struct socket_info *socket_info) { struct pw_protocol_server *this; struct server *s; @@ -1325,7 +1404,16 @@ this = &s->this; - name = get_server_name(props); + if (socket_info) { + s->socket_info = *socket_info; + s->socket_info.name = strdup(socket_info->name); + s->socket_info.selinux_context = socket_info->selinux_context ? + strdup(socket_info->selinux_context) : NULL; + name = socket_info->name; + } else { + name = get_server_name(props); + s->socket_info.name = strdup(name); + } if ((res = init_socket_name(s, name)) < 0) goto error; @@ -1349,6 +1437,14 @@ return NULL; } +static struct pw_protocol_server * +impl_add_server(struct pw_protocol *protocol, + struct pw_impl_core *core, + const struct spa_dict *props) +{ + return add_server(protocol, core, props, NULL); +} + static const struct pw_protocol_implementation protocol_impl = { PW_VERSION_PROTOCOL_IMPLEMENTATION, .new_client = impl_new_client, @@ -1462,14 +1558,121 @@ return 0; } +static int create_servers(struct pw_protocol *this, struct pw_impl_core *core, + const struct pw_properties *props, const struct pw_properties *args) +{ + const char *sockets = args ? pw_properties_get(args, "sockets") : NULL; + struct spa_json it3; + + if (sockets == NULL) { + if (add_server(this, core, &props->dict, NULL) == NULL) + return -errno; + + return 0; + } + + spa_json_init(&it0, sockets, strlen(sockets)); + + if (spa_json_enter_array(&it0, &it1) <= 0) + goto error_invalid; + + while (spa_json_enter_object(&it1, &it2) > 0) { + struct socket_info info = {0}; + char key256; + char namePATH_MAX; + char selinux_contextPATH_MAX; + + info.uid = getuid(); + info.gid = getgid(); + + while (spa_json_get_string(&it2, key, sizeof(key)) > 0) { + const char *value; + int len; + + if ((len = spa_json_next(&it2, &value)) <= 0) + goto error_invalid; + + if (spa_streq(key, "name")) { + if (spa_json_parse_stringn(value, len, name, sizeof(name)) < 0) + goto error_invalid; + info.name = name; + } else if (spa_streq(key, "selinux.context")) { + if (spa_json_parse_stringn(value, len, selinux_context, sizeof(selinux_context)) < 0) + goto error_invalid; + info.selinux_context = selinux_context; + } else if (spa_streq(key, "owner")) { + char buffer16384; + char ownerPATH_MAX; + struct passwd pwd, *result = NULL; + int64_t val; + + if (spa_json_parse_stringn(value, len, owner, sizeof(owner)) < 0) + goto error_invalid; + + if (spa_atoi64(owner, &val, 10)) + info.uid = val; + else if (getpwnam_r(owner, &pwd, buffer, sizeof(buffer), &result) == 0 && result) + info.uid = result->pw_uid; + else + goto error_invalid; + + info.has_owner = true; + } else if (spa_streq(key, "group")) { + char buffer16384; + char groupPATH_MAX; + struct group grp, *result = NULL; + int64_t val; + + if (spa_json_parse_stringn(value, len, group, sizeof(group)) < 0) + goto error_invalid; + + if (spa_atoi64(group, &val, 10)) + info.gid = val; + else if (getgrnam_r(group, &grp, buffer, sizeof(buffer), &result) == 0 && result) + info.gid = result->gr_gid; + else + goto error_invalid; + + info.has_owner = true; + } else if (spa_streq(key, "mode")) { + char modePATH_MAX; + int64_t val; + + if (spa_json_parse_stringn(value, len, mode, sizeof(mode)) < 0) + goto error_invalid; + + if (spa_atoi64(mode, &val, 0)) + info.mode = val; + else + goto error_invalid; + + info.has_mode = true; + } + } + + if (info.name == NULL) + goto error_invalid; + + if (add_server(this, core, &props->dict, &info) == NULL) + return -errno; + } + + return 0; + +error_invalid: + pw_log_error("invalid module 'sockets' argument: %s", sockets); + return -EINVAL; +} + SPA_EXPORT -int pipewire__module_init(struct pw_impl_module *module, const char *args) +int pipewire__module_init(struct pw_impl_module *module, const char *args_str) { struct pw_context *context = pw_impl_module_get_context(module); struct pw_protocol *this; struct pw_impl_core *core = context->core; struct protocol_data *d; const struct pw_properties *props; + spa_autoptr(pw_properties) args = NULL; int res; PW_LOG_TOPIC_INIT(mod_topic); @@ -1480,6 +1683,8 @@ return -EEXIST; } + args = args_str ? pw_properties_new_string(args_str) : NULL; + this = pw_protocol_new(context, PW_TYPE_INFO_PROTOCOL_Native, sizeof(struct protocol_data)); if (this == NULL) return -errno; @@ -1501,12 +1706,9 @@ props = pw_context_get_properties(context); d->local = create_server(this, core, &props->dict); - if (need_server(context, &props->dict)) { - if (impl_add_server(this, core, &props->dict) == NULL) { - res = -errno; + if (need_server(context, &props->dict)) + if ((res = create_servers(this, core, props, args)) < 0) goto error_cleanup; - } - } pw_impl_module_add_listener(module, &d->module_listener, &module_events, d);
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/manager.h -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/manager.h
Changed
@@ -9,11 +9,14 @@ extern "C" { #endif +#include <stdio.h> + #include <spa/utils/defs.h> #include <spa/pod/pod.h> #include <pipewire/pipewire.h> +struct client; struct pw_manager_object; struct pw_manager_events { @@ -68,8 +71,8 @@ struct pw_properties *props; struct pw_proxy *proxy; char *message_object_path; - int (*message_handler)(struct pw_manager *m, struct pw_manager_object *o, - const char *message, const char *params, char **response); + int (*message_handler)(struct client *client, struct pw_manager_object *o, + const char *message, const char *params, FILE *response); void *info; struct spa_param_info *params;
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/message-handler.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/message-handler.c
Changed
@@ -3,8 +3,10 @@ /* SPDX-License-Identifier: MIT */ #include <stdint.h> +#include <stdio.h> #include <regex.h> +#include <malloc.h> #include <spa/param/props.h> #include <spa/pod/builder.h> @@ -15,12 +17,13 @@ #include <pipewire/pipewire.h> +#include "client.h" #include "collect.h" #include "log.h" #include "manager.h" #include "message-handler.h" -static int bluez_card_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response) +static int bluez_card_object_message_handler(struct client *client, struct pw_manager_object *o, const char *message, const char *params, FILE *response) { struct transport_codec_info codecs64; uint32_t n_codecs, active; @@ -60,66 +63,62 @@ pw_device_set_param((struct pw_device *)o->proxy, SPA_PARAM_Props, 0, param); - return 0; } else if (spa_streq(message, "list-codecs")) { uint32_t i; - FILE *r; - size_t size; bool first = true; - r = open_memstream(response, &size); - if (r == NULL) - return -errno; - - fputc('', r); + fputc('', response); for (i = 0; i < n_codecs; ++i) { const char *desc = codecsi.description; - fprintf(r, "%s{\"name\":\"%d\",\"description\":\"%s\"}", + fprintf(response, "%s{\"name\":\"%d\",\"description\":\"%s\"}", first ? "" : ",", (int)codecsi.id, desc ? desc : "Unknown"); first = false; } - fputc('', r); - - return fclose(r) ? -errno : 0; + fputc('', response); } else if (spa_streq(message, "get-codec")) { if (active == SPA_ID_INVALID) - *response = strdup("null"); + fputs("null", response); else - *response = spa_aprintf("\"%d\"", (int)codecsactive.id); - return *response ? 0 : -ENOMEM; + fprintf(response, "\"%d\"", (int) codecsactive.id); + } else { + return -ENOSYS; } - return -ENOSYS; + return 0; } -static int core_object_message_handler(struct pw_manager *m, struct pw_manager_object *o, const char *message, const char *params, char **response) +static int core_object_message_handler(struct client *client, struct pw_manager_object *o, const char *message, const char *params, FILE *response) { pw_log_debug(": core %p object message:'%s' params:'%s'", o, message, params); if (spa_streq(message, "list-handlers")) { - FILE *r; - size_t size; bool first = true; - r = open_memstream(response, &size); - if (r == NULL) - return -errno; - - fputc('', r); - spa_list_for_each(o, &m->object_list, link) { + fputc('', response); + spa_list_for_each(o, &client->manager->object_list, link) { if (o->message_object_path) { - fprintf(r, "%s{\"name\":\"%s\",\"description\":\"%s\"}", + fprintf(response, "%s{\"name\":\"%s\",\"description\":\"%s\"}", first ? "" : ",", o->message_object_path, o->type); first = false; } } - fputc('', r); - return fclose(r) ? -errno : 0; + fputc('', response); +#ifdef HAVE_MALLOC_INFO + } else if (spa_streq(message, "pipewire-pulse:malloc-info")) { + malloc_info(0, response); +#endif +#ifdef HAVE_MALLOC_TRIM + } else if (spa_streq(message, "pipewire-pulse:malloc-trim")) { + int res = malloc_trim(0); + fprintf(response, "%d", res); +#endif + } else { + return -ENOSYS; } - return -ENOSYS; + return 0; } void register_object_message_handlers(struct pw_manager_object *o)
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -1820,6 +1820,8 @@ PW_STREAM_FLAG_MAP_BUFFERS, params, n_params); + stream_update_tag_param(stream); + return 0; error_errno: @@ -3215,7 +3217,8 @@ if (stream == NULL || stream->type == STREAM_TYPE_UPLOAD) return -ENOENT; - pw_stream_update_properties(stream->stream, &props->dict); + if (pw_stream_update_properties(stream->stream, &props->dict) > 0) + stream_update_tag_param(stream); } else { if (pw_properties_update(client->props, &props->dict) > 0) { client_update_quirks(client); @@ -5099,12 +5102,12 @@ { struct impl *impl = client->impl; struct pw_manager *manager = client->manager; - const char *object_path = NULL; - const char *message = NULL; - const char *params = NULL; - struct message *reply; + const char *object_path = NULL, *message = NULL, *params = NULL; struct pw_manager_object *o; - int len = 0; + spa_autofree char *response_str = NULL; + size_t path_len = 0, response_len = 0; + FILE *response; + int res = -ENOENT; if (message_get(m, TAG_STRING, &object_path, @@ -5120,36 +5123,42 @@ if (object_path == NULL || message == NULL) return -EINVAL; - len = strlen(object_path); - if (len > 0 && object_pathlen - 1 == '/') - --len; - - spa_autofree char *path = strndup(object_path, len); + path_len = strlen(object_path); + if (path_len > 0 && object_pathpath_len - 1 == '/') + --path_len; + spa_autofree char *path = strndup(object_path, path_len); if (path == NULL) return -ENOMEM; - spa_autofree char *response = NULL; - int res = -ENOENT; - spa_list_for_each(o, &manager->object_list, link) { - if (o->message_object_path && spa_streq(o->message_object_path, path)) { - if (o->message_handler) - res = o->message_handler(manager, o, message, params, &response); - else - res = -ENOSYS; + if (spa_streq(o->message_object_path, path)) break; - } } + if (spa_list_is_end(o, &manager->object_list, link)) + return -ENOENT; - if (res < 0) - return res; + if (o->message_handler == NULL) + return -ENOSYS; - pw_log_debug("%p: object message response:'%s'", impl, response ? response : "<null>"); + response = open_memstream(&response_str, &response_len); + if (response == NULL) + return -errno; - reply = reply_new(client, tag); - message_put(reply, TAG_STRING, response, TAG_INVALID); + res = o->message_handler(client, o, message, params, response); - return client_queue_message(client, reply); + if (fclose(response)) + return -errno; + + pw_log_debug("%p: object message response: (%d) '%s'", impl, res, response_str ? response_str : "<null>"); + + if (res >= 0) { + struct message *reply = reply_new(client, tag); + + message_put(reply, TAG_STRING, response_str, TAG_INVALID); + res = client_queue_message(client, reply); + } + + return res; } static int do_error_access(struct client *client, uint32_t command, uint32_t tag, struct message *m)
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.c -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/stream.c
Changed
@@ -8,6 +8,9 @@ #include <spa/utils/hook.h> #include <spa/utils/ringbuffer.h> +#include <spa/pod/dynamic.h> +#include <spa/param/tag-utils.h> + #include <pipewire/log.h> #include <pipewire/loop.h> #include <pipewire/map.h> @@ -412,3 +415,36 @@ } return client_queue_message(client, reply); } + +int stream_update_tag_param(struct stream *stream) +{ + struct spa_pod_dynamic_builder b; + const struct pw_properties *props = pw_stream_get_properties(stream->stream); + const struct spa_pod *param1; + struct spa_dict_item items64; + uint32_t i, n_items = 0; + uint8_t buffer4096; + + if (props == NULL) + return -EIO; + + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + + for (i = 0; i < props->dict.n_items; i++) { + if (n_items < SPA_N_ELEMENTS(items) && + spa_strstartswith(props->dict.itemsi.key, "media.")) + itemsn_items++ = props->dict.itemsi; + } + if (n_items > 0) { + struct spa_pod_frame f; + spa_tag_build_start(&b.b, &f, SPA_PARAM_Tag, SPA_DIRECTION_OUTPUT); + spa_tag_build_add_dict(&b.b, &SPA_DICT_INIT(items, n_items)); + param0 = spa_tag_build_end(&b.b, &f); + } else { + param0 = NULL; + } + if (param0 != NULL) + pw_stream_update_params(stream->stream, param, 1); + spa_pod_dynamic_builder_clean(&b); + return 0; +}
View file
pipewire-0.3.81.tar.gz/src/modules/module-protocol-pulse/stream.h -> pipewire-0.3.82.tar.gz/src/modules/module-protocol-pulse/stream.h
Changed
@@ -116,5 +116,6 @@ int stream_send_request(struct stream *stream); int stream_update_minreq(struct stream *stream, uint32_t minreq); int stream_send_moved(struct stream *stream, uint32_t peer_index, const char *peer_name); +int stream_update_tag_param(struct stream *stream); #endif /* PULSER_SERVER_STREAM_H */
View file
pipewire-0.3.81.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.82.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -45,6 +45,7 @@ #include "module-raop/rtsp-client.h" #include "module-rtp/rtp.h" +#include "module-rtp/stream.h" /** \page page_module_raop_sink PipeWire Module: AirPlay Sink * @@ -121,36 +122,37 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic -#define FRAMES_PER_TCP_PACKET 4096 -#define FRAMES_PER_UDP_PACKET 352 +#define BUFFER_SIZE (1u<<22) +#define BUFFER_MASK (BUFFER_SIZE-1) +#define BUFFER_SIZE2 (BUFFER_SIZE>>1) +#define BUFFER_MASK2 (BUFFER_SIZE2-1) -#define RAOP_LATENCY_MIN 11025u -#define DEFAULT_LATENCY_MS "1500" +#define FRAMES_PER_TCP_PACKET 4096 +#define FRAMES_PER_UDP_PACKET 352 -#define DEFAULT_TCP_AUDIO_PORT 6000 -#define DEFAULT_UDP_AUDIO_PORT 6000 -#define DEFAULT_UDP_CONTROL_PORT 6001 -#define DEFAULT_UDP_TIMING_PORT 6002 +#define RAOP_AUDIO_PORT 6000 +#define RAOP_UDP_CONTROL_PORT 6001 +#define RAOP_UDP_TIMING_PORT 6002 #define AES_CHUNK_SIZE 16 #ifndef MD5_DIGEST_LENGTH #define MD5_DIGEST_LENGTH 16 #endif -#define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH) +#define MD5_HASH_LENGTH (2*MD5_DIGEST_LENGTH) #define DEFAULT_USER_NAME "PipeWire" #define RAOP_AUTH_USER_NAME "iTunes" -#define MAX_PORT_RETRY 128 +#define MAX_PORT_RETRY 128 -#define DEFAULT_FORMAT "S16" -#define DEFAULT_RATE 44100 -#define DEFAULT_CHANNELS 2 -#define DEFAULT_POSITION " FL FR " +#define RAOP_FORMAT "S16LE" +#define RAOP_STRIDE (2*DEFAULT_CHANNELS) +#define RAOP_RATE 44100 +#define RAOP_LATENCY_MS 250 -#define VOLUME_MAX 0.0 -#define VOLUME_MIN -30.0 -#define VOLUME_MUTE -144.0 +#define VOLUME_MAX 0.0 +#define VOLUME_MIN -30.0 +#define VOLUME_MUTE -144.0 #define MODULE_USAGE "( raop.ip=<ip address of host> ) " \ "( raop.port=<remote port> ) " \ @@ -163,8 +165,8 @@ "( node.latency=<latency as fraction> ) " \ "( node.name=<name of the nodes> ) " \ "( node.description=<description of the nodes> ) " \ - "( audio.format=<format, default:"DEFAULT_FORMAT"> ) " \ - "( audio.rate=<sample rate, default: "SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ + "( audio.format=<format, default:"RAOP_FORMAT"> ) " \ + "( audio.rate=<sample rate, default: "SPA_STRINGIFY(RAOP_RATE)"> ) " \ "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \ "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ "( stream.props=<properties> ) " @@ -212,10 +214,7 @@ struct spa_hook core_listener; struct pw_properties *stream_props; - struct pw_stream *stream; - struct spa_hook stream_listener; - struct spa_audio_info_raw info; - uint32_t frame_size; + struct rtp_stream *stream; struct pw_rtsp_client *rtsp; struct spa_hook rtsp_listener; @@ -246,15 +245,15 @@ int server_fd; struct spa_source *server_source; - uint32_t block_size; + uint32_t psamples; + uint64_t rate; + uint32_t mtu; + uint32_t stride; uint32_t latency; - uint16_t seq, cseq; - uint32_t rtptime; uint32_t ssrc; uint32_t sync; uint32_t sync_period; - unsigned int first:1; unsigned int connected:1; unsigned int ready:1; unsigned int recording:1; @@ -262,17 +261,14 @@ bool mute; float volume; - uint8_t bufferFRAMES_PER_TCP_PACKET * 4; + struct spa_ringbuffer ring; + uint8_t bufferBUFFER_SIZE; + + struct spa_io_position *io_position; + uint32_t filled; }; -static void stream_destroy(void *d) -{ - struct impl *impl = d; - spa_hook_remove(&impl->stream_listener); - impl->stream = NULL; -} - static inline void bit_writer(uint8_t **p, int *pos, uint8_t data, int len) { int rb = 8 - *pos - len; @@ -307,11 +303,9 @@ return timespec_to_ntp(&now); } -static int send_udp_sync_packet(struct impl *impl, - struct sockaddr *dest_addr, socklen_t addrlen) +static int send_udp_sync_packet(struct impl *impl, uint32_t rtptime, unsigned int first) { uint32_t out3; - uint32_t rtptime = impl->rtptime; uint32_t latency = impl->latency; uint64_t transmitted; struct rtp_header header; @@ -321,11 +315,11 @@ spa_zero(header); header.v = 2; - if (impl->first) + if (first) header.x = 1; header.m = 1; header.pt = 84; - header.sequence_number = htons(impl->cseq); + header.sequence_number = 7; header.timestamp = htonl(rtptime - latency); iov0.iov_base = &header; @@ -339,8 +333,8 @@ iov1.iov_base = out; iov1.iov_len = sizeof(out); - msg.msg_name = dest_addr; - msg.msg_namelen = addrlen; + msg.msg_name = NULL; + msg.msg_namelen = 0; msg.msg_iov = iov; msg.msg_iovlen = 2; msg.msg_control = NULL; @@ -353,10 +347,8 @@ pw_log_warn("error sending control packet: %d", res); } - impl->cseq = (impl->cseq + 1) & 0xffff; - - pw_log_debug("raop control sync: cseq:%d first:%d latency:%u now:%"PRIx64" rtptime:%u", - impl->cseq, impl->first, latency, transmitted, rtptime); + pw_log_debug("raop control sync: first:%d latency:%u now:%"PRIx64" rtptime:%u", + first, latency, transmitted, rtptime); return res; } @@ -440,194 +432,86 @@ return bp - b + 1; } -static int flush_to_udp_packet(struct impl *impl) +static ssize_t send_packet(int fd, struct msghdr *msg) { - const size_t max = 8 + impl->block_size; - uint32_t outmax, len, n_frames; - struct rtp_header header; - struct iovec iov2; + ssize_t n; + n = sendmsg(fd, msg, MSG_NOSIGNAL); + if (n < 0) + pw_log_debug("sendmsg() failed: %m"); + return n; +} + +static void stream_send_packet(void *data, struct iovec *iov, size_t iovlen) +{ + struct impl *impl = data; + const size_t max = 8 + impl->mtu; + uint32_t tcp_pkt1, outmax, len, n_frames, rtptime; + struct iovec out_vec3; + struct rtp_header *header; struct msghdr msg; uint8_t *dst; - int res; if (!impl->recording) - return 0; - - if (impl->first || ++impl->sync == impl->sync_period) { - impl->sync = 0; - send_udp_sync_packet(impl, NULL, 0); - } - - spa_zero(header); - header.v = 2; - header.pt = 96; - if (impl->first) - header.m = 1; - header.sequence_number = htons(impl->seq); - header.timestamp = htonl(impl->rtptime); - header.ssrc = htonl(impl->ssrc); + return; - iov0.iov_base = &header; - iov0.iov_len = 12; + header = (struct rtp_header*)iov0.iov_base; + if (header->v != 2) + pw_log_warn("invalid rtp packet version"); - n_frames = impl->filled / impl->frame_size; - dst = (uint8_t*)&out0; + rtptime = htonl(header->timestamp); - switch (impl->codec) { - case CODEC_PCM: - case CODEC_ALAC: - len = write_codec_pcm(dst, impl->buffer, n_frames); - break; - default: - len = 8 + impl->block_size; - memset(dst, 0, len); - break; + if (header->m || ++impl->sync == impl->sync_period) { + send_udp_sync_packet(impl, rtptime, header->m); + impl->sync = 0; } - if (impl->encryption == CRYPTO_RSA) - aes_encrypt(impl, dst, len); - - iov1.iov_base = out; - iov1.iov_len = len; - impl->rtptime += n_frames; - impl->seq = (impl->seq + 1) & 0xffff; + n_frames = iov1.iov_len / impl->stride; msg.msg_name = NULL; msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 2; + msg.msg_iov = out_vec; + msg.msg_iovlen = 0; msg.msg_control = NULL; msg.msg_controllen = 0; msg.msg_flags = 0; - res = sendmsg(impl->server_fd, &msg, MSG_NOSIGNAL); - if (res < 0) { - res = -errno; - pw_log_warn("error streaming packet: %d", res); - } - - impl->first = false; - - return res; -} - -static int flush_to_tcp_packet(struct impl *impl) -{ - const size_t max = 8 + impl->block_size; - uint32_t tcp_pkt1, outmax, len, n_frames; - struct rtp_header header; - struct iovec iov3; - struct msghdr msg; - uint8_t *dst; - int res; - - if (!impl->recording) - return 0; - - tcp_pkt0 = htonl(0x24000000); - - iov0.iov_base = &tcp_pkt; - iov0.iov_len = 4; - - spa_zero(header); - header.v = 2; - header.pt = 96; - header.sequence_number = htons(impl->seq); - header.timestamp = htonl(impl->rtptime); - header.ssrc = htonl(impl->ssrc); - - iov1.iov_base = &header; - iov1.iov_len = 12; - - n_frames = impl->filled / impl->frame_size; dst = (uint8_t*)&out0; switch (impl->codec) { case CODEC_PCM: case CODEC_ALAC: - len = write_codec_pcm(dst, impl->buffer, n_frames); + len = write_codec_pcm(dst, (void *)iov1.iov_base, n_frames); break; default: - len = 8 + impl->block_size; + len = 8 + impl->mtu; memset(dst, 0, len); break; } if (impl->encryption == CRYPTO_RSA) aes_encrypt(impl, dst, len); - out0 |= htonl((uint32_t) len + 12); - - iov2.iov_base = out; - iov2.iov_len = len; - - impl->rtptime += n_frames; - impl->seq = (impl->seq + 1) & 0xffff; - - msg.msg_name = NULL; - msg.msg_namelen = 0; - msg.msg_iov = iov; - msg.msg_iovlen = 2; - msg.msg_control = NULL; - msg.msg_controllen = 0; - msg.msg_flags = 0; - - res = sendmsg(impl->server_fd, &msg, MSG_NOSIGNAL); - if (res < 0) { - res = -errno; - pw_log_warn("error streaming packet: %d", res); + if (impl->protocol == PROTO_TCP) { + out0 |= htonl((uint32_t) len + 12); + tcp_pkt0 = htonl(0x24000000); + out_vecmsg.msg_iovlen++ = (struct iovec) { tcp_pkt, 4 }; } - impl->first = false; + out_vecmsg.msg_iovlen++ = (struct iovec) { header, 12 }; + out_vecmsg.msg_iovlen++ = (struct iovec) { out, len }; - return res; + pw_log_debug("raop sending %ld", out_vec0.iov_len + out_vec1.iov_len + out_vec2.iov_len); + + send_packet(impl->server_fd, &msg); } -static void playback_stream_process(void *d) +static inline void +set_iovec(struct spa_ringbuffer *rbuf, void *buffer, uint32_t size, + uint32_t offset, struct iovec *iov, uint32_t len) { - struct impl *impl = d; - struct pw_buffer *buf; - struct spa_data *bd; - uint8_t *data; - uint32_t offs, size; - - if ((buf = pw_stream_dequeue_buffer(impl->stream)) == NULL) { - pw_log_debug("out of buffers: %m"); - return; - } - - bd = &buf->buffer->datas0; - - offs = SPA_MIN(bd->chunk->offset, bd->maxsize); - size = SPA_MIN(bd->chunk->size, bd->maxsize - offs); - data = SPA_PTROFF(bd->data, offs, uint8_t); - - while (size > 0 && impl->block_size > 0) { - uint32_t avail, to_fill; - - avail = impl->block_size - impl->filled; - to_fill = SPA_MIN(avail, size); - - memcpy(&impl->bufferimpl->filled, data, to_fill); - - impl->filled += to_fill; - avail -= to_fill; - size -= to_fill; - data += to_fill; - - if (avail == 0) { - switch (impl->protocol) { - case PROTO_UDP: - flush_to_udp_packet(impl); - break; - case PROTO_TCP: - flush_to_tcp_packet(impl); - break; - } - impl->filled = 0; - } - } - - pw_stream_queue_buffer(impl->stream, buf); + 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 int create_udp_socket(struct impl *impl, uint16_t *port) @@ -953,27 +837,6 @@ return 0; } -static int rtsp_do_flush(struct impl *impl) -{ - int res; - - if (!impl->recording) - return 0; - - pw_properties_set(impl->headers, "Range", "npt=0-"); - pw_properties_setf(impl->headers, "RTP-Info", - "seq=%u;rtptime=%u", impl->seq, impl->rtptime); - - impl->recording = false; - - 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); - - return res; -} - static int rtsp_send_volume(struct impl *impl) { if (!impl->recording) @@ -993,6 +856,11 @@ NULL, NULL, 0, rtsp_log_reply_status, impl); } +static uint32_t msec_to_samples(struct impl *impl, uint32_t msec) +{ + return msec * impl->rate / 1000; +} + static int rtsp_record_reply(void *data, int status, const struct spa_dict *headers, const struct pw_array *content) { struct impl *impl = data; @@ -1024,17 +892,18 @@ spa_zero(latency); latency.direction = PW_DIRECTION_INPUT; - latency.min_rate = latency.max_rate = impl->latency + RAOP_LATENCY_MIN; + latency.min_rate = latency.max_rate = impl->latency + msec_to_samples(impl, RAOP_LATENCY_MS); n_params = 0; spa_pod_builder_init(&b, buffer, sizeof(buffer)); paramsn_params++ = spa_latency_build(&b, SPA_PARAM_Latency, &latency); - pw_stream_update_params(impl->stream, params, n_params); + rtp_stream_update_params(impl->stream, params, n_params); + + rtp_stream_set_first(impl->stream); - impl->first = true; impl->sync = 0; - impl->sync_period = impl->info.rate / (impl->block_size / impl->frame_size); + impl->sync_period = impl->rate / (impl->mtu / impl->stride); impl->recording = true; rtsp_send_volume(impl); @@ -1046,13 +915,18 @@ static int rtsp_do_record(struct impl *impl) { int res; + uint16_t seq; + uint32_t rtptime; if (!impl->ready || impl->recording) return 0; + seq = rtp_stream_get_seq(impl->stream); + rtptime = rtp_stream_get_time(impl->stream, &impl->rate); + pw_properties_set(impl->headers, "Range", "npt=0-"); pw_properties_setf(impl->headers, "RTP-Info", - "seq=%u;rtptime=%u", impl->seq, impl->rtptime); + "seq=%u;rtptime=%u", seq, rtptime); res = rtsp_send(impl, "RECORD", NULL, NULL, rtsp_record_reply); @@ -1085,7 +959,7 @@ goto error; impl->ready = true; - if (pw_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING) + if (rtp_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING) rtsp_do_record(impl); } return; @@ -1100,7 +974,6 @@ size_t len; uint64_t ntp; uint16_t control_port, timing_port; - int res; pw_log_info("setup status: %d", status); @@ -1132,12 +1005,6 @@ return 0; } - if ((res = pw_getrandom(&impl->seq, sizeof(impl->seq), 0)) < 0 || - (res = pw_getrandom(&impl->rtptime, sizeof(impl->rtptime), 0)) < 0) { - pw_log_error("error generating random seq and rtptime: %s", spa_strerror(res)); - return 0; - } - pw_log_info("server port:%u", impl->server_port); switch (impl->protocol) { @@ -1176,7 +1043,7 @@ SPA_IO_IN, false, on_control_source_io, impl); impl->ready = true; - if (pw_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING) + if (rtp_stream_get_state(impl->stream, NULL) == PW_STREAM_STATE_STREAMING) rtsp_do_record(impl); break; default: @@ -1196,8 +1063,8 @@ break; case PROTO_UDP: - impl->control_port = DEFAULT_UDP_CONTROL_PORT; - impl->timing_port = DEFAULT_UDP_TIMING_PORT; + impl->control_port = RAOP_UDP_CONTROL_PORT; + impl->timing_port = RAOP_UDP_TIMING_PORT; impl->control_fd = create_udp_socket(impl, &impl->control_port); impl->timing_fd = create_udp_socket(impl, &impl->timing_port); @@ -1336,19 +1203,14 @@ { const char *host; uint8_t rsakey512; + uint32_t rtp_latency; char key512*2; char iv16*2; - int res, frames, rsa_len, ip_version; + int res, rsa_len, ip_version; spa_autofree char *sdp = NULL; char local_ip256; host = pw_properties_get(impl->props, "raop.ip"); - - if (impl->protocol == PROTO_TCP) - frames = FRAMES_PER_TCP_PACKET; - else - frames = FRAMES_PER_UDP_PACKET; - - impl->block_size = frames * impl->frame_size; + rtp_latency = msec_to_samples(impl, RAOP_LATENCY_MS); pw_rtsp_client_get_local_ip(impl->rtsp, &ip_version, local_ip, sizeof(local_ip)); @@ -1364,7 +1226,7 @@ "a=rtpmap:96 AppleLossless\r\n" "a=fmtp:96 %d 0 16 40 10 14 2 255 0 0 %u\r\n", impl->session_id, ip_version, local_ip, - ip_version, host, frames, impl->info.rate); + ip_version, host, impl->psamples, (uint32_t)impl->rate); if (!sdp) return -errno; break; @@ -1379,8 +1241,8 @@ "a=fmtp:96 %d 0 16 40 10 14 2 255 0 0 %u\r\n" "a=min-latency:%d", impl->session_id, ip_version, local_ip, - ip_version, host, frames, impl->info.rate, - RAOP_LATENCY_MIN); + ip_version, host, impl->psamples, (uint32_t)impl->rate, + rtp_latency); if (!sdp) return -errno; break; @@ -1416,7 +1278,7 @@ "a=rsaaeskey:%s\r\n" "a=aesiv:%s\r\n", impl->session_id, ip_version, local_ip, - ip_version, host, frames, impl->info.rate, + ip_version, host, impl->psamples, (uint32_t)impl->rate, key, iv); if (!sdp) return -errno; @@ -1638,24 +1500,23 @@ .message = rtsp_message, }; -static void stream_state_changed(void *d, enum pw_stream_state old, - enum pw_stream_state state, const char *error) +static void stream_destroy(void *d) { struct impl *impl = d; - switch (state) { - case PW_STREAM_STATE_ERROR: - case PW_STREAM_STATE_UNCONNECTED: + impl->stream = NULL; +} + +static void stream_state_changed(void *data, bool started, const char *error) +{ + struct impl *impl = data; + + if (error) { + pw_log_error("stream error: %s", error); pw_impl_module_schedule_destroy(impl->module); - break; - case PW_STREAM_STATE_PAUSED: - rtsp_do_flush(impl); - break; - case PW_STREAM_STATE_STREAMING: - rtsp_do_record(impl); - break; - default: - break; + return; } + if (started) + rtsp_do_record(impl); } static int rtsp_do_connect(struct impl *impl) @@ -1701,6 +1562,8 @@ static int rtsp_do_teardown(struct impl *impl) { + impl->recording = false; + if (!impl->ready) return 0; @@ -1768,7 +1631,7 @@ } param = spa_pod_builder_pop(&b, &f0); - pw_stream_set_param(impl->stream, id, param); + rtp_stream_set_param(impl->stream, id, param); } static void stream_param_changed(void *data, uint32_t id, const struct spa_pod *param) @@ -1791,57 +1654,14 @@ } } -static const struct pw_stream_events playback_stream_events = { - PW_VERSION_STREAM_EVENTS, +static const struct rtp_stream_events stream_events = { + RTP_VERSION_STREAM_EVENTS, .destroy = stream_destroy, .state_changed = stream_state_changed, .param_changed = stream_param_changed, - .process = playback_stream_process + .send_packet = stream_send_packet }; -static int create_stream(struct impl *impl) -{ - int res; - uint32_t n_params; - const struct spa_pod *params1; - uint8_t buffer1024; - struct spa_pod_builder b; - - impl->stream = pw_stream_new(impl->core, "RAOP sink", impl->stream_props); - impl->stream_props = NULL; - - if (impl->stream == NULL) - return -errno; - - pw_stream_add_listener(impl->stream, - &impl->stream_listener, - &playback_stream_events, impl); - - n_params = 0; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - paramsn_params++ = spa_format_audio_raw_build(&b, - SPA_PARAM_EnumFormat, &impl->info); - - if ((res = pw_stream_connect(impl->stream, - PW_DIRECTION_INPUT, - PW_ID_ANY, - PW_STREAM_FLAG_MAP_BUFFERS | - PW_STREAM_FLAG_RT_PROCESS, - params, n_params)) < 0) - return res; - - impl->headers = pw_properties_new(NULL, NULL); - - impl->rtsp = pw_rtsp_client_new(impl->loop, NULL, 0); - if (impl->rtsp == NULL) - return -errno; - - pw_rtsp_client_add_listener(impl->rtsp, &impl->rtsp_listener, - &rtsp_events, impl); - - return 0; -} - static void core_error(void *data, uint32_t id, int seq, int res, const char *message) { struct impl *impl = data; @@ -1873,7 +1693,7 @@ static void impl_destroy(struct impl *impl) { if (impl->stream) - pw_stream_destroy(impl->stream); + rtp_stream_destroy(impl->stream); if (impl->core && impl->do_disconnect) pw_core_disconnect(impl->core); @@ -1902,97 +1722,6 @@ .destroy = module_destroy, }; -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) -{ - int i; - for (i = 0; spa_type_audio_channeli.name; i++) { - if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name))) - return spa_type_audio_channeli.type; - } - return SPA_AUDIO_CHANNEL_UNKNOWN; -} - -static void parse_position(struct spa_audio_info_raw *info, const char *val, size_t len) -{ - struct spa_json it2; - char v256; - - spa_json_init(&it0, val, len); - if (spa_json_enter_array(&it0, &it1) <= 0) - spa_json_init(&it1, val, len); - - info->channels = 0; - while (spa_json_get_string(&it1, v, sizeof(v)) > 0 && - info->channels < SPA_AUDIO_MAX_CHANNELS) { - info->positioninfo->channels++ = channel_from_name(v); - } -} - -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) -{ - const char *str; - - spa_zero(*info); - if ((str = pw_properties_get(props, PW_KEY_AUDIO_FORMAT)) == NULL) - str = DEFAULT_FORMAT; - info->format = format_from_name(str, strlen(str)); - - info->rate = pw_properties_get_uint32(props, PW_KEY_AUDIO_RATE, info->rate); - if (info->rate == 0) - info->rate = DEFAULT_RATE; - - info->channels = pw_properties_get_uint32(props, PW_KEY_AUDIO_CHANNELS, info->channels); - info->channels = SPA_MIN(info->channels, SPA_AUDIO_MAX_CHANNELS); - if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) - parse_position(info, str, strlen(str)); - if (info->channels == 0) - parse_position(info, DEFAULT_POSITION, strlen(DEFAULT_POSITION)); -} - -static int calc_frame_size(struct spa_audio_info_raw *info) -{ - int res = info->channels; - switch (info->format) { - case SPA_AUDIO_FORMAT_U8: - case SPA_AUDIO_FORMAT_S8: - case SPA_AUDIO_FORMAT_ALAW: - case SPA_AUDIO_FORMAT_ULAW: - return res; - case SPA_AUDIO_FORMAT_S16: - case SPA_AUDIO_FORMAT_S16_OE: - case SPA_AUDIO_FORMAT_U16: - return res * 2; - case SPA_AUDIO_FORMAT_S24: - case SPA_AUDIO_FORMAT_S24_OE: - case SPA_AUDIO_FORMAT_U24: - return res * 3; - case SPA_AUDIO_FORMAT_S24_32: - case SPA_AUDIO_FORMAT_S24_32_OE: - case SPA_AUDIO_FORMAT_S32: - case SPA_AUDIO_FORMAT_S32_OE: - case SPA_AUDIO_FORMAT_U32: - case SPA_AUDIO_FORMAT_U32_OE: - case SPA_AUDIO_FORMAT_F32: - case SPA_AUDIO_FORMAT_F32_OE: - return res * 4; - case SPA_AUDIO_FORMAT_F64: - case SPA_AUDIO_FORMAT_F64_OE: - return res * 8; - default: - return 0; - } -} - static void copy_props(struct impl *impl, struct pw_properties *props, const char *key) { const char *str; @@ -2009,7 +1738,7 @@ struct pw_properties *props = NULL; struct impl *impl; const char *str, *name, *hostname, *ip, *port; - int res; + int res = 0; PW_LOG_TOPIC_INIT(mod_topic); @@ -2057,67 +1786,15 @@ goto error; } - if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) - pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); - - if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) - pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); - - if (pw_properties_get(props, PW_KEY_DEVICE_ICON_NAME) == NULL) - pw_properties_set(props, PW_KEY_DEVICE_ICON_NAME, "audio-speakers"); - - if ((name = pw_properties_get(props, "raop.name")) == NULL) - name = "RAOP"; - - if ((str = strstr(name, "@"))) { - str++; - if (strlen(str) > 0) - name = str; - } - if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL) - hostname = name; - - if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) - pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s", - hostname, ip, port); - if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) - pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, - "%s", name); - if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL) - pw_properties_set(props, PW_KEY_NODE_LATENCY, "352/44100"); - - if ((str = pw_properties_get(props, "stream.props")) != NULL) - pw_properties_update_string(impl->stream_props, str, strlen(str)); - - copy_props(impl, props, PW_KEY_AUDIO_FORMAT); - copy_props(impl, props, PW_KEY_AUDIO_RATE); - copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); - copy_props(impl, props, SPA_KEY_AUDIO_POSITION); - copy_props(impl, props, PW_KEY_DEVICE_ICON_NAME); - copy_props(impl, props, PW_KEY_NODE_NAME); - copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); - copy_props(impl, props, PW_KEY_NODE_GROUP); - copy_props(impl, props, PW_KEY_NODE_LATENCY); - copy_props(impl, props, PW_KEY_NODE_VIRTUAL); - copy_props(impl, props, PW_KEY_MEDIA_CLASS); - - parse_audio_info(impl->stream_props, &impl->info); - - impl->frame_size = calc_frame_size(&impl->info); - if (impl->frame_size == 0) { - pw_log_error("unsupported audio format:%d channels:%d", - impl->info.format, impl->info.channels); - res = -EINVAL; - goto error; - } - if ((str = pw_properties_get(props, "raop.transport")) == NULL) str = "udp"; - if (spa_streq(str, "udp")) + if (spa_streq(str, "udp")) { impl->protocol = PROTO_UDP; - else if (spa_streq(str, "tcp")) + impl->psamples = FRAMES_PER_UDP_PACKET; + } else if (spa_streq(str, "tcp")) { impl->protocol = PROTO_TCP; - else { + impl->psamples = FRAMES_PER_TCP_PACKET; + } else { pw_log_error( "can't handle transport %s", str); res = -EINVAL; goto error; @@ -2151,9 +1828,78 @@ str = pw_properties_get(props, "raop.password"); impl->password = str ? strdup(str) : NULL; - if ((str = pw_properties_get(props, "raop.latency.ms")) == NULL) - str = DEFAULT_LATENCY_MS; - impl->latency = SPA_MAX(atoi(str) * impl->info.rate / 1000u, RAOP_LATENCY_MIN); + if ((name = pw_properties_get(props, "raop.name")) == NULL) + name = "RAOP"; + + if ((str = strchr(name, '@')) != NULL) { + str++; + if (strlen(str) > 0) + name = str; + } + if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL) + hostname = name; + + impl->rate = RAOP_RATE; + impl->latency = msec_to_samples(impl, RAOP_LATENCY_MS); + impl->stride = RAOP_STRIDE; + impl->mtu = impl->stride * impl->psamples; + impl->sync_period = impl->rate / impl->psamples; + + if (pw_properties_get(props, PW_KEY_AUDIO_FORMAT) == NULL) + pw_properties_setf(props, PW_KEY_AUDIO_FORMAT, "%s", RAOP_FORMAT); + if (pw_properties_get(props, PW_KEY_AUDIO_RATE) == NULL) + pw_properties_setf(props, PW_KEY_AUDIO_RATE, "%ld", impl->rate); + if (pw_properties_get(props, PW_KEY_DEVICE_ICON_NAME) == NULL) + pw_properties_set(props, PW_KEY_DEVICE_ICON_NAME, "audio-speakers"); + if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) + pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s", + hostname, ip, port); + if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, "%s", name); + if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL) + pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%d/%ld", + impl->psamples, impl->rate); + if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) + pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); + if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) + pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + if (pw_properties_get(props, PW_KEY_MEDIA_FORMAT) == NULL) + pw_properties_setf(props, PW_KEY_MEDIA_FORMAT, "%d", SPA_AUDIO_FORMAT_S16_LE); + if (pw_properties_get(props, "net.mtu") == NULL) + pw_properties_setf(props, "net.mtu", "%d", impl->mtu); + if (pw_properties_get(props, "rtp.sender-ts-offset") == NULL) + pw_properties_setf(props, "rtp.sender-ts-offset", "%d", 0); + if (pw_properties_get(props, "sess.ts-direct") == NULL) + pw_properties_set(props, "sess.ts-direct", 0); + if (pw_properties_get(props, "sess.media") == NULL) + pw_properties_set(props, "sess.media", "raop"); + if (pw_properties_get(props, "sess.latency.msec") == NULL) + pw_properties_setf(props, "sess.latency.msec", "%d", RAOP_LATENCY_MS); + + if ((str = pw_properties_get(props, "stream.props")) != NULL) + pw_properties_update_string(impl->stream_props, str, strlen(str)); + + copy_props(impl, props, PW_KEY_AUDIO_FORMAT); + copy_props(impl, props, PW_KEY_AUDIO_RATE); + copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_POSITION); + copy_props(impl, props, PW_KEY_DEVICE_ICON_NAME); + copy_props(impl, props, PW_KEY_NODE_NAME); + copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); + copy_props(impl, props, PW_KEY_NODE_GROUP); + copy_props(impl, props, PW_KEY_NODE_LATENCY); + copy_props(impl, props, PW_KEY_NODE_VIRTUAL); + copy_props(impl, props, PW_KEY_MEDIA_CLASS); + copy_props(impl, props, PW_KEY_MEDIA_FORMAT); + copy_props(impl, props, "net.mtu"); + copy_props(impl, props, "rtp.sender-ts-offset"); + copy_props(impl, props, "sess.media"); + copy_props(impl, props, "sess.name"); + copy_props(impl, props, "sess.min-ptime"); + copy_props(impl, props, "sess.max-ptime"); + copy_props(impl, props, "sess.latency.msec"); + copy_props(impl, props, "sess.ts-refclk"); + copy_props(impl, props, "sess.ts-direct"); impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); if (impl->core == NULL) { @@ -2178,9 +1924,24 @@ &impl->core_listener, &core_events, impl); - if ((res = create_stream(impl)) < 0) + impl->stream = rtp_stream_new(impl->core, + PW_DIRECTION_INPUT, pw_properties_copy(impl->stream_props), + &stream_events, impl); + if (impl->stream == NULL) { + res = -errno; + pw_log_error("can't create raop stream: %m"); + goto error; + } + + impl->headers = pw_properties_new(NULL, NULL); + + impl->rtsp = pw_rtsp_client_new(impl->loop, NULL, 0); + if (impl->rtsp == NULL) goto error; + pw_rtsp_client_add_listener(impl->rtsp, &impl->rtsp_listener, + &rtsp_events, impl); + pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl); pw_impl_module_update_properties(module, &SPA_DICT_INIT_ARRAY(module_props));
View file
pipewire-0.3.81.tar.gz/src/modules/module-rt.c -> pipewire-0.3.82.tar.gz/src/modules/module-rt.c
Changed
@@ -36,7 +36,7 @@ #include <sys/thr.h> #endif #if defined(__GNU__) -#include <mach.h> +#include <hurd.h> #endif #include <fcntl.h> #include <unistd.h> @@ -225,7 +225,7 @@ thr_self(&pid); return (pid_t)pid; #elif defined(__GNU__) - mach_port_t thread = mach_thread_self(); + mach_port_t thread = hurd_thread_self(); return (pid_t)thread; #else #error "No gettid impl"
View file
pipewire-0.3.81.tar.gz/src/modules/module-rtp/audio.c -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/audio.c
Changed
@@ -226,6 +226,10 @@ iov0.iov_len = sizeof(header); while (avail >= tosend) { + if (impl->marker_on_first && impl->first) + header.m = 1; + else + header.m = 0; header.sequence_number = htons(impl->seq); header.timestamp = htonl(impl->ts_offset + timestamp); @@ -234,11 +238,12 @@ (timestamp * stride) & BUFFER_MASK, &iov1, tosend * stride); - pw_log_trace("sending %d timestamp:%d", tosend, timestamp); + pw_log_trace("sending %d avail:%d ts_offset:%d timestamp:%d", tosend, avail, impl->ts_offset, timestamp); rtp_stream_emit_send_packet(impl, iov, 3); impl->seq++; + impl->first = false; timestamp += tosend; avail -= tosend; }
View file
pipewire-0.3.81.tar.gz/src/modules/module-rtp/stream.c -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/stream.c
Changed
@@ -32,6 +32,7 @@ struct rtp_stream_events, m, v, ##__VA_ARGS__) #define rtp_stream_emit_destroy(s) rtp_stream_emit(s, destroy, 0) #define rtp_stream_emit_state_changed(s,n,e) rtp_stream_emit(s, state_changed,0,n,e) +#define rtp_stream_emit_param_changed(s,i,p) rtp_stream_emit(s, param_changed,0,i,p) #define rtp_stream_emit_send_packet(s,i,l) rtp_stream_emit(s, send_packet,0,i,l) #define rtp_stream_emit_send_feedback(s,seq) rtp_stream_emit(s, send_feedback,0,seq) @@ -58,6 +59,7 @@ unsigned have_ssrc:1; unsigned ignore_ssrc:1; unsigned have_seq:1; + unsigned marker_on_first:1; uint32_t ts_offset; uint32_t psamples; uint32_t mtu; @@ -102,6 +104,7 @@ { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_ALAW, 1, "PCMA", "audio" }, { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_ULAW, 1, "PCMU", "audio" }, { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S16_BE, 2, "L16", "audio" }, + { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S16_LE, 2, "L16", "audio" }, { SPA_MEDIA_SUBTYPE_raw, SPA_AUDIO_FORMAT_S24_BE, 3, "L24", "audio" }, { SPA_MEDIA_SUBTYPE_control, 0, 1, "rtp-midi", "audio" }, { SPA_MEDIA_SUBTYPE_opus, 0, 4, "opus", "audio" }, @@ -132,6 +135,8 @@ if (impl->started) return 0; + impl->first = true; + rtp_stream_emit_state_changed(impl, true, NULL); impl->started = true; @@ -176,10 +181,17 @@ } } +static void on_stream_param_changed (void *d, uint32_t id, const struct spa_pod *param) +{ + struct impl *impl = d; + rtp_stream_emit_param_changed(impl, id, param); +}; + static const struct pw_stream_events stream_events = { PW_VERSION_STREAM_EVENTS, .destroy = stream_destroy, .state_changed = on_stream_state_changed, + .param_changed = on_stream_param_changed, .io_changed = stream_io_changed, }; @@ -287,6 +299,12 @@ impl->info.media_subtype = SPA_MEDIA_SUBTYPE_raw; impl->payload = 127; } + else if (spa_streq(str, "raop")) { + impl->info.media_type = SPA_MEDIA_TYPE_audio; + impl->info.media_subtype = SPA_MEDIA_SUBTYPE_raw; + impl->payload = 0x60; + impl->marker_on_first = 1; + } else if (spa_streq(str, "midi")) { impl->info.media_type = SPA_MEDIA_TYPE_application; impl->info.media_subtype = SPA_MEDIA_SUBTYPE_control; @@ -364,6 +382,7 @@ if (pw_properties_get(props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(props, PW_KEY_NODE_NETWORK, "true"); + impl->marker_on_first = pw_properties_get_bool(props, "sess.marker-on-first", false); impl->ignore_ssrc = pw_properties_get_bool(props, "sess.ignore-ssrc", false); impl->direct_timestamp = pw_properties_get_bool(props, "sess.ts-direct", false); @@ -530,3 +549,40 @@ return pos->clock.position * impl->rate * pos->clock.rate.num / pos->clock.rate.denom; } + +uint16_t rtp_stream_get_seq(struct rtp_stream *s) +{ + struct impl *impl = (struct impl*)s; + + return impl->seq; +} + +void rtp_stream_set_first(struct rtp_stream *s) +{ + struct impl *impl = (struct impl*)s; + + impl->first = true; +} + +enum pw_stream_state rtp_stream_get_state(struct rtp_stream *s, const char **error) +{ + struct impl *impl = (struct impl*)s; + + return pw_stream_get_state(impl->stream, error); +} + +int rtp_stream_set_param(struct rtp_stream *s, uint32_t id, const struct spa_pod *param) +{ + struct impl *impl = (struct impl*)s; + + return pw_stream_set_param(impl->stream, id, param); +} + +int rtp_stream_update_params(struct rtp_stream *s, + const struct spa_pod **params, + uint32_t n_params) +{ + struct impl *impl = (struct impl*)s; + + return pw_stream_update_params(impl->stream, params, n_params); +} \ No newline at end of file
View file
pipewire-0.3.81.tar.gz/src/modules/module-rtp/stream.h -> pipewire-0.3.82.tar.gz/src/modules/module-rtp/stream.h
Changed
@@ -31,9 +31,11 @@ void (*state_changed) (void *data, bool started, const char *error); + void (*param_changed) (void *data, uint32_t id, const struct spa_pod *param); + void (*send_packet) (void *data, struct iovec *iov, size_t iovlen); - void (*send_feedback) (void *data, uint32_t senum); + void (*send_feedback) (void *data, uint32_t seqnum); }; struct rtp_stream *rtp_stream_new(struct pw_core *core, @@ -46,6 +48,17 @@ uint64_t rtp_stream_get_time(struct rtp_stream *s, uint64_t *rate); +uint16_t rtp_stream_get_seq(struct rtp_stream *s); + +void rtp_stream_set_first(struct rtp_stream *s); + +enum pw_stream_state rtp_stream_get_state(struct rtp_stream *s, const char **error); + +int rtp_stream_set_param(struct rtp_stream *s, uint32_t id, const struct spa_pod *param); + +int rtp_stream_update_params(struct rtp_stream *stream, + const struct spa_pod **params, + uint32_t n_params); #ifdef __cplusplus }
View file
pipewire-0.3.81.tar.gz/src/pipewire/context.c -> pipewire-0.3.82.tar.gz/src/pipewire/context.c
Changed
@@ -1027,7 +1027,7 @@ context, n, n->name); if (n->info.state >= PW_NODE_STATE_IDLE) - n->reconfigure = true; + n->need_resume = !n->pause_on_idle; pw_impl_node_set_state(n, PW_NODE_STATE_SUSPENDED); } @@ -1309,7 +1309,7 @@ uint32_t target_quantum, target_rate, current_rate, current_quantum; uint64_t quantum_stamp = 0, rate_stamp = 0; bool force_rate, force_quantum, restore_rate = false, restore_quantum = false; - bool do_reconfigure = false, was_target_pending; + bool do_reconfigure = false, need_resume, was_target_pending; const uint32_t *node_rates; uint32_t node_n_rates, node_def_rate; uint32_t node_max_quantum, node_min_quantum, node_def_quantum, node_rate_quantum; @@ -1399,13 +1399,22 @@ if (force_rate) lock_rate = false; - if (n->reconfigure) + need_resume = n->need_resume; + if (need_resume) { running = true; + n->need_resume = false; + } current_rate = n->target_rate.denom; if (!restore_rate && - (lock_rate || n->reconfigure || !running || - (!force_rate && (n->info.state > PW_NODE_STATE_IDLE)))) + (lock_rate || need_resume || !running || + (!force_rate && (n->info.state > PW_NODE_STATE_IDLE)))) { + pw_log_debug("%p: keep rate:1/%u restore:%u lock:%u resume:%u " + "running:%u force:%u state:%s", context, + current_rate, restore_rate, lock_rate, need_resume, + running, force_rate, + pw_node_state_as_string(n->info.state)); + /* when we don't need to restore or rate and * when someone wants us to lock the rate of this driver or * when we are in the process of reconfiguring the driver or @@ -1413,6 +1422,7 @@ * when the driver is busy and we don't need to force a rate, * keep the current rate */ target_rate = current_rate; + } else { /* Here we are allowed to change the rate of the driver. * Start with the default rate. If the desired rate is @@ -1464,9 +1474,15 @@ current_quantum = n->target_quantum; if (!restore_quantum && - (lock_quantum || n->reconfigure || !running || - (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE)))) + (lock_quantum || need_resume || !running || + (!force_quantum && (n->info.state > PW_NODE_STATE_IDLE)))) { + pw_log_debug("%p: keep quantum:%u restore:%u lock:%u resume:%u " + "running:%u force:%u state:%s", context, + current_quantum, restore_quantum, lock_quantum, need_resume, + running, force_quantum, + pw_node_state_as_string(n->info.state)); target_quantum = current_quantum; + } else { target_quantum = node_def_quantum; if (latency.denom != 0) @@ -1474,7 +1490,7 @@ target_quantum = SPA_CLAMP(target_quantum, node_min_quantum, node_max_quantum); target_quantum = SPA_MIN(target_quantum, lim_quantum); - if (settings->clock_power_of_two_quantum) + if (settings->clock_power_of_two_quantum && !force_quantum) target_quantum = flp2(target_quantum); }
View file
pipewire-0.3.81.tar.gz/src/pipewire/filter.c -> pipewire-0.3.82.tar.gz/src/pipewire/filter.c
Changed
@@ -1659,10 +1659,10 @@ 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, + pw_properties_setf(filter->properties, PW_KEY_NODE_FORCE_RATE, "1/%u", q.denom); - pw_properties_setf(filter->properties, PW_KEY_NODE_LATENCY, - "%u/%u", q.num, q.denom); + pw_properties_setf(filter->properties, PW_KEY_NODE_FORCE_QUANTUM, + "%u", q.num); } } if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
View file
pipewire-0.3.81.tar.gz/src/pipewire/impl-client.c -> pipewire-0.3.82.tar.gz/src/pipewire/impl-client.c
Changed
@@ -152,30 +152,53 @@ return false; } -static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter) +static bool check_client_property_update(struct pw_impl_client *client, + const char *key, const char *old, const char *new) { static const char * const ignored = { + PW_KEY_PROTOCOL, PW_KEY_OBJECT_ID, + PW_KEY_OBJECT_SERIAL, + PW_KEY_ACCESS, NULL }; + /* Refuse specific restricted keys */ + if (has_key(ignored, key)) + goto deny; + + /* Refuse all security keys */ + if (spa_strstartswith(key, "pipewire.sec.")) + goto deny; + + /* Restrict other pipewire.* keys */ + if (spa_strstartswith(key, "pipewire.")) { + /* Refuse changing existing values */ + if (old != NULL) + goto deny; + } + + return true; + +deny: + if (!spa_streq(old, new)) + pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'", + client, key, old ? old : "<unset>", new ? new : "<unset>"); + return false; +} + +static int update_properties(struct pw_impl_client *client, const struct spa_dict *dict, bool filter) +{ struct pw_resource *resource; int changed = 0; uint32_t i; - const char *old; for (i = 0; i < dict->n_items; i++) { if (filter) { - if (spa_strstartswith(dict->itemsi.key, "pipewire.") && - (old = pw_properties_get(client->properties, dict->itemsi.key)) != NULL && - (dict->itemsi.value == NULL || !spa_streq(old, dict->itemsi.value))) { - pw_log_warn("%p: refuse property update '%s' from '%s' to '%s'", - client, dict->itemsi.key, old, - dict->itemsi.value); - continue; + const char *old = pw_properties_get(client->properties, dict->itemsi.key); + const char *new = dict->itemsi.value; - } - if (has_key(ignored, dict->itemsi.key)) + if (!check_client_property_update(client, dict->itemsi.key, old, new)) continue; } changed += pw_properties_set(client->properties, dict->itemsi.key, dict->itemsi.value); @@ -501,6 +524,7 @@ PW_KEY_SEC_UID, PW_KEY_SEC_GID, PW_KEY_SEC_LABEL, + PW_KEY_SEC_SOCKET, NULL };
View file
pipewire-0.3.81.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.82.tar.gz/src/pipewire/impl-node.c
Changed
@@ -418,14 +418,6 @@ spa_list_for_each(resource, &node->global->resource_list, link) pw_resource_error(resource, res, error); } - if (node->reconfigure) { - if (state == PW_NODE_STATE_SUSPENDED && - node->pause_on_idle) { - node->reconfigure = false; - } - if (state == PW_NODE_STATE_RUNNING) - node->reconfigure = false; - } if (old == PW_NODE_STATE_RUNNING && state == PW_NODE_STATE_IDLE && node->suspend_on_idle) {
View file
pipewire-0.3.81.tar.gz/src/pipewire/keys.h -> pipewire-0.3.82.tar.gz/src/pipewire/keys.h
Changed
@@ -38,6 +38,8 @@ #define PW_KEY_SEC_GID "pipewire.sec.gid" /**< client gid, set by protocol*/ #define PW_KEY_SEC_LABEL "pipewire.sec.label" /**< client security label, set by protocol*/ +#define PW_KEY_SEC_SOCKET "pipewire.sec.socket" /**< client socket name, set by protocol */ + #define PW_KEY_LIBRARY_NAME_SYSTEM "library.name.system" /**< name of the system library to use */ #define PW_KEY_LIBRARY_NAME_LOOP "library.name.loop" /**< name of the loop library to use */ #define PW_KEY_LIBRARY_NAME_DBUS "library.name.dbus" /**< name of the dbus library to use */
View file
pipewire-0.3.81.tar.gz/src/pipewire/log.c -> pipewire-0.3.82.tar.gz/src/pipewire/log.c
Changed
@@ -233,13 +233,6 @@ } } -SPA_EXPORT -void -_pw_log_topic_new(struct spa_log_topic *topic) -{ - spa_log_topic_init(global_log, topic); -} - void pw_log_init(void) {
View file
pipewire-0.3.81.tar.gz/src/pipewire/log.h -> pipewire-0.3.82.tar.gz/src/pipewire/log.h
Changed
@@ -72,17 +72,6 @@ int line, const char *func, const char *fmt, va_list args) SPA_PRINTF_FUNC(5, 0); -/** Initialize the log topic. The returned topic is owned by the pipewire - * context and the topic must not be modified or freed. - * Do not use this function directly, use one of PW_LOG_TOPIC_* instead. - * - * \see PW_LOG_TOPIC_STATIC - * \see PW_LOG_TOPIC_EXTERN - * \see PW_LOG_TOPIC - */ -void -_pw_log_topic_new(struct spa_log_topic *topic); - /** * Declare a static log topic named \a var. The usual usage is: * \code
View file
pipewire-0.3.81.tar.gz/src/pipewire/map.h -> pipewire-0.3.82.tar.gz/src/pipewire/map.h
Changed
@@ -189,7 +189,7 @@ * \param id the index to look at * \return the item at \a id or NULL when no such item exists */ -static inline void *pw_map_lookup(struct pw_map *map, uint32_t id) +static inline void *pw_map_lookup(const struct pw_map *map, uint32_t id) { if (SPA_LIKELY(pw_map_check_id(map, id))) { union pw_map_item *item = pw_map_get_item(map, id); @@ -207,8 +207,8 @@ * \param data data to pass to \a func * \return the result of the last call to \a func or 0 when all callbacks returned 0. */ -static inline int pw_map_for_each(struct pw_map *map, - int (*func) (void *item_data, void *data), void *data) +static inline int pw_map_for_each(const struct pw_map *map, + int (*func) (void *item_data, void *data), void *data) { union pw_map_item *item; int res = 0;
View file
pipewire-0.3.81.tar.gz/src/pipewire/private.h -> pipewire-0.3.82.tar.gz/src/pipewire/private.h
Changed
@@ -671,7 +671,7 @@ unsigned int added:1; /**< the node was add to graph */ unsigned int pause_on_idle:1; /**< Pause processing when IDLE */ unsigned int suspend_on_idle:1; - unsigned int reconfigure:1; + unsigned int need_resume:1; unsigned int forced_rate:1; unsigned int forced_quantum:1; unsigned int trigger:1; /**< has the TRIGGER property and needs an extra
View file
pipewire-0.3.81.tar.gz/src/pipewire/stream.c -> pipewire-0.3.82.tar.gz/src/pipewire/stream.c
Changed
@@ -2034,10 +2034,10 @@ 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(stream->properties, PW_KEY_NODE_RATE, + pw_properties_setf(stream->properties, PW_KEY_NODE_FORCE_RATE, "1/%u", q.denom); - pw_properties_setf(stream->properties, PW_KEY_NODE_LATENCY, - "%u/%u", q.num, q.denom); + pw_properties_setf(stream->properties, PW_KEY_NODE_FORCE_QUANTUM, + "%u", q.num); } } if ((str = getenv("PIPEWIRE_LATENCY")) != NULL)
View file
pipewire-0.3.81.tar.gz/src/tools/pw-cat.c -> pipewire-0.3.82.tar.gz/src/tools/pw-cat.c
Changed
@@ -1977,7 +1977,8 @@ uint32_t i, n_items = 0; for (i = 0; i < data.props->dict.n_items; i++) { - if (spa_strstartswith(data.props->dict.itemsi.key, "media.")) + if (n_items < SPA_N_ELEMENTS(items) && + spa_strstartswith(data.props->dict.itemsi.key, "media.")) itemsn_items++ = data.props->dict.itemsi; } if (n_items > 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
.