Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 43
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Mon Aug 19 20:39:19 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.2.2 + +------------------------------------------------------------------- Sun Jun 30 17:34:39 UTC 2024 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.2.0
View file
pipewire-aptx.spec
Changed
@@ -7,12 +7,12 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 1.2.0 +Version: 1.2.2 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT URL: https://gitlab.freedesktop.org/pipewire/pipewire -Source: %{url}/-/archive/%{version}/pipewire-%{version}.tar.gz +Source: %{url}/-/archive/%{version}/pipewire-%{version}.tar.bz2 BuildRequires: c++_compiler BuildRequires: c_compiler
View file
pipewire-1.2.0.tar.gz/NEWS -> pipewire-1.2.2.tar.bz2/NEWS
Changed
@@ -1,3 +1,96 @@ +# PipeWire 1.2.2 (2024-07-31) + +This is a bugfix release that is API and ABI compatible with the +previous 1.2.x and 1.0.x releases. + +## Highlights + - Fix some more fallout of the async nodes rewrite. Fixes some + crackling, xruns and possibly also some crashes in some cases. + - Fix freewheeling timeouts in case of xruns. This fixes ardour export. + - Fix event mixdown in JACK. Fixes qsynth and possibly other apps. + - Some more small fixes and improvements. + + +## PipeWire + - Add a new SPA_IO_CLOCK_FLAG_XRUN_RECOVER flag when the process function + is called because of xrun recovery. + - Properly stop nodes in all cases, this avoids spurious xruns and + scheduling errors. (#4122) + - Make sure async nodes receive an async link in all cases. Do the + processing of source output ports slightly differently to make sure we + don't cause latency for sources. (#4138) (#4133) + - Fix some races when negotiating and starting nodes. (#4094) + - Actually include the config.h header to use malloc_trim() to reduce + memory usage in pulse-server. + +## Modules + - Avoid unloading some modules on stream errors because it is possible to + recover from the error. (#4121) + - Fix a (harmless) warning in module-rtp because of comparing samples and + time. (#4095) + +## SPA + - Let the freewheel driver detect xrun recovery and handle the timeouts + correctly. This fixes an issue with ardour export. + - Remove the HDMI/AC3 profiles. they turn out to fail on some hardware + with no way to detect this. + - Signal the eventfd when the loop is full to make sure the other thread + is woken up to process the queue. + +## JACK + - Don't check timestamps when mixing down events. The timestamps are only + checked when writing new events with the public API. This fixes an + issue where qsynth would not receive midi events anymore. + - 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 +the previous 1.2.0 release and the 1.0.x releases. + +## Highlights + - Fix a regression in the node activation counters that would break audio + when using KODI. + - Fix a regression in ardour export because of mishandling of sync groups. + - Fix a regression in KDE screen preview because of the new async + scheduling. + - Fix a regression in context.exec argument parsing that would break some + existing scripts. + - More small bug fixes and improvements. + + +## PipeWire + - Fix a regression in the node activation counters that would break audio + when using KODI. (#4087) + - Fix a regression in ardour export because of mishandling of sync groups. + (#4083) + - Fix a regression in KDE screen preview because of the new async + scheduling. Disable async for driver nodes. (#4092) + - Slightly improve node shutdown to cause less xruns. + - Fix a regression in context.exec argument parsing that would break some + existing scripts. + - Support custom thread create functions. + +## Modules + - Improve snapcast address parsing. (#4093) + +## SPA + - Fix multiple %f parsing in ACP for the new plug+a52 profiles. + - Improve v4l2 param generation. Improve recovery when framesize or rates + are unknown, support vivid. (#4063) + +## JACK + - Use the custom thread create function to correctly let module-rt kit + manage threads so that we don't end up with priorities on the wrong + threads. (#4099) + +## GStreamer + - Fix a crash when destroying a stream. + # PipeWire 1.2.0 (2024-06-27) This is the 1.2 release that is API and ABI compatible with previous @@ -69,9 +162,6 @@ ## Bluetooth - Improvements to BAP broadcast code parsing. -Older versions: - - # PipeWire 1.1.83 (2024-06-17) This is the third and hopefully the last 1.2 release candidate that is
View file
pipewire-1.2.0.tar.gz/meson.build -> pipewire-1.2.2.tar.bz2/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '1.2.0', + version : '1.2.2', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -345,9 +345,9 @@ flatpak_support = glib2_dep.found() cdata.set('HAVE_GLIB2', flatpak_support) -gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : get_option('gsettings')) -summary({'GIO (GSettings)': gio_dep.found()}, bool_yn: true, section: 'Misc dependencies') -if not gio_dep.found() and get_option('gsettings-pulse-schema').enabled() +gsettings_gio_dep = dependency('gio-2.0', version : '>= 2.26.0', required : get_option('gsettings')) +summary({'GIO (GSettings)': gsettings_gio_dep.found()}, bool_yn: true, section: 'Misc dependencies') +if not gsettings_gio_dep.found() and get_option('gsettings-pulse-schema').enabled() error('`gsettings-pulse-schema` is enabled but `gio` was not found.') endif
View file
pipewire-1.2.0.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-1.2.2.tar.bz2/pipewire-jack/src/pipewire-jack.c
Changed
@@ -1444,12 +1444,41 @@ } } +static inline jack_midi_data_t* midi_event_reserve(void *port_buffer, + jack_nframes_t time, size_t data_size) +{ + struct midi_buffer *mb = port_buffer; + uint8_t *res = NULL; + + /* Check if data_size is >0 and there is enough space in the buffer for the event. */ + if (SPA_UNLIKELY(data_size <= 0)) { + pw_log_warn("midi %p: data_size:%zd", port_buffer, data_size); + } else if (SPA_UNLIKELY(jack_midi_max_event_size (port_buffer) < data_size)) { + pw_log_warn("midi %p: event too large: data_size:%zd", port_buffer, data_size); + } else { + struct midi_event *events = SPA_PTROFF(mb, sizeof(*mb), struct midi_event); + struct midi_event *ev = &eventsmb->event_count; + + ev->time = time; + ev->size = data_size; + if (SPA_LIKELY(data_size <= MIDI_INLINE_MAX)) { + res = ev->inline_data; + } else { + mb->write_pos += data_size; + ev->byte_offset = mb->buffer_size - 1 - mb->write_pos; + res = SPA_PTROFF(mb, ev->byte_offset, uint8_t); + } + mb->event_count += 1; + } + return res; +} + 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); + jack_midi_data_t *retbuf = midi_event_reserve (port_buffer, time, data_size); if (SPA_UNLIKELY(retbuf == NULL)) return -ENOBUFS; memcpy (retbuf, data, data_size); @@ -3182,31 +3211,27 @@ void *(*start)(void*), void *arg) { struct client *c = (struct client *) object; - struct spa_thread *thr; - int res = 0; + struct spa_dict_item *items; + struct spa_dict copy; + char creator_ptr64; pw_log_info("create thread"); if (globals.creator != NULL) { - pthread_t pt; - pthread_attr_t *attr = NULL, attributes; + uint32_t i, n_items = props ? props->n_items : 0; - attr = pw_thread_fill_attr(props, &attributes); + items = alloca((n_items) + 1 * sizeof(*items)); - res = -globals.creator(&pt, attr, start, arg); - if (attr) - pthread_attr_destroy(attr); - if (res != 0) - goto error; - thr = (struct spa_thread*)pt; - } else { - thr = spa_thread_utils_create(c->context.old_thread_utils, props, start, arg); - } - return thr; -error: - pw_log_warn("create RT thread failed: %s", strerror(res)); - errno = -res; - return NULL; + for (i = 0; i < n_items; i++) + itemsi = props->itemsi; + snprintf(creator_ptr, sizeof(creator_ptr), "pointer:%p", globals.creator); + itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_THREAD_CREATOR, + creator_ptr); + + copy = SPA_DICT_INIT(items, n_items); + props = © + } + return spa_thread_utils_create(c->context.old_thread_utils, props, start, arg); } static int impl_join(void *object, @@ -5557,7 +5582,7 @@ ptr = p->get_buffer(p, frames); } done: - pw_log_trace_fp("%p: port:%p buffer:%p frames:%d", c, p, ptr, frames); + pw_log_warn("%p: port:%p buffer:%p frames:%d", c, p, ptr, frames); return ptr; } @@ -6746,7 +6771,7 @@ { struct timespec ts; clock_gettime(CLOCK_MONOTONIC, &ts); - return SPA_TIMESPEC_TO_NSEC(&ts); + return SPA_TIMESPEC_TO_USEC(&ts); } SPA_EXPORT @@ -7358,55 +7383,45 @@ } } -SPA_EXPORT -jack_midi_data_t* jack_midi_event_reserve(void *port_buffer, - jack_nframes_t time, - size_t data_size) +static inline int midi_buffer_check(void *port_buffer, jack_nframes_t time) { struct midi_buffer *mb = port_buffer; struct midi_event *events; if (SPA_UNLIKELY(mb == NULL)) { pw_log_warn("port buffer is NULL"); - return NULL; + return -EINVAL; } if (SPA_UNLIKELY(mb->magic != MIDI_BUFFER_MAGIC)) { pw_log_warn("port buffer is invalid"); - return NULL; + return -EINVAL; } if (SPA_UNLIKELY(time >= mb->nframes)) { pw_log_warn("midi %p: time:%d frames:%d", port_buffer, time, mb->nframes); - goto failed; + return -EINVAL; } events = SPA_PTROFF(mb, sizeof(*mb), struct midi_event); if (SPA_UNLIKELY(mb->event_count > 0 && time < eventsmb->event_count - 1.time)) { pw_log_warn("midi %p: time:%d ev:%d", port_buffer, time, mb->event_count); - goto failed; + return -EINVAL; } + return 0; +} - /* Check if data_size is >0 and there is enough space in the buffer for the event. */ - if (SPA_UNLIKELY(data_size <= 0)) { - pw_log_warn("midi %p: data_size:%zd", port_buffer, data_size); - goto failed; // return NULL? - } else if (SPA_UNLIKELY(jack_midi_max_event_size (port_buffer) < data_size)) { - pw_log_warn("midi %p: event too large: data_size:%zd", port_buffer, data_size); +SPA_EXPORT +jack_midi_data_t* jack_midi_event_reserve(void *port_buffer, + jack_nframes_t time, + size_t data_size) +{ + struct midi_buffer *mb = port_buffer; + jack_midi_data_t *res; + + if (midi_buffer_check(port_buffer, time) < 0) goto failed; - } else { - struct midi_event *ev = &eventsmb->event_count; - uint8_t *res; - ev->time = time; - ev->size = data_size; - if (SPA_LIKELY(data_size <= MIDI_INLINE_MAX)) { - res = ev->inline_data; - } else { - mb->write_pos += data_size; - ev->byte_offset = mb->buffer_size - 1 - mb->write_pos; - res = SPA_PTROFF(mb, ev->byte_offset, uint8_t); - } - mb->event_count += 1; + res = midi_event_reserve(port_buffer, time, data_size); + if (res != NULL) return res; - } failed: mb->lost_events++; return NULL; @@ -7418,7 +7433,17 @@ const jack_midi_data_t *data, size_t data_size) { - return midi_event_write(port_buffer, time, data, data_size, false); + jack_midi_data_t *ptr; + int res; + + if ((res = midi_buffer_check(port_buffer, time)) < 0) + return res; + + if ((ptr = midi_event_reserve(port_buffer, time, data_size)) == NULL) + return -ENOBUFS; + + memcpy (ptr, data, data_size); + return 0; } SPA_EXPORT
View file
pipewire-1.2.0.tar.gz/spa/include/spa/node/io.h -> pipewire-1.2.2.tar.bz2/spa/include/spa/node/io.h
Changed
@@ -125,7 +125,8 @@ * \ref spa_io_position.clock.id in \ref SPA_IO_Position are the same. */ struct spa_io_clock { -#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0) +#define SPA_IO_CLOCK_FLAG_FREEWHEEL (1u<<0) /* graph is freewheeling */ +#define SPA_IO_CLOCK_FLAG_XRUN_RECOVER (1u<<1) /* recovering from xrun */ uint32_t flags; /**< Clock flags */ uint32_t id; /**< Unique clock id, set by host application */ char name64; /**< Clock name prefixed with API, set by node when it receives
View file
pipewire-1.2.0.tar.gz/spa/include/spa/support/thread.h -> pipewire-1.2.2.tar.bz2/spa/include/spa/support/thread.h
Changed
@@ -118,6 +118,7 @@ #define SPA_KEY_THREAD_NAME "thread.name" /* the thread name */ #define SPA_KEY_THREAD_STACK_SIZE "thread.stack-size" /* the stack size of the thread */ #define SPA_KEY_THREAD_AFFINITY "thread.affinity" /* array of CPUs for this thread */ +#define SPA_KEY_THREAD_CREATOR "thread.creator" /* platform specific thread creator function */ /** * \}
View file
pipewire-1.2.0.tar.gz/spa/include/spa/utils/cleanup.h -> pipewire-1.2.2.tar.bz2/spa/include/spa/utils/cleanup.h
Changed
@@ -31,6 +31,7 @@ /* ========================================================================== */ +#include <errno.h> #include <unistd.h> #define spa_steal_fd(fd) spa_exchange((fd), -1) @@ -53,7 +54,9 @@ typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \ static inline void _spa_auto_cleanup_func_ ## name (__typeof__(type) *thing) \ { \ + int _save_errno = errno; \ __VA_ARGS__ \ + errno = _save_errno; \ } #define spa_auto(name) \ @@ -64,7 +67,9 @@ typedef __typeof__(type) * _spa_autoptr_cleanup_type_ ## name; \ static inline void _spa_autoptr_cleanup_func_ ## name (__typeof__(type) **thing) \ { \ + int _save_errno = errno; \ __VA_ARGS__ \ + errno = _save_errno; \ } #define spa_autoptr(name) \ @@ -77,7 +82,9 @@ static inline void _spa_autofree_cleanup_func(void *p) { + int save_errno = errno; free(*(void **) p); + errno = save_errno; } #define spa_autofree spa_cleanup(_spa_autofree_cleanup_func) @@ -85,7 +92,9 @@ static inline void _spa_autoclose_cleanup_func(int *fd) { + int save_errno = errno; spa_clear_fd(*fd); + errno = save_errno; } #define spa_autoclose spa_cleanup(_spa_autoclose_cleanup_func)
View file
pipewire-1.2.0.tar.gz/spa/meson.build -> pipewire-1.2.2.tar.bz2/spa/meson.build
Changed
@@ -47,12 +47,12 @@ summary({'ALSA': alsa_dep.found()}, bool_yn: true, section: 'Backend') bluez_dep = dependency('bluez', version : '>= 4.101', required: get_option('bluez5')) - gio_dep = dependency('gio-2.0', required : get_option('bluez5')) - gio_unix_dep = dependency('gio-unix-2.0', required : get_option('bluez5')) + bluez_gio_dep = dependency('gio-2.0', required : get_option('bluez5')) + bluez_gio_unix_dep = dependency('gio-unix-2.0', required : get_option('bluez5')) bluez_glib2_dep = dependency('glib-2.0', required : get_option('bluez5')) sbc_dep = dependency('sbc', required: get_option('bluez5')) summary({'SBC': sbc_dep.found()}, bool_yn: true, section: 'Bluetooth audio codecs') - bluez5_deps = mathlib, dbus_dep, sbc_dep, bluez_dep, bluez_glib2_dep, gio_dep, gio_unix_dep + bluez5_deps = mathlib, dbus_dep, sbc_dep, bluez_dep, bluez_glib2_dep, bluez_gio_dep, bluez_gio_unix_dep bluez_deps_found = get_option('bluez5').allowed() foreach dep: bluez5_deps if get_option('bluez5').enabled() and not dep.found()
View file
pipewire-1.2.0.tar.gz/spa/plugins/alsa/alsa-acp-device.c -> pipewire-1.2.2.tar.bz2/spa/plugins/alsa/alsa-acp-device.c
Changed
@@ -126,6 +126,29 @@ return 0; } +static int replace_string(const char *str, const char *val, const char *rep, + char *buf, size_t size) +{ + struct spa_strbuf s; + const char *p; + size_t len = strlen(val); + + spa_assert(len > 0); + spa_strbuf_init(&s, buf, size); + + while (1) { + p = strstr(str, val); + if (!p) + break; + + spa_strbuf_append(&s, "%.*s%s", (int)SPA_PTRDIFF(p, str), str, rep); + str = p + len; + } + + spa_strbuf_append(&s, "%s", str); + return 0; +} + static int emit_node(struct impl *this, struct acp_device *dev) { struct spa_dict_item *items; @@ -136,7 +159,7 @@ char positionsSPA_AUDIO_MAX_CHANNELS * 12; struct spa_device_object_info info; struct acp_card *card = this->card; - const char *stream, *devstr, *card_id; + const char *stream, *card_id; info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Node; @@ -158,15 +181,7 @@ card_id = acp_dict_lookup(&card->props, "alsa.id"); snprintf(card_name, sizeof(card_name), "%s", card_id ? card_id : card_index); - devstr = dev->device_strings0; - p = strstr(devstr, "%f"); - if (p) { - snprintf(device_name, sizeof(device_name), "%.*s%d%s", - (int)SPA_PTRDIFF(p, devstr), devstr, - card->index, p+2); - } else { - snprintf(device_name, sizeof(device_name), "%s", devstr); - } + replace_string(dev->device_strings0, "%f", card_index, device_name, sizeof(device_name)); snprintf(path, sizeof(path), "alsa:acp:%s:%d:%s", card_name, dev->index, stream); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_OBJECT_PATH, path);
View file
pipewire-1.2.0.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-1.2.2.tar.bz2/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -2245,7 +2245,9 @@ state->max_delay = state->buffer_frames / 2; if (spa_strstartswith(state->props.device, "a52") || - spa_strstartswith(state->props.device, "dca")) + spa_strstartswith(state->props.device, "dca") || + (spa_strstartswith(state->props.device, "plug:") && + strstr(state->props.device, "a52:"))) state->min_delay = SPA_MIN(2048u, state->buffer_frames); else state->min_delay = 0;
View file
pipewire-1.2.0.tar.gz/spa/plugins/alsa/mixer/profile-sets/default.conf -> pipewire-1.2.2.tar.bz2/spa/plugins/alsa/mixer/profile-sets/default.conf
Changed
@@ -237,14 +237,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround -description = Digital Surround 5.1 (HDMI/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,3'"} -paths-output = hdmi-output-0 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra1 description = Digital Stereo (HDMI 2) device-strings = hdmi:%f,1 @@ -277,14 +269,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra1 -description = Digital Surround 5.1 (HDMI 2/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,7'"} -paths-output = hdmi-output-1 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra2 description = Digital Stereo (HDMI 3) device-strings = hdmi:%f,2 @@ -317,14 +301,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra2 -description = Digital Surround 5.1 (HDMI 3/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,8'"} -paths-output = hdmi-output-2 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra3 description = Digital Stereo (HDMI 4) device-strings = hdmi:%f,3 @@ -357,14 +333,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra3 -description = Digital Surround 5.1 (HDMI 4/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,9'"} -paths-output = hdmi-output-3 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra4 description = Digital Stereo (HDMI 5) device-strings = hdmi:%f,4 @@ -397,14 +365,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra4 -description = Digital Surround 5.1 (HDMI 5/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,10'"} -paths-output = hdmi-output-4 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra5 description = Digital Stereo (HDMI 6) device-strings = hdmi:%f,5 @@ -437,14 +397,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra5 -description = Digital Surround 5.1 (HDMI 6/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,11'"} -paths-output = hdmi-output-5 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra6 description = Digital Stereo (HDMI 7) device-strings = hdmi:%f,6 @@ -477,14 +429,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra6 -description = Digital Surround 5.1 (HDMI 7/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,12'"} -paths-output = hdmi-output-6 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra7 description = Digital Stereo (HDMI 8) device-strings = hdmi:%f,7 @@ -517,14 +461,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra7 -description = Digital Surround 5.1 (HDMI 8/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,13'"} -paths-output = hdmi-output-7 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra8 description = Digital Stereo (HDMI 9) device-strings = hdmi:%f,8 @@ -557,14 +493,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra8 -description = Digital Surround 5.1 (HDMI 9/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,14'"} -paths-output = hdmi-output-8 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra9 description = Digital Stereo (HDMI 10) device-strings = hdmi:%f,9 @@ -597,14 +525,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra9 -description = Digital Surround 5.1 (HDMI 10/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,15'"} -paths-output = hdmi-output-9 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping hdmi-stereo-extra10 description = Digital Stereo (HDMI 11) device-strings = hdmi:%f,10 @@ -637,14 +557,6 @@ priority = 6 direction = output -Mapping hdmi-ac3-surround-extra10 -description = Digital Surround 5.1 (HDMI 11/AC3) -device-strings = plug:{SLAVE="a52:%f,'hw:%f,16'"} -paths-output = hdmi-output-10 -channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe -priority = 6 -direction = output - Mapping multichannel-output device-strings = hw:%f channel-map = left,right,rear-left,rear-right
View file
pipewire-1.2.0.tar.gz/spa/plugins/audioconvert/audioadapter.c -> pipewire-1.2.2.tar.bz2/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -268,23 +268,31 @@ res, spa_strerror(res)); } + return 0; +} + +static int activate_io(struct impl *this, bool active) +{ + int res; + struct spa_io_buffers *data = active ? &this->io_buffers : NULL; + uint32_t size = active ? sizeof(this->io_buffers) : 0; + if (this->follower == this->target) return 0; - this->io_buffers = SPA_IO_BUFFERS_INIT; + if (active) + this->io_buffers = SPA_IO_BUFFERS_INIT; if ((res = spa_node_port_set_io(this->follower, this->direction, 0, - SPA_IO_Buffers, - &this->io_buffers, sizeof(this->io_buffers))) < 0) { + SPA_IO_Buffers, data, size)) < 0) { spa_log_warn(this->log, "%p: set Buffers on follower failed %d %s", this, res, spa_strerror(res)); return res; } else if ((res = spa_node_port_set_io(this->convert, SPA_DIRECTION_REVERSE(this->direction), 0, - SPA_IO_Buffers, - &this->io_buffers, sizeof(this->io_buffers))) < 0) { + SPA_IO_Buffers, data, size)) < 0) { spa_log_warn(this->log, "%p: set Buffers on convert failed %d %s", this, res, spa_strerror(res)); return res; @@ -484,6 +492,8 @@ this->buffers, this->n_buffers)) < 0) return res; + activate_io(this, true); + return 0; } @@ -499,12 +509,20 @@ uint8_t buffer4096; int res; + spa_log_debug(this->log, "%p: configure format:", this); + if (format == NULL && !this->have_format) return 0; - spa_log_debug(this->log, "%p: configure format:", this); - if (format) + + if (format == NULL) { + if (!this->have_format) + return 0; + activate_io(this, false); + } + else { spa_debug_log_format(this->log, SPA_LOG_LEVEL_DEBUG, 0, NULL, format); + } if ((res = spa_node_port_set_param(this->follower, this->direction, 0,
View file
pipewire-1.2.0.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-1.2.2.tar.bz2/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -193,6 +193,7 @@ struct spa_log *log; struct spa_cpu *cpu; + struct spa_loop *data_loop; uint32_t cpu_flags; uint32_t max_align; @@ -2448,7 +2449,7 @@ port = GET_PORT(this, direction, port_id); - spa_log_debug(this->log, "%p: set format", this); + spa_log_debug(this->log, "%p: %d:%d set format", this, direction, port_id); if (format == NULL) { port->have_format = false; @@ -2677,6 +2678,20 @@ return 0; } +struct io_data { + struct port *port; + void *data; + size_t size; +}; + +static int do_set_port_io(struct spa_loop *loop, bool async, uint32_t seq, + const void *data, size_t size, void *user_data) +{ + const struct io_data *d = user_data; + d->port->io = d->data; + return 0; +} + static int impl_node_port_set_io(void *object, enum spa_direction direction, uint32_t port_id, @@ -2696,7 +2711,12 @@ switch (id) { case SPA_IO_Buffers: - port->io = data; + if (this->data_loop) { + struct io_data d = { .port = port, .data = data, .size = size }; + spa_loop_invoke(this->data_loop, do_set_port_io, 0, NULL, 0, true, &d); + } + else + port->io = data; break; case SPA_IO_RateMatch: this->io_rate_match = data; @@ -3432,6 +3452,7 @@ this = (struct impl *) handle; + this->data_loop = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DataLoop); this->log = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_Log); spa_log_topic_init(this->log, &log_topic);
View file
pipewire-1.2.0.tar.gz/spa/plugins/bluez5/backend-native.c -> pipewire-1.2.2.tar.bz2/spa/plugins/bluez5/backend-native.c
Changed
@@ -1388,7 +1388,8 @@ if (!handler(rfcomm, token)) { spa_log_debug(backend->log, "RFCOMM received unsupported event: %s", token); - rfcomm_send_error(rfcomm, CMEE_OPERATION_NOT_SUPPORTED); + if (ag) + rfcomm_send_error(rfcomm, CMEE_OPERATION_NOT_SUPPORTED); } } }
View file
pipewire-1.2.0.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-1.2.2.tar.bz2/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -5310,7 +5310,8 @@ int options = 0; int skip = 0; int sync_cte_type = 0; - int sync_factor = 1; + /* sync_factor should be >=2 to avoid invalid extended advertising interval value */ + int sync_factor = 2; int sync_timeout = 2000; int timeout = 2000;
View file
pipewire-1.2.0.tar.gz/spa/plugins/support/loop.c -> pipewire-1.2.2.tar.bz2/spa/plugins/support/loop.c
Changed
@@ -212,9 +212,12 @@ * read index before we call the function because then the item * might get overwritten. */ func = spa_steal_ptr(item->func); - if (func) + if (func) { + pthread_mutex_unlock(&impl->queue_lock); item->res = func(&impl->loop, true, item->seq, item->data, item->size, item->user_data); + pthread_mutex_lock(&impl->queue_lock); + } /* if this function did a recursive invoke, it now flushed the * ringbuffer and we can exit */ @@ -338,6 +341,7 @@ spa_log_warn(impl->log, "%p: queue full %d, need %zd (%d suppressed)", queue, avail, need, suppressed); } + loop_signal_event(impl, impl->wakeup); if (impl->retry_timeout == 0) return -EPIPE; usleep(impl->retry_timeout); @@ -884,8 +888,9 @@ if (SPA_LIKELY(value)) { its.it_value = *value; } else if (interval) { + // timer initially fires after one interval its.it_value = *interval; - absolute = true; + absolute = false; } if (SPA_UNLIKELY(interval)) its.it_interval = *interval;
View file
pipewire-1.2.0.tar.gz/spa/plugins/support/node-driver.c -> pipewire-1.2.2.tar.bz2/spa/plugins/support/node-driver.c
Changed
@@ -33,7 +33,7 @@ #define SPA_LOG_TOPIC_DEFAULT &log_topic #define DEFAULT_FREEWHEEL false -#define DEFAULT_FREEWHEEL_WAIT 10 +#define DEFAULT_FREEWHEEL_WAIT 5 #define DEFAULT_CLOCK_PREFIX "clock.system" #define DEFAULT_CLOCK_ID CLOCK_MONOTONIC #define DEFAULT_RESYNC_MS 10 @@ -524,7 +524,8 @@ spa_return_val_if_fail(this != NULL, -EINVAL); spa_log_trace(this->log, "process %d", this->props.freewheel); - if (this->props.freewheel) { + if (this->props.freewheel && + !SPA_FLAG_IS_SET(this->position->clock.flags, SPA_IO_CLOCK_FLAG_XRUN_RECOVER)) { this->next_time = gettime_nsec(this, this->timer_clockid); set_timeout(this, this->next_time); }
View file
pipewire-1.2.0.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-1.2.2.tar.bz2/spa/plugins/v4l2/v4l2-source.c
Changed
@@ -243,7 +243,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 buffer1024; struct spa_result_node_params result; uint32_t count = 0; @@ -252,12 +253,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: 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: @@ -266,21 +270,21 @@ 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_description, SPA_POD_String("The V4L2 device"), SPA_PROP_INFO_type, SPA_POD_String(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 V4L2 device name"), SPA_PROP_INFO_type, SPA_POD_String(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_deviceFd), SPA_PROP_INFO_description, SPA_POD_String("The V4L2 fd"), @@ -305,8 +309,8 @@ switch (result.index) { case 0: - spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Props, id); - spa_pod_builder_add(&b, + spa_pod_builder_push_object(&b.b, &f, SPA_TYPE_OBJECT_Props, id); + spa_pod_builder_add(&b.b, SPA_PROP_device, SPA_POD_String(p->device), SPA_PROP_deviceName, SPA_POD_String(p->device_name), SPA_PROP_deviceFd, SPA_POD_Int(p->device_fd), @@ -314,20 +318,20 @@ for (i = 0; i < port->n_controls; i++) { struct control *c = &port->controlsi; - spa_pod_builder_prop(&b, c->id, 0); + spa_pod_builder_prop(&b.b, c->id, 0); switch (c->type) { case SPA_TYPE_Int: - spa_pod_builder_int(&b, c->value); + spa_pod_builder_int(&b.b, c->value); break; case SPA_TYPE_Bool: - spa_pod_builder_bool(&b, c->value); + spa_pod_builder_bool(&b.b, c->value); break; default: - spa_pod_builder_int(&b, c->value); + spa_pod_builder_int(&b.b, c->value); break; } } - param = spa_pod_builder_pop(&b, &f); + param = spa_pod_builder_pop(&b.b, &f); break; default: return 0; @@ -338,14 +342,14 @@ return spa_v4l2_enum_format(this, seq, start, num, filter); case SPA_PARAM_Format: if((res = port_get_format(GET_OUT_PORT(this, 0), - result.index, filter, ¶m, &b)) <= 0) + result.index, filter, ¶m, &b.b)) <= 0) return res; 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); @@ -535,7 +539,8 @@ struct impl *this = object; struct port *port; 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; @@ -545,6 +550,9 @@ 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); + port = GET_PORT(this, direction, port_id); result.id = id; @@ -552,7 +560,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_PropInfo: @@ -562,7 +570,7 @@ return spa_v4l2_enum_format(this, seq, start, num, filter); case SPA_PARAM_Format: - if((res = port_get_format(port, result.index, filter, ¶m, &b)) <= 0) + if((res = port_get_format(port, result.index, filter, ¶m, &b.b)) <= 0) return res; break; case SPA_PARAM_Buffers: @@ -571,7 +579,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(4, 1, MAX_BUFFERS), SPA_PARAM_BUFFERS_blocks, SPA_POD_Int(1), @@ -582,13 +590,13 @@ 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))); break; case 1: - 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_VideoTransform), SPA_PARAM_META_size, SPA_POD_Int(sizeof(struct spa_meta_videotransform))); @@ -600,19 +608,19 @@ 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_Clock), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_clock))); break; case 2: - 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_Control), SPA_PARAM_IO_size, SPA_POD_Int(sizeof(struct spa_io_sequence))); @@ -624,7 +632,7 @@ case SPA_PARAM_Latency: switch (result.index) { case 0: case 1: - param = spa_latency_build(&b, id, &this->latencyresult.index); + param = spa_latency_build(&b.b, id, &this->latencyresult.index); break; default: return 0; @@ -634,7 +642,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); @@ -652,6 +660,8 @@ struct spa_video_info info; int res; + spa_zero(info); + if (port->have_format) { spa_v4l2_stream_off(this); spa_v4l2_clear_buffers(this);
View file
pipewire-1.2.0.tar.gz/spa/plugins/v4l2/v4l2-utils.c -> pipewire-1.2.2.tar.bz2/spa/plugins/v4l2/v4l2-utils.c
Changed
@@ -11,6 +11,8 @@ #include <sys/mman.h> #include <poll.h> +#include <spa/pod/dynamic.h> +#include <spa/utils/cleanup.h> #include <spa/utils/result.h> static int xioctl(int fd, int request, void *arg) @@ -505,7 +507,8 @@ uint32_t filter_media_type, filter_media_subtype; struct spa_v4l2_device *dev = &port->dev; uint8_t buffer1024; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; struct spa_pod_frame f2; struct spa_result_node_params result; uint32_t count = 0; @@ -513,6 +516,9 @@ if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = SPA_PARAM_EnumFormat; result.next = start; @@ -630,14 +636,31 @@ } do_frmsize: if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMESIZES, &port->frmsize)) < 0) { - if (errno == EINVAL || errno == ENOTTY) + if (errno == ENOTTY) goto next_fmtdesc; + if (errno == EINVAL) { + if (port->frmsize.index == 0) { + port->frmsize.type = V4L2_FRMSIZE_TYPE_CONTINUOUS; + port->frmsize.stepwise.min_width = 16; + port->frmsize.stepwise.min_height = 16; + port->frmsize.stepwise.max_width = 16384; + port->frmsize.stepwise.max_height = 16384; + port->frmsize.stepwise.step_width = 16; + port->frmsize.stepwise.step_height = 16; + port->fmtdesc.index++; + port->next_fmtdesc = true; + goto do_frmsize_filter; + } + else + goto next_fmtdesc; + } res = -errno; spa_log_error(this->log, "'%s' VIDIOC_ENUM_FRAMESIZES: %m", this->props.device); goto exit; } +do_frmsize_filter: if (filter) { static const struct spa_rectangle step = {1, 1}; @@ -695,34 +718,35 @@ } } - spa_pod_builder_init(&b, buffer, sizeof(buffer)); - spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); - spa_pod_builder_add(&b, + spa_pod_builder_reset(&b.b, &state); + spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat); + spa_pod_builder_add(&b.b, SPA_FORMAT_mediaType, SPA_POD_Id(info->media_type), SPA_FORMAT_mediaSubtype, SPA_POD_Id(info->media_subtype), 0); if (info->media_subtype == SPA_MEDIA_SUBTYPE_raw) { - spa_pod_builder_prop(&b, SPA_FORMAT_VIDEO_format, 0); - spa_pod_builder_id(&b, info->format); + spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_format, 0); + spa_pod_builder_id(&b.b, info->format); } - spa_pod_builder_prop(&b, SPA_FORMAT_VIDEO_size, 0); + + spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_size, 0); if (port->frmsize.type == V4L2_FRMSIZE_TYPE_DISCRETE) { - spa_pod_builder_rectangle(&b, + spa_pod_builder_rectangle(&b.b, port->frmsize.discrete.width, port->frmsize.discrete.height); } else if (port->frmsize.type == V4L2_FRMSIZE_TYPE_CONTINUOUS || port->frmsize.type == V4L2_FRMSIZE_TYPE_STEPWISE) { - spa_pod_builder_push_choice(&b, &f1, SPA_CHOICE_None, 0); - choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f1); + spa_pod_builder_push_choice(&b.b, &f1, SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b.b, &f1); - spa_pod_builder_rectangle(&b, + spa_pod_builder_rectangle(&b.b, port->frmsize.stepwise.min_width, port->frmsize.stepwise.min_height); - spa_pod_builder_rectangle(&b, + spa_pod_builder_rectangle(&b.b, port->frmsize.stepwise.min_width, port->frmsize.stepwise.min_height); - spa_pod_builder_rectangle(&b, + spa_pod_builder_rectangle(&b.b, port->frmsize.stepwise.max_width, port->frmsize.stepwise.max_height); @@ -730,35 +754,43 @@ choice->body.type = SPA_CHOICE_Range; } else { choice->body.type = SPA_CHOICE_Step; - spa_pod_builder_rectangle(&b, + spa_pod_builder_rectangle(&b.b, port->frmsize.stepwise.max_width, port->frmsize.stepwise.max_height); } - spa_pod_builder_pop(&b, &f1); + spa_pod_builder_pop(&b.b, &f1); } - spa_pod_builder_prop(&b, SPA_FORMAT_VIDEO_framerate, 0); + spa_pod_builder_prop(&b.b, SPA_FORMAT_VIDEO_framerate, 0); n_fractions = 0; - spa_pod_builder_push_choice(&b, &f1, SPA_CHOICE_None, 0); - choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b, &f1); + spa_pod_builder_push_choice(&b.b, &f1, SPA_CHOICE_None, 0); + choice = (struct spa_pod_choice*)spa_pod_builder_frame(&b.b, &f1); port->frmival.index = 0; while (true) { if ((res = xioctl(dev->fd, VIDIOC_ENUM_FRAMEINTERVALS, &port->frmival)) < 0) { res = -errno; + port->frmsize.index++; + port->next_frmsize = true; if (errno == EINVAL || errno == ENOTTY) { - port->frmsize.index++; - port->next_frmsize = true; - if (port->frmival.index == 0) - goto next_frmsize; - break; + if (port->frmival.index == 0) { + port->frmival.type = V4L2_FRMIVAL_TYPE_CONTINUOUS; + port->frmival.stepwise.min.denominator = 1; + port->frmival.stepwise.min.numerator = 1; + port->frmival.stepwise.max.denominator = 120; + port->frmival.stepwise.max.numerator = 1; + goto do_frminterval_filter; + } + else + break; } spa_log_error(this->log, "'%s' VIDIOC_ENUM_FRAMEINTERVALS: %m", this->props.device); goto exit; } +do_frminterval_filter: if (filter) { static const struct spa_fraction step = {1, 1}; @@ -810,10 +842,10 @@ if (port->frmival.type == V4L2_FRMIVAL_TYPE_DISCRETE) { choice->body.type = SPA_CHOICE_Enum; if (n_fractions == 0) - spa_pod_builder_fraction(&b, + spa_pod_builder_fraction(&b.b, port->frmival.discrete.denominator, port->frmival.discrete.numerator); - spa_pod_builder_fraction(&b, + spa_pod_builder_fraction(&b.b, port->frmival.discrete.denominator, port->frmival.discrete.numerator); port->frmival.index++; @@ -821,11 +853,11 @@ } else if (port->frmival.type == V4L2_FRMIVAL_TYPE_CONTINUOUS || port->frmival.type == V4L2_FRMIVAL_TYPE_STEPWISE) { if (n_fractions == 0) - spa_pod_builder_fraction(&b, 25, 1); - spa_pod_builder_fraction(&b, + spa_pod_builder_fraction(&b.b, 25, 1); + spa_pod_builder_fraction(&b.b, port->frmival.stepwise.min.denominator, port->frmival.stepwise.min.numerator); - spa_pod_builder_fraction(&b, + spa_pod_builder_fraction(&b.b, port->frmival.stepwise.max.denominator, port->frmival.stepwise.max.numerator); @@ -834,7 +866,7 @@ n_fractions += 2; } else { choice->body.type = SPA_CHOICE_Step; - spa_pod_builder_fraction(&b, + spa_pod_builder_fraction(&b.b, port->frmival.stepwise.step.denominator, port->frmival.stepwise.step.numerator); n_fractions += 3; @@ -849,9 +881,9 @@ goto next_frmsize; if (n_fractions == 1) choice->body.type = SPA_CHOICE_None; + spa_pod_builder_pop(&b.b, &f1); - spa_pod_builder_pop(&b, &f1); - result.param = spa_pod_builder_pop(&b, &f0); + result.param = spa_pod_builder_pop(&b.b, &f0); spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); @@ -964,7 +996,7 @@ streamparm.parm.capture.timeperframe.numerator = framerate->denom; streamparm.parm.capture.timeperframe.denominator = framerate->num; - spa_log_debug(this->log, "set %.4s %dx%d %d/%d", (char *)&fmt.fmt.pix.pixelformat, + spa_log_info(this->log, "set %.4s %dx%d %d/%d", (char *)&fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, streamparm.parm.capture.timeperframe.denominator, streamparm.parm.capture.timeperframe.numerator); @@ -1003,6 +1035,9 @@ if (flags & SPA_NODE_PARAM_FLAG_TEST_ONLY) return match ? 0 : 1; + if (streamparm.parm.capture.timeperframe.denominator == 0) + streamparm.parm.capture.timeperframe.denominator = 1; + spa_log_info(this->log, "'%s' got %.4s %dx%d %d/%d", dev->path, (char *)&fmt.fmt.pix.pixelformat, fmt.fmt.pix.width, fmt.fmt.pix.height, @@ -1118,7 +1153,8 @@ struct spa_v4l2_device *dev = &port->dev; struct v4l2_query_ext_ctrl queryctrl; struct spa_pod *param; - struct spa_pod_builder b = { 0 }; + spa_auto(spa_pod_dynamic_builder) b = { 0 }; + struct spa_pod_builder_state state; uint32_t prop_id, ctrl_id; uint8_t buffer1024; int res; @@ -1130,6 +1166,9 @@ if ((res = spa_v4l2_open(dev, this->props.device)) < 0) return res; + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); + spa_pod_builder_get_state(&b.b, &state); + result.id = SPA_PARAM_PropInfo; result.next = start; next: @@ -1180,7 +1219,7 @@ ctrl_id = queryctrl.id & ~next_fl; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_pod_builder_reset(&b.b, &state); prop_id = control_to_prop_id(this, ctrl_id); @@ -1193,7 +1232,7 @@ switch (queryctrl.type) { case V4L2_CTRL_TYPE_INTEGER: port->controlsport->n_controls.type = SPA_TYPE_Int; - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_id, SPA_POD_Id(prop_id), SPA_PROP_INFO_type, SPA_POD_CHOICE_STEP_Int( @@ -1205,7 +1244,7 @@ break; case V4L2_CTRL_TYPE_BOOLEAN: port->controlsport->n_controls.type = SPA_TYPE_Bool; - param = spa_pod_builder_add_object(&b, + param = spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, SPA_PROP_INFO_id, SPA_POD_Id(prop_id), SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool((bool)queryctrl.default_value), @@ -1214,11 +1253,10 @@ case V4L2_CTRL_TYPE_MENU: { struct v4l2_querymenu querymenu; - struct spa_pod_builder_state state; port->controlsport->n_controls.type = SPA_TYPE_Int; - spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); - spa_pod_builder_add(&b, + spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); + spa_pod_builder_add(&b.b, SPA_PROP_INFO_id, SPA_POD_Id(prop_id), SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, (int32_t)queryctrl.default_value), SPA_PROP_INFO_description, SPA_POD_String(queryctrl.name), @@ -1227,25 +1265,19 @@ spa_zero(querymenu); querymenu.id = queryctrl.id; - spa_pod_builder_prop(&b, SPA_PROP_INFO_labels, 0); + spa_pod_builder_prop(&b.b, SPA_PROP_INFO_labels, 0); - spa_pod_builder_get_state(&b, &state); - spa_pod_builder_push_struct(&b, &f1); + spa_pod_builder_push_struct(&b.b, &f1); for (querymenu.index = queryctrl.minimum; querymenu.index <= queryctrl.maximum; querymenu.index++) { if (xioctl(dev->fd, VIDIOC_QUERYMENU, &querymenu) == 0) { - spa_pod_builder_int(&b, querymenu.index); - spa_pod_builder_string(&b, (const char *)querymenu.name); + spa_pod_builder_int(&b.b, querymenu.index); + spa_pod_builder_string(&b.b, (const char *)querymenu.name); } } - if (spa_pod_builder_pop(&b, &f1) == NULL) { - spa_log_warn(this->log, "can't create Control '%s' overflow %d", - queryctrl.name, b.state.offset); - spa_pod_builder_reset(&b, &state); - spa_pod_builder_none(&b); - } - param = spa_pod_builder_pop(&b, &f0); + spa_pod_builder_pop(&b.b, &f1); + param = spa_pod_builder_pop(&b.b, &f0); break; } case V4L2_CTRL_TYPE_INTEGER_MENU: @@ -1260,7 +1292,7 @@ port->n_controls++; - 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);
View file
pipewire-1.2.0.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-1.2.2.tar.bz2/src/gst/gstpipewiresrc.c
Changed
@@ -435,6 +435,8 @@ src->autoconnect = DEFAULT_AUTOCONNECT; src->min_latency = 0; src->max_latency = GST_CLOCK_TIME_NONE; + + src->transform_value = UINT32_MAX; } static gboolean @@ -538,7 +540,7 @@ GstPipeWirePoolData *data; struct spa_meta_header *h; struct spa_meta_region *crop; - struct spa_meta_videotransform *videotransform; + enum spa_meta_videotransform_value transform_value; struct pw_time time; guint i; @@ -613,24 +615,22 @@ } } - videotransform = data->videotransform; - if (videotransform) { - if (pwsrc->transform_value != videotransform->transform) { - GstEvent *tag_event; - const char* tag_string; + transform_value = data->videotransform ? data->videotransform->transform : + SPA_META_TRANSFORMATION_None; + if (transform_value != pwsrc->transform_value) { + GstEvent *tag_event; + const char* tag_string; - tag_string = - spa_transform_value_to_gst_image_orientation(videotransform->transform); + tag_string = spa_transform_value_to_gst_image_orientation(transform_value); - GST_LOG_OBJECT (pwsrc, "got new videotransform: %u / %s", - videotransform->transform, tag_string); + GST_LOG_OBJECT (pwsrc, "got new videotransform: %u / %s", + transform_value, tag_string); - tag_event = gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION, - tag_string, NULL)); - gst_pad_push_event (GST_BASE_SRC_PAD (pwsrc), tag_event); + tag_event = gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION, + tag_string, NULL)); + gst_pad_push_event (GST_BASE_SRC_PAD (pwsrc), tag_event); - pwsrc->transform_value = videotransform->transform; - } + pwsrc->transform_value = transform_value; } if (pwsrc->is_video) { @@ -1391,6 +1391,7 @@ pwsrc->eos = false; gst_buffer_replace (&pwsrc->last_buffer, NULL); gst_caps_replace(&pwsrc->caps, NULL); + pwsrc->transform_value = UINT32_MAX; pw_thread_loop_unlock (pwsrc->stream->core->loop); return TRUE;
View file
pipewire-1.2.0.tar.gz/src/gst/gstpipewirestream.c -> pipewire-1.2.2.tar.bz2/src/gst/gstpipewirestream.c
Changed
@@ -158,7 +158,12 @@ /* destroy the pw stream */ pw_thread_loop_lock (self->core->loop); - g_clear_pointer (&self->pwstream, pw_stream_destroy); + if (self->pwstream) { + /* Do not use g_clear_pointer() here as pw_stream_destroy() may chain up to + * code requiring the pointer to still be around */ + pw_stream_destroy (self->pwstream); + self->pwstream = NULL; + } pw_thread_loop_unlock (self->core->loop); /* release the core */
View file
pipewire-1.2.0.tar.gz/src/modules/meson.build -> pipewire-1.2.2.tar.bz2/src/modules/meson.build
Changed
@@ -433,11 +433,11 @@ cdata.set('HAVE_AVAHI', true) endif -if gio_dep.found() +if gsettings_gio_dep.found() pipewire_module_protocol_pulse_sources += 'module-protocol-pulse/modules/module-gsettings.c', - pipewire_module_protocol_pulse_deps += gio_dep + pipewire_module_protocol_pulse_deps += gsettings_gio_dep cdata.set('HAVE_GIO', true) if get_option('gsettings-pulse-schema').enabled() install_data('module-protocol-pulse/modules/org.freedesktop.pulseaudio.gschema.xml',
View file
pipewire-1.2.0.tar.gz/src/modules/module-ffado-driver.c -> pipewire-1.2.2.tar.bz2/src/modules/module-ffado-driver.c
Changed
@@ -548,8 +548,8 @@ struct impl *impl = s->impl; switch (state) { case PW_FILTER_STATE_ERROR: - pw_log_error("filter state %d error: %s", state, error); - SPA_FALLTHROUGH; + pw_log_warn("filter state %d error: %s", state, error); + break; case PW_FILTER_STATE_UNCONNECTED: pw_impl_module_schedule_destroy(impl->module); break;
View file
pipewire-1.2.0.tar.gz/src/modules/module-jack-tunnel.c -> pipewire-1.2.2.tar.bz2/src/modules/module-jack-tunnel.c
Changed
@@ -306,10 +306,12 @@ struct stream *s = d; struct impl *impl = s->impl; switch (state) { - case PW_FILTER_STATE_ERROR: case PW_FILTER_STATE_UNCONNECTED: pw_impl_module_schedule_destroy(impl->module); break; + case PW_FILTER_STATE_ERROR: + pw_log_warn("stream %p: error: %s", s, error); + break; case PW_FILTER_STATE_PAUSED: s->running = false; break;
View file
pipewire-1.2.0.tar.gz/src/modules/module-jack-tunnel/weakjack.h -> pipewire-1.2.2.tar.bz2/src/modules/module-jack-tunnel/weakjack.h
Changed
@@ -101,7 +101,7 @@ hnd = dlopen(path, RTLD_NOW); if (hnd == NULL) - return -errno; + return -ENOENT; pw_log_info("opened libjack: %s", path);
View file
pipewire-1.2.0.tar.gz/src/modules/module-netjack2-driver.c -> pipewire-1.2.2.tar.bz2/src/modules/module-netjack2-driver.c
Changed
@@ -274,6 +274,8 @@ struct impl *impl = s->impl; switch (state) { case PW_FILTER_STATE_ERROR: + pw_log_warn("stream %p: error: %s", s, error); + break; case PW_FILTER_STATE_UNCONNECTED: pw_impl_module_schedule_destroy(impl->module); break;
View file
pipewire-1.2.0.tar.gz/src/modules/module-netjack2-manager.c -> pipewire-1.2.2.tar.bz2/src/modules/module-netjack2-manager.c
Changed
@@ -297,6 +297,8 @@ struct impl *impl = s->impl; switch (state) { case PW_FILTER_STATE_ERROR: + pw_log_warn("stream %p: error: %s", s, error); + break; case PW_FILTER_STATE_UNCONNECTED: pw_impl_module_schedule_destroy(impl->module); break;
View file
pipewire-1.2.0.tar.gz/src/modules/module-protocol-simple.c -> pipewire-1.2.2.tar.bz2/src/modules/module-protocol-simple.c
Changed
@@ -56,6 +56,8 @@ * sink for each connected client. * - `playback`: boolean if playback is enabled. This will create a playback or * source stream for each connected client. + * - `local.ifname = <str>`: interface name to use + * - `local.ifaddress = <str>`: interface address to use * - `server.address = `: an array of server addresses to listen on as * tcp:(<ip>:)<port>. * - `capture.props`: optional properties for the capture stream @@ -208,6 +210,8 @@ struct pw_properties *capture_props; struct pw_properties *playback_props; + char *ifname; + char *ifaddress; bool capture; bool playback; @@ -654,47 +658,16 @@ return; } -static uint16_t parse_port(const char *str, uint16_t def) -{ - uint32_t val; - if (spa_atou32(str, &val, 0) && val <= 65535u) - return val; - return def; -} - -static int make_tcp_socket(struct server *server, const char *name) +static int make_tcp_socket(struct server *server, const char *name, const char *ifname, + const char *ifaddress) { struct sockaddr_storage addr; int res, fd, on; - uint16_t port; - char *br = NULL, *col, *n; socklen_t len = 0; - n = strdupa(name); - - col = strrchr(n, ':'); - if (n0 == '') { - br = strchr(n, ''); - if (br == NULL) - return -EINVAL; - n++; - *br = 0; - } else { - } - if (br && col && col < br) - col = NULL; - - if (col) { - *col = '\0'; - port = parse_port(col+1, DEFAULT_PORT); - } else { - port = parse_port(n, DEFAULT_PORT); - n = strdupa("0.0.0.0"); - } - - if ((res = pw_net_parse_address(n, port, &addr, &len)) < 0) { - pw_log_error("%p: can't parse address:%s port:%d: %s", server, - n, port, spa_strerror(res)); + if ((res = pw_net_parse_address_port(name, ifaddress, DEFAULT_PORT, &addr, &len)) < 0) { + pw_log_error("%p: can't parse address %s: %s", server, + name, spa_strerror(res)); goto error; } @@ -703,7 +676,13 @@ pw_log_error("%p: socket() failed: %m", server); goto error; } - +#ifdef SO_BINDTODEVICE + if (ifname && setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, ifname, strlen(ifname)) < 0) { + res = -errno; + pw_log_error("%p: setsockopt(SO_BINDTODEVICE) failed: %m", server); + goto error; + } +#endif on = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const void *) &on, sizeof(on)) < 0) pw_log_warn("%p: setsockopt(): %m", server); @@ -764,7 +743,7 @@ spa_list_append(&impl->server_list, &server->link); if (spa_strstartswith(address, "tcp:")) { - fd = make_tcp_socket(server, address+4); + fd = make_tcp_socket(server, address+4, impl->ifname, impl->ifaddress); } else { pw_log_error("address %s does not start with tcp:", address); fd = -EINVAL; @@ -799,6 +778,8 @@ pw_properties_free(impl->capture_props); pw_properties_free(impl->playback_props); pw_properties_free(impl->props); + free(impl->ifname); + free(impl->ifaddress); free(impl); } @@ -976,6 +957,11 @@ pw_properties_setf(impl->playback_props, PW_KEY_NODE_RATE, "1/%u", impl->playback_info.rate); + str = pw_properties_get(impl->props, "local.ifname"); + impl->ifname = str ? strdup(str) : NULL; + str = pw_properties_get(impl->props, "local.ifaddress"); + impl->ifaddress = str ? strdup(str) : NULL; + if ((str = pw_properties_get(impl->props, "server.address")) == NULL) str = DEFAULT_SERVER; @@ -1056,9 +1042,10 @@ uint16_t port = 0; bool ipv4; - if (pw_net_get_ip(&s->addr, ip, sizeof(ip), &ipv4, &port) >= 0) - fprintf(f, " \"%s%s%s:%d\"", ipv4 ? "" : "", - ip, ipv4 ? "" : "", port); + if (pw_net_get_ip(&s->addr, ip, sizeof(ip), &ipv4, &port) < 0) + continue; + + fprintf(f, " \"%s%s%s:%d\"", ipv4 ? "" : "", ip, ipv4 ? "" : "", port); } fprintf(f, " "); fclose(f);
View file
pipewire-1.2.0.tar.gz/src/modules/module-raop-sink.c -> pipewire-1.2.2.tar.bz2/src/modules/module-raop-sink.c
Changed
@@ -23,7 +23,6 @@ #endif #include <openssl/rand.h> #include <openssl/rsa.h> -#include <openssl/engine.h> #include <openssl/aes.h> #include <openssl/md5.h> #include <openssl/evp.h> @@ -1643,10 +1642,10 @@ impl->volume = volume; rtsp_send_volume(impl); + spa_pod_builder_prop(&b, SPA_PROP_softVolumes, 0); + spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, + n_vols, soft_vols); } - spa_pod_builder_prop(&b, SPA_PROP_softVolumes, 0); - spa_pod_builder_array(&b, sizeof(float), SPA_TYPE_Float, - n_vols, soft_vols); spa_pod_builder_raw_padded(&b, prop, SPA_POD_PROP_SIZE(prop)); break; }
View file
pipewire-1.2.0.tar.gz/src/modules/module-rtp/stream.c -> pipewire-1.2.2.tar.bz2/src/modules/module-rtp/stream.c
Changed
@@ -452,7 +452,7 @@ min_samples = msec_to_samples(impl, min_ptime); max_samples = msec_to_samples(impl, max_ptime); - float ptime = 0; + float ptime = 0.0f; if ((str = pw_properties_get(props, "rtp.ptime")) != NULL) if (!spa_atof(str, &ptime)) ptime = 0.0f; @@ -502,14 +502,16 @@ impl->target_buffer = msec_to_samples(impl, latency_msec); impl->max_error = msec_to_samples(impl, ERROR_MSEC); - if (impl->target_buffer < ptime) { - pw_log_warn("sess.latency.msec cannot be lower than rtp.ptime"); + if (impl->target_buffer < impl->psamples) { + pw_log_warn("sess.latency.msec %f cannot be lower than rtp.ptime %f", + latency_msec, ptime); impl->target_buffer = impl->psamples; } /* We're not expecting odd ptimes, so this modulo should be 0 */ - if (fmodf(impl->target_buffer, ptime) != 0) { - pw_log_warn("sess.latency.msec should be an integer multiple of rtp.ptime"); + if (fmodf(impl->target_buffer, impl->psamples) != 0) { + pw_log_warn("sess.latency.msec %f should be an integer multiple of rtp.ptime %f", + latency_msec, ptime); impl->target_buffer = (uint32_t)((impl->target_buffer / ptime) * impl->psamples); }
View file
pipewire-1.2.0.tar.gz/src/modules/module-snapcast-discover.c -> pipewire-1.2.2.tar.bz2/src/modules/module-snapcast-discover.c
Changed
@@ -35,6 +35,8 @@ #include "module-protocol-pulse/format.h" #include "module-zeroconf-discover/avahi-poll.h" +#include "network-utils.h" + /** \page page_module_snapcast_discover Snapcast Discover * * Automatically creates a Snapcast sink device based on zeroconf @@ -67,7 +69,7 @@ * *\code{.unparsed} * context.modules = - * { name = libpipewire-snapcast-discover + * { name = libpipewire-module-snapcast-discover * args = { * stream.rules = * { matches = @@ -147,6 +149,7 @@ AvahiServiceBrowser *sink_browser; struct spa_list tunnel_list; + uint32_t id; }; struct tunnel_info { @@ -285,6 +288,7 @@ int res; socklen_t len; char *str; + struct impl *impl = t->impl; len = sizeof(res); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &len) < 0) { @@ -297,22 +301,23 @@ t->connecting = false; pw_log_info("connected"); - str = "{\"id\":8,\"jsonrpc\": \"2.0\",\"method\":\"Server.GetRPCVersion\"}\r\n"; + str = spa_aprintf("{\"id\":%u,\"jsonrpc\": \"2.0\",\"method\":\"Server.GetRPCVersion\"}\r\n", + impl->id++); res = write(t->source->fd, str, strlen(str)); pw_log_info("wrote %s: %d", str, res); + free(str); - str = spa_aprintf("{\"id\":4,\"jsonrpc\":\"2.0\",\"method\":\"Stream.RemoveStream\"," - "\"params\":{\"id\":\"%s\"}}\r\n", t->stream_name); + str = spa_aprintf("{\"id\":%u,\"jsonrpc\":\"2.0\",\"method\":\"Stream.RemoveStream\"," + "\"params\":{\"id\":\"%s\"}}\r\n", impl->id++, t->stream_name); res = write(t->source->fd, str, strlen(str)); pw_log_info("wrote %s: %d", str, res); free(str); - str = spa_aprintf("{\"id\":4,\"jsonrpc\":\"2.0\",\"method\":\"Stream.AddStream\"" + str = spa_aprintf("{\"id\":%u,\"jsonrpc\":\"2.0\",\"method\":\"Stream.AddStream\"" ",\"params\":{\"streamUri\":\"tcp://%s?name=%s&mode=client&" - "sampleformat=%d:%d:%d&codec=pcm&chunk_ms=20\"}}\r\n", + "sampleformat=%d:%d:%d&codec=pcm&chunk_ms=20\"}}\r\n", impl->id++, t->server_address, t->stream_name, t->audio_info.rate, get_bps(t->audio_info.format), t->audio_info.channels); - res = write(t->source->fd, str, strlen(str)); pw_log_info("wrote %s: %d", str, res); free(str); @@ -327,7 +332,6 @@ while (true) { res = read(t->source->fd, buffer, sizeof(buffer)); - pw_log_info("%d", res); if (res == 0) return -EPIPE; if (res < 0) { @@ -340,7 +344,7 @@ } } - pw_log_info("%s", buffer); + pw_log_info("received: %s", buffer); return 0; } @@ -465,9 +469,9 @@ while (spa_json_get_string(&it1, v, sizeof(v)) > 0) { t->server_address = strdup(v); snapcast_connect(t); - break; + return 0; } - return 0; + return -ENOENT; } static inline uint32_t format_from_name(const char *name, size_t len) @@ -688,6 +692,7 @@ ifreq.ifr_ifindex = interface; ioctl(fd, SIOCGIFNAME, &ifreq, sizeof(ifreq)); pw_properties_setf(props, "snapcast.ifname", "%s", ifreq.ifr_name); + pw_properties_setf(props, "local.ifname", "%s", ifreq.ifr_name); struct ifaddrs *if_addr, *ifp; if (getifaddrs(&if_addr) < 0) @@ -711,6 +716,10 @@ family == AF_INET ? "" : "", hbuf, family == AF_INET ? "" : ""); + pw_properties_setf(props, "local.ifaddress", "%s%s%s", + family == AF_INET ? "" : "", + hbuf, + family == AF_INET ? "" : ""); } else { pw_log_warn("error: %m %d %s", res, gai_strerror(res)); }
View file
pipewire-1.2.0.tar.gz/src/modules/network-utils.h -> pipewire-1.2.2.tar.bz2/src/modules/network-utils.h
Changed
@@ -38,6 +38,44 @@ return 0; } +static inline uint16_t pw_net_parse_port(const char *str, uint16_t def) +{ + uint32_t val; + if (spa_atou32(str, &val, 0) && val <= 65535u) + return val; + return def; +} + +static inline int pw_net_parse_address_port(const char *address, + const char *default_address, uint16_t default_port, + struct sockaddr_storage *addr, socklen_t *len) +{ + uint16_t port; + char *br = NULL, *col, *n; + + n = strdupa(address); + + col = strrchr(n, ':'); + if (n0 == '') { + br = strchr(n, ''); + if (br == NULL) + return -EINVAL; + n++; + *br = 0; + } + if (br && col && col < br) + col = NULL; + + if (col) { + *col = '\0'; + port = pw_net_parse_port(col+1, default_port); + } else { + port = pw_net_parse_port(n, default_port); + n = strdupa(default_address ? default_address : "0.0.0.0"); + } + return pw_net_parse_address(n, port, addr, len); +} + static inline int pw_net_get_ip(const struct sockaddr_storage *sa, char *ip, size_t len, bool *ip4, uint16_t *port) { if (sa->ss_family == AF_INET) { @@ -75,4 +113,17 @@ return ip; } +static inline bool pw_net_addr_is_any(struct sockaddr_storage *addr) +{ + if (addr->ss_family == AF_INET) { + struct sockaddr_in *sa = (struct sockaddr_in*)addr; + return sa->sin_addr.s_addr == INADDR_ANY; + } else if (addr->ss_family == AF_INET6) { + struct sockaddr_in6 *sa = (struct sockaddr_in6*)addr; + return memcmp(&sa->sin6_addr, &in6addr_any, sizeof(sa->sin6_addr)); + } + return false; +} + + #endif /* NETWORK_UTILS_H */
View file
pipewire-1.2.0.tar.gz/src/pipewire/conf.c -> pipewire-1.2.2.tar.bz2/src/pipewire/conf.c
Changed
@@ -945,9 +945,10 @@ n = realloc(strv, sizeof(char*) * (len + 2)); if (n == NULL) { - free(strv); + pw_free_strv(strv); return NULL; } + strv = n; memmove(strv+pos+1, strv+pos, sizeof(char*) * (len+1-pos)); @@ -955,15 +956,16 @@ return strv; } -static int do_exec(struct pw_context *context, const char *path, const char *args) +static int do_exec(struct pw_context *context, char *const *argv) { int pid, res; pid = fork(); if (pid == 0) { - char **arg; - int n_args; + char buf1024; + char *const *p; + struct spa_strbuf s; /* Double fork to avoid zombies; we don't want to set SIGCHLD handler */ pid = fork(); @@ -975,23 +977,16 @@ exit(0); } - arg = pw_strv_parse(args, strlen(args), INT_MAX, &n_args); - if (arg == NULL) { - pw_log_error("error parsing arguments: %m"); - goto done; - } - arg = pw_strv_insert_at(arg, n_args, 0, path); - if (arg == NULL) { - pw_log_error("error constructing arguments: %m"); - goto done; - } - pw_log_info("exec %s '%s'", path, args); - res = execvp(path, arg); - pw_free_strv(arg); + spa_strbuf_init(&s, buf, sizeof(buf)); + for (p = argv; *p; ++p) + spa_strbuf_append(&s, " '%s'", *p); + + pw_log_info("exec%s", s.buffer); + res = execvp(argv0, argv); if (res == -1) { res = -errno; - pw_log_error("execvp error '%s': %m", path); + pw_log_error("execvp error '%s': %m", argv0); } done: exit(1); @@ -1016,6 +1011,36 @@ * } * */ + +static char **make_exec_argv(const char *path, const char *value, int len) +{ + char **argv = NULL; + int n_args; + + if (spa_json_is_container(value, len)) { + if (!spa_json_is_array(value, len)) { + errno = EINVAL; + return NULL; + } + argv = pw_strv_parse(value, len, INT_MAX, &n_args); + } else { + spa_autofree char *s = calloc(1, len + 1); + if (!s) + return NULL; + + if (spa_json_parse_stringn(value, len, s, len + 1) < 0) { + errno = EINVAL; + return NULL; + } + argv = pw_split_strv(s, " \t", INT_MAX, &n_args); + } + + if (!argv) + return NULL; + + return pw_strv_insert_at(argv, n_args, 0, path); +} + static int parse_exec(void *user_data, const char *location, const char *section, const char *str, size_t len) { @@ -1034,7 +1059,9 @@ } while ((r = spa_json_enter_object(&it1, &it2)) > 0) { - char *path = NULL, *args = NULL; + char *path = NULL; + const char *args_val = ""; + int args_len = 2; bool have_match = true; while (spa_json_get_string(&it2, key, sizeof(key)) > 0) { @@ -1053,13 +1080,13 @@ } else if (spa_streq(key, "args")) { if (spa_json_is_container(val, l)) l = spa_json_container_len(&it2, val, l); - args = (char*)val; - spa_json_parse_stringn(val, l, args, l+1); + args_val = val; + args_len = l; } else if (spa_streq(key, "condition")) { if (!spa_json_is_array(val, l)) { pw_log_warn("expected array for condition in '%.*s'", (int)len, str); - break; + goto next; } spa_json_enter(&it2, &it3); have_match = find_match(&it3, &context->properties->dict, true); @@ -1072,11 +1099,23 @@ continue; if (path != NULL) { - res = do_exec(context, path, args); + char **argv = make_exec_argv(path, args_val, args_len); + + if (!argv) { + pw_log_warn("expected array or string for args in '%.*s'", + (int)len, str); + goto next; + } + + res = do_exec(context, argv); + pw_free_strv(argv); if (res < 0) break; d->count++; } + + next: + continue; } if (r < 0) pw_log_warn("malformed object array in '%.*s'", (int)len, str);
View file
pipewire-1.2.0.tar.gz/src/pipewire/context.c -> pipewire-1.2.2.tar.bz2/src/pipewire/context.c
Changed
@@ -1163,13 +1163,14 @@ * This ensures that we only activate the paths from the runnable nodes to the * driver nodes and leave the other nodes idle. */ -static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect, - char **sync) +static int collect_nodes(struct pw_context *context, struct pw_impl_node *node, struct spa_list *collect) { struct spa_list queue; struct pw_impl_node *n, *t; struct pw_impl_port *p; struct pw_impl_link *l; + uint32_t n_sync; + char *syncMAX_SYNC+1; pw_log_debug("node %p: '%s'", node, node->name); @@ -1178,20 +1179,30 @@ spa_list_append(&queue, &node->sort_link); node->visited = true; + n_sync = 0; + sync0 = NULL; + /* now follow all the links from the nodes in the queue * and add the peers to the queue. */ spa_list_consume(n, &queue, sort_link) { spa_list_remove(&n->sort_link); spa_list_append(collect, &n->sort_link); - pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); + pw_log_debug(" next node %p: '%s' runnable:%u active:%d", + n, n->name, n->runnable, n->active); if (!n->active) continue; - if (sync0 != NULL) { - if (pw_strv_find_common(n->sync_groups, sync) < 0) - continue; + if (n->sync) { + for (uint32_t i = 0; n->sync_groupsi; i++) { + if (n_sync >= MAX_SYNC) + break; + if (pw_strv_find(sync, n->sync_groupsi) >= 0) + continue; + syncn_sync++ = n->sync_groupsi; + syncn_sync = NULL; + } } spa_list_for_each(p, &n->input_ports, link) { @@ -1242,6 +1253,8 @@ spa_list_for_each(t, &context->node_list, link) { if (t->exported || !t->active || t->visited) continue; + /* the other node will be scheduled with this one if it's in + * the same group or link group */ if (pw_strv_find_common(t->groups, n->groups) < 0 && pw_strv_find_common(t->link_groups, n->link_groups) < 0 && pw_strv_find_common(t->sync_groups, sync) < 0) @@ -1253,7 +1266,8 @@ spa_list_append(&queue, &t->sort_link); } } - pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); + pw_log_debug(" next node %p: '%s' runnable:%u %p %p %p", n, n->name, n->runnable, + n->groups, n->link_groups, sync); } spa_list_for_each(n, collect, sort_link) if (!n->driving && n->runnable) { @@ -1497,10 +1511,9 @@ struct pw_impl_node *n, *s, *target, *fallback; const uint32_t *rates; uint32_t max_quantum, min_quantum, def_quantum, rate_quantum, floor_quantum, ceil_quantum; - uint32_t n_rates, def_rate, n_sync; + uint32_t n_rates, def_rate; bool freewheel, global_force_rate, global_force_quantum, transport_start; struct spa_list collect; - char *syncMAX_SYNC+1; pw_log_info("%p: busy:%d reason:%s", context, impl->recalc, reason); @@ -1514,23 +1527,11 @@ freewheel = false; transport_start = false; - /* clean up the flags first and collect sync */ - n_sync = 0; - sync0 = NULL; + /* clean up the flags first */ spa_list_for_each(n, &context->node_list, link) { n->visited = false; n->checked = 0; n->runnable = n->always_process && n->active; - if (n->sync) { - for (uint32_t i = 0; n->sync_groupsi; i++) { - if (n_sync >= MAX_SYNC) - break; - if (pw_strv_find(sync, n->sync_groupsi) >= 0) - continue; - syncn_sync++ = n->sync_groupsi; - syncn_sync = NULL; - } - } } get_quantums(context, &def_quantum, &min_quantum, &max_quantum, &rate_quantum, @@ -1551,7 +1552,7 @@ if (!n->visited) { spa_list_init(&collect); - collect_nodes(context, n, &collect, sync); + collect_nodes(context, n, &collect); move_to_driver(context, &collect, n); } /* from now on we are only interested in active driving nodes @@ -1605,7 +1606,7 @@ /* collect all nodes in this group */ spa_list_init(&collect); - collect_nodes(context, n, &collect, sync); + collect_nodes(context, n, &collect); driver = NULL; spa_list_for_each(t, &collect, sort_link) {
View file
pipewire-1.2.0.tar.gz/src/pipewire/impl-link.c -> pipewire-1.2.2.tar.bz2/src/pipewire/impl-link.c
Changed
@@ -754,9 +754,11 @@ pw_impl_port_recalc_latency(this->input); pw_impl_port_recalc_tag(this->input); - if ((res = pw_impl_port_use_buffers(port, mix, 0, NULL, 0)) < 0) { + if ((res = port_set_io(this, this->input, SPA_IO_Buffers, NULL, 0, mix)) < 0) + pw_log_warn("%p: port %p set_io error %s", this, port, spa_strerror(res)); + if ((res = pw_impl_port_use_buffers(port, mix, 0, NULL, 0)) < 0) pw_log_warn("%p: port %p clear error %s", this, port, spa_strerror(res)); - } + pw_impl_port_release_mix(port, mix); pw_work_queue_cancel(impl->work, &this->input_link, SPA_ID_INVALID); @@ -1375,8 +1377,9 @@ this->name = spa_aprintf("%d.%d.%d -> %d.%d.%d", output_node->info.id, output->port_id, this->rt.out_mix.port.port_id, input_node->info.id, input->port_id, this->rt.in_mix.port.port_id); - pw_log_info("(%s) (%s) -> (%s) async:%04x:%04x:%d", this->name, output_node->name, - input_node->name, output->flags, input->flags, impl->async); + pw_log_info("(%s) (%s) -> (%s) async:%d:%04x:%04x:%d", this->name, output_node->name, + input_node->name, output_node->driving, + output->flags, input->flags, impl->async); pw_impl_port_emit_link_added(output, this); pw_impl_port_emit_link_added(input, this);
View file
pipewire-1.2.0.tar.gz/src/pipewire/impl-node.c -> pipewire-1.2.2.tar.bz2/src/pipewire/impl-node.c
Changed
@@ -11,6 +11,8 @@ #include <malloc.h> #include <limits.h> +#include "config.h" + #include <spa/support/system.h> #include <spa/pod/parser.h> #include <spa/pod/filter.h> @@ -112,13 +114,16 @@ { struct pw_node_activation_state *state = &t->activation->state0; if (!t->active) { - if ((!node->async || node->driving) && !node->exported) { - SPA_ATOMIC_INC(state->required); - SPA_ATOMIC_INC(state->pending); + if (!node->async) { + if (!node->exported) { + SPA_ATOMIC_INC(state->required); + SPA_ATOMIC_INC(state->pending); + } } t->active = true; - pw_log_debug("%p: target state:%p id:%d pending:%d/%d", - node, state, t->id, state->pending, state->required); + pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d", + node, state, t->id, state->pending, state->required, + node->async, node->driving, node->exported); } } @@ -126,7 +131,7 @@ { if (t->active) { struct pw_node_activation_state *state = &t->activation->state0; - if (!node->async || node->driving) { + if (!node->async) { /* the driver copies the required to the pending state * so first try to resume the node and then decrement the * required state. This way we either resume with the old value @@ -137,8 +142,9 @@ SPA_ATOMIC_DEC(state->required); } t->active = false; - pw_log_debug("%p: target state:%p id:%d pending:%d/%d trigger:%"PRIu64, - node, state, t->id, state->pending, state->required, trigger); + pw_log_debug("%p: target state:%p id:%d pending:%d/%d %d:%d:%d trigger:%"PRIu64, + node, state, t->id, state->pending, state->required, + node->async, node->driving, node->exported, trigger); } } @@ -173,7 +179,8 @@ uint64_t dummy; int res; - pw_log_trace("%p: prepare %d remote:%d", this, this->rt.prepared, this->remote); + pw_log_trace("%p: prepare %d remote:%d exported:%d", this, this->rt.prepared, + this->remote, this->exported); if (this->rt.prepared) return 0; @@ -212,20 +219,21 @@ int old_state; uint64_t trigger = 0; - pw_log_trace("%p: unprepare %d remote:%d", this, this->rt.prepared, this->remote); + pw_log_trace("%p: unprepare %d remote:%d exported:%d", this, this->rt.prepared, + this->remote, this->exported); - if (!this->rt.prepared) - return 0; - - if (!this->remote || this->rt.target.activation->client_version < 1) { + 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 (old_state != PW_NODE_ACTIVATION_FINISHED) + if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state)) trigger = get_time_ns(this->rt.target.system); } + if (!this->rt.prepared) + return 0; + if (!this->remote) spa_loop_remove_source(loop, &this->source); @@ -857,7 +865,7 @@ if (node->rt.prepared) { int old_state = SPA_ATOMIC_LOAD(node->rt.target.activation->status); uint64_t trigger = 0; - if (old_state != PW_NODE_ACTIVATION_FINISHED) + if (PW_NODE_ACTIVATION_PENDING_TRIGGER(old_state)) trigger = get_time_ns(node->rt.target.system); deactivate_target(node, t, trigger); } @@ -1009,17 +1017,7 @@ remove_segment_owner(old, node->info.id); - was_driving = node->driving; - - /* When a node was driver (and is waiting for all nodes to complete - * the Start command) cancel the pending state and let the new driver - * calculate a new state so that the Start command is sent to the - * node */ - if (was_driving && !node->driving) - impl->pending_state = node->info.state; - - pw_log_debug("%p: driver %p driving:%u", node, - driver, node->driving); + pw_log_debug("%p: driver %p driving:%u", node, driver, node->driving); pw_log_info("(%s-%u) -> change driver (%s-%d -> %s-%d)", node->name, node->info.id, old->name, old->info.id, driver->name, driver->info.id); @@ -1036,11 +1034,20 @@ * scheduled so it won't trigger yet */ node->to_driver_peer = pw_node_peer_ref(node, driver); + was_driving = node->driving; + /* then set the new driver node activation */ pw_impl_node_set_io(node, SPA_IO_Position, &driver->rt.target.activation->position, sizeof(struct spa_io_position)); + /* When a node was driver (and is waiting for all nodes to complete + * the Start command) cancel the pending state and let the new driver + * calculate a new state so that the Start command is sent to the + * node */ + if (was_driving && !node->driving) + impl->pending_state = node->info.state; + /* and then make the driver trigger the node */ node->from_driver_peer = pw_node_peer_ref(driver, node); @@ -1196,6 +1203,7 @@ recalc_reason = "transport changed"; } async = pw_properties_get_bool(node->properties, PW_KEY_NODE_ASYNC, false); + async &= !node->driver; if (async != node->async) { pw_log_info("%p: async %d -> %d", node, node->async, async); node->async = async; @@ -1996,10 +2004,14 @@ 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; - uint64_t nsec; + 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; + uint64_t min_timeout = UINT64_MAX, nsec; pw_log_trace_fp("%p: ready driver:%d exported:%d %p status:%d prepared:%d", node, node->driver, node->exported, driver, status, node->rt.prepared); @@ -2012,129 +2024,118 @@ pw_log_info("%p: ready non-active node %s in state %d", node, node->name, node->info.state); return -EIO; } + if (SPA_UNLIKELY(node != driver)) { + pw_log_warn("%p: ready non-driver node %s", node, node->name); + return -EIO; + } nsec = get_time_ns(data_system); - if (SPA_LIKELY(node == driver)) { - struct pw_node_activation_state *state = &a->state0; - struct spa_io_clock *cl = &node->rt.position->clock; - int sync_type, all_ready, update_sync, target_sync; - uint32_t owner2, reposition_owner; - uint64_t min_timeout = UINT64_MAX; - int32_t pending; - int old_status; - - if (SPA_UNLIKELY((pending = pw_node_activation_state_xchg(state)) > 0)) { - pw_impl_node_rt_emit_incomplete(driver); - old_status = SPA_ATOMIC_LOAD(a->status); - if (old_status != PW_NODE_ACTIVATION_FINISHED) { - SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED); - process_node(node, nsec); - debug_xrun_graph(node, nsec); - } + if (SPA_UNLIKELY((pending = pw_node_activation_state_xchg(state)) > 0)) { + pw_impl_node_rt_emit_incomplete(driver); + old_status = SPA_ATOMIC_LOAD(a->status); + if (old_status != PW_NODE_ACTIVATION_FINISHED) { + SPA_ATOMIC_STORE(a->status, PW_NODE_ACTIVATION_TRIGGERED); + 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); } + } - /* This update is done too late, the driver should do this - * before calling the ready callback so that it can use the new target - * duration and rate to schedule the next update. We do this here to - * help drivers that don't support this yet */ - if (SPA_UNLIKELY(cl->duration != cl->target_duration || - cl->rate.denom != cl->target_rate.denom)) { - pw_log_warn("driver %s did not update duration/rate (%"PRIu64"/%"PRIu64" %u/%u)", - node->name, - cl->duration, cl->target_duration, - cl->rate.denom, cl->target_rate.denom); - cl->duration = cl->target_duration; - cl->rate = cl->target_rate; - } + /* This update is done too late, the driver should do this + * before calling the ready callback so that it can use the new target + * duration and rate to schedule the next update. We do this here to + * help drivers that don't support this yet */ + if (SPA_UNLIKELY(cl->duration != cl->target_duration || + cl->rate.denom != cl->target_rate.denom)) { + pw_log_warn("driver %s did not update duration/rate (%"PRIu64"/%"PRIu64" %u/%u)", + node->name, + cl->duration, cl->target_duration, + cl->rate.denom, cl->target_rate.denom); + cl->duration = cl->target_duration; + cl->rate = cl->target_rate; + } - sync_type = check_updates(node, &reposition_owner); - owner0 = SPA_ATOMIC_LOAD(a->segment_owner0); - owner1 = SPA_ATOMIC_LOAD(a->segment_owner1); + sync_type = check_updates(node, &reposition_owner); + owner0 = SPA_ATOMIC_LOAD(a->segment_owner0); + owner1 = SPA_ATOMIC_LOAD(a->segment_owner1); again: - all_ready = sync_type == SYNC_CHECK; - update_sync = !all_ready; - target_sync = sync_type == SYNC_START ? true : false; + all_ready = sync_type == SYNC_CHECK; + update_sync = !all_ready; + target_sync = sync_type == SYNC_START ? true : false; - spa_list_for_each(t, &driver->rt.target_list, link) { - struct pw_node_activation *ta = t->activation; - uint32_t id = t->id; + spa_list_for_each(t, &driver->rt.target_list, link) { + struct pw_node_activation *ta = t->activation; + uint32_t id = t->id; - ta->driver_id = driver->info.id; + ta->driver_id = driver->info.id; retry_status: - pw_node_activation_state_reset(&ta->state0); - /* we don't change the state of inactive nodes and don't use them - * for reposition. The pending will be at least 1 and they might - * get decremented to 0 but since the status is inactive, we don't - * do the atomic CAS from NOT_TRIGGERED to TRIGGERED and we don't - * write the eventfd. */ - old_status = SPA_ATOMIC_LOAD(ta->status); - if (SPA_UNLIKELY(old_status == PW_NODE_ACTIVATION_INACTIVE)) - continue; + pw_node_activation_state_reset(&ta->state0); + /* we don't change the state of inactive nodes and don't use them + * for reposition. The pending will be at least 1 and they might + * get decremented to 0 but since the status is inactive, we don't + * do the atomic CAS from NOT_TRIGGERED to TRIGGERED and we don't + * write the eventfd. */ + old_status = SPA_ATOMIC_LOAD(ta->status); + if (SPA_UNLIKELY(old_status == PW_NODE_ACTIVATION_INACTIVE)) + continue; - /* if this fails, the node might just have stopped and we need to retry */ - if (SPA_UNLIKELY(!SPA_ATOMIC_CAS(ta->status, old_status, PW_NODE_ACTIVATION_NOT_TRIGGERED))) - goto retry_status; + /* if this fails, the node might just have stopped and we need to retry */ + if (SPA_UNLIKELY(!SPA_ATOMIC_CAS(ta->status, old_status, PW_NODE_ACTIVATION_NOT_TRIGGERED))) + goto retry_status; - if (old_status == PW_NODE_ACTIVATION_TRIGGERED || - old_status == PW_NODE_ACTIVATION_AWAKE) { - update_xrun_stats(ta, 1, nsec / 1000, 0); - debug_xrun_target(node, t, old_status, nsec); - } + if (old_status == PW_NODE_ACTIVATION_TRIGGERED || + old_status == PW_NODE_ACTIVATION_AWAKE) { + update_xrun_stats(ta, 1, nsec / 1000, 0); + debug_xrun_target(node, t, old_status, nsec); + } - /* this is the node with reposition info */ - if (SPA_UNLIKELY(id == reposition_owner)) - reposition_target = t; + /* this is the node with reposition info */ + if (SPA_UNLIKELY(id == reposition_owner)) + reposition_target = t; - /* update extra segment info if it is the owner */ - if (SPA_UNLIKELY(id == owner0)) - a->position.segments0.bar = ta->segment.bar; - if (SPA_UNLIKELY(id == owner1)) - a->position.segments0.video = ta->segment.video; + /* update extra segment info if it is the owner */ + if (SPA_UNLIKELY(id == owner0)) + a->position.segments0.bar = ta->segment.bar; + if (SPA_UNLIKELY(id == owner1)) + a->position.segments0.video = ta->segment.video; - min_timeout = SPA_MIN(min_timeout, ta->sync_timeout); + min_timeout = SPA_MIN(min_timeout, ta->sync_timeout); - if (SPA_UNLIKELY(update_sync)) { - ta->pending_sync = target_sync; - ta->pending_new_pos = target_sync; - } else { - all_ready &= ta->pending_sync == false; - } + if (SPA_UNLIKELY(update_sync)) { + ta->pending_sync = target_sync; + ta->pending_new_pos = target_sync; + } else { + all_ready &= ta->pending_sync == false; } + } - a->prev_signal_time = a->signal_time; - node->driver_start = nsec; - - a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT); - - if (SPA_UNLIKELY(reposition_target != NULL)) { - do_reposition(node, reposition_target); - sync_type = SYNC_START; - reposition_owner = 0; - reposition_target = NULL; - goto again; - } + a->prev_signal_time = a->signal_time; + node->driver_start = nsec; - update_position(node, all_ready, nsec); + a->sync_timeout = SPA_MIN(min_timeout, DEFAULT_SYNC_TIMEOUT); - a->position.clock.cycle++; - pw_impl_node_rt_emit_start(node); + if (SPA_UNLIKELY(reposition_target != NULL)) { + do_reposition(node, reposition_target); + sync_type = SYNC_START; + reposition_owner = 0; + reposition_target = NULL; + goto again; } - /* this should not happen, driver nodes that are not currently driving - * should not emit the ready callback */ - if (SPA_UNLIKELY(node->driver && !node->driving)) - return 0; - if (SPA_UNLIKELY(!node->driver)) { - /* legacy, nodes should directly resume the graph by calling - * the peer eventfd directly, node_ready is only for drivers */ - a->status = PW_NODE_ACTIVATION_FINISHED; - a->finish_time = nsec; - } + update_position(node, all_ready, nsec); + + /* move output with previous cycle, this makes the async nodes + * pick up the new data immediately */ if (status & SPA_STATUS_HAVE_DATA) { spa_list_for_each(p, &node->rt.output_mix, rt.node_link) spa_node_process_fast(p->mix); } + + a->position.clock.cycle++; + pw_impl_node_rt_emit_start(node); + /* now signal all the nodes we drive */ trigger_targets(node, status, nsec); return 0;
View file
pipewire-1.2.0.tar.gz/src/pipewire/impl-port.c -> pipewire-1.2.2.tar.bz2/src/pipewire/impl-port.c
Changed
@@ -345,7 +345,6 @@ int pw_impl_port_init_mix(struct pw_impl_port *port, struct pw_impl_port_mix *mix) { uint32_t port_id; - struct pw_impl_node *node = port->node; int res = 0; port_id = pw_map_insert_new(&port->mix_port_map, mix); @@ -389,13 +388,6 @@ port->n_mix, port->port_id, mix->port.port_id, mix->id, mix->peer_id, mix->io, spa_strerror(res)); - if (port->n_mix == 1) { - pw_log_debug("%p: setting port io", port); - spa_node_port_set_io(node->node, - port->direction, port->port_id, - SPA_IO_Buffers, - &port->rt.io, sizeof(port->rt.io)); - } return res; error_remove_port: @@ -410,7 +402,6 @@ { int res = 0; uint32_t port_id = mix->port.port_id; - struct pw_impl_node *node = port->node; pw_map_remove(&port->mix_port_map, port_id); spa_list_remove(&mix->link); @@ -430,11 +421,6 @@ if (port->n_mix == 0) { pw_log_debug("%p: clearing port io", port); - spa_node_port_set_io(node->node, - port->direction, port->port_id, - SPA_IO_Buffers, - NULL, 0); - pw_impl_port_set_param(port, SPA_PARAM_Format, 0, NULL); } return res; @@ -830,11 +816,6 @@ spa_list_for_each(mix, &port->mix_list, link) spa_node_add_port(port->mix, mix->port.direction, mix->port.port_id, NULL); - spa_node_port_set_io(port->mix, - pw_direction_reverse(port->direction), 0, - SPA_IO_Buffers, - &port->rt.io, sizeof(port->rt.io)); - if (port->node && port->node->rt.position) { spa_node_set_io(port->mix, SPA_IO_Position, @@ -1836,6 +1817,13 @@ pw_log_debug("%p: %d set param %d %p", port, port->state, id, param); + if (id == SPA_PARAM_Format) { + pw_loop_invoke(node->data_loop, do_remove_port, SPA_ID_INVALID, NULL, 0, true, port); + spa_node_port_set_io(node->node, + port->direction, port->port_id, + SPA_IO_Buffers, NULL, 0); + } + /* set parameter on node */ res = spa_node_port_set_param(node->node, port->direction, port->port_id, @@ -1867,9 +1855,6 @@ } if (id == SPA_PARAM_Format) { - pw_log_debug("%p: %d %p %d", port, port->state, param, res); - - pw_loop_invoke(node->data_loop, do_remove_port, SPA_ID_INVALID, NULL, 0, true, port); /* setting the format always destroys the negotiated buffers */ if (port->direction == PW_DIRECTION_OUTPUT) { struct pw_impl_link *l; @@ -1915,6 +1900,10 @@ port, port->direction, port->port_id, n_buffers, node->node, alloc_flags); + spa_node_port_set_io(node->node, + port->direction, port->port_id, + SPA_IO_Buffers, NULL, 0); + pw_loop_invoke(node->data_loop, do_remove_port, SPA_ID_INVALID, NULL, 0, true, port); pw_buffers_clear(&port->mix_buffers); @@ -1946,8 +1935,17 @@ pw_direction_reverse(port->direction), 0, 0, buffers, n_buffers); } - if (n_buffers > 0) + if (n_buffers > 0) { + spa_node_port_set_io(node->node, + port->direction, port->port_id, + SPA_IO_Buffers, + &port->rt.io, sizeof(port->rt.io)); + spa_node_port_set_io(port->mix, + pw_direction_reverse(port->direction), 0, + SPA_IO_Buffers, + &port->rt.io, sizeof(port->rt.io)); pw_loop_invoke(node->data_loop, do_add_port, SPA_ID_INVALID, NULL, 0, false, port); + } return res; } @@ -1972,11 +1970,15 @@ mix->have_buffers = false; if (port->n_mix == 1) pw_impl_port_update_state(port, PW_IMPL_PORT_STATE_READY, 0, NULL); + + spa_node_port_set_io(port->mix, + mix->port.direction, mix->port.port_id, + SPA_IO_Buffers, NULL, 0); } /* first negotiate with the node, this makes it possible to let the * node allocate buffer memory if needed */ - if (port->state == PW_IMPL_PORT_STATE_READY) { + if (port->state == PW_IMPL_PORT_STATE_READY && !port->destroying) { res = negotiate_mixer_buffers(port, flags, buffers, n_buffers); if (res < 0) {
View file
pipewire-1.2.0.tar.gz/src/pipewire/private.h -> pipewire-1.2.2.tar.bz2/src/pipewire/private.h
Changed
@@ -563,6 +563,8 @@ */ #define PW_VERSION_NODE_ACTIVATION 1 +#define PW_NODE_ACTIVATION_PENDING_TRIGGER(status) ((status) <= PW_NODE_ACTIVATION_AWAKE) + /* nodes start as INACTIVE, when they are ready to be scheduled, they add their * fd to the loop and change status to FINISHED. When the node shuts down, the * status is set back to INACTIVE.
View file
pipewire-1.2.0.tar.gz/src/pipewire/thread.c -> pipewire-1.2.2.tar.bz2/src/pipewire/thread.c
Changed
@@ -90,10 +90,16 @@ pthread_attr_t *attr = NULL, attributes; const char *str; int err; + int (*create_func)(pthread_t *, const pthread_attr_t *attr, void *(*start)(void*), void *) = NULL; attr = pw_thread_fill_attr(props, &attributes); - err = pthread_create(&pt, attr, start, arg); + if (props == NULL || + (str = spa_dict_lookup(props, SPA_KEY_THREAD_CREATOR)) == NULL || + sscanf(str, "pointer:%p", &create_func) != 1) + create_func = pthread_create; + + err = create_func(&pt, attr, start, arg); if (attr) pthread_attr_destroy(attr);
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
.