Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 44
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Mon Sep 16 18:48:10 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.2.3 + +------------------------------------------------------------------- Mon Aug 19 20:39:19 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.2.2
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 1.2.2 +Version: 1.2.3 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-1.2.2.tar.bz2/NEWS -> pipewire-1.2.3.tar.bz2/NEWS
Changed
@@ -1,3 +1,47 @@ +# PipeWire 1.2.3 (2024-08-22) + +This is a bugfix release that is API and ABI compatible with the +previous 1.2.x and 1.0.x releases. + +## Highlights + - Implement freewheeling support in the FFADO driver. Also improve + buffersize and samplerate handling. + - Improve some locking on spa_loop. Remove a possible deadlock when + the queue was full. + - Allocate more space for the libcamera devices string to properly + deduplicate libcamera and v4l2 devices. + - Some more bugfixes and improvements. + + +## PipeWire + - Improve activation state changes and xrun detection some more. + (#4182) + - Avoid a memory leak when a link in error is destroyed. + +## Modules + - Improve samplerate and buffersize handling in FFADO driver so that + it is possible to force a rate and buffer size. + - Implement freewheeling support in the ffado driver. + - Always set the server side clock.quantum-limit on nodes. This fixes + a buffer size problem in Midi-bridge. (#4005) + +## SPA + - Improve some locking on spa_loop. Remove a possible deadlock when + the queue was full. (#4114) + - Allocate more space for the libcamera devices string to properly + deduplicate libcamera and v4l2 devices. + - Fix a potential race when enumerating v4l2 udev devices. (#3960) + +## Bluetooth + - Improve compatibility with some devices (Soundcore Motion 300). + +## Tools + - pw-cli can now handle arbitrarily large input and params. (#4166) + - Avoid some compiler warnings in pw-top. + +Older versions: + + # PipeWire 1.2.2 (2024-07-31) This is a bugfix release that is API and ABI compatible with the @@ -44,9 +88,6 @@ - Fix the jack_get_time() function, it was returning nano instead of micro seconds. -Older versions: - - # PipeWire 1.2.1 (2024-07-12) This is a bugfix release that is API and ABI compatible with previous
View file
pipewire-1.2.2.tar.bz2/meson.build -> pipewire-1.2.3.tar.bz2/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '1.2.2', + version : '1.2.3', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -284,10 +284,14 @@ sdl_dep = dependency('sdl2', required : get_option('sdl2')) summary({'SDL2 (video examples)': sdl_dep.found()}, bool_yn: true, section: 'Misc dependencies') drm_dep = dependency('libdrm', required : false) -readline_dep = dependency('readline', required : get_option('readline')) -if not readline_dep.found() - readline_dep = cc.find_library('readline', required : get_option('readline')) +if get_option('readline').disabled() + readline_dep = dependency('', required: false) +else + readline_dep = dependency('readline', required : false) + if not readline_dep.found() + readline_dep = cc.find_library('readline', required : get_option('readline')) + endif endif # Both the FFmpeg SPA plugin and the pw-cat FFmpeg integration use libavcodec.
View file
pipewire-1.2.2.tar.bz2/pipewire-jack/src/pipewire-jack.c -> pipewire-1.2.3.tar.bz2/pipewire-jack/src/pipewire-jack.c
Changed
@@ -2314,13 +2314,14 @@ struct link *l; pw_log_debug("%p prepared:%d ", c, c->rt.prepared); - if (!c->rt.prepared) - return 0; old_state = SPA_ATOMIC_XCHG(c->activation->status, PW_NODE_ACTIVATION_INACTIVE); if (old_state != PW_NODE_ACTIVATION_FINISHED) trigger = get_time_ns(c->l->system); + if (!c->rt.prepared) + return 0; + spa_list_for_each(l, &c->rt.target_links, target_link) { if (!c->async && trigger != 0) l->trigger(l, trigger);
View file
pipewire-1.2.2.tar.bz2/spa/plugins/alsa/alsa-pcm.c -> pipewire-1.2.3.tar.bz2/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -2292,8 +2292,10 @@ last_pitch = (uint64_t)(1000000 / state->last_rate); } - /* The pitch adjustment is limited to 1 ppm */ - if (pitch == last_pitch) + /* The pitch adjustment is limited to 1 ppm according to the spec, but + * let's avoid very granular changes so that we don't spam the host + * (and ourselves, if bind-ctls are enabled). */ + if (SPA_ABS((int)pitch - (int)last_pitch) < 10) return 0; snd_ctl_elem_value_set_integer(state->pitch_elem, 0, pitch);
View file
pipewire-1.2.2.tar.bz2/spa/plugins/bluez5/backend-native.c -> pipewire-1.2.3.tar.bz2/spa/plugins/bluez5/backend-native.c
Changed
@@ -1012,6 +1012,13 @@ } rfcomm_send_reply(rfcomm, "OK"); + } else if (spa_strstartswith(buf, "AT+CCWA=")) { + /* + * Claim that call waiting notifications are supported. + * Required for some devices (e.g. Soundcore Motion 300), + * as they stop sending commands if the reply to CCWA is not OK. + */ + rfcomm_send_reply(rfcomm, "OK"); } else if (spa_strstartswith(buf, "AT+CLCC")) { struct spa_list *calls; struct call *call;
View file
pipewire-1.2.2.tar.bz2/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-1.2.3.tar.bz2/spa/plugins/libcamera/libcamera-device.cpp
Changed
@@ -119,7 +119,7 @@ uint32_t n_items = 0; struct spa_device_info info; struct spa_param_info params2; - char path256, name256, devices_str128; + char path256, name256, devices_str256; struct spa_strbuf buf; info = SPA_DEVICE_INFO_INIT();
View file
pipewire-1.2.2.tar.bz2/spa/plugins/support/loop.c -> pipewire-1.2.3.tar.bz2/spa/plugins/support/loop.c
Changed
@@ -35,7 +35,6 @@ #define ITEM_ALIGN 8 #define DATAS_SIZE (4096*8) #define MAX_EP 32 -#define DEFAULT_RETRY (1 * SPA_USEC_PER_SEC) /** \cond */ @@ -66,7 +65,6 @@ struct spa_list destroy_list; struct spa_list queue_list; struct spa_hook_list hooks_list; - int retry_timeout; int poll_fd; pthread_t thread; @@ -86,6 +84,11 @@ struct impl *impl; struct spa_list link; +#define QUEUE_FLAG_NONE (0) +#define QUEUE_FLAG_ACK_FD (1<<0) + uint32_t flags; + struct queue *overflow; + int ack_fd; struct spa_ratelimit rate_limit; @@ -172,6 +175,52 @@ return res; } +static struct queue *loop_create_queue(void *object, uint32_t flags) +{ + struct impl *impl = object; + struct queue *queue; + int res; + + queue = calloc(1, sizeof(struct queue)); + if (queue == NULL) + return NULL; + + queue->impl = impl; + queue->flags = flags; + + queue->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; + queue->rate_limit.burst = 1; + + queue->buffer_data = SPA_PTR_ALIGN(queue->buffer_mem, MAX_ALIGN, uint8_t); + spa_ringbuffer_init(&queue->buffer); + + if (flags & QUEUE_FLAG_ACK_FD) { + if ((res = spa_system_eventfd_create(impl->system, + SPA_FD_EVENT_SEMAPHORE | SPA_FD_CLOEXEC)) < 0) { + spa_log_error(impl->log, "%p: can't create ack event: %s", + impl, spa_strerror(res)); + goto error; + } + queue->ack_fd = res; + } else { + queue->ack_fd = -1; + } + + pthread_mutex_lock(&impl->queue_lock); + spa_list_append(&impl->queue_list, &queue->link); + pthread_mutex_unlock(&impl->queue_lock); + + spa_log_info(impl->log, "%p created queue %p", impl, queue); + + return queue; + +error: + free(queue); + errno = -res; + return NULL; +} + + static inline int32_t item_compare(struct invoke_item *a, struct invoke_item *b) { return (int32_t)(a->count - b->count); @@ -185,7 +234,7 @@ pthread_mutex_lock(&impl->queue_lock); flush_count = ++impl->flush_count; while (true) { - struct queue *cqueue, *queue; + struct queue *cqueue, *queue = NULL; struct invoke_item *citem, *item = NULL; uint32_t cindex, index; spa_invoke_func_t func; @@ -228,7 +277,7 @@ block = item->block; spa_ringbuffer_read_update(&queue->buffer, index); - if (block) { + if (block && queue->ack_fd != -1) { if ((res = spa_system_eventfd_write(impl->system, queue->ack_fd, 1)) < 0) spa_log_warn(impl->log, "%p: failed to write event fd:%d: %s", queue, queue->ack_fd, spa_strerror(res)); @@ -313,7 +362,7 @@ } else { loop_signal_event(impl, impl->wakeup); - if (block) { + if (block && queue->ack_fd != -1) { uint64_t count = 1; spa_loop_control_hook_before(&impl->hooks_list); @@ -336,15 +385,18 @@ return res; xrun: - nsec = get_time_ns(impl->system); - if ((suppressed = spa_ratelimit_test(&queue->rate_limit, nsec)) >= 0) { - spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)", - queue, avail, need, suppressed); + if (queue->overflow == NULL) { + nsec = get_time_ns(impl->system); + if ((suppressed = spa_ratelimit_test(&queue->rate_limit, nsec)) >= 0) { + spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)", + queue, avail, need, suppressed); + } + queue->overflow = loop_create_queue(impl, QUEUE_FLAG_NONE); + if (queue->overflow == NULL) + return -errno; + queue->overflow->ack_fd = queue->ack_fd; } - loop_signal_event(impl, impl->wakeup); - if (impl->retry_timeout == 0) - return -EPIPE; - usleep(impl->retry_timeout); + queue = queue->overflow; goto retry; } @@ -363,50 +415,11 @@ spa_list_remove(&queue->link); pthread_mutex_unlock(&impl->queue_lock); - spa_system_close(impl->system, queue->ack_fd); + if (queue->flags & QUEUE_FLAG_ACK_FD) + spa_system_close(impl->system, queue->ack_fd); free(queue); } -static struct queue *loop_create_queue(void *object, uint32_t flags) -{ - struct impl *impl = object; - struct queue *queue; - int res; - - queue = calloc(1, sizeof(struct queue)); - if (queue == NULL) - return NULL; - - queue->impl = impl; - - queue->rate_limit.interval = 2 * SPA_NSEC_PER_SEC; - queue->rate_limit.burst = 1; - - queue->buffer_data = SPA_PTR_ALIGN(queue->buffer_mem, MAX_ALIGN, uint8_t); - spa_ringbuffer_init(&queue->buffer); - - if ((res = spa_system_eventfd_create(impl->system, - SPA_FD_EVENT_SEMAPHORE | SPA_FD_CLOEXEC)) < 0) { - spa_log_error(impl->log, "%p: can't create ack event: %s", - impl, spa_strerror(res)); - goto error; - } - queue->ack_fd = res; - - pthread_mutex_lock(&impl->queue_lock); - spa_list_append(&impl->queue_list, &queue->link); - pthread_mutex_unlock(&impl->queue_lock); - - spa_log_info(impl->log, "%p created queue %p", impl, queue); - - return queue; - -error: - free(queue); - errno = -res; - return NULL; -} - static int loop_invoke(void *object, spa_invoke_func_t func, uint32_t seq, const void *data, size_t size, bool block, void *user_data) { @@ -414,7 +427,7 @@ struct queue *local_queue = tss_get(impl->queue_tss_id); if (local_queue == NULL) { - local_queue = loop_create_queue(impl, 0); + local_queue = loop_create_queue(impl, QUEUE_FLAG_ACK_FD); if (local_queue == NULL) return -errno; tss_set(impl->queue_tss_id, local_queue); @@ -1120,13 +1133,10 @@ SPA_VERSION_LOOP_UTILS, &impl_loop_utils, impl);
View file
pipewire-1.2.2.tar.bz2/spa/plugins/v4l2/v4l2-udev.c -> pipewire-1.2.3.tar.bz2/spa/plugins/v4l2/v4l2-udev.c
Changed
@@ -477,9 +477,6 @@ spa_loop_add_source(this->main_loop, &this->notify); - for (size_t i = 0; i < this->n_devices; i++) - start_watching_device(this, &this->devicesi); - return 0; } @@ -628,10 +625,10 @@ emit_device_info(this, true); - if ((res = enum_devices(this)) < 0) + if ((res = start_monitor(this)) < 0) return res; - if ((res = start_monitor(this)) < 0) + if ((res = enum_devices(this)) < 0) return res; spa_hook_list_join(&this->hooks, &save);
View file
pipewire-1.2.2.tar.bz2/src/daemon/pipewire.conf.in -> pipewire-1.2.3.tar.bz2/src/daemon/pipewire.conf.in
Changed
@@ -254,7 +254,7 @@ node.name = Dummy-Driver node.group = pipewire.dummy node.sync-group = sync.dummy - priority.driver = 20000 + priority.driver = 200000 #clock.id = monotonic # realtime | tai | monotonic-raw | boottime #clock.name = "clock.system.monotonic" } @@ -263,7 +263,7 @@ args = { factory.name = support.node.driver node.name = Freewheel-Driver - priority.driver = 19000 + priority.driver = 190000 node.group = pipewire.freewheel node.sync-group = sync.dummy node.freewheel = true
View file
pipewire-1.2.2.tar.bz2/src/modules/module-ffado-driver.c -> pipewire-1.2.3.tar.bz2/src/modules/module-ffado-driver.c
Changed
@@ -44,9 +44,9 @@ * * - `driver.mode`: the driver mode, sink|source|duplex, default duplex * - `ffado.devices`: array of devices to open, default "hw:0" - * - `ffado.period-size`: period size,default 1024 + * - `ffado.period-size`: period size,default 1024. A value of 0 will use the graph duration. * - `ffado.period-num`: period number,default 3 - * - `ffado.sample-rate`: sample-rate, default 48000 + * - `ffado.sample-rate`: sample-rate, default 48000. A value of 0 will use the graph rate. * - `ffado.slave-mode`: slave mode * - `ffado.snoop-mode`: snoop mode * - `ffado.verbose`: ffado verbose level @@ -192,7 +192,10 @@ unsigned int ready:1; unsigned int running:1; - unsigned int transfered:1; + + struct { + unsigned int transfered:1; + } rt; }; struct impl { @@ -244,19 +247,22 @@ uint32_t output_latency; uint32_t quantum_limit; - uint32_t pw_xrun; - uint32_t ffado_xrun; uint32_t frame_time; unsigned int do_disconnect:1; unsigned int fix_midi:1; unsigned int started:1; + unsigned int freewheel:1; pthread_t thread; - unsigned int done:1; - unsigned int triggered:1; - unsigned int new_xrun:1; + struct { + unsigned int done:1; + unsigned int triggered:1; + unsigned int new_xrun:1; + uint32_t pw_xrun; + uint32_t ffado_xrun; + } rt; }; static int stop_ffado_device(struct impl *impl); @@ -573,9 +579,9 @@ struct impl *impl = s->impl; uint32_t i, n_samples = position->clock.duration; - pw_log_trace_fp("process %d", impl->triggered); - if (impl->mode == MODE_SINK && impl->triggered) { - impl->triggered = false; + pw_log_trace_fp("process %d", impl->rt.triggered); + if (impl->mode == MODE_SINK && impl->rt.triggered) { + impl->rt.triggered = false; return; } @@ -599,11 +605,11 @@ p->cleared = false; } ffado_streaming_transfer_playback_buffers(impl->dev); - s->transfered = true; + s->rt.transfered = true; if (impl->mode == MODE_SINK) { pw_log_trace_fp("done %u", impl->frame_time); - impl->done = true; + impl->rt.done = true; set_timeout(impl, position->clock.nsec); } } @@ -616,10 +622,10 @@ for (i = 0; i < s->n_ports; i++) { struct port *p = s->portsi; if (p != NULL) - clear_port_buffer(p, impl->period_size); + clear_port_buffer(p, impl->device_options.period_size); } ffado_streaming_transfer_playback_buffers(impl->dev); - s->transfered = true; + s->rt.transfered = true; } static void source_process(void *d, struct spa_io_position *position) @@ -628,21 +634,24 @@ struct impl *impl = s->impl; uint32_t i, n_samples = position->clock.duration; - pw_log_trace_fp("process %d", impl->triggered); + pw_log_trace_fp("process %d", impl->rt.triggered); + + if (SPA_FLAG_IS_SET(impl->position->clock.flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER)) + return; - if (!impl->triggered) { + if (!impl->rt.triggered) { pw_log_trace_fp("done %u", impl->frame_time); - impl->done = true; - if (!impl->sink.transfered) + impl->rt.done = true; + if (!impl->sink.rt.transfered) silence_playback(impl); set_timeout(impl, position->clock.nsec); return; } - impl->triggered = false; + impl->rt.triggered = false; ffado_streaming_transfer_capture_buffers(impl->dev); - s->transfered = true; + s->rt.transfered = true; for (i = 0; i < s->n_ports; i++) { struct port *p = s->portsi; @@ -666,10 +675,28 @@ { struct stream *s = data; struct impl *impl = s->impl; + bool freewheel; + if (port_data == NULL) { switch (id) { case SPA_IO_Position: impl->position = area; + freewheel = impl->position != NULL && + SPA_FLAG_IS_SET(impl->position->clock.flags, SPA_IO_CLOCK_FLAG_FREEWHEEL); + if (impl->freewheel != freewheel) { + pw_log_info("freewheel: %d -> %d", impl->freewheel, freewheel); + impl->freewheel = freewheel; + if (impl->started) { + if (freewheel) { + set_timeout(impl, 0); + ffado_streaming_stop(impl->dev); + } else { + ffado_streaming_start(impl->dev); + impl->rt.done = true; + set_timeout(impl, get_time_ns(impl)); + } + } + } break; default: break; @@ -895,6 +922,31 @@ .process = source_process, }; +static int update_stream_format(struct stream *s, uint32_t samplerate) +{ + uint8_t buffer1024; + struct spa_pod_builder b; + uint32_t n_params; + const struct spa_pod *params2; + + if (s->info.rate == samplerate) + return 0; + + s->info.rate = samplerate; + + if (s->filter == NULL) + return 0; + + n_params = 0; + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + paramsn_params++ = spa_format_audio_raw_build(&b, + SPA_PARAM_EnumFormat, &s->info); + paramsn_params++ = spa_format_audio_raw_build(&b, + SPA_PARAM_Format, &s->info); + + return pw_filter_update_params(s->filter, NULL, params, n_params); +} + static int make_stream(struct stream *s, const char *name) { struct impl *impl = s->impl; @@ -902,11 +954,6 @@ const struct spa_pod *params4; uint8_t buffer1024; struct spa_pod_builder b; - struct spa_latency_info latency; - - spa_zero(latency); - n_params = 0; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); s->filter = pw_filter_new(impl->core, name, pw_properties_copy(s->props)); if (s->filter == NULL) @@ -923,6 +970,8 @@ reset_volume(&s->volume, s->info.channels);
View file
pipewire-1.2.2.tar.bz2/src/modules/module-portal.c -> pipewire-1.2.3.tar.bz2/src/modules/module-portal.c
Changed
@@ -58,7 +58,7 @@ * ## Example configuration *\code{.unparsed} * context.modules = - * { name = libpipewire-portal } + * { name = libpipewire-module-portal } * *\endcode *
View file
pipewire-1.2.2.tar.bz2/src/modules/module-raop-discover.c -> pipewire-1.2.3.tar.bz2/src/modules/module-raop-discover.c
Changed
@@ -56,7 +56,7 @@ * *\code{.unparsed} * context.modules = - * { name = libpipewire-raop-discover + * { name = libpipewire-module-raop-discover * args = { * #roap.discover-local = false; * #raop.latency.ms = 1000
View file
pipewire-1.2.2.tar.bz2/src/modules/module-x11-bell.c -> pipewire-1.2.3.tar.bz2/src/modules/module-x11-bell.c
Changed
@@ -50,7 +50,7 @@ * ## Example configuration *\code{.unparsed} * context.modules = - * { name = libpipewire-x11-bell } + * { name = libpipewire-module-x11-bell } * args = { * #sink.name = @DEFAULT_SINK@ * sample.name = "bell-window-system"
View file
pipewire-1.2.2.tar.bz2/src/modules/spa/spa-node.c -> pipewire-1.2.3.tar.bz2/src/modules/spa/spa-node.c
Changed
@@ -243,15 +243,14 @@ struct pw_loop *loop; struct match match; - if (properties) { - p = pw_context_get_properties(context); - pw_properties_set(properties, "clock.quantum-limit", - pw_properties_get(p, "default.clock.quantum-limit")); - } else { + if (properties == NULL) { properties = pw_properties_new(NULL, NULL); if (properties == NULL) return NULL; } + p = pw_context_get_properties(context); + pw_properties_set(properties, "clock.quantum-limit", + pw_properties_get(p, "default.clock.quantum-limit")); match = MATCH_INIT(properties); pw_context_conf_section_match_rules(context, "node.rules",
View file
pipewire-1.2.2.tar.bz2/src/pipewire/impl-link.c -> pipewire-1.2.3.tar.bz2/src/pipewire/impl-link.c
Changed
@@ -1557,6 +1557,7 @@ free(link->name); free(link->info.format); + free((char *) link->info.error); free(impl); }
View file
pipewire-1.2.2.tar.bz2/src/pipewire/impl-node.c -> pipewire-1.2.3.tar.bz2/src/pipewire/impl-node.c
Changed
@@ -222,15 +222,14 @@ pw_log_trace("%p: unprepare %d remote:%d exported:%d", this, this->rt.prepared, this->remote, this->exported); - if (!this->exported) { - /* We mark ourself as finished now, this will avoid going further into the process loop - * in case our fd was ready (removing ourselfs from the loop should avoid that as well). - * If we were supposed to be scheduled make sure we continue the graph for the peers we - * were supposed to trigger */ - old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, PW_NODE_ACTIVATION_INACTIVE); - if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state)) - trigger = get_time_ns(this->rt.target.system); - } + /* We mark ourself as finished now, this will avoid going further into the process loop + * in case our fd was ready (removing ourselfs from the loop should avoid that as well). + * If we were supposed to be scheduled make sure we continue the graph for the peers we + * were supposed to trigger */ + old_state = SPA_ATOMIC_XCHG(this->rt.target.activation->status, PW_NODE_ACTIVATION_INACTIVE); + if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state)) + trigger = get_time_ns(this->rt.target.system); + if (!this->rt.prepared) return 0; @@ -1345,7 +1344,7 @@ str_status(status), suppressed); } -static inline void debug_xrun_graph(struct pw_impl_node *driver, uint64_t nsec) +static inline void debug_xrun_graph(struct pw_impl_node *driver, uint64_t nsec, uint32_t old_status) { int suppressed; enum spa_log_level level = SPA_LOG_LEVEL_DEBUG; @@ -1354,15 +1353,16 @@ if ((suppressed = spa_ratelimit_test(&driver->rt.rate_limit, nsec)) >= 0) level = SPA_LOG_LEVEL_WARN; - pw_log(level, "(%s-%u) graph xrun (%d suppressed)", - driver->name, driver->info.id, suppressed); + pw_log(level, "(%s-%u) graph xrun %s (%d suppressed)", + driver->name, driver->info.id, str_status(old_status), suppressed); spa_list_for_each(t, &driver->rt.target_list, link) { struct pw_node_activation *a = t->activation; struct pw_node_activation_state *state = &a->state0; + uint32_t status = SPA_ATOMIC_LOAD(a->status); - if (a->status == PW_NODE_ACTIVATION_TRIGGERED || - a->status == PW_NODE_ACTIVATION_AWAKE) { + if (status == PW_NODE_ACTIVATION_TRIGGERED || + status == PW_NODE_ACTIVATION_AWAKE) { pw_log(level, "(%s-%u) xrun state:%p pending:%d/%d s:%"PRIu64" a:%"PRIu64" f:%"PRIu64 " waiting:%"PRIu64" process:%"PRIu64" status:%s", t->name, t->id, state, @@ -1372,7 +1372,7 @@ a->finish_time, a->awake_time - a->signal_time, a->finish_time - a->awake_time, - str_status(a->status)); + str_status(status)); } } @@ -1393,6 +1393,7 @@ spa_list_for_each(t, &driver->rt.target_list, link) { struct pw_node_activation *a = t->activation; struct pw_node_activation_state *state = &a->state0; + uint32_t status = SPA_ATOMIC_LOAD(a->status); if (!a->pending_sync) continue; @@ -1406,7 +1407,7 @@ a->finish_time, a->awake_time - a->signal_time, a->finish_time - a->awake_time, - str_status(a->status)); + str_status(status)); } } @@ -1442,7 +1443,8 @@ struct pw_impl_port *p; struct pw_node_activation *a = this->rt.target.activation; struct spa_system *data_system = this->rt.target.system; - int status, old_status; + int status; + bool was_awake; if (!SPA_ATOMIC_CAS(a->status, PW_NODE_ACTIVATION_TRIGGERED, @@ -1450,8 +1452,8 @@ return 0; a->awake_time = nsec; - pw_log_trace_fp("%p: %s process remote:%u exported:%u %"PRIu64" %"PRIu64, - this, this->name, this->remote, this->exported, + pw_log_trace_fp("%p: %s-%d process remote:%u exported:%u %"PRIu64" %"PRIu64, + this, this->name, this->info.id, this->remote, this->exported, a->signal_time, nsec); /* when transport sync is not supported, just clear the flag */ @@ -1481,15 +1483,18 @@ a->state0.status = status; nsec = get_time_ns(data_system); - old_status = SPA_ATOMIC_XCHG(a->status, PW_NODE_ACTIVATION_FINISHED); + was_awake = SPA_ATOMIC_CAS(a->status, + PW_NODE_ACTIVATION_AWAKE, + PW_NODE_ACTIVATION_FINISHED); a->finish_time = nsec; - pw_log_trace_fp("%p: finished status:%d %"PRIu64, this, status, nsec); + pw_log_trace_fp("%p: finished status:%d %"PRIu64" was_awake:%d", + this, status, nsec, was_awake); /* we don't need to trigger targets when the node was driving the * graph because that means we finished the graph. */ if (SPA_LIKELY(!this->driving)) { - if ((!this->async || a->server_version < 1) && old_status == PW_NODE_ACTIVATION_AWAKE) + if ((!this->async || a->server_version < 1) && was_awake) trigger_targets(this, status, nsec); } else { /* calculate CPU time when finished */ @@ -1535,8 +1540,9 @@ nsec / 1000, 0); } - pw_log_trace_fp("%p: remote:%u exported:%u %s got process %"PRIu64, - this, this->remote, this->exported, this->name, nsec); + pw_log_trace_fp("%p: remote:%u exported:%u %s-%d got process %"PRIu64, + this, this->remote, this->exported, this->name, this->info.id, + nsec); process_node(this, nsec); } @@ -2004,13 +2010,12 @@ struct pw_impl_node *node = data; struct pw_impl_node *driver = node->driver_node; struct pw_node_activation *a = node->rt.target.activation; - struct pw_node_activation_state *state = &a->state0; struct spa_system *data_system = node->rt.target.system; struct pw_node_target *t, *reposition_target = NULL;; struct pw_impl_port *p; struct spa_io_clock *cl = &node->rt.position->clock; int sync_type, all_ready, update_sync, target_sync, old_status; - uint32_t owner2, reposition_owner, pending; + uint32_t owner2, reposition_owner; uint64_t min_timeout = UINT64_MAX, nsec; pw_log_trace_fp("%p: ready driver:%d exported:%d %p status:%d prepared:%d", node, @@ -2031,15 +2036,25 @@ nsec = get_time_ns(data_system); - if (SPA_UNLIKELY((pending = pw_node_activation_state_xchg(state)) > 0)) { - pw_impl_node_rt_emit_incomplete(driver); + while (true) { old_status = SPA_ATOMIC_LOAD(a->status); - if (old_status != PW_NODE_ACTIVATION_FINISHED) { - SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED); + if (SPA_LIKELY(old_status == PW_NODE_ACTIVATION_FINISHED)) + /* all good, graph completed */ + break; + if (SPA_ATOMIC_CAS(a->status, old_status, PW_NODE_ACTIVATION_TRIGGERED)) { + /* if we got triggered but did not run the processing yet we don't + * really have an error so we can skip the error reporting. We need + * to run recovery anyway because the ready callback is already + * emitted */ + if (old_status != PW_NODE_ACTIVATION_TRIGGERED) { + /* otherwise, something was wrong and we debug */ + debug_xrun_graph(node, nsec, old_status); + pw_impl_node_rt_emit_incomplete(driver); + } SPA_FLAG_SET(cl->flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER); process_node(node, nsec); SPA_FLAG_CLEAR(cl->flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER); - debug_xrun_graph(node, nsec); + break; } }
View file
pipewire-1.2.2.tar.bz2/src/pipewire/keys.h -> pipewire-1.2.3.tar.bz2/src/pipewire/keys.h
Changed
@@ -74,9 +74,6 @@ #define PW_KEY_LOOP_CLASS "loop.class" /**< the classes this loop handles, array of strings */ #define PW_KEY_LOOP_RT_PRIO "loop.rt-prio" /**< realtime priority of the loop */ #define PW_KEY_LOOP_CANCEL "loop.cancel" /**< if the loop can be canceled */ -#define PW_KEY_LOOP_RETRY_TIMEOUT "loop.retry-timeout" /**< when the loop invoke queue is full, the timeout - * in microseconds before retrying. - * default = 1 second, 0 = disable */ /* context */ #define PW_KEY_CONTEXT_PROFILE_MODULES "context.profile.modules" /**< a context profile for modules, deprecated */ @@ -368,9 +365,11 @@ # ifdef PW_ENABLE_DEPRECATED # define PW_KEY_PRIORITY_MASTER "priority.master" /**< deprecated, use priority.driver */ # define PW_KEY_NODE_TARGET "node.target" /**< deprecated since 0.3.64, use target.object. */ +# define PW_KEY_LOOP_RETRY_TIMEOUT "loop.retry-timeout" /**< deprecated since 1.3.0 */ # else # define PW_KEY_PRIORITY_MASTER PW_DEPRECATED("priority.master") # define PW_KEY_NODE_TARGET PW_DEPRECATED("node.target") +# define PW_KEY_LOOP_RETRY_TIMEOUT PW_DEPRECATED("loop.retry-timeout") # endif /* PW_ENABLE_DEPRECATED */ #endif /* PW_REMOVE_DEPRECATED */
View file
pipewire-1.2.2.tar.bz2/src/pipewire/private.h -> pipewire-1.2.3.tar.bz2/src/pipewire/private.h
Changed
@@ -654,17 +654,21 @@ { struct pw_node_activation *a = t->activation; struct pw_node_activation_state *state = &a->state0; + int32_t pending = SPA_ATOMIC_DEC(state->pending); pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node, - t->name, t->id, state, state->pending, state->required); + t->name, t->id, state, pending, state->required); - if (pw_node_activation_state_dec(state)) { + if (pending == 0) { if (SPA_ATOMIC_CAS(a->status, PW_NODE_ACTIVATION_NOT_TRIGGERED, PW_NODE_ACTIVATION_TRIGGERED)) { a->signal_time = nsec; if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0)) pw_log_warn("%p: write failed %m", t->node); + } else { + pw_log_trace_fp("%p: (%s-%u) not ready %d", t->node, + t->name, t->id, a->status); } } } @@ -673,11 +677,12 @@ { struct pw_node_activation *a = t->activation; struct pw_node_activation_state *state = &a->state0; + int32_t pending = SPA_ATOMIC_DEC(state->pending); pw_log_trace_fp("%p: (%s-%u) state:%p pending:%d/%d", t->node, - t->name, t->id, state, state->pending, state->required); + t->name, t->id, state, pending, state->required); - if (pw_node_activation_state_dec(state)) { + if (pending == 0) { SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED); a->signal_time = nsec; if (SPA_UNLIKELY(spa_system_eventfd_write(t->system, t->fd, 1) < 0))
View file
pipewire-1.2.2.tar.bz2/src/tools/pw-cli.c -> pipewire-1.2.3.tar.bz2/src/tools/pw-cli.c
Changed
@@ -32,7 +32,7 @@ #include <spa/debug/pod.h> #include <spa/utils/keys.h> #include <spa/utils/json-pod.h> -#include <spa/pod/builder.h> +#include <spa/pod/dynamic.h> #include <pipewire/impl.h> #include <pipewire/i18n.h> @@ -1777,10 +1777,12 @@ uint32_t param_id; struct global *global; uint8_t buffer1024; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + spa_auto(spa_pod_dynamic_builder) b = { 0 }; const struct spa_type_info *ti; struct spa_pod *pod; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + n = pw_split_ip(args, WHITESPACE, 3, a); if (n < 3) { *error = spa_aprintf("%s <object-id> <param-id> <param-json>", cmd); @@ -1802,11 +1804,11 @@ *error = spa_aprintf("%s: unknown param type: %s", cmd, a1); return false; } - if ((res = spa_json_to_pod(&b, 0, ti, a2, strlen(a2))) < 0) { + if ((res = spa_json_to_pod(&b.b, 0, ti, a2, strlen(a2))) < 0) { *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); return false; } - if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) { + if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) { *error = spa_aprintf("%s: can't make pod", cmd); return false; } @@ -1911,10 +1913,12 @@ int res, n; struct global *global; uint8_t buffer1024; - struct spa_pod_builder b = SPA_POD_BUILDER_INIT(buffer, sizeof(buffer)); + spa_auto(spa_pod_dynamic_builder) b = { 0 }; const struct spa_type_info *ti; struct spa_pod *pod; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + n = pw_split_ip(args, WHITESPACE, 3, a); if (n < 3) { *error = spa_aprintf("%s <object-id> <command-id> <command-json>", cmd); @@ -1943,11 +1947,11 @@ *error = spa_aprintf("%s: unknown node command type: %s", cmd, a1); return false; } - if ((res = spa_json_to_pod(&b, 0, ti, a2, strlen(a2))) < 0) { + if ((res = spa_json_to_pod(&b.b, 0, ti, a2, strlen(a2))) < 0) { *error = spa_aprintf("%s: can't make pod: %s", cmd, spa_strerror(res)); return false; } - if ((pod = spa_pod_builder_deref(&b, 0)) == NULL) { + if ((pod = spa_pod_builder_deref(&b.b, 0)) == NULL) { *error = spa_aprintf("%s: can't make pod", cmd); return false; } @@ -2387,23 +2391,26 @@ readline_cleanup(); #endif } else { - char buf4096, *p, *error; + FILE *buf; + char *error, *ptr; + size_t size; - p = buf; - for (i = optind; i < argc; i++) { - p = stpcpy(p, argvi); - p = stpcpy(p, " "); - } + buf = open_memstream(&ptr, &size); + for (i = optind; i < argc; i++) + fprintf(buf, "%s%s", i == optind ? "" : " ", argvi); + fclose(buf); // If we're monitoring, surface info changes as well data.monitoring_info = monitor; pw_main_loop_run(data.loop); - if (!parse(&data, buf, &error)) { + if (!parse(&data, ptr, &error)) { fprintf(stderr, "Error: \"%s\"\n", error); free(error); } + free(ptr); + if (data.current != NULL) data.current->prompt_pending = pw_core_sync(data.current->core, 0, 0);
View file
pipewire-1.2.2.tar.bz2/src/tools/pw-top.c -> pipewire-1.2.3.tar.bz2/src/tools/pw-top.c
Changed
@@ -253,7 +253,9 @@ { struct spa_audio_info_iec958 info = { 0 }; if (spa_format_audio_iec958_parse(param, &info) >= 0) { - snprintf(n->format, sizeof(n->format), "IEC958 %s %d", + /* MAX_FORMAT is 16 bytes + \0: 8 bytes in this string, upto 6 bytes for the rate, + * leaving us 2 for the format */ + snprintf(n->format, sizeof(n->format), "IEC958 %2.2s %d", spa_debug_type_find_short_name( spa_type_audio_iec958_codec, info.codec), info.rate);
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
.