Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
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); - impl->retry_timeout = DEFAULT_RETRY; if (info) { if ((str = spa_dict_lookup(info, "loop.cancel")) != NULL && spa_atob(str)) impl->control.iface.cb.funcs = &impl_loop_control_cancel; - if ((str = spa_dict_lookup(info, "loop.retry-timeout")) != NULL) - impl->retry_timeout = atoi(str); } CHECK(pthread_mutexattr_init(&attr), error_exit);
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); + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + n_params = 0; paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &s->info); @@ -950,11 +999,14 @@ uint64_t nsec; ffado_wait_response response; - pw_log_trace_fp("wakeup %d", impl->done); + pw_log_trace_fp("wakeup %d", impl->rt.done); + + if (impl->freewheel) + return; - if (!impl->done) { - impl->pw_xrun++; - impl->new_xrun = true; + if (!impl->rt.done) { + impl->rt.pw_xrun++; + impl->rt.new_xrun = true; ffado_streaming_reset(impl->dev); } again: @@ -967,8 +1019,8 @@ break; case ffado_wait_xrun: pw_log_debug("FFADO xrun"); - impl->ffado_xrun++; - impl->new_xrun = true; + impl->rt.ffado_xrun++; + impl->rt.new_xrun = true; goto again; case ffado_wait_shutdown: pw_log_info("FFADO shutdown"); @@ -981,30 +1033,31 @@ source_running = impl->source.running && impl->sink.ready; sink_running = impl->sink.running && impl->source.ready; - impl->source.transfered = false; - impl->sink.transfered = false; + impl->source.rt.transfered = false; + impl->sink.rt.transfered = false; if (!source_running) { ffado_streaming_transfer_capture_buffers(impl->dev); - impl->source.transfered = true; + impl->source.rt.transfered = true; } if (!sink_running) silence_playback(impl); - pw_log_trace_fp("process %d %u %u %p %d %"PRIu64, impl->period_size, source_running, + pw_log_trace_fp("process %d %u %u %p %d %"PRIu64, + impl->device_options.period_size, source_running, sink_running, impl->position, impl->frame_time, nsec); - if (impl->new_xrun) { + if (impl->rt.new_xrun) { pw_log_warn("Xrun FFADO:%u PipeWire:%u source:%d sink:%d", - impl->ffado_xrun, impl->pw_xrun, source_running, sink_running); - impl->new_xrun = false; + impl->rt.ffado_xrun, impl->rt.pw_xrun, source_running, sink_running); + impl->rt.new_xrun = false; } if (impl->position) { struct spa_io_clock *c = &impl->position->clock; #if 0 - if (c->target_duration != (uint64_t) impl->period_size) { + if (c->target_duration != (uint64_t) impl->device_options.period_size) { ffado_streaming_transfer_capture_buffers(impl->dev); silence_playback(impl); @@ -1012,35 +1065,35 @@ pw_log_warn("can't change period size"); } else { sleep(1); - impl->period_size = c->target_duration; + impl->device_options.period_size = c->target_duration; } goto again; } #endif c->nsec = nsec; - c->rate = SPA_FRACTION(1, impl->sample_rate); - c->position += impl->period_size; - c->duration = impl->period_size; + c->rate = SPA_FRACTION(1, impl->device_options.sample_rate); + c->position += impl->device_options.period_size; + c->duration = impl->device_options.period_size; c->delay = 0; c->rate_diff = 1.0; - c->next_nsec = nsec + (c->duration * SPA_NSEC_PER_SEC) / impl->sample_rate; + c->next_nsec = nsec + (c->duration * SPA_NSEC_PER_SEC) / impl->device_options.sample_rate; c->target_rate = c->rate; c->target_duration = c->duration; } if (impl->mode & MODE_SOURCE && source_running) { - impl->done = false; - impl->triggered = true; + impl->rt.done = false; + impl->rt.triggered = true; set_timeout(impl, nsec + SPA_NSEC_PER_SEC); pw_filter_trigger_process(impl->source.filter); } else if (impl->mode == MODE_SINK && sink_running) { - impl->done = false; - impl->triggered = true; + impl->rt.done = false; + impl->rt.triggered = true; set_timeout(impl, nsec + SPA_NSEC_PER_SEC); pw_filter_trigger_process(impl->sink.filter); } else { - impl->done = true; + impl->rt.done = true; set_timeout(impl, nsec); } } @@ -1064,14 +1117,20 @@ if (impl->dev != NULL) return 0; + target_rate = impl->sample_rate; + target_period = impl->period_size; + if (impl->position) { struct spa_io_clock *c = &impl->position->clock; - target_rate = c->target_rate.denom; - target_period = c->target_duration; - } else { - target_rate = impl->sample_rate; - target_period = impl->period_size; + if (target_rate == 0) + target_rate = c->target_rate.denom; + if (target_period == 0) + target_period = c->target_duration; } + if (target_rate == 0) + target_rate = DEFAULT_SAMPLE_RATE; + if (target_period == 0) + target_period = DEFAULT_PERIOD_SIZE; spa_zero(impl->device_info); impl->device_info.device_spec_strings = impl->devices; @@ -1102,11 +1161,6 @@ ffado_streaming_set_audio_datatype(impl->dev, ffado_audio_datatype_float); - impl->sample_rate = impl->device_options.sample_rate; - impl->period_size = impl->device_options.period_size; - impl->source.info.rate = impl->sample_rate; - impl->sink.info.rate = impl->sample_rate; - impl->source.n_ports = ffado_streaming_get_nb_capture_streams(impl->dev); impl->sink.n_ports = ffado_streaming_get_nb_playback_streams(impl->dev); @@ -1115,9 +1169,13 @@ return -EIO; } + update_stream_format(&impl->source, impl->device_options.sample_rate); + update_stream_format(&impl->sink, impl->device_options.sample_rate); + pw_log_info("opened FFADO device %s source:%d sink:%d rate:%d period:%d %p", impl->devices0, impl->source.n_ports, impl->sink.n_ports, - impl->sample_rate, impl->period_size, impl->position); + impl->device_options.sample_rate, + impl->device_options.period_size, impl->position); return 0; } @@ -1226,7 +1284,7 @@ pw_log_info("FFADO started streaming"); impl->started = true; - impl->done = true; + impl->rt.done = true; set_timeout(impl, get_time_ns(impl)); return 0; }
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
.