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 15
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sun Sep 18 13:29:55 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.58 + +------------------------------------------------------------------- Wed Sep 7 13:36:51 UTC 2022 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.57
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.57 +Version: 0.3.58 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.57.tar.gz/NEWS -> pipewire-0.3.58.tar.gz/NEWS
Changed
@@ -1,9 +1,92 @@ +# PipeWire 0.3.58 (2022-09-15) + +This is a bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a regression that could cause audio crackling. + - Fix a regression in RTKit because rlimit was not set correctly. + - JAVA sound applications will now alsa work with the pulseaudio-alsa plugin. + - pw-top will now show the negotiated formats of devices and streams. + - Fix some potential crashes when starting streams. + - The ALSA plugin has had improved timing reporting and poll descriptor + handling that should improve compatibility. + - Many more improvements and bugfixes. + + +## PipeWire + - Avoid scheduling nodes before they are added to the graph. This could + avoid some crashes when scheduling nodes that were not completely + started yet. (#2677) + +## Tools + - pw-top now also shows the negotiated formats of streams and devices. + (#2566) + - pw-top prints microseconds as "us" now to avoid unicode problems. + +## Modules + - Fix compilation with newer lv2. + - Fix setting realtime priority with RTKit, it was not setting rlimit + correctly and RTKit would refuse to change the priority. + - Fix some playback problems with RAOP sink. (#2673) + - Filter chain will now warn when a non-existing control property is + used in the config file. (#2685) + - Filter chain can now handle control port names with ":" in the name. + (#2685) + - The echo-cancel module and interface now has activate/deactivate + functions to make it possible for plugins to reset their state. + +## SPA + - Make sure audioconvert uses the given channelmap and channels for the + volumes, even when not negotiated yet. This makes it possible to change + the volume before the node has been negotiated. + - Refactor the peaks resampler. Fix an error in the SSE code. + - Fix DSD min/max rates, avoid exposing impossible rates. + - Set monitor port buffer size correctly. This could cause some crackling + and hickups. (#2677) + - Make ALSA sequencer port names unique. + +## Pulse-server + - Rework the capture buffer attributes to better match pulseaudio. This + fixes a regression where opening pavucontrol could cause crackling. + (#2671) + - Implement TRIGGER and PREBUF methods. + - Handle clients that send more than the requested amount of data. + PipeWire will now also keep this as extra buffered data like PulseAudio. + This fixes JAVA sound applications when they are running on top of the + PulseAudio ALSA plugin. (#2626,#2674) + - Update the requested amount of bytes more like PulseAudio. Fixes + stuttering after resume with the GStreamer pulseaudio sink. (#2680) + +## ALSA Plugin + - More debug info was added. The time reporting was improved. + - The poll descriptor handling was improved, avoiding some spurious + wakeups. (#1697) + + +Older versions: + + # PipeWire 0.3.57 (2022-09-02) This is a bugfix release that is API and ABI compatible with previous 0.3.x releases. ## Highlights + - Support masking of conf.d/ files. (#2629) + - Use org.freedesktop.portal.Realtime when available. This does the + correct PID/TID mappings to make realtime also work from flatpaks. + - Fix rate adjustement logic in pulse-tunnel. This would cause + increasing delays and hickups when using tunnels. (#2548) + - Add OPUS as a new vendor codec. Add OPUS-A2DP spec. PipeWire can now + send and reveive OPUS data over bluetooth. + - An AAC decoder was added so that PipeWire can now also function as + an A2DP AAC receiver. + - Fix some issues where the wrong samplerate was used. (#2614) + - Fix rate match for sources. This fixes an error where follower sources + would generate many resync warnings. + - Many more bugfixes and improvements. + ## PipeWire - Support masking of conf.d/ files. (#2629) @@ -16,7 +99,6 @@ host_machine. - Check return values of pw_getrandom(). - ## Tools - Updates to pw-cli manpages. (#2552) - Remove the pw-cli dump command. It is mostly implemented as part of @@ -85,9 +167,6 @@ - JACK clients from the same application will be added to the same group so that they share the quantum and rate. - -Older versions: - # PipeWire 0.3.56 (2022-07-19) This is a quick bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.57.tar.gz/doc/index.dox -> pipewire-0.3.58.tar.gz/doc/index.dox
Changed
@@ -40,5 +40,6 @@ - PipeWire: The Linux audio/video bus (LWN)(https://lwn.net/Articles/847412) - PipeWire Wikipedia(https://en.wikipedia.org/wiki/PipeWire) - Bluetooth, PipeWire and Whatsapp calls(https://gjhenrique.com/pipewire.html) +- Intoduction to PipeWire(https://bootlin.com/blog/an-introduction-to-pipewire/) */
View file
pipewire-0.3.57.tar.gz/man/pw-cat.1.rst.in -> pipewire-0.3.58.tar.gz/man/pw-cat.1.rst.in
Changed
@@ -26,9 +26,14 @@ server. It understands all audio file formats supported by ``libsndfile`` for PCM capture and playback. -It understands standard MIDI files for playback and recording, +It understands standard MIDI files for playback and recording. This tool +will not render MIDI files, it will simply make the MIDI events available +to the graph. You need a MIDI renderer such as qsynth, timidity or a hardware +MIDI rendered to hear the MIDI. -DSD playback is supported with the DSF file format. +DSD playback is supported with the DSF file format. This tool will only work +with native DSD capable hardware and will produce an error when no such +hardware was found. When the *FILE* is - input and output will be from STDIN and STDOUT respectively. @@ -60,10 +65,15 @@ -m | --midi MIDI mode. *FILE* is a MIDI file. If the tool is called under the name **pw-midiplay** or **pw-midirecord** this is the default. + Note that this program will *not* render the MIDI events into audible samples, + it will simply provide the MIDI events in the graph. You need a separate + MIDI renderer such as qsynth, timidity or a hardware renderer to hear the MIDI. -d | --dsd DSD mode. *FILE* is a DSF file. If the tool is called under the name **pw-dsdplay** this is the default. + Note that this program will *not* render the DSD audio. You need a DSD capable + device to play DSD content or this program will exit with an error. --media-type=VALUE Set the media type property (default Audio/Midi depending on mode).
View file
pipewire-0.3.57.tar.gz/man/pw-top.1.rst.in -> pipewire-0.3.58.tar.gz/man/pw-top.1.rst.in
Changed
@@ -61,7 +61,7 @@ The current rate (for drivers) and the suggested rate for follower nodes. - This is the rate at which the graph processes data and needs to be combined with + This is the rate at which the *graph* processes data and needs to be combined with the QUANT value to derive the duration of a processing cycle in the graph. Some nodes can have a 0 RATE, which means that they don't have any rate @@ -72,7 +72,8 @@ The RATE on (audio) driver nodes usually also translates directly to the samplerate used by the device. Although some devices might not be able to operate at the given samplerate, in which case resampling will need to be - done. + done. The negotiated samplerate with the device and stream can be found in + the FORMAT column. WAIT The waiting time of a node is the elapsed time between when the node @@ -125,6 +126,19 @@ Xruns for followers are incremented when the node started processing but did not complete before the end of the graph cycle deadline. +FORMAT + The format used by the driver node or the stream. This is the hardware format + negotiated with the device or stream. + + If the stream of driver has a different rate than the graph, resampling will + be done. + + For raw audio formats, the layout is <sampleformat> <channels> <samplerate>. + + For DSD formats, the layout is <dsd-rate> <channels>. + + For Video formats, the layout is <pixelformat> <width>x<height>. + NAME Name assigned to the device/node, as found in *pw-dump* node.name
View file
pipewire-0.3.57.tar.gz/meson.build -> pipewire-0.3.58.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.57', + version : '0.3.58', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.59.0', default_options : 'warning_level=3',
View file
pipewire-0.3.57.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.58.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -44,6 +44,15 @@ #include <pipewire/pipewire.h> +#define ATOMIC_INC(s) __atomic_add_fetch(&(s), 1, __ATOMIC_SEQ_CST) +#define ATOMIC_LOAD(s) __atomic_load_n(&(s), __ATOMIC_SEQ_CST) + +#define SEQ_WRITE(s) ATOMIC_INC(s) +#define SEQ_WRITE_SUCCESS(s1,s2) ((s1) + 1 == (s2) && ((s2) & 1) == 0) + +#define SEQ_READ(s) ATOMIC_LOAD(s) +#define SEQ_READ_SUCCESS(s1,s2) ((s1) == (s2) && ((s2) & 1) == 0) + PW_LOG_TOPIC_STATIC(alsa_log_topic, "alsa.pcm"); #define PW_LOG_TOPIC_DEFAULT alsa_log_topic @@ -58,6 +67,9 @@ typedef struct { snd_pcm_ioplug_t io; + snd_output_t *output; + FILE *log_file; + char *node_name; char *target; char *role; @@ -69,6 +81,7 @@ unsigned int draining:1; unsigned int xrun_detected:1; unsigned int hw_params_changed:1; + unsigned int active:1; snd_pcm_uframes_t hw_ptr; snd_pcm_uframes_t boundary; @@ -89,53 +102,62 @@ struct pw_stream *stream; struct spa_hook stream_listener; - struct pw_time time; + int64_t delay; + uint64_t now; + uintptr_t seq; struct spa_audio_info_raw format; } snd_pcm_pipewire_t; static int snd_pcm_pipewire_stop(snd_pcm_ioplug_t *io); -static int block_check(snd_pcm_ioplug_t *io) +static int check_active(snd_pcm_ioplug_t *io) { snd_pcm_pipewire_t *pw = io->private_data; snd_pcm_sframes_t avail; - uint64_t val; + bool active; avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr); - if (avail >= 0 && avail < (snd_pcm_sframes_t)pw->min_avail) { - spa_system_eventfd_read(pw->system, io->poll_fd, &val); - return 1; + + if (io->state == SND_PCM_STATE_DRAINING) { + active = pw->drained; } - return 0; + else if (avail >= 0 && avail < (snd_pcm_sframes_t)pw->min_avail) { + active = false; + } + else if (avail >= (snd_pcm_sframes_t)pw->min_avail) { + active = true; + } else { + active = false; + } + if (pw->active != active) { + pw_log_trace("%p: avail:%lu min-avail:%lu state:%s hw:%lu appl:%lu active:%d->%d state:%s", + pw, avail, pw->min_avail, snd_pcm_state_name(io->state), + pw->hw_ptr, io->appl_ptr, pw->active, active, + snd_pcm_state_name(io->state)); + } + return active; } -static int pcm_poll_block_check(snd_pcm_ioplug_t *io) + +static int update_active(snd_pcm_ioplug_t *io) { snd_pcm_pipewire_t *pw = io->private_data; + bool active; - if (io->state == SND_PCM_STATE_DRAINING) { + active = check_active(io); + + if (pw->active != active) { uint64_t val; - spa_system_eventfd_read(pw->system, io->poll_fd, &val); - return 0; - } else if (io->state == SND_PCM_STATE_RUNNING || - (io->state == SND_PCM_STATE_PREPARED && io->stream == SND_PCM_STREAM_CAPTURE)) { - return block_check(io); - } - return 0; -} -static inline int pcm_poll_unblock_check(snd_pcm_ioplug_t *io) -{ - snd_pcm_pipewire_t *pw = io->private_data; - snd_pcm_uframes_t avail; + pw->active = active; - avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr); - if (avail >= pw->min_avail || io->state == SND_PCM_STATE_DRAINING) { - spa_system_eventfd_write(pw->system, pw->fd, 1); - return 1; + if (active) + spa_system_eventfd_write(pw->system, io->poll_fd, 1); + else + spa_system_eventfd_read(pw->system, io->poll_fd, &val); } - return 0; + return active; } static void snd_pcm_pipewire_free(snd_pcm_pipewire_t *pw) @@ -143,7 +165,7 @@ if (pw == NULL) return; - pw_log_debug("%p:", pw); + pw_log_debug("%p: free", pw); if (pw->main_loop) pw_thread_loop_stop(pw->main_loop); if (pw->stream) @@ -156,13 +178,15 @@ pw_thread_loop_destroy(pw->main_loop); free(pw->node_name); free(pw->target); + snd_output_close(pw->output); + fclose(pw->log_file); free(pw); } static int snd_pcm_pipewire_close(snd_pcm_ioplug_t *io) { snd_pcm_pipewire_t *pw = io->private_data; - pw_log_debug("%p:", pw); + pw_log_debug("%p: close", pw); snd_pcm_pipewire_free(pw); return 0; } @@ -170,7 +194,7 @@ static int snd_pcm_pipewire_poll_descriptors(snd_pcm_ioplug_t *io, struct pollfd *pfds, unsigned int space) { snd_pcm_pipewire_t *pw = io->private_data; - pcm_poll_unblock_check(io); /* unblock socket for polling if needed */ + update_active(io); pfds->fd = pw->fd; pfds->events = POLLIN | POLLERR | POLLNVAL; return 1; @@ -188,7 +212,7 @@ return pw->error; *revents = pfds0.revents & ~(POLLIN | POLLOUT); - if (pfds0.revents & POLLIN && !pcm_poll_block_check(io)) + if (pfds0.revents & POLLIN && check_active(io)) *revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN; return 0; @@ -213,29 +237,40 @@ static int snd_pcm_pipewire_delay(snd_pcm_ioplug_t *io, snd_pcm_sframes_t *delayp) { snd_pcm_pipewire_t *pw = io->private_data; - int64_t elapsed = 0, filled, avail; + uintptr_t seq1, seq2; + int64_t elapsed = 0, delay, now, avail; + struct timespec ts; + int64_t diff; + + do { + seq1 = SEQ_READ(pw->seq); + + delay = pw->delay; + now = pw->now; + if (io->stream == SND_PCM_STREAM_PLAYBACK) + avail = snd_pcm_ioplug_hw_avail(io, pw->hw_ptr, io->appl_ptr); + else + avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr); + + seq2 = SEQ_READ(pw->seq); + } while (!SEQ_READ_SUCCESS(seq1, seq2)); - if (pw->time.rate.num != 0) { - struct timespec ts; - int64_t diff; + if (now != 0 && (io->state == SND_PCM_STATE_RUNNING || + io->state == SND_PCM_STATE_DRAINING)) { clock_gettime(CLOCK_MONOTONIC, &ts); - diff = SPA_TIMESPEC_TO_NSEC(&ts) - pw->time.now; - elapsed = (pw->time.rate.denom * diff) / (pw->time.rate.num * SPA_NSEC_PER_SEC); - } - if (io->stream == SND_PCM_STREAM_PLAYBACK)
View file
pipewire-0.3.57.tar.gz/spa/include/spa/interfaces/audio/aec.h -> pipewire-0.3.58.tar.gz/spa/include/spa/interfaces/audio/aec.h
Changed
@@ -36,7 +36,7 @@ #define SPA_TYPE_INTERFACE_AUDIO_AEC SPA_TYPE_INFO_INTERFACE_BASE "Audio:AEC" -#define SPA_VERSION_AUDIO_AEC 0 +#define SPA_VERSION_AUDIO_AEC 1 struct spa_audio_aec { struct spa_interface iface; const char *name; @@ -60,7 +60,7 @@ }; struct spa_audio_aec_methods { -#define SPA_VERSION_AUDIO_AEC_METHODS 0 +#define SPA_VERSION_AUDIO_AEC_METHODS 1 uint32_t version; int (*add_listener) (void *object, @@ -71,6 +71,10 @@ int (*init) (void *object, const struct spa_dict *args, const struct spa_audio_info_raw *info); int (*run) (void *object, const float *rec, const float *play, float *out, uint32_t n_samples); int (*set_props) (void *object, const struct spa_dict *args); + /* since 0.3.58, version 1:1 */ + int (*activate) (void *object); + /* since 0.3.58, version 1:1 */ + int (*deactivate) (void *object); }; #define spa_audio_aec_method(o,method,version,...) \ @@ -87,6 +91,8 @@ #define spa_audio_aec_init(o,...) spa_audio_aec_method(o, init, 0, __VA_ARGS__) #define spa_audio_aec_run(o,...) spa_audio_aec_method(o, run, 0, __VA_ARGS__) #define spa_audio_aec_set_props(o,...) spa_audio_aec_method(o, set_props, 0, __VA_ARGS__) +#define spa_audio_aec_activate(o) spa_audio_aec_method(o, activate, 1) +#define spa_audio_aec_deactivate(o) spa_audio_aec_method(o, deactivate, 1) #ifdef __cplusplus } /* extern "C" */
View file
pipewire-0.3.57.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.58.tar.gz/spa/include/spa/support/log.h
Changed
@@ -293,6 +293,24 @@ #define spa_log_trace_fp(l,...) #endif +#define spa_log_hexdump(l,lev,indent,data,len) \ +({ \ + char str512; \ + uint8_t *buf = (uint8_t *)data; \ + size_t i; \ + int pos = 0; \ + \ + for (i = 0; i < len; i++) { \ + if (i % 16 == 0) \ + pos = 0; \ + pos += sprintf(str + pos, "%02x ", bufi); \ + if (i % 16 == 15 || i == len - 1) { \ + spa_log_log(l,lev,__FILE__,__LINE__,__func__, \ + "%*s" "%s",indent,"", str); \ + } \ + } \ +}) + /** \fn spa_log_error */ /** keys can be given when initializing the logger handle */
View file
pipewire-0.3.57.tar.gz/spa/include/spa/utils/keys.h -> pipewire-0.3.58.tar.gz/spa/include/spa/utils/keys.h
Changed
@@ -62,6 +62,8 @@ #define SPA_KEY_API_ALSA_USE_UCM "api.alsa.use-ucm" /**< if UCM should be used */ #define SPA_KEY_API_ALSA_IGNORE_DB "api.alsa.ignore-dB" /**< if decibel info should be ignored */ #define SPA_KEY_API_ALSA_OPEN_UCM "api.alsa.open.ucm" /**< if UCM should be opened card */ +#define SPA_KEY_API_ALSA_DISABLE_LONGNAME \ + "api.alsa.disable-longname" /**< if card long name should not be passed to MIDI port */ /** info from alsa card_info */ #define SPA_KEY_API_ALSA_CARD_ID "api.alsa.card.id" /**< id from card_info */
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -1546,7 +1546,7 @@ } impl->ucm.default_sample_spec.format = PA_SAMPLE_S16NE; - impl->ucm.default_sample_spec.rate = 44100; + impl->ucm.default_sample_spec.rate = 48000; impl->ucm.default_sample_spec.channels = 2; pa_channel_map_init_extend(&impl->ucm.default_channel_map, impl->ucm.default_sample_spec.channels, PA_CHANNEL_MAP_ALSA);
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -56,9 +56,9 @@ if (full) this->info.change_mask = this->info_all; if (this->info.change_mask) { - struct spa_dict_item items4; + struct spa_dict_item items7; uint32_t i, n_items = 0; - char latency64; + char latency64, period64, nperiods64, headroom64; itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa"); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Sink"); @@ -66,6 +66,12 @@ if (this->have_format) { snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency); + snprintf(period, sizeof(period), "%lu", this->period_frames); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", period); + snprintf(nperiods, sizeof(nperiods), "%lu", this->buffer_frames / this->period_frames); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", nperiods); + snprintf(headroom, sizeof(headroom), "%u", this->headroom); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", headroom); } this->info.props = &SPA_DICT_INIT(items, n_items);
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -57,9 +57,9 @@ if (full) this->info.change_mask = this->info_all; if (this->info.change_mask) { - struct spa_dict_item items4; + struct spa_dict_item items7; uint32_t i, n_items = 0; - char latency64; + char latency64, period64, nperiods64, headroom64; itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_API, "alsa"); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_MEDIA_CLASS, "Audio/Source"); @@ -67,6 +67,12 @@ if (this->have_format) { snprintf(latency, sizeof(latency), "%lu/%d", this->buffer_frames / 2, this->rate); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, latency); + snprintf(period, sizeof(period), "%lu", this->period_frames); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", period); + snprintf(nperiods, sizeof(nperiods), "%lu", this->buffer_frames / this->period_frames); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", nperiods); + snprintf(headroom, sizeof(headroom), "%u", this->headroom); + itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", headroom); } this->info.props = &SPA_DICT_INIT(items, n_items);
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -782,7 +782,7 @@ return false; } -static int add_rate(struct state *state, uint32_t scale, bool all, uint32_t index, uint32_t *next, +static int add_rate(struct state *state, uint32_t scale, uint32_t interleave, bool all, uint32_t index, uint32_t *next, uint32_t min_allowed_rate, snd_pcm_hw_params_t *params, struct spa_pod_builder *b) { struct spa_pod_frame f1; @@ -794,11 +794,13 @@ CHECK(snd_pcm_hw_params_get_rate_min(params, &min, &dir), "get_rate_min"); CHECK(snd_pcm_hw_params_get_rate_max(params, &max, &dir), "get_rate_max"); - spa_log_debug(state->log, "min:%u max:%u min-allowed:%u scale:%u all:%d", - min, max, min_allowed_rate, scale, all); + spa_log_debug(state->log, "min:%u max:%u min-allowed:%u scale:%u interleave:%u all:%d", + min, max, min_allowed_rate, scale, interleave, all); - min_allowed_rate /= scale; - min = SPA_MAX(min_allowed_rate, min); + min = SPA_MAX(min_allowed_rate * scale / interleave, min) * interleave / scale; + max = max * interleave / scale; + if (max < min) + return 0; if (!state->multi_rate && state->card->format_ref > 0) rate = state->card->rate; @@ -1068,7 +1070,7 @@ choice->body.type = SPA_CHOICE_Enum; spa_pod_builder_pop(b, &f1); - if ((res = add_rate(state, 1, false, index & 0xffff, next, 0, params, b)) != 1) + if ((res = add_rate(state, 1, 1, false, index & 0xffff, next, 0, params, b)) != 1) return res; if ((res = add_channels(state, false, index & 0xffff, next, params, b)) != 1) @@ -1163,7 +1165,7 @@ } spa_pod_builder_pop(b, &f1); - if ((res = add_rate(state, 1, true, index & 0xffff, next, 0, params, b)) != 1) + if ((res = add_rate(state, 1, 1, true, index & 0xffff, next, 0, params, b)) != 1) return res; (*next)++; @@ -1227,7 +1229,8 @@ * 176400. This would correspond to "DSD32" (which does not exist). Trying * to use such a rate with DSD hardware does not work and may cause undefined * behavior in said hardware. */ - if ((res = add_rate(state, SPA_ABS(interleave), true, index & 0xffff, next, 44100 * 64 / 8, params, b)) != 1) + if ((res = add_rate(state, 8, SPA_ABS(interleave), true, index & 0xffff, + next, 44100, params, b)) != 1) return res; if ((res = add_channels(state, true, index & 0xffff, next, params, b)) != 1)
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-seq-bridge.c
Changed
@@ -48,6 +48,7 @@ { strncpy(props->device, DEFAULT_DEVICE, sizeof(props->device)); strncpy(props->clock_name, DEFAULT_CLOCK_NAME, sizeof(props->clock_name)); + props->disable_longname = 0; } static int impl_node_enum_params(void *object, int seq, @@ -249,7 +250,7 @@ snd_seq_port_info_t *info; snd_seq_client_info_t *client_info; char card8; - char name128; + char name256; char path128; char alias128; @@ -261,11 +262,34 @@ snd_seq_get_any_client_info(this->sys.hndl, port->addr.client, client_info); - snprintf(name, sizeof(name), "%s:(%s_%d) %s", - snd_seq_client_info_get_name(client_info), - port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback", - port->addr.port, - snd_seq_port_info_get_name(info)); + int card_id; + + // Failed to obtain card number (software device) or disabled + if (this->props.disable_longname || (card_id = snd_seq_client_info_get_card(client_info)) < 0) { + snprintf(name, sizeof(name), "%s:(%s_%d) %s", + snd_seq_client_info_get_name(client_info), + port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback", + port->addr.port, + snd_seq_port_info_get_name(info)); + } else { + char *longname; + if (snd_card_get_longname(card_id, &longname) == 0) { + snprintf(name, sizeof(name), "%s:(%s_%d) %s", + longname, + port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback", + port->addr.port, + snd_seq_port_info_get_name(info)); + free(longname); + } else { + // At least add card number to be distinct + snprintf(name, sizeof(name), "%s %d:(%s_%d) %s", + snd_seq_client_info_get_name(client_info), + card_id, + port->direction == SPA_DIRECTION_OUTPUT ? "capture" : "playback", + port->addr.port, + snd_seq_port_info_get_name(info)); + } + } clean_name(name); snprintf(path, sizeof(path), "alsa:seq:%s:client_%d:%s_%d", @@ -927,6 +951,8 @@ } else if (spa_streq(k, "clock.name")) { spa_scnprintf(this->props.clock_name, sizeof(this->props.clock_name), "%s", s); + } else if (spa_streq(k, SPA_KEY_API_ALSA_DISABLE_LONGNAME)) { + this->props.disable_longname = spa_atob(s); } }
View file
pipewire-0.3.57.tar.gz/spa/plugins/alsa/alsa-seq.h -> pipewire-0.3.58.tar.gz/spa/plugins/alsa/alsa-seq.h
Changed
@@ -52,6 +52,7 @@ struct props { char device64; char clock_name64; + bool disable_longname; }; #define MAX_EVENT_SIZE 1024
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -32,6 +32,7 @@ #include <spa/support/log.h> #include <spa/utils/result.h> #include <spa/utils/list.h> +#include <spa/utils/json.h> #include <spa/utils/names.h> #include <spa/utils/string.h> #include <spa/node/node.h> @@ -839,10 +840,6 @@ spa_log_info(this->log, "key:'%s' val:'%s'", name, value); changed += audioconvert_set_param(this, name, value); } - if (changed) { - channelmix_init(&this->mix); - set_volume(this); - } return changed; } @@ -924,6 +921,7 @@ else if (have_channel_volume) p->have_soft_volume = false; + channelmix_init(&this->mix); set_volume(this); } return changed; @@ -1255,7 +1253,7 @@ float volumesSPA_AUDIO_MAX_CHANNELS; struct dir *dir = &this->dirthis->direction; - spa_log_debug(this->log, "%p", this); + spa_log_debug(this->log, "%p have_format:%d", this, dir->have_format); if (dir->have_format) remap_volumes(this, &dir->format); @@ -1726,20 +1724,20 @@ case SPA_PARAM_Buffers: { uint32_t size; - struct dir *dir; if (!port->have_format) return -EIO; if (result.index > 0) return 0; - dir = &this->dirdirection; - if (dir->mode == SPA_PARAM_PORT_CONFIG_MODE_dsp) { + if (PORT_IS_DSP(this, direction, port_id)) { /* DSP ports always use the quantum_limit as the buffer * size. */ size = this->quantum_limit; } else { uint32_t irate, orate; + struct dir *dir = &this->dirdirection; + /* Convert ports are scaled so that they can always * provide one quantum of data */ irate = dir->format.info.raw.rate; @@ -2772,6 +2770,34 @@ return sizeof(struct impl); } +static uint32_t channel_from_name(const char *name) +{ + int i; + for (i = 0; spa_type_audio_channeli.name; i++) { + if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name))) + return spa_type_audio_channeli.type; + } + return SPA_AUDIO_CHANNEL_UNKNOWN; +} + +static inline uint32_t parse_position(uint32_t *pos, const char *val, size_t len) +{ + struct spa_json it2; + char v256; + uint32_t i = 0; + + spa_json_init(&it0, val, len); + if (spa_json_enter_array(&it0, &it1) <= 0) + spa_json_init(&it1, val, len); + + while (spa_json_get_string(&it1, v, sizeof(v)) > 0 && + i < SPA_AUDIO_MAX_CHANNELS) { + posi++ = channel_from_name(v); + } + return i; +} + + static int impl_init(const struct spa_handle_factory *factory, struct spa_handle *handle, @@ -2822,10 +2848,16 @@ else this->direction = SPA_DIRECTION_INPUT; } + else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) + this->props.n_channels = parse_position(this->props.channel_map, s, strlen(s)); else audioconvert_set_param(this, k, s); } + this->props.channel.n_volumes = this->props.n_channels; + this->props.soft.n_volumes = this->props.n_channels; + this->props.monitor.n_volumes = this->props.n_channels; + this->dirSPA_DIRECTION_INPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT); this->dirSPA_DIRECTION_OUTPUT.latency = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT);
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/channelmix-ops.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/channelmix-ops.c
Changed
@@ -31,21 +31,9 @@ #include <spa/support/log.h> #include <spa/utils/defs.h> -#define VOLUME_MIN 0.0f -#define VOLUME_NORM 1.0f - #include "channelmix-ops.h" #include "hilbert.h" - -#define _M(ch) (1UL << SPA_AUDIO_CHANNEL_ ## ch) -#define MASK_MONO _M(FC)|_M(MONO)|_M(UNKNOWN) -#define MASK_STEREO _M(FL)|_M(FR)|_M(UNKNOWN) -#define MASK_QUAD _M(FL)|_M(FR)|_M(RL)|_M(RR)|_M(UNKNOWN) -#define MASK_3_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE) -#define MASK_5_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) -#define MASK_7_1 _M(FL)|_M(FR)|_M(FC)|_M(LFE)|_M(SL)|_M(SR)|_M(RL)|_M(RR) - #define ANY ((uint32_t)-1) #define EQ ((uint32_t)-2) @@ -199,8 +187,11 @@ for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) matrixii= 1.0f; } + if (dst_mask & FRONT) + filter_fc = true; + if (dst_mask & _MASK(LFE)) + filter_lfe = true; src_mask = dst_mask = ~0LU; - filter_fc = filter_lfe = true; goto done; } else { spa_log_debug(mix->log, "matching channels");
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/meson.build -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/meson.build
Changed
@@ -27,7 +27,7 @@ 'resample-peaks-sse.c', 'volume-ops-sse.c', 'channelmix-ops-sse.c' , - c_args : sse_args, '-O3', '-DHAVE_SSE', + c_args : sse_args, '-Ofast', '-DHAVE_SSE', dependencies : spa_dep , install : false )
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-avx.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-avx.c
Changed
@@ -27,7 +27,7 @@ #include <assert.h> #include <immintrin.h> -static void inner_product_avx(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_avx(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT taps, uint32_t n_taps) { __m256 sy2 = { _mm256_setzero_ps(), _mm256_setzero_ps() }, ty; @@ -56,7 +56,7 @@ _mm_store_ss(d, sx0); } -static void inner_product_ip_avx(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ip_avx(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x, uint32_t n_taps) {
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-c.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-c.c
Changed
@@ -24,7 +24,7 @@ #include "resample-native-impl.h" -static void inner_product_c(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_c(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT taps, uint32_t n_taps) { float sum = 0.0f; @@ -40,7 +40,7 @@ *d = sum; } -static void inner_product_ip_c(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ip_c(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x, uint32_t n_taps) {
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-neon.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-neon.c
Changed
@@ -26,7 +26,7 @@ #include <arm_neon.h> -static void inner_product_neon(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_neon(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT taps, uint32_t n_taps) { unsigned int remainder = n_taps % 16; @@ -137,7 +137,7 @@ #endif } -static void inner_product_ip_neon(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ip_neon(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x, uint32_t n_taps) {
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-sse.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-sse.c
Changed
@@ -26,7 +26,7 @@ #include <xmmintrin.h> -static void inner_product_sse(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_sse(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT taps, uint32_t n_taps) { __m128 sum = _mm_setzero_ps(); @@ -68,7 +68,7 @@ _mm_store_ss(d, sum); } -static void inner_product_ip_sse(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ip_sse(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x, uint32_t n_taps) {
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-native-ssse3.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-native-ssse3.c
Changed
@@ -26,7 +26,7 @@ #include <tmmintrin.h> -static void inner_product_ssse3(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ssse3(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT taps, uint32_t n_taps) { __m128 sum = _mm_setzero_ps(); @@ -97,7 +97,7 @@ _mm_store_ss(d, sum); } -static void inner_product_ip_ssse3(float *d, const float * SPA_RESTRICT s, +static inline void inner_product_ip_ssse3(float *d, const float * SPA_RESTRICT s, const float * SPA_RESTRICT t0, const float * SPA_RESTRICT t1, float x, uint32_t n_taps) {
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-c.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-c.c
Changed
@@ -26,48 +26,12 @@ #include "resample-peaks-impl.h" -void resample_peaks_process_c(struct resample *r, - const void * SPA_RESTRICT src, uint32_t *in_len, - void * SPA_RESTRICT dst, uint32_t *out_len) +static inline float find_abs_max_c(const float *s, uint32_t n_samples, float m) { - struct peaks_data *pd = r->data; - uint32_t c, i, o, end, chunk, o_count, i_count; - - if (SPA_UNLIKELY(r->channels == 0)) - return; - - for (c = 0; c < r->channels; c++) { - const float *s = srcc; - float *d = dstc, m = pd->max_fc; - - o_count = pd->o_count; - i_count = pd->i_count; - o = i = 0; - - while (i < *in_len && o < *out_len) { - end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate; - end = end > i_count ? end - i_count : 0; - chunk = SPA_MIN(end, *in_len); - - for (; i < chunk; i++) - m = SPA_MAX(fabsf(si), m); - - if (i == end) { - do++ = m; - m = 0.0f; - o_count++; - } - } - pd->max_fc = m; - } - - *out_len = o; - *in_len = i; - pd->o_count = o_count; - pd->i_count = i_count + i; - - while (pd->i_count >= r->i_rate) { - pd->i_count -= r->i_rate; - pd->o_count -= r->o_rate; - } + uint32_t n; + for (n = 0; n < n_samples; n++) + m = fmaxf(fabsf(sn), m); + return m; } + +MAKE_PEAKS(c);
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-impl.h
Changed
@@ -34,11 +34,59 @@ float max_f; }; -void resample_peaks_process_c(struct resample *r, - const void * SPA_RESTRICT src, uint32_t *in_len, - void * SPA_RESTRICT dst, uint32_t *out_len); +#define DEFINE_PEAKS(arch) \ +void resample_peaks_process_##arch(struct resample *r, \ + const void * SPA_RESTRICT src, uint32_t *in_len, \ + void * SPA_RESTRICT dst, uint32_t *out_len) + +#define MAKE_PEAKS(arch) \ +DEFINE_PEAKS(arch) \ +{ \ + struct peaks_data *pd = r->data; \ + uint32_t c, i, o, end, chunk, i_count, o_count; \ + \ + if (SPA_UNLIKELY(r->channels == 0)) \ + return; \ + \ + for (c = 0; c < r->channels; c++) { \ + const float *s = srcc; \ + float *d = dstc, m = pd->max_fc; \ + \ + o_count = pd->o_count; \ + i_count = pd->i_count; \ + o = i = 0; \ + \ + while (i < *in_len && o < *out_len) { \ + end = ((uint64_t) (o_count + 1) \ + * r->i_rate) / r->o_rate; \ + end = end > i_count ? end - i_count : 0; \ + chunk = SPA_MIN(end, *in_len); \ + \ + m = find_abs_max_##arch(&si, chunk - i, m); \ + \ + i += chunk; \ + \ + if (i == end) { \ + do++ = m; \ + m = 0.0f; \ + o_count++; \ + } \ + } \ + pd->max_fc = m; \ + } \ + *out_len = o; \ + *in_len = i; \ + pd->o_count = o_count; \ + pd->i_count = i_count + i; \ + \ + while (pd->i_count >= r->i_rate) { \ + pd->i_count -= r->i_rate; \ + pd->o_count -= r->o_rate; \ + } \ +} + + +DEFINE_PEAKS(c); #if defined (HAVE_SSE) -void resample_peaks_process_sse(struct resample *r, - const void * SPA_RESTRICT src, uint32_t *in_len, - void * SPA_RESTRICT dst, uint32_t *out_len); +DEFINE_PEAKS(sse); #endif
View file
pipewire-0.3.57.tar.gz/spa/plugins/audioconvert/resample-peaks-sse.c -> pipewire-0.3.58.tar.gz/spa/plugins/audioconvert/resample-peaks-sse.c
Changed
@@ -32,65 +32,33 @@ { __m128 t = _mm_movehl_ps(val, val); t = _mm_max_ps(t, val); - val = _mm_shuffle_ps(val, t, 0x55); + val = _mm_shuffle_ps(t, t, 0x55); val = _mm_max_ss(t, val); return _mm_cvtss_f32(val); } -void resample_peaks_process_sse(struct resample *r, - const void * SPA_RESTRICT src, uint32_t *in_len, - void * SPA_RESTRICT dst, uint32_t *out_len) +static inline float find_abs_max_sse(const float *s, uint32_t n_samples, float m) { - struct peaks_data *pd = r->data; - uint32_t c, i, o, end, chunk, unrolled, i_count, o_count; - __m128 in, max, mask = _mm_andnot_ps(_mm_set_ps1(-0.0f), - _mm_cmpeq_ps(_mm_setzero_ps(), _mm_setzero_ps())); + __m128 in2, max; + uint32_t n, unrolled; + const __m128 mask = _mm_set1_ps(-0.0f); - if (r->channels == 0) - return; + max = _mm_set1_ps(m); - for (c = 0; c < r->channels; c++) { - const float *s = srcc; - float *d = dstc, m = pd->max_fc; + unrolled = n_samples & ~7; - o_count = pd->o_count; - i_count = pd->i_count; - o = i = 0; - - max = _mm_set1_ps(m); - - while (i < *in_len && o < *out_len) { - end = ((uint64_t) (o_count + 1) * r->i_rate) / r->o_rate; - end = end > i_count ? end - i_count : 0; - chunk = SPA_MIN(end, *in_len); - - unrolled = chunk - ((chunk - i) & 3); - - for (; i < unrolled; i+=4) { - in = _mm_loadu_ps(&si); - in = _mm_and_ps(mask, in); - max = _mm_max_ps(in, max); - } - for (; i < chunk; i++) - m = SPA_MAX(fabsf(si), m); - - if (i == end) { - do++ = SPA_MAX(hmax_ps(max), m); - m = 0.0f; - max = _mm_set1_ps(m); - o_count++; - } - } - pd->max_fc = SPA_MAX(hmax_ps(max), m); + for (n = 0; n < unrolled; n += 8) { + in0 = _mm_loadu_ps(&sn + 0); + in1 = _mm_loadu_ps(&sn + 4); + in0 = _mm_andnot_ps(mask, in0); + in1 = _mm_andnot_ps(mask, in1); + max = _mm_max_ps(max, in0); + max = _mm_max_ps(max, in1); } + for (; n < n_samples; n++) + m = fmaxf(fabsf(sn), m); - *out_len = o; - *in_len = i; - pd->o_count = o_count; - pd->i_count = i_count + i; - - while (pd->i_count >= r->i_rate) { - pd->i_count -= r->i_rate; - pd->o_count -= r->o_rate; - } + return fmaxf(hmax_ps(max), m); } + +MAKE_PEAKS(sse);
View file
pipewire-0.3.57.tar.gz/spa/plugins/audiomixer/audiomixer.c -> pipewire-0.3.58.tar.gz/spa/plugins/audiomixer/audiomixer.c
Changed
@@ -45,6 +45,9 @@ #define SPA_LOG_TOPIC_DEFAULT log_topic static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.audiomixer"); +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 + #define MAX_BUFFERS 64 #define MAX_PORTS 128 #define MAX_CHANNELS 64 @@ -353,8 +356,10 @@ SPA_AUDIO_FORMAT_U24_32, SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX)); + SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_RATE, 1, INT32_MAX), + SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_CHANNELS, 1, INT32_MAX)); } break; default:
View file
pipewire-0.3.57.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c -> pipewire-0.3.58.tar.gz/spa/plugins/audiotestsrc/audiotestsrc.c
Changed
@@ -55,6 +55,9 @@ WAVE_SQUARE, }; +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 + #define DEFAULT_LIVE true #define DEFAULT_WAVE WAVE_SINE #define DEFAULT_FREQ 440.0 @@ -583,8 +586,10 @@ SPA_AUDIO_FORMAT_S32, SPA_AUDIO_FORMAT_F32, SPA_AUDIO_FORMAT_F64), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX)); + SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_RATE, 1, INT32_MAX), + SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_CHANNELS, 1, INT32_MAX)); break; default: return 0;
View file
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/README-OPUS-A2DP.md -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/README-OPUS-A2DP.md
Changed
@@ -6,31 +6,18 @@ # OPUS-A2DP-0.5 specification -DRAFT +In this file, a way to use Opus as an A2DP vendor codec is specified. -In this file, we specify how to use Opus as an A2DP vendor codec. We -will call this "OPUS-A2DP-0.5". There is no previous public +We will call this "OPUS-A2DP-0.5". There is no previous public specification for using Opus as an A2DP vendor codec (to my knowledge), which is why we need this one. _TOC_ -# A2DP Codec Capabilities +# Media Codec Capabilities -The A2DP capability structure is as follows. - -Integer fields and multi-byte bitfields are laid out in **little -endian** order. All integer fields are unsigned. - -Each entry may have different meaning when present as a capability. -Below, we indicate this by abbreviations CAP/SNK for sink capability, -CAP/SRC for source capability, CAP for capability as either, and SEL -for the selected value by SRC. - -Bits in fields marked RFA (Reserved For Additions) shall be set to -zero. - -The capability and configuration structure is as follows: +The Media Codec Specific Information Elements (AVDTP v1.3, §8.21.5) +capability and configuration structure is as follows: | Octet | Bits | Meaning | |-------|------|-----------------------------------------------| @@ -42,7 +29,19 @@ | 17-20 | 0-7 | Return Direction Audio Location Configuration | | 21-23 | 0-7 | Return Direction Limits Configuration | -See `a2dp-codec-caps.h` for definition as C structs. +All integer fields and multi-byte bitfields are laid out in **little +endian** order. All integer fields are unsigned. + +Each entry may have different meaning when present as a capability. +Below, we indicate this by abbreviations CAP for capability and SEL +for the value selected by SRC. + +Bits in fields marked RFA (Reserved For Additions) shall be set to +zero. + +> **Note** +> +> See `a2dp-codec-caps.h` for definition as C structs. ## Vendor ID Part @@ -53,13 +52,16 @@ | 0-3 | 0-7 | A2DP Vendor ID (0x05F1) | | 4-5 | 0-7 | A2DP Vendor Codec ID (0x1005) | -The Vendor ID is that of the Linux Foundation, and we are using it -here unofficially. +> **Note** +> +> The Vendor ID is that of the Linux Foundation, and we are using it +> here unofficially. ## Channel Configuration -The channel configuration consists of the channel count and a bitfield -indicating which of them are encoded in coupled streams. +The channel configuration consists of the channel count, and the count +of coupled streams. The latter indicates which channels are encoded as +left/right pairs, as defined in Sec. 5.1.1 of Opus Ogg Encapsulation RFC7845. | Octet | Bits | Meaning | |-------|------|------------------------------------------------------------| @@ -74,26 +76,23 @@ `(Channel Count) >= 2*(Coupled Stream Count)`. The Stream Count is `(Channel Count) - (Coupled Stream Count)`. -Streams and Coupled Streams have the same meaning as in Sec. 5.1.1 of -Opus Multistream RFC7845. - The logical Channels are identified by a Channel Index *j* such that `0 <= j < (Channel Count)`. The channels `0 <= j < 2*(Coupled Stream Count)` are encoded in the *k*-th stream of the payload, where `k = floor(j/2)` and `j mod 2` determines which of the two channels of the stream the logical channel is. The channels `2*(Coupled Stream Count) <= j < (Channel Count)` are encoded in the *k*-th stream of the payload, where `k = j - (Coupled Stream Count)`. -The prescription here is identical to RFC7845 with channel mapping -`mappingj = j`. -The semantic meaning for each channel is determined by their Audio -Location. +> **Note** +> +> The prescription here is identical to RFC7845 with channel mapping +> `mappingj = j`. We do not want to include the mapping table in the +> A2DP capabilities, so it is assumed to be trivial. ## Audio Location Configuration -The channel audio location specification is similar to the location -bitfield of the `Audio_Channel_Allocation` LTV structure in Bluetooth -SIG Assigned Numbers, Generic Audio used in the LE Audio. +The semantic meaning for each channel is determined by their Audio +Location bitfield. | Octet | Bits | Meaning | |-------|------|------------------------------------------------------| @@ -103,11 +102,9 @@ that were not set in CAP. SNK shall handle unsupported audio locations. It may do this for example by ignoring unsupported channels or via suitable up/downmixing. Hence, SRC may transmit channels with -audio locations that are not marked supported by SNK. The maximum -Channel Count however shall not be exceeded. +audio locations that are not marked supported by SNK. -The audio location bitfield values defined in Assigned Numbers, -Generic Audio are: +The audio location bit values are: | Channel Order | Bitmask | Audio Location | |---------------|------------|-------------------------| @@ -144,8 +141,8 @@ | 30 | 0x40000000 | RFA | | 31 | 0x80000000 | RFA | -In addition, we define a specific Channel Order for each. The bits -set in the bitfield define audio locations for the streams present in the +Each bit value is associated with a Channel Order. The bits set in +the bitfield define audio locations for the streams present in the payload. The set bit with the smallest Channel Order value defines the audio location for the Channel Index *j=0*, the bit with the next lowest Channel Order value defines the audio location for the Channel @@ -154,46 +151,53 @@ When the Channel Count is larger than the number of bits set in the Audio Location bitfield, the audio locations of the remaining channels are unspecified. Implementations may handle them as appropriate for -their use case, considering them as AUX0-AUXN, or in the case of +their use case, considering them as AUX0–AUXN, or in the case of Channel Count = 1, as the single mono audio channel. When the Channel Count is smaller than the number of bits set in the Audio Location bitfield, the audio locations for the channels are assigned as above, and remaining excess bits shall be ignored. -The channel ordering defined here is compatible with the internal -stream ordering in the reference Opus Multistream surround encoder -Mapping Family 0 and 1 output. This allows making use of its surround -masking and LFE handling capabilities. The stream ordering of the -reference Opus surround encoder, although being unchanged since its -addition in 2013, is an internal detail of the -encoder. Implementations using the surround encoder shall check that -the mapping table used by the encoder corresponds to the above channel -ordering. - -For reference, we list the Audio Location bitfield values -corresponding to the different channel counts in Opus Mapping Family 0 -and 1 surround encoder output, and the expected mapping table: - -| Mapping Family | Channel Count | Audio Location Value | Stream Ordering | Mapping Table | -|----------------|---------------|----------------------|---------------------------------|--------------------------| -| 0 | 1 | 0x00000000 | mono | {0} | -| 0 | 2 | 0x00000003 | FL, FR | {0, 1} | -| 1 | 1 | 0x00000000 | mono | {0} | -| 1 | 2 | 0x00000003 | FL, FR | {0, 1} | -| 1 | 3 | 0x00000007 | FL, FR, FC | {0, 2, 1} | -| 1 | 4 | 0x00000033 | FL, FR, BL, BR | {0, 1, 2, 3} | -| 1 | 5 | 0x00000037 | FL, FR, BL, BR, FC | {0, 4, 1, 2, 3} | -| 1 | 6 | 0x0000003f | FL, FR, BL, BR, FC, LFE | {0, 4, 1, 2, 3, 5} | -| 1 | 7 | 0x00000d0f | FL, FR, SL, SR, FC, BC, LFE | {0, 4, 1, 2, 3, 5, 6} | -| 1 | 8 | 0x00000c3f | FL, FR, SL, SR, BL, BR, FC, LFE | {0, 6, 1, 2, 3, 4, 5, 7} | - -The Mapping Table in the table indicates the mapping table selected by -`opus_multistream_surround_encoder_create` (Opus 1.3.1). If the -encoder outputs a different mapping table in a future Opus encoder -release, the channel ordering will be incorrect, and the surround -encoder can not be used. We expect that the probability of the Opus -encoder authors making such changes is negligible. +> **Note** +> +> The channel audio location specification is similar to the location +> bitfield of the `Audio_Channel_Allocation` LTV structure in Bluetooth +> SIG Assigned Numbers, Generic Audio used in the LE Audio, and the +> bitmasks defined above are the same. +> +> The channel ordering differs from LE Audio, and is defined here to be +> compatible with the internal stream ordering in the reference Opus +> Multistream surround encoder Mapping Family 0 and 1 output. This +> allows making use of its surround masking and LFE handling +> capabilities. The stream ordering of the reference Opus surround +> encoder, although being unchanged since its addition in 2013, is an +> internal detail of the encoder. Implementations using the surround +> encoder need to check that the mapping table used by the encoder +> corresponds to the above channel ordering. +>
View file
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/a2dp-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/a2dp-sink.c
Changed
@@ -885,7 +885,7 @@ static int do_start(struct impl *this) { - int i, res, val, size; + int res, val, size; struct port *port; socklen_t len; uint8_t *conf; @@ -907,8 +907,8 @@ conf = this->transport->configuration; size = this->transport->configuration_len; - for (i = 0; i < size; i++) - spa_log_debug(this->log, " %d: %02x", i, confi); + spa_log_debug(this->log, "Transport configuration:"); + spa_log_hexdump(this->log, SPA_LOG_LEVEL_DEBUG, 2, conf, (size_t)size); this->codec_data = this->codec->init(this->codec, this->is_duplex ? A2DP_CODEC_FLAG_SINK : 0,
View file
pipewire-0.3.57.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.58.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -491,7 +491,7 @@ uint8_t *pconf = (uint8_t *) config; DBusMessage *r; DBusError err; - int i, size, res; + int size, res; const struct a2dp_codec *codec; bool sink; @@ -506,8 +506,7 @@ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } spa_log_info(monitor->log, "%p: %s select conf %d", monitor, path, size); - for (i = 0; i < size; i++) - spa_log_debug(monitor->log, " %d: %02x", i, capi); + spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, cap, (size_t)size); codec = a2dp_endpoint_to_codec(monitor, path, &sink); if (codec != NULL) @@ -529,8 +528,7 @@ return DBUS_HANDLER_RESULT_NEED_MEMORY; goto exit_send; } - for (i = 0; i < size; i++) - spa_log_debug(monitor->log, " %d: %02x", i, pconfi); + spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, pconf, (size_t)size); if ((r = dbus_message_new_method_return(m)) == NULL) return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -1734,7 +1732,7 @@ else if (spa_streq(key, "Capabilities")) { DBusMessageIter iter; uint8_t *value; - int i, len; + int len; if (!check_iter_signature(&it1, "ay")) goto next; @@ -1743,8 +1741,7 @@ dbus_message_iter_get_fixed_array(&iter, &value, &len); spa_log_debug(monitor->log, "remote_endpoint %p: %s=%d", remote_endpoint, key, len); - for (i = 0; i < len; i++) - spa_log_debug(monitor->log, " %d: %02x", i, valuei); + spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, value, (size_t)len); free(remote_endpoint->capabilities); remote_endpoint->capabilities_len = 0; @@ -2267,7 +2264,7 @@ else if (spa_streq(key, "Configuration")) { DBusMessageIter iter; uint8_t *value; - int i, len; + int len; if (!check_iter_signature(&it1, "ay")) goto next; @@ -2276,8 +2273,7 @@ dbus_message_iter_get_fixed_array(&iter, &value, &len); spa_log_debug(monitor->log, "transport %p: %s=%d", transport, key, len); - for (i = 0; i < len; i++) - spa_log_debug(monitor->log, " %d: %02x", i, valuei); + spa_log_hexdump(monitor->log, SPA_LOG_LEVEL_DEBUG, 2, value, (size_t)len); free(transport->configuration); transport->configuration_len = 0;
View file
pipewire-0.3.57.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp -> pipewire-0.3.58.tar.gz/spa/plugins/libcamera/libcamera-utils.cpp
Changed
@@ -417,7 +417,7 @@ port->streamConfig = impl->config->at(0); if ((res = allocBuffers(impl, port, port->streamConfig.bufferCount)) < 0) - return res; + goto error; port->have_format = true;
View file
pipewire-0.3.57.tar.gz/spa/plugins/support/null-audio-sink.c -> pipewire-0.3.58.tar.gz/spa/plugins/support/null-audio-sink.c
Changed
@@ -71,7 +71,7 @@ } #define DEFAULT_CHANNELS 2 -#define DEFAULT_RATE 44100 +#define DEFAULT_RATE 48000 #define MAX_BUFFERS 16 #define MAX_PORTS 1
View file
pipewire-0.3.57.tar.gz/spa/plugins/v4l2/v4l2-source.c -> pipewire-0.3.58.tar.gz/spa/plugins/v4l2/v4l2-source.c
Changed
@@ -314,7 +314,7 @@ switch (SPA_NODE_COMMAND_ID(command)) { case SPA_NODE_COMMAND_ParamBegin: - if ((res = spa_v4l2_open(&port->dev, NULL)) < 0) + if ((res = spa_v4l2_open(&port->dev, this->props.device)) < 0) return res; break; case SPA_NODE_COMMAND_ParamEnd:
View file
pipewire-0.3.57.tar.gz/spa/plugins/videoconvert/videoadapter.c -> pipewire-0.3.58.tar.gz/spa/plugins/videoconvert/videoadapter.c
Changed
@@ -24,23 +24,32 @@ #include <spa/support/plugin.h> #include <spa/support/log.h> +#include <spa/support/cpu.h> #include <spa/node/node.h> #include <spa/node/io.h> #include <spa/node/utils.h> #include <spa/node/keys.h> -#include <spa/utils/result.h> #include <spa/utils/names.h> +#include <spa/utils/result.h> #include <spa/utils/string.h> #include <spa/buffer/alloc.h> #include <spa/pod/parser.h> #include <spa/pod/filter.h> +#include <spa/pod/dynamic.h> +#include <spa/param/param.h> +#include <spa/param/video/format-utils.h> +#include <spa/param/latency-utils.h> #include <spa/debug/format.h> #include <spa/debug/pod.h> +#undef SPA_LOG_TOPIC_DEFAULT +#define SPA_LOG_TOPIC_DEFAULT log_topic +static struct spa_log_topic *log_topic = &SPA_LOG_TOPIC(0, "spa.videoadapter"); + #define DEFAULT_ALIGN 16 -#define NAME "videoadapter" +#define MAX_PORTS 1 /** \cond */ @@ -49,19 +58,22 @@ struct spa_node node; struct spa_log *log; + struct spa_cpu *cpu; + uint32_t max_align; enum spa_direction direction; struct spa_node *target; - struct spa_hook target_listener; struct spa_node *follower; struct spa_hook follower_listener; uint32_t follower_flags; + struct spa_video_info follower_current_format; + struct spa_video_info default_format; struct spa_handle *hnd_convert; struct spa_node *convert; - + struct spa_hook convert_listener; uint32_t convert_flags; uint32_t n_buffers; @@ -69,32 +81,71 @@ struct spa_io_buffers io_buffers; struct spa_io_rate_match io_rate_match; + struct spa_io_position *io_position; uint64_t info_all; struct spa_node_info info; - struct spa_param_info params5; +#define IDX_EnumFormat 0 +#define IDX_PropInfo 1 +#define IDX_Props 2 +#define IDX_Format 3 +#define IDX_EnumPortConfig 4 +#define IDX_PortConfig 5 +#define IDX_Latency 6 +#define IDX_ProcessLatency 7 +#define N_NODE_PARAMS 8 + struct spa_param_info paramsN_NODE_PARAMS; + uint32_t convert_params_flagsN_NODE_PARAMS; + uint32_t follower_params_flagsN_NODE_PARAMS; struct spa_hook_list hooks; struct spa_callbacks callbacks; - unsigned int use_converter:1; + unsigned int add_listener:1; + unsigned int have_format:1; unsigned int started:1; - unsigned int active:1; unsigned int driver:1; - unsigned int driving:1; - unsigned int monitor:1; + unsigned int async:1; + unsigned int passthrough:1; + unsigned int follower_removing:1; }; /** \endcond */ +static int follower_enum_params(struct impl *this, + uint32_t id, + uint32_t idx, + struct spa_result_node_params *result, + const struct spa_pod *filter, + struct spa_pod_builder *builder) +{ + int res; + if (result->next < 0x100000) { + if (this->convert != NULL && + (res = spa_node_enum_params_sync(this->convert, + id, &result->next, filter, &result->param, builder)) == 1) + return res; + result->next = 0x100000; + } + if (result->next < 0x200000 && this->follower_params_flagsidx & SPA_PARAM_INFO_READ) { + result->next &= 0xfffff; + if ((res = spa_node_enum_params_sync(this->follower, + id, &result->next, filter, &result->param, builder)) == 1) { + result->next |= 0x100000; + return res; + } + result->next = 0x200000; + } + return 0; +} + static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, const struct spa_pod *filter) { struct impl *this = object; - struct spa_pod *param; - struct spa_pod_builder b = { 0 }; - uint8_t buffer1024; + uint8_t buffer4096; + struct spa_pod_dynamic_builder b; struct spa_result_node_params result; uint32_t count = 0; int res; @@ -105,50 +156,65 @@ result.id = id; result.next = start; next: - result.index = result.next++; + result.index = result.next; - spa_pod_builder_init(&b, buffer, sizeof(buffer)); + spa_log_debug(this->log, "%p: %d id:%u", this, seq, id); + + spa_pod_dynamic_builder_init(&b, buffer, sizeof(buffer), 4096); switch (id) { + case SPA_PARAM_EnumPortConfig: + case SPA_PARAM_PortConfig: + if (this->convert == NULL) + return 0; + res = spa_node_enum_params(this->convert, seq, id, start, num, filter); + return res; case SPA_PARAM_PropInfo: + res = follower_enum_params(this, + id, IDX_PropInfo, &result, filter, &b.b); + break; case SPA_PARAM_Props: - if ((res = spa_node_enum_params_sync(this->target, - id, &start, filter, ¶m, &b)) != 1) - return res; + res = follower_enum_params(this, + id, IDX_Props, &result, filter, &b.b); + break; + case SPA_PARAM_ProcessLatency: + res = follower_enum_params(this, + id, IDX_ProcessLatency, &result, filter, &b.b); break; - case SPA_PARAM_EnumFormat: case SPA_PARAM_Format: - if ((res = spa_node_port_enum_params_sync(this->follower, + case SPA_PARAM_Latency: + res = spa_node_port_enum_params_sync(this->follower, this->direction, 0, - id, &start, filter, ¶m, &b)) != 1) - return res; + id, &result.next, filter, &result.param, &b.b); break; - default: return -ENOENT; } - if (spa_pod_filter(&b, &result.param, param, filter) < 0) - goto next; + if (res == 1) { + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + count++; + } + spa_pod_dynamic_builder_clean(&b); - spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + if (res != 1)
View file
pipewire-0.3.57.tar.gz/spa/plugins/volume/volume.c -> pipewire-0.3.58.tar.gz/spa/plugins/volume/volume.c
Changed
@@ -39,6 +39,9 @@ #define NAME "volume" +#define DEFAULT_RATE 48000 +#define DEFAULT_CHANNELS 2 + #define DEFAULT_VOLUME 1.0 #define DEFAULT_MUTE false @@ -322,8 +325,10 @@ SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S16, SPA_AUDIO_FORMAT_S32), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int(44100, 1, INT32_MAX), - SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int(2, 1, INT32_MAX)); + SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_RATE, 1, INT32_MAX), + SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( + DEFAULT_CHANNELS, 1, INT32_MAX)); break; default: return 0;
View file
pipewire-0.3.57.tar.gz/src/modules/module-echo-cancel.c -> pipewire-0.3.58.tar.gz/src/modules/module-echo-cancel.c
Changed
@@ -402,7 +402,7 @@ pw_stream_queue_buffer(impl->capture, buf); } -static void input_state_changed(void *data, enum pw_stream_state old, +static void capture_state_changed(void *data, enum pw_stream_state old, enum pw_stream_state state, const char *error) { struct impl *impl = data; @@ -423,6 +423,44 @@ } } +static void source_state_changed(void *data, enum pw_stream_state old, + enum pw_stream_state state, const char *error) +{ + struct impl *impl = data; + int res; + + switch (state) { + case PW_STREAM_STATE_PAUSED: + pw_stream_flush(impl->source, false); + pw_stream_flush(impl->capture, false); + + if (old == PW_STREAM_STATE_STREAMING) { + pw_log_debug("%p: deactivate %s", impl, impl->aec->name); + res = spa_audio_aec_deactivate(impl->aec); + if (res < 0 && res != -EOPNOTSUPP) { + pw_log_error("aec plugin %s deactivate failed: %s", impl->aec->name, spa_strerror(res)); + } + } + break; + case PW_STREAM_STATE_STREAMING: + pw_log_debug("%p: activate %s", impl, impl->aec->name); + res = spa_audio_aec_activate(impl->aec); + if (res < 0 && res != -EOPNOTSUPP) { + pw_log_error("aec plugin %s activate failed: %s", impl->aec->name, spa_strerror(res)); + } + break; + case PW_STREAM_STATE_UNCONNECTED: + pw_log_info("%p: input unconnected", impl); + pw_impl_module_schedule_destroy(impl->module); + break; + case PW_STREAM_STATE_ERROR: + pw_log_info("%p: input error: %s", impl, error); + break; + default: + break; + } +} + static void input_param_latency_changed(struct impl *impl, const struct spa_pod *param) { struct spa_latency_info latency; @@ -455,7 +493,7 @@ static const struct pw_stream_events capture_events = { PW_VERSION_STREAM_EVENTS, .destroy = capture_destroy, - .state_changed = input_state_changed, + .state_changed = capture_state_changed, .process = capture_process, .param_changed = input_param_changed }; @@ -470,7 +508,7 @@ static const struct pw_stream_events source_events = { PW_VERSION_STREAM_EVENTS, .destroy = source_destroy, - .state_changed = input_state_changed, + .state_changed = source_state_changed, .param_changed = input_param_changed }; @@ -976,7 +1014,7 @@ handle = spa_plugin_loader_load(impl->loader, SPA_NAME_AEC, &info); if (handle == NULL) { - pw_log_error("AEC codec plugin %s not available library.name %s", SPA_NAME_AEC, path); + pw_log_error("aec plugin %s not available library.name %s", SPA_NAME_AEC, path); return -ENOENT; } @@ -986,14 +1024,16 @@ } impl->aec = iface; impl->spa_handle = handle; - if (impl->aec->iface.version != SPA_VERSION_AUDIO_AEC) { - pw_log_error("codec plugin %s has incompatible ABI version (%d != %d)", + + if (impl->aec->iface.version > SPA_VERSION_AUDIO_AEC) { + pw_log_error("codec plugin %s has incompatible ABI version (%d > %d)", SPA_NAME_AEC, impl->aec->iface.version, SPA_VERSION_AUDIO_AEC); res = -ENOENT; goto error; } - pw_log_info("Using plugin AEC %s", impl->aec->name); + pw_log_info("Using plugin AEC %s with version %d", impl->aec->name, + impl->aec->iface.version); if ((str = pw_properties_get(props, "aec.args")) != NULL) aec_props = pw_properties_new_string(str); @@ -1005,7 +1045,7 @@ pw_properties_free(aec_props); if (res < 0) { - pw_log_error("codec plugin %s create failed: %s", impl->aec->name, + pw_log_error("aec plugin %s create failed: %s", impl->aec->name, spa_strerror(res)); goto error; }
View file
pipewire-0.3.57.tar.gz/src/modules/module-filter-chain.c -> pipewire-0.3.58.tar.gz/src/modules/module-filter-chain.c
Changed
@@ -682,11 +682,21 @@ str = strdupa(name); col = strchr(str, ':'); if (col != NULL) { + struct node *find; node_name = str; port_name = col + 1; *col = '\0'; - node = find_node(node->graph, node_name); - } else { + find = find_node(node->graph, node_name); + if (find == NULL) { + /* it's possible that the : is part of the port name, + * try again without splitting things up. */ + *col = ':'; + col = NULL; + } else { + node = find; + } + } + if (col == NULL) { node_name = node->name; port_name = str; } @@ -838,7 +848,7 @@ port = find_port(node, name, FC_PORT_INPUT | FC_PORT_CONTROL); if (port == NULL) - return 0; + return -ENOENT; node = port->node; desc = node->desc; @@ -853,7 +863,7 @@ { struct spa_pod_parser prs; struct spa_pod_frame f; - int changed = 0; + int res, changed = 0; struct node *def_node; def_node = spa_list_first(&graph->node_list, struct node, link); @@ -886,7 +896,8 @@ struct spa_pod *pod; spa_pod_parser_get_pod(&prs, &pod); } - changed += set_control_value(def_node, name, val); + if ((res = set_control_value(def_node, name, val)) > 0) + changed += res; } return changed; } @@ -1338,15 +1349,17 @@ while (spa_json_get_string(control, key, sizeof(key)) > 0) { float fl; const char *val; - int len; + int res, len; if ((len = spa_json_next(control, &val)) < 0) break; - if (spa_json_parse_float(val, len, &fl) <= 0) + if (spa_json_parse_float(val, len, &fl) <= 0) { pw_log_warn("control '%s' expects a number, ignoring", key); - else - set_control_value(node, key, &fl); + } + else if ((res = set_control_value(node, key, &fl)) < 0) { + pw_log_warn("control '%s' can not be set: %s", key, spa_strerror(res)); + } } return 0; }
View file
pipewire-0.3.57.tar.gz/src/modules/module-filter-chain/lv2_plugin.c -> pipewire-0.3.58.tar.gz/src/modules/module-filter-chain/lv2_plugin.c
Changed
@@ -35,11 +35,27 @@ #include <pipewire/array.h> #include <lilv/lilv.h> -#include <lv2/lv2plug.in/ns/ext/atom/atom.h> -#include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h> -#include <lv2/lv2plug.in/ns/ext/worker/worker.h> -#include <lv2/lv2plug.in/ns/ext/options/options.h> -#include <lv2/lv2plug.in/ns/ext/parameters/parameters.h> + +#if defined __has_include +# if __has_include (<lv2/atom/atom.h>) + + #include <lv2/atom/atom.h> + #include <lv2/buf-size/buf-size.h> + #include <lv2/worker/worker.h> + #include <lv2/options/options.h> + #include <lv2/parameters/parameters.h> + +# else + + #include <lv2/lv2plug.in/ns/ext/atom/atom.h> + #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h> + #include <lv2/lv2plug.in/ns/ext/worker/worker.h> + #include <lv2/lv2plug.in/ns/ext/options/options.h> + #include <lv2/lv2plug.in/ns/ext/parameters/parameters.h> + +# endif + +#endif #include "plugin.h"
View file
pipewire-0.3.57.tar.gz/src/modules/module-loopback.c -> pipewire-0.3.58.tar.gz/src/modules/module-loopback.c
Changed
@@ -519,10 +519,6 @@ if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true"); - if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) - pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, - "loopback-%u-%u", pid, id); - if ((str = pw_properties_get(props, "capture.props")) != NULL) pw_properties_update_string(impl->capture_props, str, strlen(str)); if ((str = pw_properties_get(props, "playback.props")) != NULL) @@ -549,6 +545,10 @@ if (pw_properties_get(impl->playback_props, PW_KEY_NODE_NAME) == NULL) pw_properties_setf(impl->playback_props, PW_KEY_NODE_NAME, "output.%s", str); + if (pw_properties_get(impl->capture_props, PW_KEY_NODE_DESCRIPTION) == NULL) + pw_properties_set(impl->capture_props, PW_KEY_NODE_DESCRIPTION, str); + if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL) + pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str); parse_audio_info(impl->capture_props, &impl->capture_info); parse_audio_info(impl->playback_props, &impl->playback_info);
View file
pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/pulse-server.c -> pipewire-0.3.58.tar.gz/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -87,6 +87,9 @@ #define DEFAULT_POSITION " FL FR " #define MAX_FORMATS 32 +/* The max amount of data we send in one block when capturing. In PulseAudio this + * size is derived from the mempool PA_MEMPOOL_SLOT_SIZE */ +#define MAX_FRAGSIZE (64*1024) #define TEMPORARY_MOVE_TIMEOUT (SPA_NSEC_PER_SEC) @@ -442,7 +445,15 @@ return (uint32_t) u; } -static uint32_t fix_playback_buffer_attr(struct stream *s, struct buffer_attr *attr) +static void clamp_latency(struct stream *s, struct spa_fraction *lat) +{ + if (lat->num * s->min_quantum.denom / lat->denom < s->min_quantum.num) + lat->num = (s->min_quantum.num * lat->denom + + (s->min_quantum.denom -1)) / s->min_quantum.denom; +} + +static uint64_t fix_playback_buffer_attr(struct stream *s, struct buffer_attr *attr, + uint32_t rate, struct spa_fraction *lat) { uint32_t frame_size, max_prebuf, minreq, latency, max_latency; struct defs *defs = &s->impl->defs; @@ -521,11 +532,15 @@ attr->fragsize = 0; - pw_log_info("%s maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u %u", + lat->num = latency / frame_size; + lat->denom = rate; + clamp_latency(s, lat); + + pw_log_info("%s maxlength:%u tlength:%u minreq:%u/%u prebuf:%u latency:%u/%u %u", s->client->name, attr->maxlength, attr->tlength, - attr->minreq, minreq, attr->prebuf, latency, frame_size); + attr->minreq, minreq, attr->prebuf, lat->num, lat->denom, frame_size); - return latency / frame_size; + return lat->num * SPA_USEC_PER_SEC / lat->denom; } static uint64_t set_playback_buffer_attr(struct stream *s, struct buffer_attr *attr) @@ -539,16 +554,10 @@ char attr_prebuf32; char attr_minreq32; - lat.denom = s->ss.rate; - lat.num = fix_playback_buffer_attr(s, attr); + lat_usec = fix_playback_buffer_attr(s, attr, s->ss.rate, &lat); s->attr = *attr; - if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num) - lat.num = (s->min_quantum.num * lat.denom + - (s->min_quantum.denom -1)) / s->min_quantum.denom; - lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; - snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); snprintf(rate, sizeof(rate), "1/%u", lat.denom); snprintf(attr_maxlength, sizeof(attr_maxlength), "%u", s->attr.maxlength); @@ -643,7 +652,8 @@ return client_queue_message(client, reply); } -static uint32_t fix_record_buffer_attr(struct stream *s, struct buffer_attr *attr) +static uint64_t fix_record_buffer_attr(struct stream *s, struct buffer_attr *attr, + uint32_t rate, struct spa_fraction *lat) { uint32_t frame_size, minfrag, latency; @@ -652,8 +662,9 @@ if (frame_size == 0) frame_size = 4; - pw_log_info("%s maxlength:%u fragsize:%u", - s->client->name, attr->maxlength, attr->fragsize); + pw_log_info("%s maxlength:%u fragsize:%u framesize:%u", + s->client->name, attr->maxlength, attr->fragsize, + frame_size); if (attr->maxlength == (uint32_t) -1 || attr->maxlength > MAXLENGTH) attr->maxlength = MAXLENGTH; @@ -668,25 +679,23 @@ attr->fragsize = SPA_ROUND_UP(attr->fragsize, frame_size); attr->fragsize = SPA_MAX(attr->fragsize, minfrag); - /* pulseaudio configures the source to half of the fragsize. It also - * immediately sends chunks to clients. Configure a 2/3 of the fragsize - * as the latency. */ - latency = attr->fragsize * 2 / 3; - - if (s->adjust_latency) - attr->fragsize = SPA_ROUND_UP(latency, frame_size); - - attr->tlength = attr->prebuf = 0; + attr->tlength = attr->minreq = attr->prebuf = 0; /* make sure can queue at least to fragsize without overruns */ if (attr->maxlength < attr->fragsize * 4) attr->maxlength = attr->fragsize * 4; - pw_log_info("%s maxlength:%u fragsize:%u minfrag:%u latency:%u", + latency = attr->fragsize / frame_size; + + lat->num = latency; + lat->denom = rate; + clamp_latency(s, lat); + + pw_log_info("%s maxlength:%u fragsize:%u minfrag:%u latency:%u/%u", s->client->name, attr->maxlength, attr->fragsize, minfrag, - latency); + lat->num, lat->denom); - return latency / frame_size; + return lat->num * SPA_USEC_PER_SEC / lat->denom; } static uint64_t set_record_buffer_attr(struct stream *s, struct buffer_attr *attr) @@ -698,13 +707,9 @@ struct spa_fraction lat; uint64_t lat_usec; - lat.denom = s->ss.rate; - lat.num = fix_record_buffer_attr(s, &s->attr); + lat_usec = fix_record_buffer_attr(s, attr, s->ss.rate, &lat); - if (lat.num * s->min_quantum.denom / lat.denom < s->min_quantum.num) - lat.num = (s->min_quantum.num * lat.denom + - (s->min_quantum.denom -1)) / s->min_quantum.denom; - lat_usec = lat.num * SPA_USEC_PER_SEC / lat.denom; + s->attr = *attr; snprintf(latency, sizeof(latency), "%u/%u", lat.num, lat.denom); snprintf(rate, sizeof(rate), "1/%u", lat.denom); @@ -1336,7 +1341,8 @@ pw_log_trace("avail:%d index:%u", avail, index); while ((uint32_t)avail >= stream->attr.fragsize) { - towrite = SPA_MIN((uint32_t)avail, stream->attr.fragsize); + towrite = SPA_MIN(avail, MAX_FRAGSIZE); + towrite = SPA_ROUND_DOWN(towrite, stream->frame_size); msg = message_alloc(impl, stream->channel, towrite); if (msg == NULL) @@ -1732,9 +1738,11 @@ stream->underrun_for = -1; if (rate != 0) { + struct spa_fraction lat; + fix_playback_buffer_attr(stream, &attr, rate, &lat); pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate); pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", - fix_playback_buffer_attr(stream, &attr), rate); + lat.num, lat.denom); } if (no_remix) pw_properties_set(props, PW_KEY_STREAM_DONT_REMIX, "true"); @@ -1993,9 +2001,11 @@ no_move = false; if (rate != 0) { + struct spa_fraction lat; + fix_record_buffer_attr(stream, &attr, rate, &lat); pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", rate); pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", - fix_record_buffer_attr(stream, &attr), rate); + lat.num, lat.denom); } if (peak_detect) pw_properties_set(props, PW_KEY_STREAM_MONITOR, "true"); @@ -2717,11 +2727,17 @@ break; case COMMAND_TRIGGER_PLAYBACK_STREAM: case COMMAND_PREBUF_PLAYBACK_STREAM: + if (stream->type != STREAM_TYPE_PLAYBACK) + return -ENOENT; + if (command == COMMAND_TRIGGER_PLAYBACK_STREAM) + stream->in_prebuf = false; + else if (stream->attr.prebuf > 0) + stream->in_prebuf = true; + stream_send_request(stream); break; default: return -EINVAL; } - return reply_simple_ack(client, tag); }
View file
pipewire-0.3.57.tar.gz/src/modules/module-protocol-pulse/server.c -> pipewire-0.3.58.tar.gz/src/modules/module-protocol-pulse/server.c
Changed
@@ -166,6 +166,8 @@ index += diff; filled += diff; stream->write_index += diff; + if ((flags & FLAG_SEEKMASK) == SEEK_RELATIVE) + stream->requested -= diff; if (filled < 0) { /* underrun, reported on reader side */ @@ -182,9 +184,10 @@ msg->data, SPA_MIN(msg->length, MAXLENGTH)); index += msg->length; - stream->write_index += msg->length; spa_ringbuffer_write_update(&stream->ring, index); - stream->requested -= SPA_MIN(msg->length, stream->requested); + + stream->write_index += msg->length; + stream->requested -= msg->length; stream_send_request(stream);
View file
pipewire-0.3.57.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.58.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -66,10 +66,63 @@ * * Creates a new Sink to stream to an Airplay device. * + * Normally this sink is automatically created with \ref page_module_raop_discover + * with the right parameters but it is possible to manually create a RAOP sink + * as well. + * * ## Module Options * + * Options specific to the behavior of this module + * + * - `raop.hostname`: The hostname of the remote end. + * - `raop.port`: The port of the remote end. + * - `raop.transport`: The data transport to use, one of "udp" or "tcp". Defaults + * to "udp". + * - `raop.encryption.type`: The encryption type to use. One of "none", "RSA" or + * "auth_setup". Default is "none". + * - `raop.audio.codec`: The audio codec to use. Needs to be "PCM". Defaults to "PCM". + * - `raop.password`: The password to use. + * - `stream.props = {}`: properties to be passed to the sink stream + * + * Options with well-known behavior. + * + * - \ref PW_KEY_REMOTE_NAME + * - \ref PW_KEY_AUDIO_FORMAT + * - \ref PW_KEY_AUDIO_RATE + * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_POSITION + * - \ref PW_KEY_NODE_NAME + * - \ref PW_KEY_NODE_DESCRIPTION + * - \ref PW_KEY_NODE_GROUP + * - \ref PW_KEY_NODE_LATENCY + * - \ref PW_KEY_NODE_VIRTUAL + * - \ref PW_KEY_MEDIA_CLASS + * * ## Example configuration * + *\code{.unparsed} + * context.modules = + * { name = libpipewire-module-raop-sink + * args = { + * # Set the remote address to tunnel to + * raop.hostname = "my-raop-device" + * raop.port = 8190 + * #raop.transport = "udp" + * raop.encryption = "RSA" + * #raop.audio.codec = "PCM" + * #raop.password = "****" + * #audio.format = "S16" + * #audio.rate = 44100 + * #audio.channels = 22 + * #audio.position = FL FR + * stream.props = { + * # extra sink properties + * } + * } + * } + * + *\endcode + * * ## See also * * \ref page_module_raop_discover @@ -106,7 +159,13 @@ #define DEFAULT_LATENCY (DEFAULT_RATE*2) -#define MODULE_USAGE " node.latency=<latency as fraction> " \ +#define MODULE_USAGE " raop.hostname=<name of host> " \ + " raop.port=<remote port> " \ + " raop.transport=<transport, default:udp> " \ + " raop.encryption.type=<encryption, default:none> " \ + " raop.audio.codec=PCM " \ + " raop.password=<password for auth> " \ + " node.latency=<latency as fraction> " \ " node.name=<name of the nodes> " \ " node.description=<description of the nodes> " \ " audio.format=<format, default:"DEFAULT_FORMAT"> " \ @@ -1072,17 +1131,14 @@ static int rtsp_do_auth_setup(struct impl *impl) { - int res; - - char output = + static const unsigned char content33 = "\x01" "\x59\x02\xed\xe9\x0d\x4e\xf2\xbd\x4c\xb6\x8a\x63\x30\x03\x82\x07" "\xa9\x4d\xbd\x50\xd8\xaa\x46\x5b\x5d\x8c\x01\x2a\x0c\x7e\x1d\x4e"; - res = pw_rtsp_client_url_send(impl->rtsp, "/auth-setup", "POST", &impl->headers->dict, - "application/octet-stream", output, rtsp_auth_setup_reply, impl); - - return res; + return pw_rtsp_client_url_send(impl->rtsp, "/auth-setup", "POST", &impl->headers->dict, + "application/octet-stream", content, sizeof(content), + rtsp_auth_setup_reply, impl); } static const char *find_attr(char **tokens, const char *key)
View file
pipewire-0.3.57.tar.gz/src/modules/module-raop/rtsp-client.c -> pipewire-0.3.58.tar.gz/src/modules/module-raop/rtsp-client.c
Changed
@@ -44,11 +44,18 @@ void *data; size_t len; size_t offset; - int cseq; + uint32_t cseq; void (*reply) (void *user_data, int status, const struct spa_dict *headers); void *user_data; }; +enum client_recv_state { + CLIENT_RECV_NONE, + CLIENT_RECV_STATUS, + CLIENT_RECV_HEADERS, + CLIENT_RECV_CONTENT, +}; + struct pw_rtsp_client { struct pw_loop *loop; struct pw_properties *props; @@ -67,15 +74,15 @@ struct spa_source *source; unsigned int connecting:1; unsigned int need_flush:1; - unsigned int wait_status:1; + enum client_recv_state recv_state; int status; char line_buf1024; size_t line_pos; struct pw_properties *headers; + size_t content_length; - char *session; - int cseq; + uint32_t cseq; struct spa_list messages; struct spa_list pending; @@ -102,6 +109,7 @@ spa_list_init(&client->pending); spa_hook_list_init(&client->listener_list); client->headers = pw_properties_new(NULL, NULL); + client->recv_state = CLIENT_RECV_NONE; pw_log_info("new client %p", client); @@ -145,7 +153,7 @@ if (ip) inet_ntop(client->local_addr.sa.sa_family, &client->local_addr.in.sin_addr, ip, len); - } else if (client->local_addr.sa.sa_family == AF_INET6) { + } else if (client->local_addr.sa.sa_family == AF_INET6) { *version = 6; if (ip) inet_ntop(client->local_addr.sa.sa_family, @@ -160,7 +168,7 @@ { int res, ip_version; socklen_t len; - char local_ipINET6_ADDRSTRLEN; + char local_ipINET6_ADDRSTRLEN; len = sizeof(res); if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &res, &len) < 0) { @@ -180,13 +188,19 @@ if (ip_version == 4) asprintf(&client->url, "rtsp://%s/%s", local_ip, client->session_id); - else + else asprintf(&client->url, "rtsp://%s/%s", local_ip, client->session_id); pw_log_info("connected local ip %s", local_ip); client->connecting = false; - client->wait_status = true; + + client->recv_state = CLIENT_RECV_STATUS; + pw_properties_clear(client->headers); + client->status = 0; + client->line_pos = 0; + client->content_length = 0; + pw_rtsp_client_emit_connected(client); return 0; @@ -226,7 +240,7 @@ return 0; } -static struct message *find_pending(struct pw_rtsp_client *client, int cseq) +static struct message *find_pending(struct pw_rtsp_client *client, uint32_t cseq) { struct message *msg; spa_list_for_each(msg, &client->pending, link) { @@ -236,92 +250,145 @@ return NULL; } -static int process_input(struct pw_rtsp_client *client) +static int process_status(struct pw_rtsp_client *client, char *buf) { - char *buf = NULL; - int res; + const char *state = NULL, *s; + size_t len; - if ((res = read_line(client, &buf)) <= 0) - return res; + pw_log_info("status: %s", buf); - pw_log_debug("%s", buf); + s = pw_split_walk(buf, " ", &len, &state); + if (!spa_strstartswith(s, "RTSP/")) + return -EPROTO; - if (client->wait_status) { - const char *state = NULL, *s; - size_t len; + s = pw_split_walk(buf, " ", &len, &state); + if (s == NULL) + return -EPROTO; - pw_log_info("status: %s", buf); + client->status = atoi(s); + if (client->status == 0) + return -EPROTO; - s = pw_split_walk(buf, " ", &len, &state); - if (!spa_strstartswith(s, "RTSP/")) - goto error; + s = pw_split_walk(buf, " ", &len, &state); + if (s == NULL) + return -EPROTO; - s = pw_split_walk(buf, " ", &len, &state); - if (s == NULL) - goto error; + pw_properties_clear(client->headers); + client->recv_state = CLIENT_RECV_HEADERS; - client->status = atoi(s); + return 0; +} - s = pw_split_walk(buf, " ", &len, &state); - if (s == NULL) - goto error; +static void dispatch_handler(struct pw_rtsp_client *client) +{ + uint32_t cseq; + if (pw_properties_fetch_uint32(client->headers, "CSeq", &cseq) < 0) + return; - client->wait_status = false; - pw_properties_clear(client->headers); - } else { - if (strlen(buf) == 0) { - int cseq; - struct message *msg; - const struct spa_dict_item *it; - const char *content_type; - unsigned int content_length; - - spa_dict_for_each(it, &client->headers->dict) - pw_log_info(" %s: %s", it->key, it->value); - - cseq = pw_properties_get_int32(client->headers, "CSeq", 0); - content_type = pw_properties_get(client->headers, "Content-Type"); - if (content_type != NULL && strcmp(content_type, "application/octet-stream") == 0) { - pw_log_info("binary response received"); - content_length = pw_properties_get_uint64(client->headers, "Content-Length", 0); - char content_bufcontent_length; - res = read(client->source->fd, content_buf, content_length); - pw_log_debug("read %d bytes", res); - if (res == 0) - return -EPIPE; - if (res < 0) { - res = -errno; - if (res != -EAGAIN && res != -EWOULDBLOCK) - return res; - return 0; - } - pw_properties_set(client->headers, "body", content_buf); - } - if ((msg = find_pending(client, cseq)) != NULL) { - msg->reply(msg->user_data, client->status, &client->headers->dict); - spa_list_remove(&msg->link); - free(msg); - } else { - pw_rtsp_client_emit_message(client, client->status, - &client->headers->dict); - } - client->wait_status = true; - } else { - char *key, *value; + pw_log_info("received reply to request with cseq:%" PRIu32, cseq); - key = buf;
View file
pipewire-0.3.57.tar.gz/src/modules/module-raop/rtsp-client.h -> pipewire-0.3.58.tar.gz/src/modules/module-raop/rtsp-client.h
Changed
@@ -73,7 +73,7 @@ int pw_rtsp_client_url_send(struct pw_rtsp_client *client, const char *url, const char *cmd, const struct spa_dict *headers, - const char *content_type, const char *content, + const char *content_type, const void *content, size_t content_length, void (*reply) (void *user_data, int status, const struct spa_dict *headers), void *user_data);
View file
pipewire-0.3.57.tar.gz/src/modules/module-rt.c -> pipewire-0.3.58.tar.gz/src/modules/module-rt.c
Changed
@@ -976,7 +976,6 @@ if (set_nice(impl, impl->nice_level, !can_use_rtkit) < 0) use_rtkit = can_use_rtkit; } - set_rlimit(impl); #ifdef HAVE_DBUS impl->use_rtkit = use_rtkit; @@ -1012,6 +1011,7 @@ set_nice(impl, impl->nice_level, true); } #endif + set_rlimit(impl); impl->thread_utils.iface = SPA_INTERFACE_INIT( SPA_TYPE_INTERFACE_ThreadUtils,
View file
pipewire-0.3.57.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.58.tar.gz/src/pipewire/impl-link.c
Changed
@@ -619,7 +619,7 @@ pw_log_debug("%p: activate activated:%d state:%s", this, impl->activated, pw_link_state_as_string(this->info.state)); - if (impl->activated || !this->prepared || !impl->inode->active || !impl->onode->active) + if (impl->activated || !this->prepared || !impl->inode->added || !impl->onode->active) return 0; if (!impl->io_set) {
View file
pipewire-0.3.57.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.58.tar.gz/src/pipewire/impl-node.c
Changed
@@ -167,6 +167,7 @@ spa_loop_remove_source(loop, &this->source); remove_node(this); } + this->added = false; return 0; } @@ -210,19 +211,26 @@ return res; } -static void node_activate(struct pw_impl_node *this) +static void node_activate_outputs(struct pw_impl_node *this) { struct pw_impl_port *port; pw_log_debug("%p: activate", this); - spa_list_for_each(port, &this->input_ports, link) { + spa_list_for_each(port, &this->output_ports, link) { struct pw_impl_link *link; - spa_list_for_each(link, &port->links, input_link) + spa_list_for_each(link, &port->links, output_link) pw_impl_link_activate(link); } - spa_list_for_each(port, &this->output_ports, link) { +} + +static void node_activate_inputs(struct pw_impl_node *this) +{ + struct pw_impl_port *port; + + pw_log_debug("%p: activate", this); + spa_list_for_each(port, &this->input_ports, link) { struct pw_impl_link *link; - spa_list_for_each(link, &port->links, output_link) + spa_list_for_each(link, &port->links, input_link) pw_impl_link_activate(link); } } @@ -232,7 +240,9 @@ struct impl *impl = SPA_CONTAINER_OF(this, struct impl, this); int res = 0; - node_activate(this); + /* First activate the outputs so that when the node starts pushing, + * we can process the outputs */ + node_activate_outputs(this); if (impl->pending_state >= PW_NODE_STATE_RUNNING) return 0; @@ -336,6 +346,7 @@ spa_loop_add_source(loop, &this->source); add_node(this, driver); } + this->added = true; return 0; } @@ -354,8 +365,11 @@ error = spa_aprintf("Start error: %s", spa_strerror(res)); } } - if (res >= 0) + if (res >= 0) { pw_loop_invoke(node->data_loop, do_node_add, 1, NULL, 0, true, node); + /* now activate the inputs */ + node_activate_inputs(node); + } break; default: break; @@ -1078,6 +1092,12 @@ a->status = PW_NODE_ACTIVATION_AWAKE; a->awake_time = SPA_TIMESPEC_TO_NSEC(&ts); + if (!this->added) { + /* This should not happen here. We activate the input + * links after we add the node to the graph. */ + pw_log_warn("%p: scheduling non-active node", this); + return -EIO; + } pw_log_trace_fp("%p: process %"PRIu64, this, a->awake_time); /* when transport sync is not supported, just clear the flag */
View file
pipewire-0.3.57.tar.gz/src/pipewire/private.h -> pipewire-0.3.58.tar.gz/src/pipewire/private.h
Changed
@@ -704,6 +704,7 @@ unsigned int transport_sync:1; /**< supports transport sync */ unsigned int current_pending:1; /**< a quantum/rate update is pending */ unsigned int moved:1; /**< the node was moved drivers */ + unsigned int added:1; /**< the node was add to graph */ uint32_t port_user_data_size; /**< extra size for port user data */
View file
pipewire-0.3.57.tar.gz/src/pipewire/stream.c -> pipewire-0.3.58.tar.gz/src/pipewire/stream.c
Changed
@@ -125,12 +125,12 @@ uint32_t port_change_mask_all; struct spa_port_info port_info; struct pw_properties *port_props; -#define IDX_EnumFormat 0 -#define IDX_Meta 1 -#define IDX_IO 2 -#define IDX_Format 3 -#define IDX_Buffers 4 -#define IDX_Latency 5 +#define PORT_EnumFormat 0 +#define PORT_Meta 1 +#define PORT_IO 2 +#define PORT_Format 3 +#define PORT_Buffers 4 +#define PORT_Latency 5 #define N_PORT_PARAMS 6 struct spa_param_info port_paramsN_PORT_PARAMS; @@ -138,9 +138,11 @@ uint32_t change_mask_all; struct spa_node_info info; -#define IDX_PropInfo 0 -#define IDX_Props 1 -#define N_NODE_PARAMS 2 +#define NODE_PropInfo 0 +#define NODE_Props 1 +#define NODE_EnumFormat 2 +#define NODE_Format 3 +#define N_NODE_PARAMS 4 struct spa_param_info paramsN_NODE_PARAMS; uint32_t media_type; @@ -179,9 +181,13 @@ { switch (id) { case SPA_PARAM_PropInfo: - return IDX_PropInfo; + return NODE_PropInfo; case SPA_PARAM_Props: - return IDX_Props; + return NODE_Props; + case SPA_PARAM_EnumFormat: + return NODE_EnumFormat; + case SPA_PARAM_Format: + return NODE_Format; default: return -1; } @@ -191,17 +197,17 @@ { switch (id) { case SPA_PARAM_EnumFormat: - return IDX_EnumFormat; + return PORT_EnumFormat; case SPA_PARAM_Meta: - return IDX_Meta; + return PORT_Meta; case SPA_PARAM_IO: - return IDX_IO; + return PORT_IO; case SPA_PARAM_Format: - return IDX_Format; + return PORT_Format; case SPA_PARAM_Buffers: - return IDX_Buffers; + return PORT_Buffers; case SPA_PARAM_Latency: - return IDX_Latency; + return PORT_Latency; default: return -1; } @@ -267,7 +273,8 @@ impl->info.change_mask |= SPA_NODE_CHANGE_MASK_PARAMS; impl->paramsidx.flags |= SPA_PARAM_INFO_READ; impl->paramsidx.user++; - } else if ((idx = get_port_param_index(id)) != -1) { + } + if ((idx = get_port_param_index(id)) != -1) { impl->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; impl->port_paramsidx.flags |= SPA_PARAM_INFO_READ; impl->port_paramsidx.user++; @@ -867,6 +874,7 @@ if (stream->state == PW_STREAM_STATE_ERROR) return -EIO; + emit_node_info(impl, false); emit_port_info(impl, false); return 0; @@ -1835,8 +1843,10 @@ if (!impl->process_rt) impl->info.flags |= SPA_NODE_FLAG_ASYNC; impl->info.props = &stream->properties->dict; - impl->paramsIDX_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); - impl->paramsIDX_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); + impl->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, 0); + impl->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_WRITE); + impl->paramsNODE_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0); + impl->paramsNODE_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); impl->info.params = impl->params; impl->info.n_params = N_NODE_PARAMS; impl->info.change_mask = impl->change_mask_all; @@ -1851,12 +1861,12 @@ impl->port_info.flags = 0; if (SPA_FLAG_IS_SET(flags, PW_STREAM_FLAG_ALLOC_BUFFERS)) impl->port_info.flags |= SPA_PORT_FLAG_CAN_ALLOC_BUFFERS; - impl->port_paramsIDX_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0); - impl->port_paramsIDX_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0); - impl->port_paramsIDX_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0); - impl->port_paramsIDX_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); - impl->port_paramsIDX_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); - impl->port_paramsIDX_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE); + impl->port_paramsPORT_EnumFormat = SPA_PARAM_INFO(SPA_PARAM_EnumFormat, 0); + impl->port_paramsPORT_Meta = SPA_PARAM_INFO(SPA_PARAM_Meta, 0); + impl->port_paramsPORT_IO = SPA_PARAM_INFO(SPA_PARAM_IO, 0); + impl->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); + impl->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); + impl->port_paramsPORT_Latency = SPA_PARAM_INFO(SPA_PARAM_Latency, SPA_PARAM_INFO_WRITE); impl->port_info.props = &impl->port_props->dict; impl->port_info.params = impl->port_params; impl->port_info.n_params = N_PORT_PARAMS;
View file
pipewire-0.3.57.tar.gz/src/tools/pw-top.c -> pipewire-0.3.58.tar.gz/src/tools/pw-top.c
Changed
@@ -32,10 +32,14 @@ #include <spa/utils/string.h> #include <spa/pod/parser.h> #include <spa/debug/pod.h> +#include <spa/param/format-utils.h> +#include <spa/param/audio/format-utils.h> +#include <spa/param/video/format-utils.h> #include <pipewire/impl.h> #include <pipewire/extensions/profiler.h> +#define MAX_FORMAT 16 #define MAX_NAME 128 struct driver { @@ -59,13 +63,17 @@ struct node { struct spa_list link; uint32_t id; - char nameMAX_NAME; + char nameMAX_NAME+1; struct measurement measurement; struct driver info; struct node *driver; uint32_t errors; int32_t last_error_status; uint32_t generation; + char formatMAX_FORMAT+1; + struct pw_proxy *proxy; + struct spa_hook proxy_listener; + struct spa_hook object_listener; }; struct data { @@ -131,6 +139,98 @@ return NULL; } +static void on_node_removed(void *data) +{ + struct node *n = data; + pw_proxy_destroy(n->proxy); +} + +static void on_node_destroy(void *data) +{ + struct node *n = data; + n->proxy = NULL; + spa_hook_remove(&n->proxy_listener); + spa_hook_remove(&n->object_listener); +} + +static const struct pw_proxy_events proxy_events = { + PW_VERSION_PROXY_EVENTS, + .removed = on_node_removed, + .destroy = on_node_destroy, +}; + +static void node_param(void *data, int seq, + uint32_t id, uint32_t index, uint32_t next, + const struct spa_pod *param) +{ + struct node *n = data; + + switch (id) { + case SPA_PARAM_Format: + { + uint32_t media_type, media_subtype; + + spa_format_parse(param, &media_type, &media_subtype); + + switch(media_type) { + case SPA_MEDIA_TYPE_audio: + switch(media_subtype) { + case SPA_MEDIA_SUBTYPE_raw: + { + struct spa_audio_info_raw info; + if (spa_format_audio_raw_parse(param, &info) >= 0) { + snprintf(n->format, sizeof(n->format), "%6.6s %d %d", + spa_debug_type_find_short_name(spa_type_audio_format, info.format), + info.channels, info.rate); + } + break; + } + case SPA_MEDIA_SUBTYPE_dsd: + { + struct spa_audio_info_dsd info; + if (spa_format_audio_dsd_parse(param, &info) >= 0) { + snprintf(n->format, sizeof(n->format), "DSD%d %d ", + 8 * info.rate / 44100, info.channels); + + } + break; + } + } + break; + case SPA_MEDIA_TYPE_video: + switch(media_subtype) { + case SPA_MEDIA_SUBTYPE_raw: + { + struct spa_video_info_raw info; + if (spa_format_video_raw_parse(param, &info) >= 0) { + snprintf(n->format, sizeof(n->format), "%6.6s %dx%d", + spa_debug_type_find_short_name(spa_type_video_format, info.format), + info.size.width, info.size.height); + } + break; + } + } + break; + case SPA_MEDIA_TYPE_application: + switch(media_subtype) { + case SPA_MEDIA_SUBTYPE_control: + snprintf(n->format, sizeof(n->format), "%s", "CONTROL"); + break; + } + break; + } + break; + } + default: + break; + } +} + +static const struct pw_node_events node_events = { + PW_VERSION_NODE, + .param = node_param, +}; + static struct node *add_node(struct data *d, uint32_t id, const char *name) { struct node *n; @@ -139,11 +239,23 @@ return NULL; if (name) - strncpy(n->name, name, MAX_NAME-1); + strncpy(n->name, name, MAX_NAME); else snprintf(n->name, sizeof(n->name), "%u", id); n->id = id; n->driver = n; + n->proxy = pw_registry_bind(d->registry, id, PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, 0); + if (n->proxy) { + uint32_t ids1 = { SPA_PARAM_Format }; + + pw_proxy_add_listener(n->proxy, + &n->proxy_listener, &proxy_events, n); + pw_proxy_add_object_listener(n->proxy, + &n->object_listener, &node_events, n); + + pw_node_subscribe_params((struct pw_node*)n->proxy, + ids, 1); + } spa_list_append(&d->node_list, &n->link); d->n_nodes++; @@ -152,6 +264,8 @@ static void remove_node(struct data *d, struct node *n) { + if (n->proxy) + pw_proxy_destroy(n->proxy); spa_list_remove(&n->link); d->n_nodes--; free(n); @@ -235,7 +349,7 @@ else if (val == (uint64_t)-2) snprintf(buf, len, " +++ "); else if (val < 1000000llu) - snprintf(buf, len, "%5.1fµs", val/1000.f); + snprintf(buf, len, "%5.1fus", val/1000.f); else if (val < 1000000000llu) snprintf(buf, len, "%5.1fms", val/1000000.f); else @@ -290,7 +404,7 @@ else busy = -1; - mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %s%s", + mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %16.16s %s%s", n->measurement.status != 3 ? "!" : " ", n->id, frac.num, frac.denom, @@ -299,6 +413,7 @@ print_perc(buf3, 64, waiting, quantum), print_perc(buf4, 64, busy, quantum), i->xrun_count + n->errors, + n->measurement.status != 3 ? "" : n->format, n->driver == n ? "" : " + ", n->name); } @@ -310,7 +425,7 @@ wclear(d->win); wattron(d->win, A_REVERSE); - wprintw(d->win, "%-*.*s", COLS, COLS, "S ID QUANT RATE WAIT BUSY W/Q B/Q ERR NAME "); + wprintw(d->win, "%-*.*s", COLS, COLS, "S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME "); wattroff(d->win, A_REVERSE);
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
.