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