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 39
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Fri Nov 24 19:29:49 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.85 + +------------------------------------------------------------------- Fri Nov 3 13:41:27 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.84
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.84 +Version: 0.3.85 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.84.tar.gz/NEWS -> pipewire-0.3.85.tar.gz/NEWS
Changed
@@ -1,3 +1,61 @@ +# PipeWire 0.3.85 (2023-11-16) + +This is the fifth (and last) 1.0 release candidate that is API and ABI +compatible with previous 0.3.x releases. + +## Highlights + - Fix an issue where a link could end up paused while not negotiated. + - Fix an infinite recursion issue when finding runnable nodes. + - Support XDG base directories when loading ACP config. + - Fix MIDI event recording preview in Ardour. + - Many more small fixes, cleanups and improvements. + + +## PipeWire + - Fix an issue where a link could end up paused while not negotiated. + (#3619) + - Fix an infinite recursion issue when finding runnable nodes by stopping + the scan on feedback links around the driver. (#3621) + - The system service now has better socket permissions. + +## Modules + - Add support for uclamp. This allows the scheduler to make better informed + decisions about where tasks should be placed, and what pstate to set + for the CPU it is running on. + - Emit warnings when applications are not doing the right locking instead + of crashing. + - Improve media.name for RAOP sinks. (#3801) + - Support pause/resume in pipe-tunnel. (#3197) + - Remove time rlimit when probing for realtime to avoid SIGXCPU. + +## SPA + - Fix a bug where the resampler would be activated even when there is an + ALSA pitch element. (#3628) + - Improve resume from suspend in ALSA. (#3646) + - Add option to expose ALSA controls as prop params. + - Support XDG base directories when loading ACP config. This makes it possible + to override the ACP config files. + +## Bluetooth + - Schedule nodes in the same ISO group together. + - More BAP fixes and cleanups. + +## JACK + - Fix MIDI events from peer ports. This makes the MIDI event recording preview + of Ardour work correctly. + +## GStreamer + - Fix some error handling in the source and sink. + +## ALSA plugin + - Improve poll descriptor handling. (#3648) + +## Docs + - Many improvements to the layout and organization. + +Older versions: + + # PipeWire 0.3.84 (2023-11-02) This is the fourth 1.0 release candidate that is API and ABI compatible @@ -56,9 +114,6 @@ ## ALSA - The ALSA plugin now handles NULL values from mmap_areas. (#3600) -Older versions: - - # PipeWire 0.3.83 (2023-10-19) This is the third 1.0 release candidate that is API and ABI compatible
View file
pipewire-0.3.84.tar.gz/doc/Doxyfile.in -> pipewire-0.3.85.tar.gz/doc/Doxyfile.in
Changed
@@ -1,7 +1,7 @@ PROJECT_NAME = PipeWire PROJECT_NUMBER = @PACKAGE_VERSION@ OUTPUT_DIRECTORY = "@output_directory@" -FULL_PATH_NAMES = NO +FULL_PATH_NAMES = YES JAVADOC_AUTOBRIEF = YES TAB_SIZE = 8 OPTIMIZE_OUTPUT_FOR_C = YES @@ -36,6 +36,9 @@ SEARCHENGINE = YES GENERATE_LATEX = NO +TOC_INCLUDE_HEADINGS = 0 +LAYOUT_FILE = @layout@ + MACRO_EXPANSION = YES EXPAND_ONLY_PREDEF = YES PREDEFINED = PA_C_DECL_BEGIN= \
View file
pipewire-0.3.85.tar.gz/doc/DoxygenLayout.xml
Added
@@ -0,0 +1,238 @@ +<doxygenlayout version="1.0"> + <navindex> + <tab type="mainpage" visible="yes" title=""/> + <tab type="pages" visible="yes" title="Pages" intro=""/> + <tab type="modules" visible="yes" title="API Reference" intro="" /> + <tab type="namespaces" visible="no" title=""> + <tab type="namespacelist" visible="yes" title="" intro=""/> + <tab type="namespacemembers" visible="yes" title="" intro=""/> + </tab> + <tab type="concepts" visible="no" title=""> + </tab> + <tab type="interfaces" visible="no" title=""> + <tab type="interfacelist" visible="yes" title="" intro=""/> + <tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/> + <tab type="interfacehierarchy" visible="yes" title="" intro=""/> + </tab> + <tab type="classes" visible="yes" title=""> + <tab type="classlist" visible="yes" title="" intro=""/> + <tab type="classindex" visible="yes" title=""/> + <tab type="hierarchy" visible="yes" title="" intro=""/> + <tab type="classmembers" visible="no" title="" intro=""/> + </tab> + <tab type="structs" visible="no" title=""> + <tab type="structlist" visible="yes" title="" intro=""/> + <tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/> + </tab> + <tab type="exceptions" visible="no" title=""> + <tab type="exceptionlist" visible="yes" title="" intro=""/> + <tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/> + <tab type="exceptionhierarchy" visible="yes" title="" intro=""/> + </tab> + <tab type="files" visible="yes" title=""> + <tab type="filelist" visible="yes" title="" intro=""/> + <tab type="globals" visible="no" title="" intro=""/> + </tab> + <tab type="examples" visible="yes" title="" intro=""/> + </navindex> + + <!-- Layout definition for a class page --> + <class> + <briefdescription visible="yes"/> + <includes visible="$SHOW_HEADERFILE"/> + <inheritancegraph visible="$CLASS_GRAPH"/> + <collaborationgraph visible="$COLLABORATION_GRAPH"/> + <memberdecl> + <nestedclasses visible="yes" title=""/> + <publictypes title=""/> + <services title=""/> + <interfaces title=""/> + <publicslots title=""/> + <signals title=""/> + <publicmethods title=""/> + <publicstaticmethods title=""/> + <publicattributes title=""/> + <publicstaticattributes title=""/> + <protectedtypes title=""/> + <protectedslots title=""/> + <protectedmethods title=""/> + <protectedstaticmethods title=""/> + <protectedattributes title=""/> + <protectedstaticattributes title=""/> + <packagetypes title=""/> + <packagemethods title=""/> + <packagestaticmethods title=""/> + <packageattributes title=""/> + <packagestaticattributes title=""/> + <properties title=""/> + <events title=""/> + <privatetypes title=""/> + <privateslots title=""/> + <privatemethods title=""/> + <privatestaticmethods title=""/> + <privateattributes title=""/> + <privatestaticattributes title=""/> + <friends title=""/> + <related title="" subtitle=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <typedefs title=""/> + <enums title=""/> + <services title=""/> + <interfaces title=""/> + <constructors title=""/> + <functions title=""/> + <related title=""/> + <variables title=""/> + <properties title=""/> + <events title=""/> + </memberdef> + <allmemberslink visible="yes"/> + <usedfiles visible="$SHOW_USED_FILES"/> + <authorsection visible="yes"/> + </class> + + <!-- Layout definition for a namespace page --> + <namespace> + <briefdescription visible="yes"/> + <memberdecl> + <nestednamespaces visible="yes" title=""/> + <constantgroups visible="yes" title=""/> + <interfaces visible="yes" title=""/> + <classes visible="yes" title=""/> + <concepts visible="yes" title=""/> + <structs visible="yes" title=""/> + <exceptions visible="yes" title=""/> + <typedefs title=""/> + <sequences title=""/> + <dictionaries title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <typedefs title=""/> + <sequences title=""/> + <dictionaries title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + </memberdef> + <authorsection visible="yes"/> + </namespace> + + <!-- Layout definition for a concept page --> + <concept> + <briefdescription visible="yes"/> + <includes visible="$SHOW_HEADERFILE"/> + <definition visible="yes" title=""/> + <detaileddescription title=""/> + <authorsection visible="yes"/> + </concept> + + <!-- Layout definition for a file page --> + <file> + <briefdescription visible="yes"/> + <includes visible="$SHOW_INCLUDE_FILES"/> + <includegraph visible="$INCLUDE_GRAPH"/> + <includedbygraph visible="$INCLUDED_BY_GRAPH"/> + <sourcelink visible="yes"/> + <memberdecl> + <interfaces visible="yes" title=""/> + <classes visible="yes" title=""/> + <structs visible="yes" title=""/> + <exceptions visible="yes" title=""/> + <namespaces visible="yes" title=""/> + <concepts visible="yes" title=""/> + <constantgroups visible="yes" title=""/> + <defines title=""/> + <typedefs title=""/> + <sequences title=""/> + <dictionaries title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + <membergroups visible="yes"/> + </memberdecl> + <detaileddescription title=""/> + <memberdef> + <inlineclasses title=""/> + <defines title=""/> + <typedefs title=""/> + <sequences title=""/> + <dictionaries title=""/> + <enums title=""/> + <functions title=""/> + <variables title=""/> + </memberdef> + <authorsection/> + </file> + + <!-- Layout definition for a group page --> + <group> + <briefdescription visible="yes"/> + <groupgraph visible="$GROUP_GRAPHS"/> + <memberdecl> + <nestedgroups visible="yes" title=""/> + <dirs visible="yes" title=""/> + <files visible="yes" title=""/> + <namespaces visible="yes" title=""/> + <concepts visible="yes" title=""/> + <classes visible="yes" title=""/> + <typedefs title=""/> + <sequences title=""/> + <dictionaries title=""/> + <enums title=""/> + <enumvalues title=""/> + <defines title=""/> + <functions title=""/> + <variables title=""/> + <signals title=""/> + <publicslots title=""/> + <protectedslots title=""/> + <privateslots title=""/>
View file
pipewire-0.3.84.tar.gz/doc/api-tree.dox -> pipewire-0.3.85.tar.gz/doc/api-tree.dox
Changed
@@ -89,6 +89,7 @@ \addtogroup spa_hooks \addtogroup spa_interfaces \addtogroup spa_json +\addtogroup spa_json_pod \addtogroup spa_keys \addtogroup spa_names \addtogroup spa_result @@ -119,8 +120,4 @@ \{ \} -\defgroup pwtest Test Suite -\{ -\} - */
View file
pipewire-0.3.84.tar.gz/doc/custom.css -> pipewire-0.3.85.tar.gz/doc/custom.css
Changed
@@ -17,3 +17,20 @@ --fragment-link: #729fcf; } } + +#nav-tree .arrow { + opacity: 1; + padding-right: 0.25em; +} + +.textblock h1 { + font-size: 150%; +} +.textblock h2 { + font-size: 100%; +} +.textblock h3, .textblock h4, .textblock h5, .textblock h6 { + font-size: 100%; + font-style: italic; + font-size: medium; +}
View file
pipewire-0.3.84.tar.gz/doc/index.dox -> pipewire-0.3.85.tar.gz/doc/index.dox
Changed
@@ -43,4 +43,13 @@ - Intoduction to PipeWire(https://bootlin.com/blog/an-introduction-to-pipewire/) - A custom PipeWire node(https://bootlin.com/blog/a-custom-pipewire-node/) + +\page page_overview +\page page_pipewire +\page page_tools +\page page_pipewire_modules +\page page_api +\page page_spa +\page page_tutorial + */
View file
pipewire-0.3.84.tar.gz/doc/manpage.dox.in -> pipewire-0.3.85.tar.gz/doc/manpage.dox.in
Changed
@@ -1,5 +1,7 @@ /** \page @pagename@ @title@ +\brief Manual page for @title@ + \verbinclude @filename@ */
View file
pipewire-0.3.84.tar.gz/doc/meson.build -> pipewire-0.3.85.tar.gz/doc/meson.build
Changed
@@ -68,7 +68,6 @@ foreach h : module_sources inputs += meson.project_source_root() / 'src' / 'modules' / h endforeach -inputs += meson.project_source_root() / 'test' / 'pwtest.h' input_dirs = meson.project_source_root() / 'spa' / 'include' / 'spa' path_prefixes = @@ -141,11 +140,16 @@ configuration: pw_tools_dox_conf) input_dirs += 'doc/pipewire-tools.dox' +doxygen_layout = meson.project_source_root() / 'doc' / 'DoxygenLayout.xml' +doxygen_filter_c = meson.project_source_root() / 'doc' / 'input-filter.sh' +doxygen_filter_h = meson.project_source_root() / 'doc' / 'input-filter-h.sh' + doxyfile_conf.set('inputs', ' '.join(inputs + input_dirs)) doxyfile_conf.set('cssfiles', ' '.join(cssfiles)) +doxyfile_conf.set('layout', doxygen_layout) doxyfile_conf.set('path_prefixes', ' '.join(path_prefixes)) -doxyfile_conf.set('c_input_filter', meson.project_source_root() / 'doc' / 'input-filter.sh') -doxyfile_conf.set('h_input_filter', meson.project_source_root() / 'doc' / 'input-filter-h.sh') +doxyfile_conf.set('c_input_filter', doxygen_filter_c) +doxyfile_conf.set('h_input_filter', doxygen_filter_h) doxyfile = configure_file(input: 'Doxyfile.in', output: 'Doxyfile', @@ -157,7 +161,7 @@ endif html_target = custom_target('pipewire-docs', - input: doxyfile, examples_dox, pw_tools_dox + inputs + cssfiles + man_doxygen, + input: doxyfile, doxygen_layout, examples_dox, pw_tools_dox, doxygen_filter_c, doxygen_filter_h + inputs + cssfiles + man_doxygen, output: 'html' , command: doxygen, doxyfile , install: true,
View file
pipewire-0.3.84.tar.gz/doc/pipewire.dox -> pipewire-0.3.85.tar.gz/doc/pipewire.dox
Changed
@@ -17,10 +17,8 @@ # Components - \subpage page_daemon -- \subpage page_tools - \subpage page_session_manager - # Backends - \subpage page_pulseaudio
View file
pipewire-0.3.84.tar.gz/doc/tutorial4.c -> pipewire-0.3.85.tar.gz/doc/tutorial4.c
Changed
@@ -42,6 +42,8 @@ stride = sizeof(int16_t) * DEFAULT_CHANNELS; n_frames = buf->datas0.maxsize / stride; + if (b->requested) + n_frames = SPA_MIN(b->requested, n_frames); for (i = 0; i < n_frames; i++) { data->accumulator += M_PI_M2 * 440 / DEFAULT_RATE;
View file
pipewire-0.3.84.tar.gz/meson.build -> pipewire-0.3.85.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.84', + version : '0.3.85', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -219,8 +219,7 @@ cdata.set_quoted('PIPEWIRE_CONFIG_DIR', pipewire_configdir) cdata.set_quoted('PLUGINDIR', spa_plugindir) cdata.set_quoted('SPADATADIR', spa_datadir) -cdata.set_quoted('PA_ALSA_PATHS_DIR', alsadatadir / 'paths') -cdata.set_quoted('PA_ALSA_PROFILE_SETS_DIR', alsadatadir / 'profile-sets') +cdata.set_quoted('PA_ALSA_DATA_DIR', alsadatadir) if host_machine.endian() == 'big' cdata.set('WORDS_BIGENDIAN', 1)
View file
pipewire-0.3.84.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.85.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -89,7 +89,7 @@ static int snd_pcm_pipewire_stop(snd_pcm_ioplug_t *io); -static int check_active(snd_pcm_ioplug_t *io) +static int update_active(snd_pcm_ioplug_t *io) { snd_pcm_pipewire_t *pw = io->private_data; snd_pcm_sframes_t avail; @@ -97,7 +97,10 @@ avail = snd_pcm_ioplug_avail(io, pw->hw_ptr, io->appl_ptr); - if (io->state == SND_PCM_STATE_DRAINING) { + if (pw->error > 0) { + active = true; + } + else if (io->state == SND_PCM_STATE_DRAINING) { active = pw->drained; } else if (avail >= 0 && avail < (snd_pcm_sframes_t)pw->min_avail) { @@ -105,33 +108,27 @@ } else if (avail >= (snd_pcm_sframes_t)pw->min_avail) { active = true; - } else { + } + else { active = false; } if (pw->active != active) { + uint64_t val; + 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)); + + pw->active = active; + if (active) + spa_system_eventfd_write(pw->system, io->poll_fd, 1); + else + spa_system_eventfd_read(pw->system, io->poll_fd, &val); } return active; } - -static int update_active(snd_pcm_ioplug_t *io) -{ - snd_pcm_pipewire_t *pw = io->private_data; - pw->active = check_active(io); - uint64_t val; - - if (pw->active || pw->error < 0) - spa_system_eventfd_write(pw->system, io->poll_fd, 1); - else - spa_system_eventfd_read(pw->system, io->poll_fd, &val); - - return pw->active; -} - static void snd_pcm_pipewire_free(snd_pcm_pipewire_t *pw) { if (pw == NULL) @@ -162,15 +159,6 @@ return 0; } -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; - update_active(io); - pfds->fd = pw->fd; - pfds->events = POLLIN | POLLERR | POLLNVAL; - return 1; -} - static int snd_pcm_pipewire_poll_revents(snd_pcm_ioplug_t *io, struct pollfd *pfds, unsigned int nfds, unsigned short *revents) @@ -183,10 +171,10 @@ return pw->error; *revents = pfds0.revents & ~(POLLIN | POLLOUT); - if (pfds0.revents & POLLIN && check_active(io)) { + if (pfds0.revents & POLLIN && update_active(io)) *revents |= (io->stream == SND_PCM_STREAM_PLAYBACK) ? POLLOUT : POLLIN; - update_active(io); - } + + pw_log_trace_fp("poll %d", *revents); return 0; } @@ -911,7 +899,6 @@ .delay = snd_pcm_pipewire_delay, .drain = snd_pcm_pipewire_drain, .prepare = snd_pcm_pipewire_prepare, - .poll_descriptors = snd_pcm_pipewire_poll_descriptors, .poll_revents = snd_pcm_pipewire_poll_revents, .hw_params = snd_pcm_pipewire_hw_params, .sw_params = snd_pcm_pipewire_sw_params,
View file
pipewire-0.3.84.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.85.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -110,6 +110,10 @@ static struct globals globals; static bool mlock_warned = false; +#define MIDI_SCRATCH_FRAMES 8192 +static float midi_scratchMIDI_SCRATCH_FRAMES; + + #define OBJECT_CHUNK 8 #define RECYCLE_THRESHOLD 128 @@ -122,9 +126,10 @@ struct client *client; -#define INTERFACE_Port 0 -#define INTERFACE_Node 1 -#define INTERFACE_Link 2 +#define INTERFACE_Invalid 0 +#define INTERFACE_Port 1 +#define INTERFACE_Node 2 +#define INTERFACE_Link 3 uint32_t type; uint32_t id; uint32_t serial; @@ -502,7 +507,7 @@ pthread_mutex_lock(&globals.lock); spa_list_for_each_safe(o, t, &c->context.objects, link) { if (o->removed) { - pw_log_info("%p: recycle object:%p type:%d id:%u/%u", + pw_log_debug("%p: recycle object:%p type:%d id:%u/%u", c, o, o->type, o->id, o->serial); spa_list_remove(&o->link); memset(o, 0, sizeof(struct object)); @@ -531,6 +536,15 @@ } +static inline struct object *port_to_object(const jack_port_t *port) +{ + return (struct object*)port; +} +static inline jack_port_t *object_to_port(struct object *o) +{ + return (jack_port_t*)o; +} + struct io_info { struct mix *mix; void *data; @@ -2522,6 +2536,17 @@ return 0; } +static void midi_init_buffer(void *data, uint32_t max_frames) +{ + struct midi_buffer *mb = data; + mb->magic = MIDI_BUFFER_MAGIC; + mb->buffer_size = max_frames * sizeof(float); + mb->nframes = max_frames; + mb->write_pos = 0; + mb->event_count = 0; + mb->lost_events = 0; +} + static inline void *init_buffer(struct port *p) { struct client *c = p->client; @@ -2531,12 +2556,7 @@ if (p->object->port.type_id == TYPE_ID_MIDI) { struct midi_buffer *mb = data; - mb->magic = MIDI_BUFFER_MAGIC; - mb->buffer_size = c->max_frames * sizeof(float); - mb->nframes = c->max_frames; - mb->write_pos = 0; - mb->event_count = 0; - mb->lost_events = 0; + midi_init_buffer(data, c->max_frames); pw_log_debug("port %p: init midi buffer size:%d", p, mb->buffer_size); } else memset(data, 0, c->max_frames * sizeof(float)); @@ -3218,7 +3238,7 @@ } static const struct pw_node_events node_events = { - PW_VERSION_NODE, + PW_VERSION_NODE_EVENTS, .info = node_info, }; @@ -3243,7 +3263,7 @@ } static const struct pw_port_events port_events = { - PW_VERSION_PORT, + PW_VERSION_PORT_EVENTS, .param = port_param, }; @@ -5005,7 +5025,7 @@ goto error_free; } - return (jack_port_t *) o; + return object_to_port(o); error_free: free_port(c, p, true); @@ -5037,7 +5057,7 @@ int jack_port_unregister (jack_client_t *client, jack_port_t *port) { struct client *c = (struct client *) client; - struct object *o = (struct object *) port; + struct object *o = port_to_object(port); struct port *p; int res; @@ -5214,41 +5234,58 @@ SPA_EXPORT void * jack_port_get_buffer (jack_port_t *port, jack_nframes_t frames) { - struct object *o = (struct object *) port; - struct port *p; - void *ptr; + struct object *o = port_to_object(port); + struct port *p = NULL; + void *ptr = NULL; return_val_if_fail(o != NULL, NULL); if (o->type != INTERFACE_Port || o->client == NULL) - return NULL; + goto done; if ((p = o->port.port) == NULL) { struct mix *mix; struct buffer *b; if ((mix = find_mix_peer(o->client, o->id)) == NULL) - return NULL; + goto done; pw_log_trace("peer mix: %p %d", mix, mix->peer_id); if ((b = get_mix_buffer(mix, frames)) == NULL) - return NULL; + goto done; - return get_buffer_data(b, frames); + if (o->port.type_id == TYPE_ID_MIDI) { + struct spa_pod_sequence *seq1; + struct spa_data *d; + void *pod; + + ptr = midi_scratch; + midi_init_buffer(ptr, MIDI_SCRATCH_FRAMES); + + d = &b->datas0; + if ((pod = spa_pod_from_data(d->data, d->maxsize, + d->chunk->offset, d->chunk->size)) == NULL) + goto done; + if (!spa_pod_is_sequence(pod)) + goto done; + seq0 = pod; + convert_to_midi(seq, 1, ptr, o->client->fix_midi_events); + } else { + ptr = get_buffer_data(b, frames); + } + } else if (p->valid) { + ptr = p->get_buffer(p, frames); } - if (!p->valid) - return NULL; - - ptr = p->get_buffer(p, frames); - pw_log_trace_fp("%p: port %p buffer %p empty:%u", p->client, p, ptr, p->empty_out); +done: + pw_log_trace_fp("%p: port %p buffer %p", p->client, p, ptr); return ptr; } SPA_EXPORT jack_uuid_t jack_port_uuid (const jack_port_t *port) { - struct object *o = (struct object *) port; + struct object *o = port_to_object(port); return_val_if_fail(o != NULL, 0); return jack_port_uuid_generate(o->serial); } @@ -5269,47 +5306,57 @@ SPA_EXPORT const char * jack_port_name (const jack_port_t *port) { - struct object *o = (struct object *) port; + struct object *o = port_to_object(port); return_val_if_fail(o != NULL, NULL); + if (o->type != INTERFACE_Port) + return NULL; return port_name(o);
View file
pipewire-0.3.84.tar.gz/spa/include/spa/debug/log.h -> pipewire-0.3.85.tar.gz/spa/include/spa/debug/log.h
Changed
@@ -38,7 +38,7 @@ SPA_PRINTF_FUNC(2,3) static inline void spa_debug_log_log(struct spa_debug_context *ctx, const char *fmt, ...) { - struct spa_debug_log_ctx *c = (struct spa_debug_log_ctx*)ctx; + struct spa_debug_log_ctx *c = SPA_CONTAINER_OF(ctx, struct spa_debug_log_ctx, ctx); va_list args; va_start(args, fmt); spa_log_logtv(c->log, c->level, c->topic, c->file, c->line, c->func, fmt, args);
View file
pipewire-0.3.84.tar.gz/spa/include/spa/param/props.h -> pipewire-0.3.85.tar.gz/spa/include/spa/param/props.h
Changed
@@ -64,24 +64,26 @@ SPA_PROP_patternType, SPA_PROP_ditherType, SPA_PROP_truncate, - SPA_PROP_channelVolumes, /**< a volume array, one volume per channel + SPA_PROP_channelVolumes, /**< a volume array, one (linear) volume per channel * (Array of Float). 0.0 is silence, 1.0 is - * without attenuation. This is the effective volume - * that is applied. It can result in a hardware volume - * and software volume (see softVolumes) */ + * without attenuation. This is the effective + * volume that is applied. It can result + * in a hardware volume and software volume + * (see softVolumes) */ SPA_PROP_volumeBase, /**< a volume base (Float) */ SPA_PROP_volumeStep, /**< a volume step (Float) */ SPA_PROP_channelMap, /**< a channelmap array * (Array (Id enum spa_audio_channel)) */ SPA_PROP_monitorMute, /**< mute (Bool) */ - SPA_PROP_monitorVolumes, /**< a volume array, one volume per + SPA_PROP_monitorVolumes, /**< a volume array, one (linear) volume per * channel (Array of Float) */ SPA_PROP_latencyOffsetNsec, /**< delay adjustment */ SPA_PROP_softMute, /**< mute (Bool) applied in software */ - SPA_PROP_softVolumes, /**< a volume array, one volume per channel + SPA_PROP_softVolumes, /**< a volume array, one (linear) volume per channel * (Array of Float). 0.0 is silence, 1.0 is without - * attenuation. This is the volume applied in software, - * there might be a part applied in hardware. */ + * attenuation. This is the volume applied in + * software, there might be a part applied in + * hardware. */ SPA_PROP_iec958Codecs, /**< enabled IEC958 (S/PDIF) codecs, * (Array (Id enum spa_audio_iec958_codec) */
View file
pipewire-0.3.84.tar.gz/spa/include/spa/utils/keys.h -> pipewire-0.3.85.tar.gz/spa/include/spa/utils/keys.h
Changed
@@ -44,6 +44,7 @@ #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 */ +#define SPA_KEY_API_ALSA_BIND_CTLS "api.alsa.bind-ctls" /**< alsa controls to bind as params */ /** 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.84.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/acp/alsa-mixer.c
Changed
@@ -2795,20 +2795,6 @@ return 0; } -static const char *get_default_paths_dir(void) { - const char *str; -#ifdef HAVE_RUNNING_FROM_BUILD_TREE - if (pa_run_from_build_tree()) - return PA_SRCDIR "mixer/paths"; - else -#endif - if (getenv("ACP_BUILDDIR") != NULL) - return "mixer/paths"; - if ((str = getenv("ACP_PATHS_DIR")) != NULL) - return str; - return PA_ALSA_PATHS_DIR; -} - pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) { pa_alsa_path *p; char *fn; @@ -2873,10 +2859,9 @@ items2.data = &p->description; items3.data = &mute_during_activation; - if (!paths_dir) - paths_dir = get_default_paths_dir(); + fn = get_data_path(paths_dir, "paths", fname); - fn = pa_maybe_prefix_path(fname, paths_dir); + pa_log_info("Loading path config: %s", fn); r = pa_config_parse(fn, NULL, items, p->proplist, false, p); pa_xfree(fn); @@ -4827,20 +4812,6 @@ pa_xfree(db_values); } -static const char *get_default_profile_dir(void) { - const char *str; -#ifdef HAVE_RUNNING_FROM_BUILD_TREE - if (pa_run_from_build_tree()) - return PA_SRCDIR "mixer/profile-sets"; - else -#endif - if (getenv("ACP_BUILDDIR") != NULL) - return "mixer/profile-sets"; - if ((str = getenv("ACP_PROFILES_DIR")) != NULL) - return str; - return PA_ALSA_PROFILE_SETS_DIR; -} - pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel_map *bonus) { pa_alsa_profile_set *ps; pa_alsa_profile *p; @@ -4890,13 +4861,14 @@ items0.data = &ps->auto_profiles; - fn = pa_maybe_prefix_path(fname ? fname : "default.conf", - get_default_profile_dir()); + fn = get_data_path(NULL, "profile-sets", fname ? fname : "default.conf"); + + pa_log_info("Loading profile set: %s", fn); + if ((r = access(fn, R_OK)) != 0) { if (fname != NULL) { pa_log_warn("profile-set '%s' can't be accessed: %m", fn); - fn = pa_maybe_prefix_path("default.conf", - get_default_profile_dir()); + fn = get_data_path(NULL, "profile-sets", "default.conf"); r = access(fn, R_OK); } if (r != 0) {
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/acp/compat.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/acp/compat.c
Changed
@@ -18,9 +18,13 @@ along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. ***/ +#include <spa/utils/string.h> +#include <spa/utils/cleanup.h> + #include "compat.h" #include "device-port.h" #include "alsa-mixer.h" +#include "config.h" static const char *port_types = { PA_DEVICE_PORT_TYPE_UNKNOWN = "unknown", @@ -208,3 +212,76 @@ return true; } + +static char *try_path(const char *fname, const char *path) +{ + char *result = pa_maybe_prefix_path(fname, path); + + pa_log_trace("Check for file: %s", result); + + if (access(result, R_OK) == 0) + return result; + + pa_xfree(result); + return NULL; +} + +static char *get_xdg_home(const char *key, const char *fallback) +{ + const char *e; + + e = getenv(key); + if (e && *e) { + return strdup(e); + } else { + e = getenv("HOME"); + if (!(e && *e)) + e = getenv("USERPROFILE"); + if (e && *e) + return spa_aprintf("%s/%s", e, fallback); + } + return NULL; +} + +char *get_data_path(const char *data_dir, const char *data_type, const char *fname) +{ + static const char * const subpaths = { + "alsa-card-profile/mixer", + "alsa-card-profile", + }; + const char *e; + spa_autofree char *base = NULL; + char *result; + + if (data_dir) + if ((result = try_path(fname, data_dir)) != NULL) + return result; + + e = getenv("ACP_PATHS_DIR"); + if (e && *e && spa_streq(data_type, "paths")) + if ((result = try_path(fname, e)) != NULL) + return result; + + e = getenv("ACP_PROFILES_DIR"); + if (e && *e && spa_streq(data_type, "profile-sets")) + if ((result = try_path(fname, e)) != NULL) + return result; + + base = get_xdg_home("XDG_CONFIG_HOME", ".config"); + if (base) { + SPA_FOR_EACH_ELEMENT_VAR(subpaths, subpath) { + spa_autofree char *path = spa_aprintf("%s/%s/%s", base, *subpath, data_type); + if ((result = try_path(fname, path)) != NULL) + return result; + } + } + + SPA_FOR_EACH_ELEMENT_VAR(subpaths, subpath) { + spa_autofree char *path = spa_aprintf("/etc/%s/%s", *subpath, data_type); + if ((result = try_path(fname, path)) != NULL) + return result; + } + + spa_autofree char *path = spa_aprintf("%s/%s", PA_ALSA_DATA_DIR, data_type); + return pa_maybe_prefix_path(fname, path); +}
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/acp/compat.h -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/acp/compat.h
Changed
@@ -214,6 +214,7 @@ PA_LOG_NOTICE = 2, /* Notice messages */ PA_LOG_INFO = 3, /* Info messages */ PA_LOG_DEBUG = 4, /* Debug messages */ + PA_LOG_TRACE = 5, PA_LOG_LEVEL_MAX } pa_log_level_t; @@ -245,6 +246,7 @@ #define pa_log_notice(fmt,...) pa_logl(PA_LOG_NOTICE, fmt, ##__VA_ARGS__) #define pa_log_info(fmt,...) pa_logl(PA_LOG_INFO, fmt, ##__VA_ARGS__) #define pa_log_debug(fmt,...) pa_logl(PA_LOG_DEBUG, fmt, ##__VA_ARGS__) +#define pa_log_trace(fmt,...) pa_logl(PA_LOG_TRACE, fmt, ##__VA_ARGS__) #define pa_log pa_log_error #define pa_assert_se(expr) \ @@ -677,6 +679,8 @@ #endif } +char *get_data_path(const char *data_dir, const char *data_type, const char *fname); + #include <spa/support/i18n.h> extern struct spa_i18n *acp_i18n;
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/alsa-compress-offload-device.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/alsa-compress-offload-device.c
Changed
@@ -86,7 +86,7 @@ * hardware that can capture audio is difficult to do. The only hardware * known is the Wolfson ADSP; the only driver in the kernel that exposes * Compress-Offload capture devices is the one for that hardware. */ - assert(false); + spa_assert_not_reached(); } info.change_mask = SPA_DEVICE_OBJECT_CHANGE_MASK_PROPS;
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/alsa-pcm-sink.c
Changed
@@ -8,8 +8,6 @@ #include <spa/node/node.h> #include <spa/node/utils.h> -#include <spa/node/keys.h> -#include <spa/monitor/device.h> #include <spa/utils/keys.h> #include <spa/utils/names.h> #include <spa/utils/string.h> @@ -31,75 +29,6 @@ props->use_chmap = DEFAULT_USE_CHMAP; } -static void emit_node_info(struct state *this, bool full) -{ - uint64_t old = full ? this->info.change_mask : 0; - - if (full) - this->info.change_mask = this->info_all; - if (this->info.change_mask) { - struct spa_dict_item items7; - uint32_t i, n_items = 0; - 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"); - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true"); - 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->period_frames != 0 ? this->buffer_frames / this->period_frames : 0); - 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); - } else { - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", NULL); - } - this->info.props = &SPA_DICT_INIT(items, n_items); - - if (this->info.change_mask & SPA_NODE_CHANGE_MASK_PARAMS) { - for (i = 0; i < this->info.n_params; i++) { - if (this->paramsi.user > 0) { - this->paramsi.flags ^= SPA_PARAM_INFO_SERIAL; - this->paramsi.user = 0; - } - } - } - spa_node_emit_info(&this->hooks, &this->info); - - this->info.change_mask = old; - } -} - -static void emit_port_info(struct state *this, bool full) -{ - uint64_t old = full ? this->port_info.change_mask : 0; - - if (full) - this->port_info.change_mask = this->port_info_all; - if (this->port_info.change_mask) { - uint32_t i; - - if (this->port_info.change_mask & SPA_PORT_CHANGE_MASK_PARAMS) { - for (i = 0; i < this->port_info.n_params; i++) { - if (this->port_paramsi.user > 0) { - this->port_paramsi.flags ^= SPA_PARAM_INFO_SERIAL; - this->port_paramsi.user = 0; - } - } - } - spa_node_emit_port_info(&this->hooks, - SPA_DIRECTION_INPUT, 0, &this->port_info); - this->port_info.change_mask = old; - } -} - static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, const struct spa_pod *filter) @@ -348,8 +277,8 @@ info.ns = lat_ns; handle_process_latency(this, &info); } - emit_node_info(this, false); - emit_port_info(this, false); + spa_alsa_emit_node_info(this, false); + spa_alsa_emit_port_info(this, false); break; } case SPA_PARAM_ProcessLatency: @@ -362,8 +291,8 @@ handle_process_latency(this, &info); - emit_node_info(this, false); - emit_port_info(this, false); + spa_alsa_emit_node_info(this, false); + spa_alsa_emit_port_info(this, false); break; } default: @@ -425,8 +354,8 @@ spa_hook_list_isolate(&this->hooks, &save, listener, events, data); - emit_node_info(this, true); - emit_port_info(this, true); + spa_alsa_emit_node_info(this, true); + spa_alsa_emit_port_info(this, true); spa_hook_list_join(&this->hooks, &save); @@ -673,7 +602,7 @@ } this->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS; - emit_node_info(this, false); + spa_alsa_emit_node_info(this, false); this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_RATE; this->port_info.rate = SPA_FRACTION(1, this->rate); @@ -686,7 +615,7 @@ this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); } - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); return err; } @@ -722,7 +651,7 @@ this->latencyinfo.direction = info; this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Latency.user++; - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); break; } case SPA_PARAM_Tag: @@ -741,7 +670,7 @@ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Tag.user++; - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); } break; }
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/alsa-pcm-source.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/alsa-pcm-source.c
Changed
@@ -8,12 +8,10 @@ #include <spa/node/node.h> #include <spa/node/utils.h> -#include <spa/node/keys.h> #include <spa/utils/keys.h> #include <spa/utils/names.h> #include <spa/utils/list.h> #include <spa/utils/string.h> -#include <spa/monitor/device.h> #include <spa/param/audio/format.h> #include <spa/pod/filter.h> #include <spa/pod/dynamic.h> @@ -32,73 +30,6 @@ props->use_chmap = DEFAULT_USE_CHMAP; } -static void emit_node_info(struct state *this, bool full) -{ - uint64_t old = full ? this->info.change_mask : 0; - if (full) - this->info.change_mask = this->info_all; - if (this->info.change_mask) { - struct spa_dict_item items7; - uint32_t i, n_items = 0; - 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"); - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_DRIVER, "true"); - 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->period_frames != 0 ? this->buffer_frames / this->period_frames : 0); - 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); - } else { - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_NODE_MAX_LATENCY, NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-size", NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.period-num", NULL); - itemsn_items++ = SPA_DICT_ITEM_INIT("api.alsa.headroom", NULL); - } - this->info.props = &SPA_DICT_INIT(items, n_items); - - if (this->info.change_mask & SPA_NODE_CHANGE_MASK_PARAMS) { - for (i = 0; i < this->info.n_params; i++) { - if (this->paramsi.user > 0) { - this->paramsi.flags ^= SPA_PARAM_INFO_SERIAL; - this->paramsi.user = 0; - } - } - } - spa_node_emit_info(&this->hooks, &this->info); - this->info.change_mask = old; - } -} - -static void emit_port_info(struct state *this, bool full) -{ - uint64_t old = full ? this->port_info.change_mask : 0; - if (full) - this->port_info.change_mask = this->port_info_all; - if (this->port_info.change_mask) { - uint32_t i; - - if (this->port_info.change_mask & SPA_PORT_CHANGE_MASK_PARAMS) { - for (i = 0; i < this->port_info.n_params; i++) { - if (this->port_paramsi.user > 0) { - this->port_paramsi.flags ^= SPA_PARAM_INFO_SERIAL; - this->port_paramsi.user = 0; - } - } - } - spa_node_emit_port_info(&this->hooks, - SPA_DIRECTION_OUTPUT, 0, &this->port_info); - this->port_info.change_mask = old; - } -} - - static int impl_node_enum_params(void *object, int seq, uint32_t id, uint32_t start, uint32_t num, const struct spa_pod *filter) @@ -311,8 +242,8 @@ handle_process_latency(this, &info); } - emit_node_info(this, false); - emit_port_info(this, false); + spa_alsa_emit_node_info(this, false); + spa_alsa_emit_port_info(this, false); break; } case SPA_PARAM_ProcessLatency: @@ -325,8 +256,8 @@ handle_process_latency(this, &info); - emit_node_info(this, false); - emit_port_info(this, false); + spa_alsa_emit_node_info(this, false); + spa_alsa_emit_port_info(this, false); break; } default: @@ -388,8 +319,8 @@ spa_hook_list_isolate(&this->hooks, &save, listener, events, data); - emit_node_info(this, true); - emit_port_info(this, true); + spa_alsa_emit_node_info(this, true); + spa_alsa_emit_port_info(this, true); spa_hook_list_join(&this->hooks, &save); @@ -607,7 +538,7 @@ } this->info.change_mask |= SPA_NODE_CHANGE_MASK_PROPS; - emit_node_info(this, false); + spa_alsa_emit_node_info(this, false); this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_RATE; this->port_info.rate = SPA_FRACTION(1, this->rate); @@ -620,7 +551,7 @@ this->port_paramsPORT_Format = SPA_PARAM_INFO(SPA_PARAM_Format, SPA_PARAM_INFO_WRITE); this->port_paramsPORT_Buffers = SPA_PARAM_INFO(SPA_PARAM_Buffers, 0); } - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); return err; } @@ -656,7 +587,7 @@ this->latencyinfo.direction = info; this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Latency.user++; - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); break; } case SPA_PARAM_Tag: @@ -675,7 +606,7 @@ this->port_info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; this->port_paramsPORT_Tag.user++; - emit_port_info(this, false); + spa_alsa_emit_port_info(this, false); } break; }
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -13,6 +13,8 @@ #include <spa/utils/result.h> #include <spa/support/system.h> #include <spa/utils/keys.h> +#include <spa/node/keys.h> +#include <spa/monitor/device.h> #include "alsa-pcm.h" @@ -184,6 +186,69 @@ return 0; } +static struct spa_pod *enum_bind_ctl_propinfo(struct state *state, uint32_t idx, struct spa_pod_builder *b) +{ + char param_name1024; + char param_desc1024; + snd_ctl_elem_info_t *info = state->bound_ctlsidx.info; + + if (!info) { + // This will end iteration early, so print a warning + spa_log_warn(state->log, "Don't have prop info for bind ctl, bailing"); + return NULL; + } + + snprintf(param_name, sizeof(param_name), "api.alsa.bind-ctl.%s", + snd_ctl_elem_info_get_name(info)); + snprintf(param_desc, sizeof(param_desc), "Value of ALSA control '%s'", + snd_ctl_elem_info_get_name(info)); + + // We don't have meaningful default values + switch (snd_ctl_elem_info_get_type(info)) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + return spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String(param_name), + SPA_PROP_INFO_description, SPA_POD_String(param_desc), + SPA_PROP_INFO_type, SPA_POD_Bool(false), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + + case SND_CTL_ELEM_TYPE_INTEGER: + return spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String(param_name), + SPA_PROP_INFO_description, SPA_POD_String(param_desc), + SPA_PROP_INFO_type, SPA_POD_Int(0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + + case SND_CTL_ELEM_TYPE_INTEGER64: + return spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String(param_name), + SPA_PROP_INFO_description, SPA_POD_String(param_desc), + SPA_PROP_INFO_type, SPA_POD_Long(0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + + case SND_CTL_ELEM_TYPE_ENUMERATED: + return spa_pod_builder_add_object(b, + SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo, + SPA_PROP_INFO_name, SPA_POD_String(param_name), + SPA_PROP_INFO_description, SPA_POD_String(param_desc), + SPA_PROP_INFO_type, SPA_POD_Int(0), + SPA_PROP_INFO_params, SPA_POD_Bool(true)); + break; + + default: + // FIXME: we can probably support bytes but the length seems unknown in the API + spa_log_warn(state->log, "%s ctl '%s' not supported", + snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info)), + snd_ctl_elem_info_get_name(info)); + return NULL; + } +} + struct spa_pod *spa_alsa_enum_propinfo(struct state *state, uint32_t idx, struct spa_pod_builder *b) { @@ -346,12 +411,67 @@ SPA_PROP_INFO_type, SPA_POD_String(state->clock_name), SPA_PROP_INFO_params, SPA_POD_Bool(true)); break; + // While adding params here, update the math in default too default: - return NULL; + idx -= 17; + if (idx <= state->num_bind_ctls) + param = enum_bind_ctl_propinfo(state, idx - 1, b); + else + return NULL; } return param; } +static void add_bind_ctl_param(struct state *state, const snd_ctl_elem_value_t *elem, const snd_ctl_elem_info_t *info, + struct spa_pod_builder *b) +{ + char param_name1024; + + snprintf(param_name, sizeof(param_name), "api.alsa.bind-ctl.%s", + snd_ctl_elem_info_get_name(info)); + spa_pod_builder_string(b, param_name); + + switch (snd_ctl_elem_info_get_type(info)) { + case SND_CTL_ELEM_TYPE_BOOLEAN: + spa_pod_builder_bool(b, snd_ctl_elem_value_get_boolean(elem, 0)); + break; + + case SND_CTL_ELEM_TYPE_INTEGER: + spa_pod_builder_int(b, snd_ctl_elem_value_get_integer(elem, 0)); + break; + + case SND_CTL_ELEM_TYPE_INTEGER64: + spa_pod_builder_long(b, snd_ctl_elem_value_get_integer64(elem, 0)); + break; + + case SND_CTL_ELEM_TYPE_ENUMERATED: + spa_pod_builder_int(b, snd_ctl_elem_value_get_enumerated(elem, 0)); + break; + + default: + // FIXME: we can probably support bytes but the length seems unknown in the API + spa_log_warn(state->log, "%s ctl '%s' not supported", + snd_ctl_elem_type_name(snd_ctl_elem_info_get_type(info)), + snd_ctl_elem_info_get_name(info)); + break; + } +} + +static void add_bind_ctl_params(struct state *state, struct spa_pod_builder *b) +{ + int err; + + for (unsigned int i = 0; i < state->num_bind_ctls; i++) { + err = snd_ctl_elem_read(state->ctl, state->bound_ctlsi.value); + if (err < 0) { + spa_log_warn(state->log, "Could not read elem value for '%s': %s", + state->bound_ctlsi.name, snd_strerror(err)); + } + + add_bind_ctl_param(state, state->bound_ctlsi.value, state->bound_ctlsi.info, b); + } +} + int spa_alsa_add_prop_params(struct state *state, struct spa_pod_builder *b) { struct spa_pod_frame f1; @@ -419,6 +539,8 @@ spa_pod_builder_string(b, "clock.name"); spa_pod_builder_string(b, state->clock_name); + add_bind_ctl_params(state, b); + spa_pod_builder_pop(b, &f0); return 0; } @@ -498,6 +620,123 @@ { } +static void fill_device_name(struct state *state, const char *params, char device_name, size_t len) +{ + spa_scnprintf(device_name, len, "%s%s%s", + state->card->ucm_prefix ? state->card->ucm_prefix : "", + state->props.device, params ? params : ""); +} + +static void bind_ctl_event(struct spa_source *source) +{ + // We don't know if a bound element changed or not, so let's find out + struct state *state = source->data; + snd_ctl_elem_value_t *old_value; + bool changed = false; + + snd_ctl_elem_value_alloca(&old_value); + + for (unsigned int i = 0; i < state->num_bind_ctls; i++) { + int err; + + snd_ctl_elem_value_copy(old_value, state->bound_ctlsi.value); + + err = snd_ctl_elem_read(state->ctl, state->bound_ctlsi.value); + if (err < 0) { + spa_log_warn(state->log, "Could not read ctl '%s': %s", + state->bound_ctlsi.name, snd_strerror(err)); + continue; + } + + if (snd_ctl_elem_value_compare(old_value, state->bound_ctlsi.value) != 0) { + // We don't need to check all the ctls, if one changed, + // we'll emit a notification and they'll be read when + // the props are read + spa_log_debug(state->log, "bound ctl '%s' has changed", state->bound_ctlsi.name); + changed = true; + break; + } + } + + if (changed) {
View file
pipewire-0.3.84.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.85.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -92,6 +92,12 @@ unsigned int following:1; }; +struct bound_ctl { + char name256; + snd_ctl_elem_info_t *info; + snd_ctl_elem_value_t *value; +}; + struct state { struct spa_handle handle; struct spa_node node; @@ -240,11 +246,19 @@ struct spa_pod *tag2; - /* Rate match via an ALSA ctl */ + /* for rate match and bind ctls */ snd_ctl_t *ctl; + + /* Rate match via an ALSA ctl */ snd_ctl_elem_value_t *pitch_elem; double last_rate; + /* ALSA ctls exposed as params */ + unsigned int num_bind_ctls; + struct bound_ctl bound_ctls16; + struct spa_source ctl_sourcesMAX_POLL; + int ctl_n_fds; + struct spa_list link; struct spa_list followers; @@ -282,6 +296,9 @@ void spa_alsa_recycle_buffer(struct state *state, uint32_t buffer_id); +void spa_alsa_emit_node_info(struct state *state, bool full); +void spa_alsa_emit_port_info(struct state *state, bool full); + static inline uint32_t spa_alsa_format_from_name(const char *name, size_t len) { int i;
View file
pipewire-0.3.84.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c -> pipewire-0.3.85.tar.gz/spa/plugins/bluez5/bap-codec-lc3.c
Changed
@@ -556,12 +556,13 @@ spa_pod_builder_int(b, 8000); spa_pod_builder_int(b, 8000); } - if (i == 0) - return -EINVAL; if (i > 1) choice->body.type = SPA_CHOICE_Enum; spa_pod_builder_pop(b, &f1); + if (i == 0) + return -EINVAL; + res = channels_to_positions(conf.channels, position); if (res == 0) return -EINVAL; @@ -674,6 +675,8 @@ if (endpoint_qos->latency >= 0x0005 && endpoint_qos->latency <= 0x0FA0) /* Values outside the range are RFU */ qos->latency = endpoint_qos->latency; + if (endpoint_qos->retransmission) + qos->retransmission = endpoint_qos->retransmission; if (endpoint_qos->delay_min) qos->delay = SPA_MAX(qos->delay, endpoint_qos->delay_min); if (endpoint_qos->delay_max)
View file
pipewire-0.3.84.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.85.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -971,6 +971,11 @@ goto error_invalid; } + spa_log_debug(monitor->log, "select qos: interval:%d framing:%d phy:%d sdu:%d " + "rtn:%d latency:%d delay:%d target_latency:%d", + qos.interval, qos.framing, qos.phy, qos.sdu, qos.retransmission, + qos.latency, (int)qos.delay, qos.target_latency); + dbus_message_iter_open_container(&dict, DBUS_TYPE_DICT_ENTRY, NULL, &entry); dbus_message_iter_append_basic(&entry, DBUS_TYPE_STRING, &entry_key); dbus_message_iter_open_container(&entry, DBUS_TYPE_VARIANT, "a{sv}", &variant); @@ -3465,6 +3470,9 @@ SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) continue; + if (t->device->adapter != transport->device->adapter) + continue; + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { if (t->bap_big != transport->bap_big) @@ -3587,10 +3595,10 @@ /* For broadcast there initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */ if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { - spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); + spa_bt_transport_set_state(t_linked, SPA_BT_TRANSPORT_STATE_ACTIVE); } else { if (!transport->bap_initiator) - spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); + spa_bt_transport_set_state(t_linked, SPA_BT_TRANSPORT_STATE_ACTIVE); } }
View file
pipewire-0.3.84.tar.gz/spa/plugins/bluez5/codec-loader.c -> pipewire-0.3.85.tar.gz/spa/plugins/bluez5/codec-loader.c
Changed
@@ -173,7 +173,7 @@ #undef MEDIA_CODEC_FACTORY_LIB }; - impl = calloc(sizeof(struct impl), 1); + impl = calloc(1, sizeof(struct impl)); if (impl == NULL) return NULL;
View file
pipewire-0.3.84.tar.gz/spa/plugins/bluez5/iso-io.c -> pipewire-0.3.85.tar.gz/spa/plugins/bluez5/iso-io.c
Changed
@@ -37,7 +37,7 @@ struct spa_source source; struct spa_list streams; int timerfd; - uint8_t cig; + uint8_t id; uint64_t next; uint64_t duration; uint32_t paused; @@ -155,7 +155,7 @@ if ((res = spa_system_timerfd_read(group->data_system, group->timerfd, &exp)) < 0) { if (res != -EAGAIN) spa_log_warn(group->log, "%p: ISO group:%u error reading timerfd: %s", - group, group->cig, spa_strerror(res)); + group, group->id, spa_strerror(res)); return; } @@ -178,7 +178,7 @@ if (group->paused) { --group->paused; - spa_log_debug(group->log, "%p: ISO group:%d paused:%u", group, group->cig, group->paused); + spa_log_debug(group->log, "%p: ISO group:%u paused:%u", group, group->id, group->paused); } /* Produce output */ @@ -194,7 +194,7 @@ } if (stream->this.size == 0) { spa_log_debug(group->log, "%p: ISO group:%u miss fd:%d", - group, group->cig, stream->fd); + group, group->id, stream->fd); if (stream_silence(stream) < 0) { fail = true; continue; @@ -208,7 +208,7 @@ } spa_log_trace(group->log, "%p: ISO group:%u sent fd:%d size:%u ts:%u idle:%d res:%d", - group, group->cig, stream->fd, (unsigned)stream->this.size, + group, group->id, stream->fd, (unsigned)stream->this.size, (unsigned)stream->this.timestamp, stream->idle, res); stream->this.size = 0; @@ -243,19 +243,29 @@ struct spa_log *log, struct spa_loop *data_loop, struct spa_system *data_system) { struct group *group; + uint8_t id; if (t->bap_interval <= 5000) { errno = EINVAL; return NULL; } + if (t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE)) { + id = t->bap_cig; + } else if (t->profile & (SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { + id = t->bap_big; + } else { + errno = EINVAL; + return NULL; + } + group = calloc(1, sizeof(struct group)); if (group == NULL) return NULL; spa_log_topic_init(log, &log_topic); - group->cig = t->bap_cig; + group->id = id; group->log = log; group->data_loop = data_loop; group->data_system = data_system;
View file
pipewire-0.3.84.tar.gz/spa/plugins/bluez5/media-sink.c -> pipewire-0.3.85.tar.gz/spa/plugins/bluez5/media-sink.c
Changed
@@ -1405,6 +1405,21 @@ static void emit_node_info(struct impl *this, bool full) { + char node_group_buf256; + char *node_group = NULL; + + if (this->transport && (this->transport->profile & SPA_BT_PROFILE_BAP_SINK)) { + spa_scnprintf(node_group_buf, sizeof(node_group_buf), "bluez-iso-%s-cig-%d", + this->transport->device->adapter->address, + this->transport->bap_cig); + node_group = node_group_buf; + } else if (this->transport && (this->transport->profile & SPA_BT_PROFILE_BAP_BROADCAST_SINK)) { + spa_scnprintf(node_group_buf, sizeof(node_group_buf), "bluez-iso-%s-big-%d", + this->transport->device->adapter->address, + this->transport->bap_big); + node_group = node_group_buf; + } + struct spa_dict_item node_info_items = { { SPA_KEY_DEVICE_API, "bluez5" }, { SPA_KEY_MEDIA_CLASS, this->is_internal ? "Audio/Sink/Internal" : @@ -1412,6 +1427,7 @@ { "media.name", ((this->transport && this->transport->device->name) ? this->transport->device->name : this->codec->bap ? "BAP" : "A2DP" ) }, { SPA_KEY_NODE_DRIVER, this->is_output ? "true" : "false" }, + { "node.group", node_group }, }; uint64_t old = full ? this->info.change_mask : 0; if (full)
View file
pipewire-0.3.84.tar.gz/spa/plugins/libcamera/libcamera-device.cpp -> pipewire-0.3.85.tar.gz/spa/plugins/libcamera/libcamera-device.cpp
Changed
@@ -106,7 +106,7 @@ uint32_t n_items = 0; struct spa_device_info info; struct spa_param_info params2; - char path256, model256, name256, devices_str128; + char path256, name256, devices_str128; struct spa_strbuf buf; info = SPA_DEVICE_INFO_INIT(); @@ -123,9 +123,10 @@ if (auto location = cameraLoc(impl->camera.get())) ADD_ITEM(SPA_KEY_API_LIBCAMERA_LOCATION, location); - snprintf(model, sizeof(model), "%s", cameraModel(impl->camera.get()).c_str()); - ADD_ITEM(SPA_KEY_DEVICE_PRODUCT_NAME, model); - ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, model); + const auto model = cameraModel(impl->camera.get()); + ADD_ITEM(SPA_KEY_DEVICE_PRODUCT_NAME, model.c_str()); + ADD_ITEM(SPA_KEY_DEVICE_DESCRIPTION, model.c_str()); + snprintf(name, sizeof(name), "libcamera_device.%s", impl->device_id.c_str()); ADD_ITEM(SPA_KEY_DEVICE_NAME, name);
View file
pipewire-0.3.84.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.85.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -31,6 +31,8 @@ rt.prio = 65 #rt.time.soft = -1 #rt.time.hard = -1 + #uclamp.min = 0 + #uclamp.max = 1024 } flags = ifexists nofail }
View file
pipewire-0.3.84.tar.gz/src/daemon/pipewire.conf.in -> pipewire-0.3.85.tar.gz/src/daemon/pipewire.conf.in
Changed
@@ -90,13 +90,16 @@ # Uses realtime scheduling to boost the audio thread priorities. This uses # RTKit if the user doesn't have permission to use regular realtime - # scheduling. + # scheduling. You can also clamp utilisation values to improve scheduling + # on embedded and heterogeneous systems, e.g. Arm big.LITTLE devices. { name = libpipewire-module-rt args = { nice.level = -11 #rt.prio = 88 #rt.time.soft = -1 #rt.time.hard = -1 + #uclamp.min = 0 + #uclamp.max = 1024 } flags = ifexists nofail }
View file
pipewire-0.3.84.tar.gz/src/daemon/systemd/system/meson.build -> pipewire-0.3.85.tar.gz/src/daemon/systemd/system/meson.build
Changed
@@ -3,7 +3,7 @@ systemd_system_services_dir = get_option('systemd-system-unit-dir') endif -install_data(sources : 'pipewire.socket', +install_data(sources : 'pipewire.socket', 'pipewire-manager.socket', install_dir : systemd_system_services_dir) systemd_config = configuration_data()
View file
pipewire-0.3.85.tar.gz/src/daemon/systemd/system/pipewire-manager.socket
Added
@@ -0,0 +1,13 @@ +Unit +Description=PipeWire Multimedia System Manager Socket + +Socket +Service=pipewire.service +Priority=6 +ListenStream=%t/pipewire/pipewire-0-manager +SocketUser=pipewire +SocketGroup=pipewire +SocketMode=0600 + +Install +WantedBy=sockets.target
View file
pipewire-0.3.84.tar.gz/src/daemon/systemd/system/pipewire.service.in -> pipewire-0.3.85.tar.gz/src/daemon/systemd/system/pipewire.service.in
Changed
@@ -31,5 +31,5 @@ Environment=PIPEWIRE_RUNTIME_DIR=%t/pipewire Install -Also=pipewire.socket +Also=pipewire.socket pipewire-manager.socket WantedBy=default.target
View file
pipewire-0.3.84.tar.gz/src/daemon/systemd/system/pipewire.socket -> pipewire-0.3.85.tar.gz/src/daemon/systemd/system/pipewire.socket
Changed
@@ -1,10 +1,9 @@ Unit -Description=PipeWire Multimedia System Sockets +Description=PipeWire Multimedia System Socket Socket Priority=6 ListenStream=%t/pipewire/pipewire-0 -ListenStream=%t/pipewire/pipewire-0-manager SocketUser=pipewire SocketGroup=pipewire SocketMode=0660
View file
pipewire-0.3.84.tar.gz/src/gst/gstpipewiresink.c -> pipewire-0.3.85.tar.gz/src/gst/gstpipewiresink.c
Changed
@@ -532,8 +532,13 @@ pw_stream_trigger_process (pwsink->stream); break; case PW_STREAM_STATE_ERROR: - GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED, - ("stream error: %s", error), (NULL)); + /* make the error permanent, if it is not already; + pw_stream_set_error() will recursively call us again */ + if (pw_stream_get_state (pwsink->stream, NULL) != PW_STREAM_STATE_ERROR) + pw_stream_set_error (pwsink->stream, -EPIPE, "%s", error); + else + GST_ELEMENT_ERROR (pwsink, RESOURCE, FAILED, + ("stream error: %s", error), (NULL)); break; } pw_thread_loop_signal (pwsink->core->loop, FALSE);
View file
pipewire-0.3.84.tar.gz/src/gst/gstpipewiresrc.c -> pipewire-0.3.85.tar.gz/src/gst/gstpipewiresrc.c
Changed
@@ -681,9 +681,13 @@ case PW_STREAM_STATE_STREAMING: break; case PW_STREAM_STATE_ERROR: - pw_stream_set_error (pwsrc->stream, -EPIPE, "%s", error); - GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, - ("stream error: %s", error), (NULL)); + /* make the error permanent, if it is not already; + pw_stream_set_error() will recursively call us again */ + if (pw_stream_get_state (pwsrc->stream, NULL) != PW_STREAM_STATE_ERROR) + pw_stream_set_error (pwsrc->stream, -EPIPE, "%s", error); + else + GST_ELEMENT_ERROR (pwsrc, RESOURCE, FAILED, + ("stream error: %s", error), (NULL)); break; } pw_thread_loop_signal (pwsrc->core->loop, FALSE);
View file
pipewire-0.3.84.tar.gz/src/modules/meson.build -> pipewire-0.3.85.tar.gz/src/modules/meson.build
Changed
@@ -218,8 +218,10 @@ summary({'ffado-driver': build_module_ffado_driver}, bool_yn: true, section: 'Optional Modules') opus_custom_h = cc.has_header('opus/opus_custom.h', dependencies: opus_dep) +opus_custom_lib = cc.has_function('opus_custom_encoder_ctl', dependencies: opus_dep) + # One would imagine that opus_dep is a requirement but for some reason it's not, so we need to manually check that -if opus_dep.found() and opus_custom_h +if opus_dep.found() and opus_custom_h and opus_custom_lib opus_custom_dep = declare_dependency(compile_args: '-DHAVE_OPUS_CUSTOM', dependencies: opus_dep) else opus_custom_dep = dependency('', required: false)
View file
pipewire-0.3.84.tar.gz/src/modules/module-pipe-tunnel.c -> pipewire-0.3.85.tar.gz/src/modules/module-pipe-tunnel.c
Changed
@@ -40,6 +40,7 @@ * ## Module Options * * - `tunnel.mode`: the desired tunnel to create. (Default `playback`) + * - `tunnel.may-pause`: if the tunnel stream is allowed to pause on xrun * - `pipe.filename`: the filename of the pipe. * - `stream.props`: Extra properties for the local stream. * @@ -55,6 +56,12 @@ * When `tunnel.mode` is `source`, a source node is created. Samples read from * the the pipe will be made available on the source. * + * `tunnel.may-pause` allows the tunnel stream to become inactive (paused) when + * there is no data in the fifo or when the fifo is full. For `capture` and + * `playback` `tunnel.mode` this is by default true. For `source` and `sink` + * `tunnel.mode`, this is by default false. A paused stream will consume no + * CPU and will resume when the fifo becomes readable or writable again. + * * When `pipe.filename` is not given, a default fifo in `/tmp/fifo_input` or * `/tmp/fifo_output` will be created that can be written and read respectively, * depending on the selected `tunnel.mode`. @@ -86,6 +93,7 @@ * { name = libpipewire-module-pipe-tunnel * args = { * tunnel.mode = playback + * #tunnel.may-pause = true * # Set the pipe name to tunnel to * pipe.filename = "/tmp/fifo_output" * #audio.format=<sample format> @@ -128,6 +136,7 @@ "( audio.channels=<number of channels> ) " \ "( audio.position=<channel map> ) " \ "( tunnel.mode=capture|playback|sink|source )" \ + "( tunnel.may-pause=<bool, if the stream can pause> )" \ "( pipe.filename=<filename> )" \ "( stream.props=<properties> ) " @@ -141,6 +150,7 @@ struct impl { struct pw_context *context; + struct pw_loop *main_loop; struct pw_loop *data_loop; #define MODE_PLAYBACK 0 @@ -174,6 +184,8 @@ unsigned int do_disconnect:1; unsigned int driving:1; unsigned int have_sync:1; + unsigned int may_pause:1; + unsigned int paused:1; struct spa_ringbuffer ring; void *buffer; @@ -262,7 +274,7 @@ break; case PW_STREAM_STATE_PAUSED: if (impl->direction == PW_DIRECTION_OUTPUT) { - pw_loop_update_io(impl->data_loop, impl->socket, 0); + pw_loop_update_io(impl->data_loop, impl->socket, impl->paused ? SPA_IO_IN : 0); set_timeout(impl, 0); } break; @@ -281,6 +293,26 @@ } } +static int do_pause(struct spa_loop *loop, bool async, uint32_t seq, const void *data, + size_t size, void *user_data) +{ + struct impl *impl = user_data; + const bool *paused = data; + pw_log_info("set paused: %d", *paused); + impl->paused = *paused; + pw_stream_set_active(impl->stream, !*paused); + return 0; +} + +static void pause_stream(struct impl *impl, bool paused) +{ + if (!impl->may_pause) + return; + if (impl->direction == PW_DIRECTION_INPUT) + pw_loop_update_io(impl->data_loop, impl->socket, paused ? SPA_IO_OUT : 0); + pw_loop_invoke(impl->main_loop, do_pause, 1, &paused, sizeof(bool), false, impl); +} + static void playback_stream_process(void *data) { struct impl *impl = data; @@ -308,8 +340,8 @@ continue; } else if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Don't continue writing */ - pw_log_debug("pipe (%s) overrun: %m", - impl->filename); + pw_log_debug("pipe (%s) overrun: %m", impl->filename); + pause_stream(impl, true); break; } else { pw_log_warn("Failed to write to pipe (%s): %m", @@ -370,8 +402,10 @@ if (avail < (int32_t)size) { memset(bd->data, 0, size); - if (avail > 0) + if (avail >= 0) { pw_log_warn("underrun %d < %u", avail, size); + pause_stream(impl, true); + } impl->have_sync = false; } if (avail > (int32_t)RINGBUFFER_SIZE) { @@ -456,6 +490,8 @@ paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &impl->info); + impl->paused = false; + if ((res = pw_stream_connect(impl->stream, impl->direction, PW_ID_ANY, @@ -550,6 +586,8 @@ pw_loop_update_io(impl->data_loop, impl->socket, 0); return; } + if (impl->paused) + pause_stream(impl, false); if (mask & SPA_IO_IN) handle_pipe_read(impl); } @@ -839,6 +877,7 @@ impl->module = module; impl->context = context; + impl->main_loop = pw_context_get_main_loop(context); data_loop = pw_context_get_data_loop(context); impl->data_loop = pw_data_loop_get_loop(data_loop); @@ -848,22 +887,28 @@ if (spa_streq(str, "capture")) { impl->mode = MODE_CAPTURE; impl->direction = PW_DIRECTION_INPUT; + impl->may_pause = true; } else if (spa_streq(str, "playback")) { impl->mode = MODE_PLAYBACK; impl->direction = PW_DIRECTION_OUTPUT; + impl->may_pause = true; }else if (spa_streq(str, "sink")) { impl->mode = MODE_SINK; impl->direction = PW_DIRECTION_INPUT; + impl->may_pause = false; media_class = "Audio/Sink"; } else if (spa_streq(str, "source")) { impl->mode = MODE_SOURCE; impl->direction = PW_DIRECTION_OUTPUT; + impl->may_pause = false; media_class = "Audio/Source"; } else { pw_log_error("invalid tunnel.mode '%s'", str); res = -EINVAL; goto error; } + if ((str = pw_properties_get(props, "tunnel.may-pause")) != NULL) + impl->may_pause = spa_atob(str); if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL) pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
View file
pipewire-0.3.84.tar.gz/src/modules/module-protocol-native.c -> pipewire-0.3.85.tar.gz/src/modules/module-protocol-native.c
Changed
@@ -1489,6 +1489,7 @@ { struct pw_core *core = proxy->core; struct client *impl = SPA_CONTAINER_OF(core->conn, struct client, this); + ensure_loop(impl->context->main_loop); assert_single_pod(builder); marshal_core_footers(&impl->footer_state, core, builder); return core->send_seq = pw_protocol_native_connection_end(impl->connection, builder); @@ -1518,6 +1519,7 @@ { struct client_data *data = resource->client->user_data; struct pw_impl_client *client = resource->client; + ensure_loop(client->context->main_loop); assert_single_pod(builder); marshal_client_footers(&data->footer_state, client, builder); return client->send_seq = pw_protocol_native_connection_end(data->connection, builder);
View file
pipewire-0.3.84.tar.gz/src/modules/module-raop-sink.c -> pipewire-0.3.85.tar.gz/src/modules/module-raop-sink.c
Changed
@@ -1854,6 +1854,8 @@ if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL) pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s", hostname, ip, port); + if (pw_properties_get(props, PW_KEY_MEDIA_NAME) == NULL) + pw_properties_setf(props, PW_KEY_MEDIA_NAME, "RAOP to %s", name); if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL) pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, "%s", name); if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL) @@ -1891,6 +1893,7 @@ copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); copy_props(impl, props, PW_KEY_MEDIA_FORMAT); + copy_props(impl, props, PW_KEY_MEDIA_NAME); copy_props(impl, props, "net.mtu"); copy_props(impl, props, "rtp.sender-ts-offset"); copy_props(impl, props, "sess.media");
View file
pipewire-0.3.84.tar.gz/src/modules/module-rt.c -> pipewire-0.3.85.tar.gz/src/modules/module-rt.c
Changed
@@ -82,6 +82,8 @@ * - `rlimits.enabled`: enable the use of rtlimits, default true. * - `rtportal.enabled`: enable the use of realtime portal, default true * - `rtkit.enabled`: enable the use of rtkit, default true + * - `uclamp.min`: the minimum utilisation value the scheduler should consider + * - `uclamp.max`: the maximum utilisation value the scheduler should consider * The nice level is by default set to an invalid value so that clients don't * automatically have the nice level raised. @@ -101,6 +103,8 @@ * #rlimits.enabled = true * #rtportal.enabled = true * #rtkit.enabled = true + * #uclamp.min = 0 + * #uclamp.max = 1024 * } * flags = ifexists nofail * } @@ -131,13 +135,18 @@ #define DEFAULT_RT_TIME_SOFT -1 #define DEFAULT_RT_TIME_HARD -1 +#define DEFAULT_UCLAMP_MIN 0 +#define DEFAULT_UCLAMP_MAX 1024 + #define MODULE_USAGE "( nice.level=<priority: default "SPA_STRINGIFY(DEFAULT_NICE_LEVEL)"(don't change)> ) " \ "( rt.prio=<priority: default "SPA_STRINGIFY(DEFAULT_RT_PRIO)"> ) " \ "( rt.time.soft=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_SOFT)"> ) " \ "( rt.time.hard=<in usec: default "SPA_STRINGIFY(DEFAULT_RT_TIME_HARD)"> ) " \ "( rlimits.enabled=<default true> ) " \ "( rtportal.enabled=<default true> ) " \ - "( rtkit.enabled=<default true> ) " + "( rtkit.enabled=<default true> ) " \ + "( uclamp.min=<default "SPA_STRINGIFY(DEFAULT_UCLAMP_MIN)"> ) " \ + "( uclamp.max=<default "SPA_STRINGIFY(DEFAULT_UCLAMP_MAX)"> )" static const struct spa_dict_item module_props = { { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, @@ -183,6 +192,9 @@ rlim_t rt_time_soft; rlim_t rt_time_hard; + int uclamp_min; + int uclamp_max; + struct spa_hook module_listener; unsigned rlimits_enabled:1; @@ -537,6 +549,8 @@ int err, old_policy, new_policy, min, max; struct sched_param old_sched_params; struct sched_param new_sched_params; + struct rlimit old_rlim; + struct rlimit no_rlim = { -1, -1 }; int try = 0; if (!impl->rlimits_enabled) @@ -584,11 +598,21 @@ if ((old_policy & PW_SCHED_RESET_ON_FORK) != 0) new_policy |= PW_SCHED_RESET_ON_FORK; + /* Disable RLIMIT_RTTIME while trying new_policy. */ + if ((err = getrlimit(RLIMIT_RTTIME, &old_rlim)) < 0) + pw_log_debug("getrlimit() failed: %s", spa_strerror(err)); + if ((err = setrlimit(RLIMIT_RTTIME, &no_rlim)) < 0) + pw_log_debug("setrlimit() failed: %s", spa_strerror(err)); + if (pthread_setschedparam(pthread_self(), new_policy, &new_sched_params) == 0) { impl->rt_prio = new_sched_params.sched_priority; pthread_setschedparam(pthread_self(), old_policy, &old_sched_params); + if ((err = setrlimit(RLIMIT_RTTIME, &old_rlim)) < 0) + pw_log_debug("setrlimit() failed: %s", spa_strerror(err)); return true; } + if ((err = setrlimit(RLIMIT_RTTIME, &old_rlim)) < 0) + pw_log_debug("setrlimit() failed: %s", spa_strerror(err)); } pw_log_info("Can't set rt prio to %d: %m (try increasing rlimits)", (int)priority); return false; @@ -636,18 +660,18 @@ return res; } -static int set_rlimit(struct impl *impl) +static int set_rlimit(struct rlimit *rlim) { int res = 0; - if (setrlimit(RLIMIT_RTTIME, &impl->rl) < 0) + if (setrlimit(RLIMIT_RTTIME, rlim) < 0) res = -errno; if (res < 0) pw_log_debug("setrlimit() failed: %s", spa_strerror(res)); else pw_log_debug("rt.time.soft:%"PRIi64" rt.time.hard:%"PRIi64, - (int64_t)impl->rl.rlim_cur, (int64_t)impl->rl.rlim_max); + (int64_t)rlim->rlim_cur, (int64_t)rlim->rlim_max); return res; } @@ -1011,12 +1035,56 @@ impl->rl.rlim_cur = SPA_MIN(impl->rl.rlim_cur, impl->rttime_max); impl->rl.rlim_max = SPA_MIN(impl->rl.rlim_max, impl->rttime_max); - set_rlimit(impl); + set_rlimit(&impl->rl); return 0; } #endif /* HAVE_DBUS */ +int set_uclamp(int uclamp_min, int uclamp_max, pid_t pid) { +#ifdef __linux__ + int ret; + struct sched_attr { + uint32_t size; + uint32_t sched_policy; + uint64_t sched_flags; + int32_t sched_nice; + uint32_t sched_priority; + uint64_t sched_runtime; + uint64_t sched_deadline; + uint64_t sched_period; + uint32_t sched_util_min; + uint32_t sched_util_max; + } attr; + + ret = syscall(SYS_sched_getattr, pid, &attr, sizeof(struct sched_attr), 0); + if (ret) { + pw_log_warn("Could not retrieve scheduler attributes: %d", -errno); + return -errno; + } + + /* SCHED_FLAG_KEEP_POLICY | + * SCHED_FLAG_KEEP_PARAMS | + * SCHED_FLAG_UTIL_CLAMP_MIN | + * SCHED_FLAG_UTIL_CLAMP_MAX */ + attr.sched_flags = 0x8 | 0x10 | 0x20 | 0x40; + attr.sched_util_min = uclamp_min; + attr.sched_util_max = uclamp_max; + + ret = syscall(SYS_sched_setattr, pid, &attr, 0); + + if (ret) { + pw_log_warn("Could not set scheduler attributes: %d", -errno); + return -errno; + } + return 0; +#else + pw_log_warn("Setting UCLAMP values is only supported on Linux"); + return -EOPNOTSUPP; +#endif /* __linux__ */ +} + + SPA_EXPORT int pipewire__module_init(struct pw_impl_module *module, const char *args) { @@ -1047,6 +1115,8 @@ impl->rlimits_enabled = pw_properties_get_bool(props, "rlimits.enabled", true); impl->rtportal_enabled = pw_properties_get_bool(props, "rtportal.enabled", true); impl->rtkit_enabled = pw_properties_get_bool(props, "rtkit.enabled", true); + impl->uclamp_min = pw_properties_get_int32(props, "uclamp.min", DEFAULT_UCLAMP_MIN); + impl->uclamp_max = pw_properties_get_int32(props, "uclamp.max", DEFAULT_UCLAMP_MAX); impl->rl.rlim_cur = impl->rt_time_soft; impl->rl.rlim_max = impl->rt_time_hard; @@ -1086,7 +1156,15 @@ use_rtkit = can_use_rtkit; } if (!use_rtkit) - set_rlimit(impl); + set_rlimit(&impl->rl); + + if (impl->uclamp_max > 1024) { + pw_log_warn("uclamp.max out of bounds. Got %d, clamping to 1024.", impl->uclamp_max); + impl->uclamp_max = 1024; + } + + if (impl->uclamp_min || impl->uclamp_max < 1024) + set_uclamp(impl->uclamp_min, impl->uclamp_max, impl->main_pid); #ifdef HAVE_DBUS impl->use_rtkit = use_rtkit;
View file
pipewire-0.3.84.tar.gz/src/pipewire/context.c -> pipewire-0.3.85.tar.gz/src/pipewire/context.c
Changed
@@ -32,6 +32,8 @@ PW_LOG_TOPIC_EXTERN(log_context); #define PW_LOG_TOPIC_DEFAULT log_context +#define MAX_HOPS 64 + /** \cond */ struct impl { struct pw_context this; @@ -791,12 +793,17 @@ * and groups to active nodes and make them recursively runnable as well. */ static inline int run_nodes(struct pw_context *context, struct pw_impl_node *node, - struct spa_list *nodes, enum pw_direction direction) + struct spa_list *nodes, enum pw_direction direction, int hop) { struct pw_impl_node *t; struct pw_impl_port *p; struct pw_impl_link *l; + if (hop == MAX_HOPS) { + pw_log_warn("exceeded hops (%d)", hop); + return -EIO; + } + pw_log_debug("node %p: '%s' direction:%s", node, node->name, pw_direction_as_string(direction)); @@ -810,10 +817,12 @@ if (!t->active || !l->prepared || (!t->driving && SPA_FLAG_IS_SET(t->checked, 1u<<direction))) continue; + if (t->driving && p->node == t) + continue; pw_log_debug(" peer %p: '%s'", t, t->name); t->runnable = true; - run_nodes(context, t, nodes, direction); + run_nodes(context, t, nodes, direction, hop + 1); } } } else { @@ -824,10 +833,12 @@ if (!t->active || !l->prepared || (!t->driving && SPA_FLAG_IS_SET(t->checked, 1u<<direction))) continue; + if (t->driving && p->node == t) + continue; pw_log_debug(" peer %p: '%s'", t, t->name); t->runnable = true; - run_nodes(context, t, nodes, direction); + run_nodes(context, t, nodes, direction, hop + 1); } } } @@ -847,7 +858,7 @@ pw_log_debug(" group %p: '%s'", t, t->name); t->runnable = true; if (!t->driving) - run_nodes(context, t, nodes, direction); + run_nodes(context, t, nodes, direction, hop + 1); } } return 0; @@ -950,8 +961,8 @@ } spa_list_for_each(n, collect, sort_link) if (!n->driving && n->runnable) { - run_nodes(context, n, collect, PW_DIRECTION_OUTPUT); - run_nodes(context, n, collect, PW_DIRECTION_INPUT); + run_nodes(context, n, collect, PW_DIRECTION_OUTPUT, 0); + run_nodes(context, n, collect, PW_DIRECTION_INPUT, 0); } return 0;
View file
pipewire-0.3.84.tar.gz/src/pipewire/impl-client.h -> pipewire-0.3.85.tar.gz/src/pipewire/impl-client.h
Changed
@@ -13,6 +13,8 @@ /** \page page_client_impl Client Implementation * + * \see \ref pw_impl_client + * * \section sec_page_client_impl_overview Overview * * The \ref pw_impl_client object is created by a protocol implementation when @@ -51,7 +53,7 @@ * Each client has its own list of resources it is bound to along with * a mapping between the client types and server types. * - * See: \ref page_client_impl + * \see \ref page_client_impl */ /**
View file
pipewire-0.3.84.tar.gz/src/pipewire/impl-link.c -> pipewire-0.3.85.tar.gz/src/pipewire/impl-link.c
Changed
@@ -884,9 +884,11 @@ impl->activated = false; pw_log_info("(%s) deactivated", this->name); - link_update_state(this, this->destroyed ? - PW_LINK_STATE_INIT : PW_LINK_STATE_PAUSED, - 0, NULL); + + if (this->info.state < PW_LINK_STATE_PAUSED || this->destroyed) + link_update_state(this, PW_LINK_STATE_INIT, 0, NULL); + else + link_update_state(this, PW_LINK_STATE_PAUSED, 0, NULL); return 0; }
View file
pipewire-0.3.84.tar.gz/src/pipewire/proxy.h -> pipewire-0.3.85.tar.gz/src/pipewire/proxy.h
Changed
@@ -13,6 +13,8 @@ /** \page page_proxy Proxy * + * \see \ref pw_proxy + * * \section sec_page_proxy_overview Overview * * The proxy object is a client side representation of a resource @@ -76,7 +78,7 @@ * invoked by the client to PipeWire messages. Events will call the handlers * set in listener. * - * See \ref page_proxy + * \see \ref page_proxy */ /**
View file
pipewire-0.3.84.tar.gz/src/pipewire/stream.h -> pipewire-0.3.85.tar.gz/src/pipewire/stream.h
Changed
@@ -11,6 +11,8 @@ /** \page page_streams Streams * + * \see \ref pw_stream + * * \section sec_overview Overview * * \ref pw_stream "Streams" are used to exchange data with the @@ -162,7 +164,7 @@ * The stream object provides a convenient way to send and * receive data streams from/to PipeWire. * - * See also \ref page_streams and \ref api_pw_core + * \see \ref page_streams, \ref api_pw_core */ /**
View file
pipewire-0.3.84.tar.gz/src/pipewire/thread-loop.h -> pipewire-0.3.85.tar.gz/src/pipewire/thread-loop.h
Changed
@@ -13,6 +13,8 @@ /** \page page_thread_loop Thread Loop * + * \see \ref pw_thread_loop + * * \section sec_thread_loop_overview Overview * * The threaded loop implementation is a special wrapper around the @@ -68,7 +70,7 @@ * All of the loop callbacks will be executed with the loop * lock held. * - * See also \ref page_thread_loop + * \see \ref page_thread_loop */ /**
View file
pipewire-0.3.84.tar.gz/src/pipewire/utils.c -> pipewire-0.3.85.tar.gz/src/pipewire/utils.c
Changed
@@ -162,7 +162,7 @@ * \since 0.3.84 */ SPA_EXPORT -int pw_strv_find(char **a, char *b) +int pw_strv_find(char **a, const char *b) { int i; if (a == NULL || b == NULL)
View file
pipewire-0.3.84.tar.gz/src/pipewire/utils.h -> pipewire-0.3.85.tar.gz/src/pipewire/utils.h
Changed
@@ -48,7 +48,7 @@ char **pw_strv_parse(const char *val, size_t len, int max_tokens, int *n_tokens); -int pw_strv_find(char **a, char *b); +int pw_strv_find(char **a, const char *b); int pw_strv_find_common(char **a, char **b);
View file
pipewire-0.3.84.tar.gz/src/tools/pw-top.c -> pipewire-0.3.85.tar.gz/src/tools/pw-top.c
Changed
@@ -282,7 +282,7 @@ } static const struct pw_node_events node_events = { - PW_VERSION_NODE, + PW_VERSION_NODE_EVENTS, .info = node_info, .param = node_param, };
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
.