Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 33
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Wed Aug 30 13:49:39 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 0.3.79 + +------------------------------------------------------------------- Wed Aug 9 15:43:07 UTC 2023 - Bjørn Lie <zaitor@opensuse.org> - Update to version 0.3.77
View file
pipewire-aptx.spec
Changed
@@ -7,7 +7,7 @@ %define soversion 0_2 Name: pipewire-aptx -Version: 0.3.77 +Version: 0.3.79 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
pipewire-0.3.77.tar.gz/NEWS -> pipewire-0.3.79.tar.gz/NEWS
Changed
@@ -1,3 +1,111 @@ +# PipeWire 0.3.79 (2023-08-29) + +This is a quick bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - Fix a regression in suspend that could cause silence. + - Fix a regression in JACK port registration that could cause all kinds of + JACK problems. (#3485) + - Fix a typo in the neon sample conversion functions that could cause + distortion. + - Add BAP broadcast source and sink support. + - pw-top now has a batch mode to dump the output to stdout. + - Many more bugfixes and improvements. + + +## PipeWire + - Fix a regression in shutdown where a node might not first suspend + properly. This cause loss of sound in some cases. (#3378) + - Failure to compile a regular expression in the config file will now + be reported and ! can be used to negate the match. (#3460) + - Fix a regression where some nodes might not set running in some + cases. + - Nodes are now suspended before the format is cleared, which might + fix some crashes. + +## Tools + - pw-top now has a batch mode to dump the output to stdout. + +## SPA + - The queued samples in audioconvert are now correctly reported in the + delay. (#3454) + - Make it easier to add a custom profile in ACP. + - Fix a typo in the neon sample conversion functions that could cause + distortion. (#3463) + - device.profile.pro=true is added for pro audio nodes. + - An xrun counter was added to spa_io_clock to detect and track skipped + data because of xruns. + +## Pulse-server + - Add alsa-sink and alsa-source modules. (#3456) + +## Bluetooth + - Fix a regression where only the BAP off profile is shown. + - Add BAP broadcast source and sink support. + +## JACK + - Also emit a latency notify when the buffer size changes. + - Fix a regression in JACK port registration. (#3485) + - jack_port_tie() is now supported. + +## ALSA + - Improve property handling, support lists and ranges in addition to + fixed values. (#3451) + +Older versions: + + +# PipeWire 0.3.78 (2023-08-22) + +This is a small bugfix release that is API and ABI compatible with previous +0.3.x releases. + +## Highlights + - An old regression was fixed with where some nodes would not run. + - A regression was fixed where removed events would not be shown in some + cases. This would result in duplicate entries in audio clients. + - Fix an off-by-one in the vban audio receiver. Tweak the rate adaption + a little. + - ACP will now set a UCM verb before probing the pro-audio devices. + - More bugfixes and improvements. + + +## PipeWire + - An old regression was fixed with where some nodes would not run. (#3405) + - Suspend was improved a little to avoid races when the session manager would + suspend right when a driver was starting. + +## Modules + - module-rtp-sap does not use the deprecated inet_aton anymore. + - Fix an off-by-one in the vban audio receiver. Tweak the rate adaption + a little. (#3380) + +## SPA + - ACP will now set a UCM verb before probing the pro-audio devices. (#3407) + - The mandatory flag will be set now on the video modifiers. + - EVL was updated to Xenomai4 r46 and xbuf creation was improved. + - An option was added to force colors in the log even when logging to !tty. + - The return type of spa_pod_builder_control() was fixed. + - inotify errors are handled better now. (#3439) + +## pulse-server + - A regression was fixed where removed events would not be shown in some + cases. (#3414) + +## Bluetooth + - Improve compatibility with more devices, avoid reusing the same transport + for different media-sink instances to avoid encoder resets. + - Improve enumeration of codec profiles for BAP and A2DP. + +## JACK + - Ensure we can't iterate ports from a deactivated client. Also make sure + the JACK clients with the node.always-process=false always show their + ports. (#3416) + +## GStreamer + - A potential crash was fixed in the device provider when stopping. + # PipeWire 0.3.77 (2023-08-04) This is a quick bugfix release that is API and ABI compatible with previous @@ -49,9 +157,6 @@ ## bluetooth - Use some more autoptr cleanups, fix some leaks. -Older versions: - - # PipeWire 0.3.76 (2023-07-28) This is a quick bugfix release that is API and ABI compatible with previous
View file
pipewire-0.3.77.tar.gz/doc/dma-buf.dox -> pipewire-0.3.79.tar.gz/doc/dma-buf.dox
Changed
@@ -1,7 +1,7 @@ /** \page page_dma_buf DMA-BUF Sharing PipeWire supports sharing Direct Memory Access buffers (DMA-BUFs) between -clients via the `SPA_DATA_DmaBuf` data type. However properly negotiating +clients via the \ref SPA_DATA_DmaBuf data type. However properly negotiating DMA-BUF support on both the producer and the consumer side require following a specific procedure. This page describes said procedure by using events and methods from the filter or stream API. @@ -21,37 +21,37 @@ ## pw_stream_connect -The stream parameters should contain two `SPA_PARAM_EnumFormat` objects for +The stream parameters should contain two \ref SPA_PARAM_EnumFormat objects for each format: one for DMA-BUFs, one for shared memory buffers as a fallback. Query the list of all supported modifiers from your graphics API of choice. -Add a `SPA_FORMAT_VIDEO_modifier` property to the first stream parameter with +Add a \ref SPA_FORMAT_VIDEO_modifier property to the first stream parameter with the flags `SPA_POD_PROP_FLAG_MANDATORY | SPA_POD_PROP_FLAG_DONT_FIXATE`. The -value of the property should be set to a `SPA_CHOICE_Enum` containing one +value of the property should be set to a \ref SPA_CHOICE_Enum containing one `long` choice per supported modifier, plus `DRM_FORMAT_MOD_INVALID` if the graphics API supports modifier-less buffers. Note: When a producer is only supporting modifier-less buffers it can omit -the `SPA_POD_PROP_FLAG_DONT_FIXATE` (see param_changed hook, For producers). +the \ref SPA_POD_PROP_FLAG_DONT_FIXATE (see param_changed hook, For producers). -The second stream parameter should not contain any `SPA_FORMAT_VIDEO_modifier` +The second stream parameter should not contain any \ref SPA_FORMAT_VIDEO_modifier property. -To prioritise DMA-BUFs place those `SPA_PARAM_EnumFormat` containing modifiers +To prioritise DMA-BUFs place those \ref SPA_PARAM_EnumFormat containing modifiers first, when emitting them to PipeWire. ## param_changed Hook -When the `param_changed` hook is called for a `SPA_PARAM_Format` the client +When the `param_changed` hook is called for a \ref SPA_PARAM_Format the client has to parse the `spa_pod` directly. Use `spa_pod_find_prop(param, NULL, SPA_FORMAT_VIDEO_modifier)` to check whether modifiers were negotiated. If they were negotiated, set the -`SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_DmaBuf`. If they were +\ref SPA_PARAM_BUFFERS_dataType property to `1 << SPA_DATA_DmaBuf`. If they were not negotiated, fall back to shared memory by setting the -`SPA_PARAM_BUFFERS_dataType` property to `1 << SPA_DATA_MemFd`, +\ref SPA_PARAM_BUFFERS_dataType property to `1 << SPA_DATA_MemFd`, `1 << SPA_DATA_MemPtr`, or both. -While consumers only have to parse the resulting `SPA_PARAM_Format` for any +While consumers only have to parse the resulting \ref SPA_PARAM_Format for any format related information, it's up to the producer to fixate onto a single format modifier pair. The producer is also responsible to check if all clients announce sufficient capabilities or fallback to shared memory buffers when @@ -59,7 +59,7 @@ ### For Consumers -Use `spa_format_video_raw_parse` to get the format and modifier. +Use \ref spa_format_video_raw_parse to get the format and modifier. ### For Producers @@ -70,28 +70,28 @@ - modifier-less: In this case only the modifier `DRM_FORMAT_MOD_INVALID` was announced with the format. - It is sufficient to check if the `SPA_PARAM_Format` contains the modifier + It is sufficient to check if the \ref SPA_PARAM_Format contains the modifier property as described above. If that is the case, use DMA-BUFs for screen-sharing, else fall back to SHM, if possible. - modifier-aware: In this case a list with all supported modifiers will be returned in the format. (using `DRM_FORMAT_MOD_INVALID` as the token for the modifier-less API). On the `param_changed` event check if the modifier key is present and has the flag - `SPA_POD_PROP_FLAG_DONT_FIXATE` attached to it. In this case, extract all modifiers + \ref SPA_POD_PROP_FLAG_DONT_FIXATE attached to it. In this case, extract all modifiers from the list and do a test allocation with your allocator to choose the preferred - modifier. Fixate on that `EnumFormat` by announcing a `SPA_PARAM_EnumFormat` with - only one modifier in the `SPA_CHOICE_Enum` and without the - `SPA_POD_PROP_FLAG_DONT_FIXATE` flag, followed by the previous announced - `EnumFormat`. This will retrigger the `param_changed` event with an - `SPA_PARAM_Format` as described below. - If the `SPA_PARAM_Format` contains a modifier key, without the flag - `SPA_POD_PROP_FLAG_DONT_FIXATE`, it should only contain one value in the - `SPA_CHOICE_Enum`. In this case announce the `SPA_PARAM_Buffers` accordingly + modifier. Fixate on that \ref EnumFormat by announcing a \ref SPA_PARAM_EnumFormat with + only one modifier in the \ref SPA_CHOICE_Enum and without the + \ref SPA_POD_PROP_FLAG_DONT_FIXATE flag, followed by the previous announced + \ref EnumFormat. This will retrigger the `param_changed` event with an + \ref SPA_PARAM_Format as described below. + If the \ref SPA_PARAM_Format contains a modifier key, without the flag + \ref SPA_POD_PROP_FLAG_DONT_FIXATE, it should only contain one value in the + \ref SPA_CHOICE_Enum. In this case announce the \ref SPA_PARAM_Buffers accordingly to the selected format and modifier. It is important to query the plane count of the used format modifier pair and set `SPA_PARAM_BUFFERS_blocks` accordingly. Note: When test allocating a buffer, collect all possible modifiers, while omitting -`DRM_FORMAT_MOD_INVALID` from the `SPA_FORMAT_VIDEO_modifier` property and +`DRM_FORMAT_MOD_INVALID` from the \ref SPA_FORMAT_VIDEO_modifier property and pass them all to the graphics API. If the allocation fails and the list of possible modifiers contains `DRM_FORMAT_MOD_INVALID`, fall back to allocating without an explicit modifier if the graphics API allows it. @@ -106,9 +106,9 @@ This is relevant for consumers. -Check the type of the dequeued buffer. If its `SPA_DATA_MemFd` or -`SPA_DATA_MemPtr` use the fallback SHM import mechanism. -If it's `SPA_DATA_DmaBuf` +Check the type of the dequeued buffer. If its \ref SPA_DATA_MemFd or +\ref SPA_DATA_MemPtr use the fallback SHM import mechanism. +If it's \ref SPA_DATA_DmaBuf get the DMA-BUF FDs (the plane count is encoded in the `n_datas` variable of the `spa_buffer` struct) and import them with the graphics API. @@ -150,15 +150,18 @@ # SPA param video format helpers SPA offers helper functions to parse and build a spa_pod object to/from the spa_video_info_* -struct. The flags `SPA_VIDEO_FLAG_MODIFIER` and `SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED` +struct. The flags \ref SPA_VIDEO_FLAG_MODIFIER and \ref SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED are used to indicate modifier usage with the format. `SPA_VIDEO_FLAG_MODIFIER` declares the parsed/provided spa_video_info_* struct contains valid modifier information. For legacy reasons `spa_format_video_*_build` will announce any modifier != 0 even when this flag is unused. `SPA_VIDEO_FLAG_MODIFIER_FIXATION_REQUIRED` is exclusive to the parse helpers and declares that the parsed spa_pod contains modifier information which needs to be fixated as -described aboath. The list of available modifiers has to be parsed manually from the spa_pod +described above. The list of available modifiers has to be parsed manually from the spa_pod object. +- \ref spa_video_info_raw, \ref spa_format_video_raw_parse, \ref spa_format_video_raw_build +- \ref spa_video_info_dsp, \ref spa_format_video_dsp_parse, \ref spa_format_video_dsp_build + # v4l2 Another use case for streaming via DMA-BUFs are exporting a camera feed from v4l2
View file
pipewire-0.3.77.tar.gz/doc/pipewire-daemon.dox -> pipewire-0.3.79.tar.gz/doc/pipewire-daemon.dox
Changed
@@ -171,5 +171,7 @@ - `PIPEWIRE_LOG_SYSTEMD=false`: Disable logging to the systemd journal. - `PIPEWIRE_LOG=<filename>`: Redirect the log to the given filename. - `PIPEWIRE_LOG_LINE=false`: Don't log filename, function, and source code line. +- `PIPEWIRE_LOG_COLOR=true/false/force`: Enable/disable color logging, and optionally force + colors even when logging to a file. */
View file
pipewire-0.3.77.tar.gz/meson.build -> pipewire-0.3.79.tar.gz/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '0.3.77', + version : '0.3.79', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3',
View file
pipewire-0.3.77.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> pipewire-0.3.79.tar.gz/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -22,6 +22,7 @@ #include <spa/utils/atomic.h> #include <spa/utils/result.h> #include <spa/utils/string.h> +#include <spa/utils/json.h> #include <pipewire/pipewire.h> @@ -919,118 +920,199 @@ .query_chmaps = snd_pcm_pipewire_query_chmaps, }; -static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw) +#define MAX_VALS 64 +struct param_info { + const char *prop; + int key; +#define TYPE_LIST 0 +#define TYPE_MIN_MAX 1 + int type; + unsigned int valsMAX_VALS; + unsigned int n_vals; + int (*collect) (const char *str, int len, unsigned int *val); + +}; + +static int collect_access(const char *str, int len, unsigned int *val) +{ + char key64; + + if (spa_json_parse_stringn(str, len, key, sizeof(key)) <= 0) + return -EINVAL; + + if (strcasecmp(key, "MMAP_INTERLEAVED") == 0) + *val = SND_PCM_ACCESS_MMAP_INTERLEAVED; + else if (strcasecmp(key, "MMAP_NONINTERLEAVED") == 0) + *val = SND_PCM_ACCESS_MMAP_NONINTERLEAVED; + else if (strcasecmp(key, "RW_INTERLEAVED") == 0) + *val = SND_PCM_ACCESS_RW_INTERLEAVED; + else if (strcasecmp(key, "RW_NONINTERLEAVED") == 0) + *val = SND_PCM_ACCESS_RW_NONINTERLEAVED; + else + return -EINVAL; + return 0; +} + +static int collect_format(const char *str, int len, unsigned int *val) +{ + char key64; + snd_pcm_format_t fmt; + + if (spa_json_parse_stringn(str, len, key, sizeof(key)) < 0) + return -EINVAL; + + fmt = snd_pcm_format_value(key); + if (fmt != SND_PCM_FORMAT_UNKNOWN) + *val = fmt; + else + return -EINVAL; + return 0; +} + +static int collect_int(const char *str, int len, unsigned int *val) { - unsigned int access_list = { - SND_PCM_ACCESS_MMAP_INTERLEAVED, - SND_PCM_ACCESS_MMAP_NONINTERLEAVED, - SND_PCM_ACCESS_RW_INTERLEAVED, - SND_PCM_ACCESS_RW_NONINTERLEAVED - }; - unsigned int format_list = { + int v; + if (spa_json_parse_int(str, len, &v) > 0) + *val = v; + else + return -EINVAL; + return 0; +} + +struct param_info infos = { + { "alsa.access", SND_PCM_IOPLUG_HW_ACCESS, TYPE_LIST, + { SND_PCM_ACCESS_MMAP_INTERLEAVED, + SND_PCM_ACCESS_MMAP_NONINTERLEAVED, + SND_PCM_ACCESS_RW_INTERLEAVED, + SND_PCM_ACCESS_RW_NONINTERLEAVED }, 4, collect_access }, + { "alsa.format", SND_PCM_IOPLUG_HW_FORMAT, TYPE_LIST, + { #if __BYTE_ORDER == __LITTLE_ENDIAN - SND_PCM_FORMAT_FLOAT_LE, - SND_PCM_FORMAT_S32_LE, - SND_PCM_FORMAT_S24_LE, - SND_PCM_FORMAT_S24_3LE, - SND_PCM_FORMAT_S24_3BE, - SND_PCM_FORMAT_S16_LE, + SND_PCM_FORMAT_FLOAT_LE, + SND_PCM_FORMAT_S32_LE, + SND_PCM_FORMAT_S24_LE, + SND_PCM_FORMAT_S24_3LE, + SND_PCM_FORMAT_S24_3BE, + SND_PCM_FORMAT_S16_LE, #elif __BYTE_ORDER == __BIG_ENDIAN - SND_PCM_FORMAT_FLOAT_BE, - SND_PCM_FORMAT_S32_BE, - SND_PCM_FORMAT_S24_BE, - SND_PCM_FORMAT_S24_3LE, - SND_PCM_FORMAT_S24_3BE, - SND_PCM_FORMAT_S16_BE, + SND_PCM_FORMAT_FLOAT_BE, + SND_PCM_FORMAT_S32_BE, + SND_PCM_FORMAT_S24_BE, + SND_PCM_FORMAT_S24_3LE, + SND_PCM_FORMAT_S24_3BE, + SND_PCM_FORMAT_S16_BE, #endif - SND_PCM_FORMAT_U8, - }; - int val; - int min_rate; - int max_rate; - int min_channels; - int max_channels; - int min_period_bytes; - int max_period_bytes; - int min_buffer_bytes; - int max_buffer_bytes; - const char *str; - snd_pcm_format_t format; - int err; + SND_PCM_FORMAT_U8 }, 7, collect_format }, + { "alsa.rate", SND_PCM_IOPLUG_HW_RATE, TYPE_MIN_MAX, + { 1, MAX_RATE }, 2, collect_int }, + { "alsa.channels", SND_PCM_IOPLUG_HW_CHANNELS, TYPE_MIN_MAX, + { 1, MAX_CHANNELS }, 2, collect_int }, + { "alsa.buffer-bytes", SND_PCM_IOPLUG_HW_BUFFER_BYTES, TYPE_MIN_MAX, + { MIN_BUFFER_BYTES, MAX_BUFFER_BYTES }, 2, collect_int }, + { "alsa.period-bytes", SND_PCM_IOPLUG_HW_PERIOD_BYTES, TYPE_MIN_MAX, + { MIN_PERIOD_BYTES, MAX_PERIOD_BYTES }, 2, collect_int }, + { "alsa.periods", SND_PCM_IOPLUG_HW_PERIODS, TYPE_MIN_MAX, + { MIN_BUFFERS, 1024 }, 2, collect_int }, +}; - val = pw_properties_get_uint32(pw->props, "alsa.rate", 0); - if (val > 0) { - min_rate = max_rate = SPA_CLAMP(val, 1, MAX_RATE); - } else { - min_rate = 1; - max_rate = MAX_RATE; - } - val = pw_properties_get_uint32(pw->props, "alsa.channels", 0); - if (val > 0) { - min_channels = max_channels = SPA_CLAMP(val, 1, MAX_CHANNELS); - } else { - min_channels = 1; - max_channels = MAX_CHANNELS; +static struct param_info *param_info_by_key(int key) +{ + SPA_FOR_EACH_ELEMENT_VAR(infos, p) { + if (p->key == key) + return p; } - val = pw_properties_get_uint32(pw->props, "alsa.period-bytes", 0); - if (val > 0) { - min_period_bytes = max_period_bytes = SPA_CLAMP(val, - MIN_PERIOD_BYTES, MAX_PERIOD_BYTES); - } else { - min_period_bytes = MIN_PERIOD_BYTES; - max_period_bytes = MAX_PERIOD_BYTES; + return NULL; +} + +static int parse_value(const char *str, struct param_info *info) +{ + struct spa_json it2; + unsigned int v; + const char *val; + int len; + + spa_json_init(&it0, str, strlen(str)); + if ((len = spa_json_next(&it0, &val)) <= 0) + return -EINVAL; + + if (spa_json_is_array(val, len)) { + info->type = TYPE_LIST; + info->n_vals = 0; + spa_json_enter(&it0, &it1); + while ((len = spa_json_next(&it1, &val)) > 0 && info->n_vals < MAX_VALS) { + if (info->collect(val, len, &v) < 0) + continue; + info->valsinfo->n_vals++ = v; + } } - val = pw_properties_get_uint32(pw->props, "alsa.buffer-bytes", 0); - if (val > 0) { - min_buffer_bytes = max_buffer_bytes = SPA_CLAMP(val, - MIN_BUFFER_BYTES, MAX_BUFFER_BYTES); - } else { - min_buffer_bytes = MIN_BUFFER_BYTES; - max_buffer_bytes = MAX_BUFFER_BYTES; + else if (spa_json_is_object(val, len)) { + char key64; + info->type = TYPE_MIN_MAX; + info->n_vals = 2; + spa_json_enter(&it0, &it1); + while (spa_json_get_string(&it1, key, sizeof(key)) > 0) { + if ((len = spa_json_next(&it1, &val)) <= 0) + break; + if (info->collect(val, len, &v) < 0) + continue; + if (spa_streq(key, "min")) + info->vals0 = v; + else if (spa_streq(key, "max")) + info->vals1 = v; + } } - if (min_period_bytes * 2 > max_buffer_bytes) - min_period_bytes = max_period_bytes = max_buffer_bytes / 2; - - if ((err = snd_pcm_ioplug_set_param_list(&pw->io, SND_PCM_IOPLUG_HW_ACCESS, - SPA_N_ELEMENTS(access_list), access_list)) < 0 || - (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_CHANNELS, - min_channels, max_channels)) < 0 || - (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_RATE, - min_rate, max_rate)) < 0 || - (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_BUFFER_BYTES, - min_buffer_bytes, - max_buffer_bytes)) < 0 || - (err = snd_pcm_ioplug_set_param_minmax(&pw->io, - SND_PCM_IOPLUG_HW_PERIOD_BYTES, - min_period_bytes, - max_period_bytes)) < 0 || - (err = snd_pcm_ioplug_set_param_minmax(&pw->io, SND_PCM_IOPLUG_HW_PERIODS, - MIN_BUFFERS, 1024)) < 0) { - pw_log_warn("Can't set param list: %s", snd_strerror(err)); - return err; + else if (info->collect(val, len, &v) >= 0) { + info->type = TYPE_LIST; + info->vals0 = v; + info->n_vals = 1; } - format = SND_PCM_FORMAT_UNKNOWN; - if ((str = pw_properties_get(pw->props, "alsa.format"))) - format = snd_pcm_format_value(str); - - if (format != SND_PCM_FORMAT_UNKNOWN) { - err = snd_pcm_ioplug_set_param_list(&pw->io, - SND_PCM_IOPLUG_HW_FORMAT, - 1, (unsigned int *)&format); - if (err < 0) { - pw_log_warn("Can't set param list: %s", snd_strerror(err)); - return err; - } - } else { - err = snd_pcm_ioplug_set_param_list(&pw->io, - SND_PCM_IOPLUG_HW_FORMAT, - SPA_N_ELEMENTS(format_list), - format_list); - if (err < 0) { - pw_log_warn("Can't set param list: %s", snd_strerror(err)); - return err; - } + return 0; +} + +static int set_constraint(snd_pcm_pipewire_t *pw, int key) +{ + struct param_info *p = param_info_by_key(key), info; + const char *str; + int err; + + if (p == NULL) + return -EINVAL; + + info = *p; + + str = pw_properties_get(pw->props, p->prop); + if (str != NULL) + parse_value(str, &info); + + switch (info.type) { + case TYPE_LIST: + pw_log_info("%s: list %d", p->prop, info.n_vals); + err = snd_pcm_ioplug_set_param_list(&pw->io, key, info.n_vals, info.vals); + break; + case TYPE_MIN_MAX: + pw_log_info("%s: min:%u max:%u", p->prop, info.vals0, info.vals1); + err = snd_pcm_ioplug_set_param_minmax(&pw->io, key, info.vals0, info.vals1); + break; + default: + return -EIO; } + if (err < 0) + pw_log_warn("Can't set param %s: %s", info.prop, snd_strerror(err)); + + return err; + +} +static int pipewire_set_hw_constraint(snd_pcm_pipewire_t *pw) +{ + int err; + if ((err = set_constraint(pw, SND_PCM_IOPLUG_HW_ACCESS)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_FORMAT)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_RATE)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_CHANNELS)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_PERIOD_BYTES)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_BUFFER_BYTES)) < 0 || + (err = set_constraint(pw, SND_PCM_IOPLUG_HW_PERIODS)) < 0) + return err; return 0; }
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/intclient.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/intclient.h
Changed
@@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/jack.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/jack.h
Changed
@@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/jslist.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/jslist.h
Changed
@@ -18,7 +18,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/metadata.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/metadata.h
Changed
@@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software Foundation, - Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ /**
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/midiport.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/midiport.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/net.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/net.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/ringbuffer.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/ringbuffer.h
Changed
@@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/session.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/session.h
Changed
@@ -15,7 +15,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifndef __jack_session_h__
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/thread.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/thread.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/transport.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/transport.h
Changed
@@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/types.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/types.h
Changed
@@ -14,7 +14,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/uuid.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/uuid.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/weakjack.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/weakjack.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/jack/weakmacros.h -> pipewire-0.3.79.tar.gz/pipewire-jack/jack/weakmacros.h
Changed
@@ -13,7 +13,7 @@ You should have received a copy of the GNU Lesser General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */
View file
pipewire-0.3.77.tar.gz/pipewire-jack/src/pipewire-jack.c -> pipewire-0.3.79.tar.gz/pipewire-jack/src/pipewire-jack.c
Changed
@@ -86,12 +86,12 @@ #define NOTIFY_TYPE_REGISTRATION ((1<<4)) #define NOTIFY_TYPE_PORTREGISTRATION ((2<<4)|NOTIFY_ACTIVE_FLAG) #define NOTIFY_TYPE_CONNECT ((3<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_GRAPH ((4<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_BUFFER_FRAMES ((5<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_SAMPLE_RATE ((6<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_FREEWHEEL ((7<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_SHUTDOWN ((8<<4)|NOTIFY_ACTIVE_FLAG) -#define NOTIFY_TYPE_LATENCY ((9<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_BUFFER_FRAMES ((4<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_SAMPLE_RATE ((5<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_FREEWHEEL ((6<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_SHUTDOWN ((7<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_LATENCY ((8<<4)|NOTIFY_ACTIVE_FLAG) +#define NOTIFY_TYPE_TOTAL_LATENCY ((9<<4)|NOTIFY_ACTIVE_FLAG) int type; struct object *object; int arg1; @@ -171,6 +171,7 @@ struct spa_hook proxy_listener; struct spa_hook object_listener; int registered; + unsigned int visible; unsigned int removing:1; unsigned int removed:1; }; @@ -248,6 +249,8 @@ struct spa_list mix; struct mix *global_mix; + struct port *tied; + unsigned int empty_out:1; unsigned int zeroed:1; @@ -718,12 +721,20 @@ return false; } +static inline bool client_port_visible(struct client *c, struct object *o) +{ + if (o->port.port != NULL && o->port.port->client == c) + return true; + return o->visible; +} + static struct object *find_port_by_name(struct client *c, const char *name) { struct object *o; spa_list_for_each(o, &c->context.objects, link) { - if (o->type != INTERFACE_Port || o->removed) + if (o->type != INTERFACE_Port || o->removed || + (!client_port_visible(c, o))) continue; if (spa_streq(o->port.name, name) || spa_streq(o->port.alias1, name) || @@ -900,12 +911,6 @@ return name; } -static void recompute_latencies(struct client *c) -{ - do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg); - do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg); -} - #define freeze_callbacks(c) \ ({ \ (c)->frozen_callbacks++; \ @@ -928,7 +933,7 @@ int32_t avail; uint32_t index; struct notify *notify; - bool do_graph = false; + bool do_graph = false, do_recompute_capture = false, do_recompute_playback = false; if (c->frozen_callbacks != 0 || !c->pending_callbacks) return; @@ -981,10 +986,7 @@ c->connect_arg); do_graph = true; - break; - case NOTIFY_TYPE_GRAPH: - pw_log_debug("%p: graph", c); - do_graph = true; + do_recompute_capture = do_recompute_playback = true; break; case NOTIFY_TYPE_BUFFER_FRAMES: pw_log_debug("%p: buffer frames %d", c, notify->arg1); @@ -992,7 +994,7 @@ do_callback_expr(c, c->buffer_frames = notify->arg1, bufsize_callback, c->active, notify->arg1, c->bufsize_arg); - recompute_latencies(c); + do_recompute_capture = do_recompute_playback = true; } break; case NOTIFY_TYPE_SAMPLE_RATE: @@ -1019,7 +1021,14 @@ break; case NOTIFY_TYPE_LATENCY: pw_log_debug("%p: latency %d", c, notify->arg1); - do_callback(c, latency_callback, c->active, notify->arg1, c->latency_arg); + if (notify->arg1 == JackCaptureLatency) + do_recompute_capture = true; + else if (notify->arg1 == JackPlaybackLatency) + do_recompute_playback = true; + break; + case NOTIFY_TYPE_TOTAL_LATENCY: + pw_log_debug("%p: total latency", c); + do_recompute_capture = do_recompute_playback = true; break; default: break; @@ -1035,10 +1044,13 @@ index += sizeof(struct notify); spa_ringbuffer_read_update(&c->notify_ring, index); } - if (do_graph) { - recompute_latencies(c); + if (do_recompute_capture) + do_callback(c, latency_callback, c->active, JackCaptureLatency, c->latency_arg); + if (do_recompute_playback) + do_callback(c, latency_callback, c->active, JackPlaybackLatency, c->latency_arg); + if (do_graph) do_callback(c, graph_callback, c->active, c->graph_arg); - } + thaw_callbacks(c); pw_log_debug("%p: leave", c); } @@ -1049,6 +1061,7 @@ uint32_t index; struct notify *notify; bool emit = false; + int res = 0; switch (type) { case NOTIFY_TYPE_REGISTRATION: @@ -1056,13 +1069,11 @@ break; case NOTIFY_TYPE_PORTREGISTRATION: emit = c->portregistration_callback != NULL && o != NULL; + o->visible = arg1; break; case NOTIFY_TYPE_CONNECT: emit = c->connect_callback != NULL && o != NULL; break; - case NOTIFY_TYPE_GRAPH: - emit = c->graph_callback != NULL || c->latency_callback != NULL; - break; case NOTIFY_TYPE_BUFFER_FRAMES: emit = c->bufsize_callback != NULL; break; @@ -1076,6 +1087,7 @@ emit = c->info_shutdown_callback != NULL || c->shutdown_callback != NULL; break; case NOTIFY_TYPE_LATENCY: + case NOTIFY_TYPE_TOTAL_LATENCY: emit = c->latency_callback != NULL; break; default: @@ -1084,8 +1096,10 @@ if (!emit || ((type & NOTIFY_ACTIVE_FLAG) && !c->active)) { switch (type) { case NOTIFY_TYPE_BUFFER_FRAMES: - if (!emit) + if (!emit) { c->buffer_frames = arg1; + queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL); + } break; case NOTIFY_TYPE_SAMPLE_RATE: if (!emit) @@ -1098,13 +1112,15 @@ o->removing = false; free_object(c, o); } - return 0; + return res; } + pthread_mutex_lock(&c->context.lock); filled = spa_ringbuffer_get_write_index(&c->notify_ring, &index); if (filled < 0 || filled + sizeof(struct notify) > NOTIFY_BUFFER_SIZE) { pw_log_warn("%p: notify queue full %d", c, type); - return -ENOSPC; + res = -ENOSPC; + goto done; } notify = SPA_PTROFF(c->notify_buffer, index & NOTIFY_BUFFER_MASK, struct notify); @@ -1118,7 +1134,9 @@ spa_ringbuffer_write_update(&c->notify_ring, index); c->pending_callbacks = true; check_callbacks(c); - return 0; +done: + pthread_mutex_unlock(&c->context.lock); + return res; } static void on_notify_event(void *data, uint64_t count) @@ -1419,22 +1437,27 @@ static inline void process_empty(struct port *p, uint32_t frames) { - void *ptr; + void *ptr, *src = p->emptyptr; + struct port *tied = p->tied; + + if (SPA_UNLIKELY(tied != NULL)) { + if ((src = tied->get_buffer(tied, frames)) == NULL) + src = p->emptyptr; + } switch (p->object->port.type_id) { case TYPE_ID_AUDIO: ptr = get_buffer_output(p, frames, sizeof(float), NULL); if (SPA_LIKELY(ptr != NULL)) - memcpy(ptr, p->emptyptr, frames * sizeof(float)); + memcpy(ptr, src, frames * sizeof(float)); break; case TYPE_ID_MIDI: { struct buffer *b; ptr = get_buffer_output(p, MAX_BUFFER_FRAMES, 1, &b); - if (SPA_LIKELY(ptr != NULL)) { - b->datas0.chunk->size = convert_from_midi(p->emptyptr, + if (SPA_LIKELY(ptr != NULL)) + b->datas0.chunk->size = convert_from_midi(src, ptr, MAX_BUFFER_FRAMES * sizeof(float)); - } break; } default: @@ -1447,7 +1470,7 @@ { struct mix *mix; - if (SPA_UNLIKELY(p->empty_out)) + if (SPA_UNLIKELY(p->empty_out || p->tied)) process_empty(p, frames); spa_list_for_each(mix, &p->mix, port_link) { @@ -1462,6 +1485,15 @@ struct mix *mix; union pw_map_item *item; + pw_array_for_each(item, &c->portsSPA_DIRECTION_OUTPUT.items) { + if (pw_map_item_is_free(item)) + continue; + p = item->data; + if (!p->valid) + continue; + prepare_output(p, frames); + p->io.status = SPA_STATUS_NEED_DATA; + } pw_array_for_each(item, &c->portsSPA_DIRECTION_INPUT.items) { if (pw_map_item_is_free(item)) continue; @@ -1473,15 +1505,6 @@ mix->io->status = SPA_STATUS_NEED_DATA; } } - pw_array_for_each(item, &c->portsSPA_DIRECTION_OUTPUT.items) { - if (pw_map_item_is_free(item)) - continue; - p = item->data; - if (!p->valid) - continue; - prepare_output(p, frames); - p->io.status = SPA_STATUS_NEED_DATA; - } } static inline void debug_position(struct client *c, jack_position_t *p) @@ -3073,11 +3096,18 @@ { struct object *n = data; struct client *c = n->client; + const char *str; + + if (info->change_mask & PW_NODE_CHANGE_MASK_PROPS) { + str = spa_dict_lookup(info->props, PW_KEY_NODE_ALWAYS_PROCESS); + n->node.is_jack = str ? spa_atob(str) : false; + } - pw_log_info("DSP node %d state change %s", info->id, - pw_node_state_as_string(info->state)); + n->node.is_running = !n->node.is_jack || (info->state == PW_NODE_STATE_RUNNING); - n->node.is_running = (info->state == PW_NODE_STATE_RUNNING); + pw_log_debug("DSP node %d %08"PRIx64" jack:%u state change %s running:%d", info->id, + info->change_mask, n->node.is_jack, + pw_node_state_as_string(info->state), n->node.is_running); if (info->change_mask & PW_NODE_CHANGE_MASK_STATE) { struct object *p; @@ -5256,15 +5286,32 @@ SPA_EXPORT int jack_port_tie (jack_port_t *src, jack_port_t *dst) { - pw_log_warn("not implemented %p %p", src, dst); - return -ENOTSUP; + struct object *s = (struct object *) src; + struct object *d = (struct object *) dst; + struct port *sp, *dp; + + sp = s->port.port; + dp = d->port.port; + if (sp == NULL || !sp->valid || + dp == NULL || !dp->valid || + sp->client != dp->client) + return -EINVAL; + + dp->tied = sp; + return 0; } SPA_EXPORT int jack_port_untie (jack_port_t *port) { - pw_log_warn("not implemented %p", port); - return -ENOTSUP; + struct object *o = (struct object *) port; + struct port *p; + + p = o->port.port; + if (p == NULL || !p->valid) + return -EINVAL; + p->tied = NULL; + return 0; } SPA_EXPORT @@ -5851,9 +5898,7 @@ int jack_recompute_total_latencies (jack_client_t *client) { struct client *c = (struct client *) client; - queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackCaptureLatency, NULL); - queue_notify(c, NOTIFY_TYPE_LATENCY, NULL, JackPlaybackLatency, NULL); - return 0; + return queue_notify(c, NOTIFY_TYPE_TOTAL_LATENCY, NULL, 0, NULL); } static jack_nframes_t port_get_latency (jack_port_t *port) @@ -5989,7 +6034,7 @@ count = 0; spa_list_for_each(o, &c->context.objects, link) { - if (o->type != INTERFACE_Port || o->removed) + if (o->type != INTERFACE_Port || o->removed || !o->visible) continue; pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c, o->port.type_id, o->port.flags, o->port.name);
View file
pipewire-0.3.77.tar.gz/po/ka.po -> pipewire-0.3.79.tar.gz/po/ka.po
Changed
@@ -1,25 +1,25 @@ -# Georgian translation for pipewire. -# Copyright (C) 2022 pipewire'S authors +# Georgian translation of pipewire +# Copyright (C) 2023 pipewire's authors # This file is distributed under the same license as the pipewire package. -# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2022. +# Temuri Doghonadze <temuri.doghonadze@gmail.com>, 2023. # msgid "" msgstr "" "Project-Id-Version: pipewire\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/" "issues/new\n" -"POT-Creation-Date: 2022-06-30 12:50+0200\n" -"PO-Revision-Date: 2022-11-20 11:50+0100\n" +"POT-Creation-Date: 2023-08-07 22:01+0200\n" +"PO-Revision-Date: 2023-08-07 22:06+0200\n" "Last-Translator: Temuri Doghonadze <temuri.doghonadze@gmail.com>\n" -"Language-Team: \n" +"Language-Team: Georgian <(nothing)>\n" "Language: ka\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n" -"X-Generator: Poedit 3.2\n" +"X-Generator: Poedit 3.3.2\n" -#: src/daemon/pipewire.c:46 +#: src/daemon/pipewire.c:26 #, c-format msgid "" "%s options\n" @@ -32,36 +32,44 @@ " --version ვერსიის ჩვენება\n" " -c, --config ჩატვირთვის კონფიგურაცია (ნაგულისხმები %s)\n" -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:180 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:180 +#: src/daemon/pipewire.desktop.in:4 +msgid "PipeWire Media System" +msgstr "PipeWire Media System" + +#: src/daemon/pipewire.desktop.in:5 +msgid "Start the PipeWire Media System" +msgstr "PipeWire Media System-ის გაშვება" + +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:141 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:141 #, c-format -msgid "Tunnel to %s/%s" -msgstr "გვირაბი %s/%s -მდე" +msgid "Tunnel to %s%s%s" +msgstr "გვირაბი %s%s%s-მდე" -#: src/modules/module-fallback-sink.c:51 +#: src/modules/module-fallback-sink.c:31 msgid "Dummy Output" msgstr "ნულოვანი გამოყვანა" -#: src/modules/module-pulse-tunnel.c:662 +#: src/modules/module-pulse-tunnel.c:847 #, c-format msgid "Tunnel for %s@%s" msgstr "გვირაბი %s@%s-სთვის" -#: src/modules/module-zeroconf-discover.c:332 +#: src/modules/module-zeroconf-discover.c:311 msgid "Unknown device" msgstr "უცნობი მოწყობილობა" -#: src/modules/module-zeroconf-discover.c:344 +#: src/modules/module-zeroconf-discover.c:323 #, c-format msgid "%s on %s@%s" msgstr "%s %s@%s -ზე" -#: src/modules/module-zeroconf-discover.c:348 +#: src/modules/module-zeroconf-discover.c:327 #, c-format msgid "%s on %s" msgstr "%s %s-ზე" -#: src/tools/pw-cat.c:784 +#: src/tools/pw-cat.c:979 #, c-format msgid "" "%s options <file>|-\n" @@ -76,14 +84,15 @@ " -v, --verbose დამატებითი შეტყობინებების გამოტანა\n" "\n" -#: src/tools/pw-cat.c:791 +#: src/tools/pw-cat.c:986 #, c-format msgid "" " -R, --remote Remote daemon name\n" " --media-type Set media type (default %s)\n" " --media-category Set media category (default %s)\n" " --media-role Set media role (default %s)\n" -" --target Set node target (default %s)\n" +" --target Set node target serial or name " +"(default %s)\n" " 0 means don't link\n" " --latency Set node latency (default %s)\n" " Xunit (unit = s, ms, us, ns)\n" @@ -106,7 +115,7 @@ "ფაილი\n" " -P --properties კვანძის თვისებების დაყენება\n" -#: src/tools/pw-cat.c:809 +#: src/tools/pw-cat.c:1004 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -139,21 +148,23 @@ " -q --quality Resampler ხარისხი (0 - 15) " "(ნაგულისხმები %d)\n" -#: src/tools/pw-cat.c:826 +#: src/tools/pw-cat.c:1021 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" " -m, --midi Midi mode\n" " -d, --dsd DSD mode\n" +" -o, --encoded Encoded mode\n" "\n" msgstr "" -" -p, --playback დაკვრის რეჟიმი\n" -" -r, -- record ჩაწერის რეჟიმი\n" -" -m, --midi Midi რეჟიმი\n" -" -d, --dsd DSD რეჟიმი\n" +" -p, --playback დაკვრის რეჟიმი\n" +" -r, --record ჩაწერის რეჟიმი\n" +" -m, --midi Midi რეჟიმი\n" +" -d, --dsd DSD რეჟიმი\n" +" -o, --encoded დაშიფრული რეჟიმი\n" "\n" -#: src/tools/pw-cli.c:2250 +#: src/tools/pw-cli.c:2220 #, c-format msgid "" "%s options command\n" @@ -161,23 +172,26 @@ " --version Show version\n" " -d, --daemon Start as daemon (Default false)\n" " -r, --remote Remote daemon name\n" +" -m, --monitor Monitor activity\n" "\n" msgstr "" "%s პარამეტრები ბრძანება\n" -" -h, --help ამ დახმარების ჩვენება\n" -" --version ვერსიის ჩვენება\n" -" -d, --daemon დაწყება როგორც დემონი (ნაგულისხმები " -"false)\n" -" -r, --remote დაშორებული დემონის სახელი\n" +" -h, --help ამ დახმარების ჩვენება\n" +" --version ვერსიის ჩვენება\n" +" -d, --daemon დემონის სახით გაშვება (ნაგულისხმევად " +"გამორთულია)\n" +" -r, --remote დაშორებული დემონის სახელი\n" +" -m, --monitor აქტივობის მონიტორინგი\n" +"\n" -#: spa/plugins/alsa/acp/acp.c:321 +#: spa/plugins/alsa/acp/acp.c:325 msgid "Pro Audio" msgstr "Pro Audio" -#: spa/plugins/alsa/acp/acp.c:444 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1236 +#: spa/plugins/alsa/acp/acp.c:449 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1586 msgid "Off" -msgstr "გამორთული" +msgstr "გამორთულია" #: spa/plugins/alsa/acp/alsa-mixer.c:2652 msgid "Input" @@ -193,7 +207,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2655 msgid "Docking Station Line In" -msgstr "Docking Station Line In" +msgstr "Docking Station-ის Line In პორტი" #: spa/plugins/alsa/acp/alsa-mixer.c:2656 #: spa/plugins/alsa/acp/alsa-mixer.c:2747 @@ -202,7 +216,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1454 +#: spa/plugins/bluez5/bluez5-device.c:1831 msgid "Microphone" msgstr "მიკროფონი" @@ -268,7 +282,7 @@ msgstr "Bass-ის გაძლიერების გარეშე" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1460 +#: spa/plugins/bluez5/bluez5-device.c:1837 msgid "Speaker" msgstr "დინამიკი" @@ -383,7 +397,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:4484 #: spa/plugins/alsa/acp/alsa-mixer.c:4642 -#: spa/plugins/bluez5/bluez5-device.c:1442 +#: spa/plugins/bluez5/bluez5-device.c:1819 msgid "Headset" msgstr "ყურსაცვამები & მიკროფონი" @@ -497,12 +511,12 @@ msgid "Mono Chat + 7.1 Surround" msgstr "მონო ჩატი + 7.1 სივრცითი" -#: spa/plugins/alsa/acp/alsa-mixer.c:4754 +#: spa/plugins/alsa/acp/alsa-mixer.c:4748 #, c-format msgid "%s Output" msgstr "%s გამოყვანა" -#: spa/plugins/alsa/acp/alsa-mixer.c:4761 +#: spa/plugins/alsa/acp/alsa-mixer.c:4756 #, c-format msgid "%s Input" msgstr "%s შეყვანა" @@ -533,13 +547,13 @@ #: spa/plugins/alsa/acp/alsa-util.c:1253 #, c-format msgid "" -"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s" -"%lu ms).\n" +"snd_pcm_delay() returned a value that is exceptionally large: %li byte " +"(%s%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." msgid_plural "" -"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s" -"%lu ms).\n" +"snd_pcm_delay() returned a value that is exceptionally large: %li bytes " +"(%s%lu ms).\n" "Most likely this is a bug in the ALSA driver '%s'. Please report this issue " "to the ALSA developers." msgstr0 "" @@ -601,92 +615,104 @@ msgid "Modem" msgstr "მოდემი" -#: spa/plugins/bluez5/bluez5-device.c:1247 +#: spa/plugins/bluez5/bluez5-device.c:1597 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "Audio Gateway (A2DP წყარო & HSP/HFP AG)" -#: spa/plugins/bluez5/bluez5-device.c:1272 +#: spa/plugins/bluez5/bluez5-device.c:1622 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "მაღალი ხარისხის ხმა (A2DP Sink, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1275 +#: spa/plugins/bluez5/bluez5-device.c:1625 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "მაღალი ხარისხის დუპლექსი (A2DP წყარო/Sink, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1283 +#: spa/plugins/bluez5/bluez5-device.c:1633 msgid "High Fidelity Playback (A2DP Sink)" msgstr "მაღალი ხარისხის ხმა (A2DP Sink)" -#: spa/plugins/bluez5/bluez5-device.c:1285 +#: spa/plugins/bluez5/bluez5-device.c:1635 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "მაღალი ხარისხის დუპლექსი(A2DP წყარო/Sink)" -#: spa/plugins/bluez5/bluez5-device.c:1322 +#: spa/plugins/bluez5/bluez5-device.c:1677 #, c-format msgid "High Fidelity Playback (BAP Sink, codec %s)" msgstr "მაღალი ხარისხის დაკვრა (BAP Sink, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1326 +#: spa/plugins/bluez5/bluez5-device.c:1681 #, c-format msgid "High Fidelity Input (BAP Source, codec %s)" msgstr "მაღალი ხარისხის შეყვანა (BAP წყარო, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1330 +#: spa/plugins/bluez5/bluez5-device.c:1685 #, c-format msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)" msgstr "მაღალი ხარისხის დუპლექსი (BAP წყარო/Sink, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1359 +#: spa/plugins/bluez5/bluez5-device.c:1693 +msgid "High Fidelity Playback (BAP Sink)" +msgstr "მაღალი ხარისხის დაკვრა (BAP Sink)" + +#: spa/plugins/bluez5/bluez5-device.c:1696 +msgid "High Fidelity Input (BAP Source)" +msgstr "მაღალი ხარისხის შეყვანა (BAP წყარო)" + +#: spa/plugins/bluez5/bluez5-device.c:1699 +msgid "High Fidelity Duplex (BAP Source/Sink)" +msgstr "მაღალი ხარისხის დუპლექსი (BAP წყარო/Sink)" + +#: spa/plugins/bluez5/bluez5-device.c:1735 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "Headset Head Unit (HSP/HFP, კოდეკი %s)" -#: spa/plugins/bluez5/bluez5-device.c:1364 +#: spa/plugins/bluez5/bluez5-device.c:1740 msgid "Headset Head Unit (HSP/HFP)" msgstr "Headset Head Unit (HSP/HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1443 -#: spa/plugins/bluez5/bluez5-device.c:1448 -#: spa/plugins/bluez5/bluez5-device.c:1455 -#: spa/plugins/bluez5/bluez5-device.c:1461 -#: spa/plugins/bluez5/bluez5-device.c:1467 -#: spa/plugins/bluez5/bluez5-device.c:1473 -#: spa/plugins/bluez5/bluez5-device.c:1479 -#: spa/plugins/bluez5/bluez5-device.c:1485 -#: spa/plugins/bluez5/bluez5-device.c:1491 +#: spa/plugins/bluez5/bluez5-device.c:1820 +#: spa/plugins/bluez5/bluez5-device.c:1825 +#: spa/plugins/bluez5/bluez5-device.c:1832 +#: spa/plugins/bluez5/bluez5-device.c:1838 +#: spa/plugins/bluez5/bluez5-device.c:1844 +#: spa/plugins/bluez5/bluez5-device.c:1850 +#: spa/plugins/bluez5/bluez5-device.c:1856 +#: spa/plugins/bluez5/bluez5-device.c:1862 +#: spa/plugins/bluez5/bluez5-device.c:1868 msgid "Handsfree" msgstr "ხელის გარეშე სამართავი" -#: spa/plugins/bluez5/bluez5-device.c:1449 +#: spa/plugins/bluez5/bluez5-device.c:1826 msgid "Handsfree (HFP)" msgstr "ხელის გარეშე სამართავი (HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1466 +#: spa/plugins/bluez5/bluez5-device.c:1843 msgid "Headphone" msgstr "ყურსაცვამი" -#: spa/plugins/bluez5/bluez5-device.c:1472 +#: spa/plugins/bluez5/bluez5-device.c:1849 msgid "Portable" msgstr "გადატანადი" -#: spa/plugins/bluez5/bluez5-device.c:1478 +#: spa/plugins/bluez5/bluez5-device.c:1855 msgid "Car" msgstr "მანქანა" -#: spa/plugins/bluez5/bluez5-device.c:1484 +#: spa/plugins/bluez5/bluez5-device.c:1861 msgid "HiFi" msgstr "HiFi" -#: spa/plugins/bluez5/bluez5-device.c:1490 +#: spa/plugins/bluez5/bluez5-device.c:1867 msgid "Phone" msgstr "ტელეფონი" -#: spa/plugins/bluez5/bluez5-device.c:1497 +#: spa/plugins/bluez5/bluez5-device.c:1874 msgid "Bluetooth" -msgstr "Bluetooth" +msgstr "ლურჯკბილა" -#: spa/plugins/bluez5/bluez5-device.c:1498 +#: spa/plugins/bluez5/bluez5-device.c:1875 msgid "Bluetooth (HFP)" -msgstr "Bluetooth (HFP)" +msgstr "ბლუთუზი (HFP)"
View file
pipewire-0.3.77.tar.gz/po/sv.po -> pipewire-0.3.79.tar.gz/po/sv.po
Changed
@@ -19,8 +19,8 @@ "Project-Id-Version: pipewire\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" "issues\n" -"POT-Creation-Date: 2023-02-26 15:27+0000\n" -"PO-Revision-Date: 2023-02-26 17:32+0100\n" +"POT-Creation-Date: 2023-08-07 15:27+0000\n" +"PO-Revision-Date: 2023-05-12 18:46+0200\n" "Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n" "Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n" "Language: sv\n" @@ -51,36 +51,36 @@ msgid "Start the PipeWire Media System" msgstr "Starta mediasystemet PipeWire" -#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159 -#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159 +#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:141 +#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:141 #, c-format -msgid "Tunnel to %s/%s" -msgstr "Tunnel till %s/%s" +msgid "Tunnel to %s%s%s" +msgstr "Tunnel till %s%s%s" #: src/modules/module-fallback-sink.c:31 msgid "Dummy Output" msgstr "Attrapputgång" -#: src/modules/module-pulse-tunnel.c:675 +#: src/modules/module-pulse-tunnel.c:847 #, c-format msgid "Tunnel for %s@%s" msgstr "Tunnel för %s@%s" -#: src/modules/module-zeroconf-discover.c:315 +#: src/modules/module-zeroconf-discover.c:311 msgid "Unknown device" msgstr "Okänd enhet" -#: src/modules/module-zeroconf-discover.c:327 +#: src/modules/module-zeroconf-discover.c:323 #, c-format msgid "%s on %s@%s" msgstr "%s på %s@%s" -#: src/modules/module-zeroconf-discover.c:331 +#: src/modules/module-zeroconf-discover.c:327 #, c-format msgid "%s on %s" msgstr "%s på %s" -#: src/tools/pw-cat.c:974 +#: src/tools/pw-cat.c:979 #, c-format msgid "" "%s options <file>|-\n" @@ -95,7 +95,7 @@ " -v, --verbose Aktivera utförliga operationer\n" "\n" -#: src/tools/pw-cat.c:981 +#: src/tools/pw-cat.c:986 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -127,7 +127,7 @@ " -P --properties Sätt nodegenskaper\n" "\n" -#: src/tools/pw-cat.c:999 +#: src/tools/pw-cat.c:1004 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -162,7 +162,7 @@ "%d)\n" "\n" -#: src/tools/pw-cat.c:1016 +#: src/tools/pw-cat.c:1021 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -178,7 +178,7 @@ " -o, --encoded Kodat läge\n" "\n" -#: src/tools/pw-cli.c:2216 +#: src/tools/pw-cli.c:2220 #, c-format msgid "" "%s options command\n" @@ -197,12 +197,12 @@ " -m, --monitor Övervaka aktivitet\n" "\n" -#: spa/plugins/alsa/acp/acp.c:303 +#: spa/plugins/alsa/acp/acp.c:325 msgid "Pro Audio" msgstr "Professionellt ljud" -#: spa/plugins/alsa/acp/acp.c:427 spa/plugins/alsa/acp/alsa-mixer.c:4648 -#: spa/plugins/bluez5/bluez5-device.c:1283 +#: spa/plugins/alsa/acp/acp.c:449 spa/plugins/alsa/acp/alsa-mixer.c:4648 +#: spa/plugins/bluez5/bluez5-device.c:1586 msgid "Off" msgstr "Av" @@ -229,7 +229,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:2657 #: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1519 +#: spa/plugins/bluez5/bluez5-device.c:1831 msgid "Microphone" msgstr "Mikrofon" @@ -295,7 +295,7 @@ msgstr "Ingen basökning" #: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1525 +#: spa/plugins/bluez5/bluez5-device.c:1837 msgid "Speaker" msgstr "Högtalare" @@ -410,7 +410,7 @@ #: spa/plugins/alsa/acp/alsa-mixer.c:4484 #: spa/plugins/alsa/acp/alsa-mixer.c:4642 -#: spa/plugins/bluez5/bluez5-device.c:1507 +#: spa/plugins/bluez5/bluez5-device.c:1819 msgid "Headset" msgstr "Headset" @@ -524,12 +524,12 @@ msgid "Mono Chat + 7.1 Surround" msgstr "Mono Chatt + 7.1 Surround" -#: spa/plugins/alsa/acp/alsa-mixer.c:4754 +#: spa/plugins/alsa/acp/alsa-mixer.c:4748 #, c-format msgid "%s Output" msgstr "%s-utgång" -#: spa/plugins/alsa/acp/alsa-mixer.c:4761 +#: spa/plugins/alsa/acp/alsa-mixer.c:4756 #, c-format msgid "%s Input" msgstr "%s-ingång" @@ -628,104 +628,104 @@ msgid "Modem" msgstr "Modem" -#: spa/plugins/bluez5/bluez5-device.c:1294 +#: spa/plugins/bluez5/bluez5-device.c:1597 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)" -#: spa/plugins/bluez5/bluez5-device.c:1319 +#: spa/plugins/bluez5/bluez5-device.c:1622 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1322 +#: spa/plugins/bluez5/bluez5-device.c:1625 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1330 +#: spa/plugins/bluez5/bluez5-device.c:1633 msgid "High Fidelity Playback (A2DP Sink)" msgstr "High fidelity-uppspelning (A2DP-utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1332 +#: spa/plugins/bluez5/bluez5-device.c:1635 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "High fidelity duplex (A2DP-källa/utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1374 +#: spa/plugins/bluez5/bluez5-device.c:1677 #, c-format msgid "High Fidelity Playback (BAP Sink, codec %s)" msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1378 +#: spa/plugins/bluez5/bluez5-device.c:1681 #, c-format msgid "High Fidelity Input (BAP Source, codec %s)" msgstr "High fidelity-ingång (BAP-källa, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1382 +#: spa/plugins/bluez5/bluez5-device.c:1685 #, c-format msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)" msgstr "High fidelity duplex (BAP-källa/utgång, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1390 +#: spa/plugins/bluez5/bluez5-device.c:1693 msgid "High Fidelity Playback (BAP Sink)" msgstr "High fidelity-uppspelning (BAP-utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1393 +#: spa/plugins/bluez5/bluez5-device.c:1696 msgid "High Fidelity Input (BAP Source)" msgstr "High fidelity-ingång (BAP-källa)" -#: spa/plugins/bluez5/bluez5-device.c:1396 +#: spa/plugins/bluez5/bluez5-device.c:1699 msgid "High Fidelity Duplex (BAP Source/Sink)" msgstr "High fidelity duplex (BAP-källa/utgång)" -#: spa/plugins/bluez5/bluez5-device.c:1424 +#: spa/plugins/bluez5/bluez5-device.c:1735 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)" -#: spa/plugins/bluez5/bluez5-device.c:1429 +#: spa/plugins/bluez5/bluez5-device.c:1740 msgid "Headset Head Unit (HSP/HFP)" msgstr "Headset-huvudenhet (HSP/HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1508 -#: spa/plugins/bluez5/bluez5-device.c:1513 -#: spa/plugins/bluez5/bluez5-device.c:1520 -#: spa/plugins/bluez5/bluez5-device.c:1526 -#: spa/plugins/bluez5/bluez5-device.c:1532 -#: spa/plugins/bluez5/bluez5-device.c:1538 -#: spa/plugins/bluez5/bluez5-device.c:1544 -#: spa/plugins/bluez5/bluez5-device.c:1550 -#: spa/plugins/bluez5/bluez5-device.c:1556 +#: spa/plugins/bluez5/bluez5-device.c:1820 +#: spa/plugins/bluez5/bluez5-device.c:1825 +#: spa/plugins/bluez5/bluez5-device.c:1832 +#: spa/plugins/bluez5/bluez5-device.c:1838 +#: spa/plugins/bluez5/bluez5-device.c:1844 +#: spa/plugins/bluez5/bluez5-device.c:1850 +#: spa/plugins/bluez5/bluez5-device.c:1856 +#: spa/plugins/bluez5/bluez5-device.c:1862 +#: spa/plugins/bluez5/bluez5-device.c:1868 msgid "Handsfree" msgstr "Handsfree" -#: spa/plugins/bluez5/bluez5-device.c:1514 +#: spa/plugins/bluez5/bluez5-device.c:1826 msgid "Handsfree (HFP)" msgstr "Handsfree (HFP)" -#: spa/plugins/bluez5/bluez5-device.c:1531 +#: spa/plugins/bluez5/bluez5-device.c:1843 msgid "Headphone" msgstr "Hörlurar" -#: spa/plugins/bluez5/bluez5-device.c:1537 +#: spa/plugins/bluez5/bluez5-device.c:1849 msgid "Portable" msgstr "Bärbar" -#: spa/plugins/bluez5/bluez5-device.c:1543 +#: spa/plugins/bluez5/bluez5-device.c:1855 msgid "Car" msgstr "Bil" -#: spa/plugins/bluez5/bluez5-device.c:1549 +#: spa/plugins/bluez5/bluez5-device.c:1861 msgid "HiFi" msgstr "HiFi" -#: spa/plugins/bluez5/bluez5-device.c:1555 +#: spa/plugins/bluez5/bluez5-device.c:1867 msgid "Phone" msgstr "Telefon" -#: spa/plugins/bluez5/bluez5-device.c:1562 +#: spa/plugins/bluez5/bluez5-device.c:1874 msgid "Bluetooth" msgstr "Bluetooth" -#: spa/plugins/bluez5/bluez5-device.c:1563 +#: spa/plugins/bluez5/bluez5-device.c:1875 msgid "Bluetooth (HFP)" msgstr "Bluetooth (HFP)"
View file
pipewire-0.3.77.tar.gz/spa/include/spa/node/io.h -> pipewire-0.3.79.tar.gz/spa/include/spa/node/io.h
Changed
@@ -117,7 +117,7 @@ * is unique per clock and can be used to check if nodes * share the same clock. */ uint64_t nsec; /**< time in nanoseconds against monotonic clock */ - struct spa_fraction rate; /**< rate for position/duration/delay */ + struct spa_fraction rate; /**< rate for position/duration/delay/xrun */ uint64_t position; /**< current position */ uint64_t duration; /**< duration of current cycle */ int64_t delay; /**< delay between position and hardware, @@ -129,8 +129,8 @@ uint64_t target_duration; /**< target duration of next cycle */ uint32_t target_seq; /**< seq counter. must be equal at start and * end of read and lower bit must be 0 */ - - uint32_t padding3; + uint32_t padding; + uint64_t xrun; /**< estimated accumulated xrun duration */ }; /* the size of the video in this cycle */
View file
pipewire-0.3.77.tar.gz/spa/include/spa/param/video/dsp-utils.h -> pipewire-0.3.79.tar.gz/spa/include/spa/param/video/dsp-utils.h
Changed
@@ -49,9 +49,11 @@ if (info->format != SPA_VIDEO_FORMAT_UNKNOWN) spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_format, SPA_POD_Id(info->format), 0); - if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) - spa_pod_builder_add(builder, - SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); + if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) { + spa_pod_builder_prop(builder, + SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY); + spa_pod_builder_long(builder, info->modifier); + } return (struct spa_pod*)spa_pod_builder_pop(builder, &f); }
View file
pipewire-0.3.77.tar.gz/spa/include/spa/param/video/raw-utils.h -> pipewire-0.3.79.tar.gz/spa/include/spa/param/video/raw-utils.h
Changed
@@ -68,9 +68,11 @@ if (info->framerate.denom != 0) spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_framerate, SPA_POD_Fraction(&info->framerate), 0); - if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) - spa_pod_builder_add(builder, - SPA_FORMAT_VIDEO_modifier, SPA_POD_Long(info->modifier), 0); + if (info->modifier != 0 || info->flags & SPA_VIDEO_FLAG_MODIFIER) { + spa_pod_builder_prop(builder, + SPA_FORMAT_VIDEO_modifier, SPA_POD_PROP_FLAG_MANDATORY); + spa_pod_builder_long(builder, info->modifier); + } if (info->max_framerate.denom != 0) spa_pod_builder_add(builder, SPA_FORMAT_VIDEO_maxFramerate, SPA_POD_Fraction(info->max_framerate), 0);
View file
pipewire-0.3.77.tar.gz/spa/include/spa/pod/builder.h -> pipewire-0.3.79.tar.gz/spa/include/spa/pod/builder.h
Changed
@@ -441,7 +441,7 @@ return res; } -static inline uint32_t +static inline int spa_pod_builder_control(struct spa_pod_builder *builder, uint32_t offset, uint32_t type) { const struct { uint32_t offset; uint32_t type; } p = { offset, type };
View file
pipewire-0.3.77.tar.gz/spa/include/spa/support/log.h -> pipewire-0.3.79.tar.gz/spa/include/spa/support/log.h
Changed
@@ -284,7 +284,8 @@ /** keys can be given when initializing the logger handle */ #define SPA_KEY_LOG_LEVEL "log.level" /**< the default log level */ -#define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger */ +#define SPA_KEY_LOG_COLORS "log.colors" /**< enable colors in the logger, set to "force" to enable + * colors even when not logging to a terminal */ #define SPA_KEY_LOG_FILE "log.file" /**< log to the specified file instead of * stderr. */ #define SPA_KEY_LOG_TIMESTAMP "log.timestamp" /**< log timestamps */
View file
pipewire-0.3.77.tar.gz/spa/plugins/alsa/acp/acp.c -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/acp/acp.c
Changed
@@ -281,6 +281,18 @@ } } +static const char *find_best_verb(pa_card *impl) +{ + const char *res = NULL; + unsigned prio = 0; + pa_alsa_ucm_verb *verb; + PA_LLIST_FOREACH(verb, impl->ucm.verbs) { + if (verb->priority >= prio) + res = pa_proplist_gets(verb->proplist, PA_ALSA_PROP_UCM_NAME); + } + return res; +} + static int add_pro_profile(pa_card *impl, uint32_t index) { snd_ctl_t *ctl_hndl; @@ -293,6 +305,16 @@ pa_sample_spec ss; snd_pcm_uframes_t try_period_size, try_buffer_size; + if (impl->use_ucm) { + const char *verb = find_best_verb(impl); + if (verb == NULL) + return -ENOTSUP; + if ((err = snd_use_case_set(impl->ucm.ucm_mgr, "_verb", verb)) < 0) { + pa_log_error("error setting verb: %s", snd_strerror(err)); + return err; + } + } + ss.format = PA_SAMPLE_S32LE; ss.rate = impl->rate; ss.channels = impl->pro_channels; @@ -365,6 +387,7 @@ 0, NULL, NULL, false))) { pa_alsa_init_proplist_pcm(NULL, m->output_proplist, m->output_pcm); pa_proplist_setf(m->output_proplist, "clock.name", "api.alsa.%u", index); + pa_proplist_setf(m->output_proplist, "device.profile.pro", "true"); pa_alsa_close(&m->output_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX); @@ -395,6 +418,7 @@ 0, NULL, NULL, false))) { pa_alsa_init_proplist_pcm(NULL, m->input_proplist, m->input_pcm); pa_proplist_setf(m->input_proplist, "clock.name", "api.alsa.%u", index); + pa_proplist_setf(m->input_proplist, "device.profile.pro", "true"); pa_alsa_close(&m->input_pcm); m->supported = true; pa_channel_map_init_auto(&m->channel_map, m->sample_spec.channels, PA_CHANNEL_MAP_AUX);
View file
pipewire-0.3.77.tar.gz/spa/plugins/alsa/alsa-pcm.c -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -499,9 +499,13 @@ { uint32_t i; int err; + const char *str; snd_config_update_free_global(); + if ((str = spa_dict_lookup(info, "device.profile.pro")) != NULL) + state->is_pro = spa_atob(str); + state->multi_rate = true; state->htimestamp = false; for (i = 0; info && i < info->n_items; i++) { @@ -1645,31 +1649,27 @@ dir = 0; period_size = state->default_period_size; - is_batch = snd_pcm_hw_params_is_batch(params) && - !state->disable_batch; + is_batch = snd_pcm_hw_params_is_batch(params) && !state->disable_batch; /* no period size specified. If we are batch or not using timers, * use the graph duration as the period */ if (period_size == 0 && (is_batch || state->disable_tsched)) - period_size = state->position ? state->position->clock.duration : DEFAULT_PERIOD; - - if (is_batch) { - if (period_size == 0) - period_size = DEFAULT_PERIOD; - /* batch devices get their hw pointers updated every period. Make - * the period smaller and add one period of headroom. Limit the - * period size to our default so that we don't create too much - * headroom. */ - if (!state->disable_tsched) + period_size = state->position ? state->position->clock.target_duration : DEFAULT_PERIOD; + if (period_size == 0) + period_size = DEFAULT_PERIOD; + + if (!state->disable_tsched) { + if (is_batch) { + /* batch devices get their hw pointers updated every period. Make + * the period smaller and add one period of headroom. Limit the + * period size to our default so that we don't create too much + * headroom. */ period_size = SPA_MIN(period_size, DEFAULT_PERIOD) / 2; - spa_log_info(state->log, "%s: batch mode, period_size:%ld", - state->props.device, period_size); - } else { - if (period_size == 0) - period_size = DEFAULT_PERIOD; - /* disable ALSA wakeups, if we use a timer */ - if (!state->disable_tsched && snd_pcm_hw_params_can_disable_period_wakeup(params)) - CHECK(snd_pcm_hw_params_set_period_wakeup(hndl, params, 0), "set_period_wakeup"); + } else { + /* disable ALSA wakeups */ + if (snd_pcm_hw_params_can_disable_period_wakeup(params)) + CHECK(snd_pcm_hw_params_set_period_wakeup(hndl, params, 0), "set_period_wakeup"); + } } CHECK(snd_pcm_hw_params_set_period_size_near(hndl, params, &period_size, &dir), "set_period_size_near"); @@ -1729,7 +1729,7 @@ spa_log_info(state->log, "%s (%s): format:%s access:%s-%s rate:%d channels:%d " "buffer frames %lu, period frames %lu, periods %u, frame_size %zd " - "headroom %u start-delay:%u tsched:%u", + "headroom %u start-delay:%u batch:%u tsched:%u", state->props.device, state->stream == SND_PCM_STREAM_CAPTURE ? "capture" : "playback", snd_pcm_format_name(state->format), @@ -1737,7 +1737,7 @@ planar ? "planar" : "interleaved", state->rate, state->channels, state->buffer_frames, state->period_frames, periods, state->frame_size, state->headroom, state->start_delay, - !state->disable_tsched); + is_batch, !state->disable_tsched); /* write the parameters to device */ CHECK(snd_pcm_hw_params(hndl, params), "set_hw_params"); @@ -1931,14 +1931,18 @@ delay = SPA_TIMEVAL_TO_USEC(&diff); missing = delay * state->rate / SPA_USEC_PER_SEC; + if (missing == 0) + missing = state->threshold; spa_log_trace(state->log, "%p: xrun of %"PRIu64" usec %"PRIu64, state, delay, missing); + if (state->clock) + state->clock->xrun += missing; + state->sample_count += missing; + spa_node_call_xrun(&state->callbacks, SPA_TIMEVAL_TO_USEC(&trigger), delay, NULL); - - state->sample_count += missing ? missing : state->threshold; break; } case SND_PCM_STATE_SUSPENDED:
View file
pipewire-0.3.77.tar.gz/spa/plugins/alsa/alsa-pcm.h -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -199,6 +199,7 @@ unsigned int is_hdmi:1; unsigned int multi_rate:1; unsigned int htimestamp:1; + unsigned int is_pro:1; uint64_t iec958_codecs;
View file
pipewire-0.3.79.tar.gz/spa/plugins/alsa/mixer/profile-sets/9999-custom.conf
Added
@@ -0,0 +1,22 @@ +# This file is part of PulseAudio. +# +# PulseAudio is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as +# published by the Free Software Foundation; either version 2.1 of the +# License, or (at your option) any later version. +# +# PulseAudio is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. + +; Put your custom profiles here. + +; An example for defining multiple-sink profiles +#Profile output:analog-stereo+output:iec958-stereo+input:analog-stereo +#description = Foobar +#output-mappings = analog-stereo iec958-stereo +#input-mappings = analog-stereo
View file
pipewire-0.3.77.tar.gz/spa/plugins/alsa/mixer/profile-sets/default.conf -> pipewire-0.3.79.tar.gz/spa/plugins/alsa/mixer/profile-sets/default.conf
Changed
@@ -573,8 +573,4 @@ priority = 1 direction = input -; An example for defining multiple-sink profiles -#Profile output:analog-stereo+output:iec958-stereo+input:analog-stereo -#description = Foobar -#output-mappings = analog-stereo iec958-stereo -#input-mappings = analog-stereo +.include 9999-custom.conf
View file
pipewire-0.3.77.tar.gz/spa/plugins/audioconvert/audioconvert.c -> pipewire-0.3.79.tar.gz/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -2594,7 +2594,7 @@ spa_log_trace_fp(this->log, "%p: next match %u", this, match_size); if (this->io_rate_match) { - this->io_rate_match->delay = delay; + this->io_rate_match->delay = delay + in_queued; this->io_rate_match->size = match_size; } return match_size;
View file
pipewire-0.3.77.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c -> pipewire-0.3.79.tar.gz/spa/plugins/audioconvert/fmt-ops-neon.c
Changed
@@ -294,7 +294,7 @@ " beq 4f\n" "3:" " ld1 { v0.s }0, %s0, #4\n" - " ld1 { v2.s }0, %s1, #4\n" + " ld1 { v1.s }0, %s1, #4\n" " subs %remainder, %remainder, #1\n" " sqadd v0.4s, v0.4s, v2.4s\n" " sqadd v1.4s, v1.4s, v2.4s\n"
View file
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/bluez5-dbus.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -193,13 +193,14 @@ * stopped/started rapidly, postpone release until the transport has remained * unused for a time. * - * Avoiding unnecessary release+reacquire also makes sense for other transports, - * so we use the release timeout for all of them. + * Avoiding unnecessary release+reacquire also makes sense for ISO. */ #define TRANSPORT_RELEASE_TIMEOUT_MSEC 1000 #define TRANSPORT_VOLUME_TIMEOUT_MSEC 200 +#define SPA_BT_TRANSPORT_IS_A2DP(transport) ((transport)->profile & (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_A2DP_SINK)) + static int spa_bt_transport_stop_volume_timer(struct spa_bt_transport *transport); static int spa_bt_transport_start_volume_timer(struct spa_bt_transport *transport); static int spa_bt_transport_stop_release_timer(struct spa_bt_transport *transport); @@ -406,8 +407,12 @@ if (direction == SPA_BT_MEDIA_SOURCE) endpoint = codec->bap ? BAP_SOURCE_ENDPOINT : A2DP_SOURCE_ENDPOINT; - else + else if (direction == SPA_BT_MEDIA_SINK) endpoint = codec->bap ? BAP_SINK_ENDPOINT : A2DP_SINK_ENDPOINT; + else if (direction == SPA_BT_MEDIA_SOURCE_BROADCAST) + endpoint = BAP_BROADCAST_SOURCE_ENDPOINT; + else if (direction == SPA_BT_MEDIA_SINK_BROADCAST) + endpoint = BAP_BROADCAST_SINK_ENDPOINT; *object_path = spa_aprintf("%s/%s", endpoint, codec->endpoint_name ? codec->endpoint_name : codec->name); @@ -435,6 +440,12 @@ } else if (spa_strstartswith(endpoint, BAP_SINK_ENDPOINT "/")) { ep_name = endpoint + strlen(BAP_SINK_ENDPOINT "/"); *sink = true; + } else if (spa_strstartswith(endpoint, BAP_BROADCAST_SOURCE_ENDPOINT "/")) { + ep_name = endpoint + strlen(BAP_BROADCAST_SOURCE_ENDPOINT "/"); + *sink = false; + } else if (spa_strstartswith(endpoint, BAP_BROADCAST_SINK_ENDPOINT "/")) { + ep_name = endpoint + strlen(BAP_BROADCAST_SINK_ENDPOINT "/"); + *sink = true; } else { *sink = true; return NULL; @@ -471,6 +482,10 @@ return SPA_BT_PROFILE_BAP_SOURCE; else if (spa_strstartswith(endpoint, BAP_SOURCE_ENDPOINT "/")) return SPA_BT_PROFILE_BAP_SINK; + else if (spa_strstartswith(endpoint, BAP_BROADCAST_SINK_ENDPOINT "/")) + return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + else if (spa_strstartswith(endpoint, BAP_BROADCAST_SOURCE_ENDPOINT "/")) + return SPA_BT_PROFILE_BAP_BROADCAST_SINK; else return SPA_BT_PROFILE_NULL; } @@ -484,8 +499,10 @@ { switch (direction) { case SPA_BT_MEDIA_SOURCE: + case SPA_BT_MEDIA_SOURCE_BROADCAST: return codec->encode; case SPA_BT_MEDIA_SINK: + case SPA_BT_MEDIA_SINK_BROADCAST: return codec->decode; default: spa_assert_not_reached(); @@ -500,6 +517,10 @@ return codec->bap ? SPA_BT_PROFILE_BAP_SOURCE : SPA_BT_PROFILE_A2DP_SOURCE; case SPA_BT_MEDIA_SINK: return codec->bap ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_A2DP_SINK; + case SPA_BT_MEDIA_SOURCE_BROADCAST: + return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + case SPA_BT_MEDIA_SINK_BROADCAST: + return SPA_BT_PROFILE_BAP_BROADCAST_SINK; default: spa_assert_not_reached(); } @@ -963,6 +984,10 @@ adapter->profiles |= SPA_BT_PROFILE_BAP_SINK; spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_SOURCE); adapter->profiles |= SPA_BT_PROFILE_BAP_SOURCE; + spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_BROADCAST_SOURCE); + adapter->profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + spa_log_debug(monitor->log, "adapter %p: add UUID=%s", adapter, SPA_BT_UUID_BAP_BROADCAST_SINK); + adapter->profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SINK; } dbus_message_iter_next(&iter); } @@ -1010,6 +1035,14 @@ spa_log_info(monitor->log, "Adapter %s: LE Audio supported", adapter->path); } + + if (spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE) || + spa_streq(uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) { + adapter->le_audio_bcast_supported = true; + spa_log_info(monitor->log, "Adapter %s: LE Broadcast Audio supported", + adapter->path); + } + dbus_message_iter_next(&iter); } } @@ -1163,6 +1196,11 @@ if (profiles & SPA_BT_PROFILE_BAP_SOURCE) mask |= SPA_BT_PROFILE_BAP_SINK; + if (profiles & SPA_BT_PROFILE_BAP_BROADCAST_SINK) + mask |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + if (profiles & SPA_BT_PROFILE_BAP_BROADCAST_SOURCE) + mask |= SPA_BT_PROFILE_BAP_BROADCAST_SINK; + if (profiles & SPA_BT_PROFILE_HSP_AG) mask |= SPA_BT_PROFILE_HSP_HS; if (profiles & SPA_BT_PROFILE_HSP_HS) @@ -1624,6 +1662,10 @@ device_try_connect_profile(device, SPA_BT_UUID_BAP_SINK); if (reconnect & SPA_BT_PROFILE_BAP_SOURCE) device_try_connect_profile(device, SPA_BT_UUID_BAP_SOURCE); + if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SINK) + device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SINK); + if (reconnect & SPA_BT_PROFILE_BAP_BROADCAST_SOURCE) + device_try_connect_profile(device, SPA_BT_UUID_BAP_BROADCAST_SOURCE); return reconnect; } @@ -2228,13 +2270,15 @@ return false; } - if (codec->bap) - codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; - else - codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE; - spa_list_for_each(ep, &device->remote_endpoint_list, device_link) { - const enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid); + enum spa_bt_profile profile = spa_bt_profile_from_uuid(ep->uuid); + if (codec->bap) { + if ((profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) + codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + else + codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; + } else + codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE; if (profile != codec_profile) continue; @@ -2252,6 +2296,14 @@ * can only know that the currently configured codec is supported. */ spa_list_for_each(t, &device->transport_list, device_link) { + if (codec->bap) { + if((t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) + codec_profile = sink ? SPA_BT_PROFILE_BAP_BROADCAST_SINK : SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + else + codec_profile = sink ? SPA_BT_PROFILE_BAP_SINK : SPA_BT_PROFILE_BAP_SOURCE; + } else + codec_profile = sink ? SPA_BT_PROFILE_A2DP_SINK : SPA_BT_PROFILE_A2DP_SOURCE; + if (t->profile != codec_profile) continue; @@ -2321,6 +2373,41 @@ return NULL; } +static struct spa_bt_device* create_bcast_device(struct spa_bt_monitor *monitor, + const char *object_path) +{ + struct spa_bt_device *d; + d = device_create(monitor, object_path); + if (d == NULL) { + spa_log_warn(monitor->log, "can't create Bluetooth device %s: %m", + object_path); + return NULL; + } + + d->adapter = adapter_find(monitor, object_path); + if (d->adapter == NULL) { + spa_log_warn(monitor->log, "unknown adapter %s", d->adapter_path); + } + d->adapter_path = d->adapter->path; + d->alias = strdup("bcast_device"); + d->name = strdup("bcast_device"); + d->address = strdup("00:00:00:00:00:00"); + + spa_bt_device_check_profiles(d, false); + d->reconnect_state = BT_DEVICE_RECONNECT_INIT; + + if (!device_props_ready(d)) + { + return NULL; + } + + device_update_hw_volume_profiles(d); + + spa_bt_device_add_profile(d, SPA_BT_PROFILE_NULL); + + return d; +} + static int remote_endpoint_update_props(struct spa_bt_remote_endpoint *remote_endpoint, DBusMessageIter *props_iter, DBusMessageIter *invalidated_iter) @@ -2353,8 +2440,25 @@ else if (spa_streq(key, "Device")) { struct spa_bt_device *device; device = spa_bt_device_find(monitor, value); - if (device == NULL) - goto next; + if (device == NULL) { + /* + * If a broadcast sink endpoint is detected (over DBus) a new device + * will be created. This device will be our simulated remote device. + * This is done because BlueZ sets the adapter as the device + * that is connected to for a broadcast sink endpoint/transport. + */ + if(spa_streq(remote_endpoint->uuid, SPA_BT_UUID_BAP_BROADCAST_SINK)) { + device = create_bcast_device(monitor, value); + if(device == NULL) { + goto next; + } + remote_endpoint->acceptor = true; + device_set_connected(device, 1); + } else { + goto next; + } + } + spa_log_debug(monitor->log, "remote_endpoint %p: device -> %p", remote_endpoint, device); if (remote_endpoint->device != device) { @@ -2492,6 +2596,8 @@ t->latency_us = SPA_BT_UNKNOWN_DELAY; t->bap_cig = 0xff; t->bap_cis = 0xff; + t->bap_big = 0xff; + t->bap_bis = 0xff; t->user_data = SPA_PTROFF(t, sizeof(struct spa_bt_transport), void); spa_hook_list_init(&t->listener_list); spa_list_init(&t->bap_transport_linked); @@ -2700,7 +2806,8 @@ /* Postpone active transport releases, since we might need it again soon. * If not active, release now since it has to be reacquired before using again. */ - if (transport->state == SPA_BT_TRANSPORT_STATE_ACTIVE) { + if (transport->state == SPA_BT_TRANSPORT_STATE_ACTIVE && + !SPA_BT_TRANSPORT_IS_A2DP(transport)) { return spa_bt_transport_start_release_timer(transport); } else { spa_bt_transport_do_release(transport); @@ -2954,6 +3061,12 @@ case SPA_BT_PROFILE_BAP_SINK: transport->profile = SPA_BT_PROFILE_BAP_SOURCE; break; + case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: + transport->profile = SPA_BT_PROFILE_BAP_BROADCAST_SINK; + break; + case SPA_BT_PROFILE_BAP_BROADCAST_SINK: + transport->profile = SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + break; default: spa_log_warn(monitor->log, "unknown profile %s", value); break; @@ -3165,6 +3278,20 @@ else transport->bap_cis = value; } + else if (spa_streq(key, "BIG") || spa_streq(key, "BIS")) { + uint8_t value; + + if (type != DBUS_TYPE_BYTE) + goto next; + dbus_message_iter_get_basic(&it1, &value); + + spa_log_debug(monitor->log, "transport %p: %s=%d", transport, key, (int)value); + + if (spa_streq(key, "BIG")) + transport->bap_big = value; + else + transport->bap_bis = value; + } next: dbus_message_iter_next(props_iter); } @@ -3261,11 +3388,18 @@ struct spa_bt_monitor *monitor = transport->monitor; struct spa_bt_transport *t; - if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE))) + if (!(transport->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE | + SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) return 0; - if (transport->bap_cig == 0xff || transport->bap_cis == 0xff) - return -EINVAL; + if ((transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK) || + (transport->profile == SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { + if (transport->bap_big == 0xff || transport->bap_bis == 0xff) + return -EINVAL; + } else { + if (transport->bap_cig == 0xff || transport->bap_cis == 0xff) + return -EINVAL; + } if (transport->iso_io) { spa_log_debug(monitor->log, "transport %p: remove ISO IO", transport); @@ -3275,11 +3409,19 @@ /* Transports in same connected iso group share the same i/o */ spa_list_for_each(t, &monitor->transport_list, link) { - if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE))) - continue; - if (t->bap_cig != transport->bap_cig) + if (!(t->profile & (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE | + SPA_BT_PROFILE_BAP_BROADCAST_SINK | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) 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) + continue; + } else { + if (t->bap_cig != transport->bap_cig) + continue; + } + if (t->iso_io) { spa_log_debug(monitor->log, "transport %p: attach ISO IO to %p", transport, t); @@ -3358,9 +3500,15 @@ if (transport_create_iso_io(transport) < 0) spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed", transport); - - if (!transport->bap_initiator) + /* For broadcast the initiator moves the transport state to SPA_BT_TRANSPORT_STATE_ACTIVE */ + /* TODO: handeling multiple BIGs support */ + 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); + } else { + if (!transport->bap_initiator) + spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); + } } /* For LE Audio, multiple transport from the same device may share the same @@ -3384,8 +3532,14 @@ spa_log_error(monitor->log, "transport %p: transport_create_iso_io failed", t_linked); - if (!transport->bap_initiator) - spa_bt_transport_set_state(t_linked, SPA_BT_TRANSPORT_STATE_ACTIVE); + /* 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); + } else { + if (!transport->bap_initiator) + spa_bt_transport_set_state(transport, SPA_BT_TRANSPORT_STATE_ACTIVE); + } } /* @@ -4525,6 +4679,8 @@ } else if (dbus_message_is_method_call(m, "org.freedesktop.DBus.ObjectManager", "GetManagedObjects")) { spa_autoptr(DBusMessage) r = NULL; + struct spa_bt_adapter *a; + bool register_bcast = false; if ((r = dbus_message_new_method_return(m)) == NULL) return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -4532,6 +4688,17 @@ dbus_message_iter_init_append(r, &iter); dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "{oa{sa{sv}}}", &array); + /* + * Verify if an adapter exists that supports bap broadcast. + * If this adapter exists will register the broadcast endpoint. + */ + spa_list_for_each(a, &monitor->adapter_list, link) { + if (a->le_audio_bcast_supported) { + register_bcast = true; + break; + } + } + for (i = 0; media_codecsi; i++) { const struct media_codec *codec = media_codecsi; uint8_t capsA2DP_MAX_CAPS_SIZE; @@ -4573,6 +4740,38 @@ codec_id, caps, caps_size); } } + + if (codec->bap && register_bcast) { + if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST)) { + caps_size = codec->fill_caps(codec, 0, caps); + if (caps_size < 0) + continue; + + spa_autofree char *endpoint = NULL; + ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SOURCE_BROADCAST, &endpoint); + if (ret == 0) { + spa_log_info(monitor->log, "register media source codec %s: %s", media_codecsi->name, endpoint); + append_media_object(&array, endpoint, + SPA_BT_UUID_BAP_BROADCAST_SOURCE, + codec_id, caps, caps_size); + } + } + + if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST)) { + caps_size = codec->fill_caps(codec, MEDIA_CODEC_FLAG_SINK, caps); + if (caps_size < 0) + continue; + + spa_autofree char *endpoint = NULL; + ret = media_codec_to_endpoint(codec, SPA_BT_MEDIA_SINK_BROADCAST, &endpoint); + if (ret == 0) { + spa_log_info(monitor->log, "register broadcast media sink codec %s: %s", media_codecsi->name, endpoint); + append_media_object(&array, endpoint, + SPA_BT_UUID_BAP_BROADCAST_SINK, + codec_id, caps, caps_size); + } + } + } } dbus_message_iter_close_container(&iter, &array); @@ -4700,6 +4899,10 @@ register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE); register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK); + if (codec->bap) { + register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST); + register_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST); + } } return 0; @@ -4732,6 +4935,10 @@ unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE); unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK); + if (codec->bap) { + unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST); + unregister_media_endpoint(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST); + } } dbus_connection_unregister_object_path(monitor->conn, BAP_OBJECT_MANAGER_PATH); @@ -4749,7 +4956,9 @@ if (codec->bap != bap) continue; if (endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK) || - endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE)) + endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE) || + endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SOURCE_BROADCAST) || + endpoint_should_be_registered(monitor, codec, SPA_BT_MEDIA_SINK_BROADCAST)) return true; } return false; @@ -4768,7 +4977,7 @@ if (!bap && a->a2dp_application_registered) return 0; - if (bap && !a->le_audio_supported) { + if ((bap && !a->le_audio_supported) && (bap && !a->le_audio_bcast_supported)) { spa_log_info(monitor->log, "Adapter %s indicates LE Audio unsupported: not registering application", a->path); return -ENOTSUP; @@ -5485,6 +5694,10 @@ profiles |= SPA_BT_PROFILE_BAP_SINK; } else if (spa_streq(role_name, "bap_source")) { profiles |= SPA_BT_PROFILE_BAP_SOURCE; + } else if (spa_streq(role_name, "bap_bcast_source")) { + profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + } else if (spa_streq(role_name, "bap_bcast_sink")) { + profiles |= SPA_BT_PROFILE_BAP_BROADCAST_SINK; } }
View file
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/bluez5-device.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -1051,6 +1051,26 @@ emit_device_set_node(this, DEVICE_ID_SINK_SET); } + if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_BAP_BROADCAST_SINK)) { + t = find_transport(this, SPA_BT_PROFILE_BAP_BROADCAST_SINK, this->props.codec); + if (t) { + this->props.codec = t->media_codec->id; + emit_node(this, t, DEVICE_ID_SINK, SPA_NAME_API_BLUEZ5_MEDIA_SINK, false); + } + + if (this->device_set.leader && this->device_set.sinks > 0) + emit_device_set_node(this, DEVICE_ID_SINK_SET); + } + + if (this->bt_dev->connected_profiles & (SPA_BT_PROFILE_BAP_BROADCAST_SOURCE)) { + t = find_transport(this, SPA_BT_PROFILE_BAP_BROADCAST_SOURCE, this->props.codec); + if (t) { + this->props.codec = t->media_codec->id; + emit_dynamic_node(&this->dyn_media_source, this, t, + DEVICE_ID_SOURCE, SPA_NAME_API_BLUEZ5_MEDIA_SOURCE, false); + } + } + if (get_supported_media_codec(this, this->props.codec, NULL) == NULL) this->props.codec = 0; break; @@ -1467,19 +1487,8 @@ if (profile == DEVICE_PROFILE_OFF || profile == DEVICE_PROFILE_AG) return profile; - if (profile == DEVICE_PROFILE_A2DP) { - if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_MEDIA_SOURCE)) - return profile; - - return codec + DEVICE_PROFILE_LAST; - } - - if (profile == DEVICE_PROFILE_BAP) { - if (codec == 0) - return profile; - + if ((profile == DEVICE_PROFILE_A2DP) || (profile == DEVICE_PROFILE_BAP)) return codec + DEVICE_PROFILE_LAST; - } if (profile == DEVICE_PROFILE_HSP_HFP) { if (codec == 0 || (this->bt_dev->connected_profiles & SPA_BT_PROFILE_HFP_AG)) @@ -1607,6 +1616,11 @@ if (!(profile & SPA_BT_PROFILE_A2DP_SINK)) { return NULL; } + + /* A2DP will only enlist codec profiles */ + if (!codec) + return NULL; + name = spa_bt_profile_name(profile); n_sink++; if (codec) { @@ -1617,7 +1631,15 @@ return NULL; } name_and_codec = spa_aprintf("%s-%s", name, media_codec->name); - name = name_and_codec; + + /* + * Give base name to highest priority profile, so that best codec can be + * selected at command line with out knowing which codecs are actually + * supported + */ + if (idx != 0) + name = name_and_codec; + if (profile == SPA_BT_PROFILE_A2DP_SINK && !media_codec->duplex_codec) { desc_and_codec = spa_aprintf(_("High Fidelity Playback (A2DP Sink, codec %s)"), media_codec->description); @@ -1641,29 +1663,28 @@ case DEVICE_PROFILE_BAP: { uint32_t profile = device->connected_profiles & - (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE); + (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE + | SPA_BT_PROFILE_BAP_BROADCAST_SOURCE + | SPA_BT_PROFILE_BAP_BROADCAST_SINK); size_t idx; const struct media_codec *media_codec; + /* BAP will only enlist codec profiles */ + if (codec == 0) + return NULL; + if (profile == 0) return NULL; - if (profile & (SPA_BT_PROFILE_BAP_SINK)) + if ((profile & (SPA_BT_PROFILE_BAP_SINK)) || + (profile & (SPA_BT_PROFILE_BAP_BROADCAST_SINK))) n_sink++; - if (profile & (SPA_BT_PROFILE_BAP_SOURCE)) + if ((profile & (SPA_BT_PROFILE_BAP_SOURCE)) || + (profile & (SPA_BT_PROFILE_BAP_BROADCAST_SOURCE))) n_source++; name = spa_bt_profile_name(profile); - /* If we can't codec switch, emit codecless profile */ - if (current && !can_bap_codec_switch(this)) { - codec = 0; - index = get_index_from_profile(this, profile_index, codec); - } else if ((codec != 0) != can_bap_codec_switch(this)) { - errno = -EINVAL; - return NULL; - } - if (codec) { media_codec = get_supported_media_codec(this, codec, &idx); if (media_codec == NULL) { @@ -1671,13 +1692,23 @@ return NULL; } name_and_codec = spa_aprintf("%s-%s", name, media_codec->name); - name = name_and_codec; + + /* + * Give base name to highest priority profile, so that best codec can be + * selected at command line with out knowing which codecs are actually + * supported + */ + if (idx != 0) + name = name_and_codec; + switch (profile) { case SPA_BT_PROFILE_BAP_SINK: + case SPA_BT_PROFILE_BAP_BROADCAST_SINK: desc_and_codec = spa_aprintf(_("High Fidelity Playback (BAP Sink, codec %s)"), media_codec->description); break; case SPA_BT_PROFILE_BAP_SOURCE: + case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: desc_and_codec = spa_aprintf(_("High Fidelity Input (BAP Source, codec %s)"), media_codec->description); break; @@ -1690,9 +1721,11 @@ } else { switch (profile) { case SPA_BT_PROFILE_BAP_SINK: + case SPA_BT_PROFILE_BAP_BROADCAST_SINK: desc = _("High Fidelity Playback (BAP Sink)"); break; case SPA_BT_PROFILE_BAP_SOURCE: + case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: desc = _("High Fidelity Input (BAP Source)"); break; default:
View file
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/defs.h -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/defs.h
Changed
@@ -125,6 +125,8 @@ #define SPA_BT_UUID_PACS "00001850-0000-1000-8000-00805f9b34fb" #define SPA_BT_UUID_BAP_SINK "00002bc9-0000-1000-8000-00805f9b34fb" #define SPA_BT_UUID_BAP_SOURCE "00002bcb-0000-1000-8000-00805f9b34fb" +#define SPA_BT_UUID_BAP_BROADCAST_SOURCE "00001852-0000-1000-8000-00805f9b34fb" +#define SPA_BT_UUID_BAP_BROADCAST_SINK "00001851-0000-1000-8000-00805f9b34fb" #define PROFILE_HSP_AG "/Profile/HSPAG" #define PROFILE_HSP_HS "/Profile/HSPHS" @@ -149,6 +151,8 @@ #define BAP_OBJECT_MANAGER_PATH "/MediaEndpointLE" #define BAP_SINK_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPSink" #define BAP_SOURCE_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPSource" +#define BAP_BROADCAST_SOURCE_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPBroadcastSource" +#define BAP_BROADCAST_SINK_ENDPOINT BAP_OBJECT_MANAGER_PATH "/BAPBroadcastSink" #define SPA_BT_UNKNOWN_DELAY 0 @@ -163,6 +167,8 @@ enum spa_bt_media_direction { SPA_BT_MEDIA_SOURCE, SPA_BT_MEDIA_SINK, + SPA_BT_MEDIA_SOURCE_BROADCAST, + SPA_BT_MEDIA_SINK_BROADCAST, }; enum spa_bt_profile { @@ -175,6 +181,8 @@ SPA_BT_PROFILE_HSP_AG = (1 << 5), SPA_BT_PROFILE_HFP_HF = (1 << 6), SPA_BT_PROFILE_HFP_AG = (1 << 7), + SPA_BT_PROFILE_BAP_BROADCAST_SOURCE = (1 << 8), + SPA_BT_PROFILE_BAP_BROADCAST_SINK = (1 << 9), SPA_BT_PROFILE_A2DP_DUPLEX = (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_A2DP_SOURCE), SPA_BT_PROFILE_BAP_DUPLEX = (SPA_BT_PROFILE_BAP_SINK | SPA_BT_PROFILE_BAP_SOURCE), @@ -182,8 +190,10 @@ SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY = (SPA_BT_PROFILE_HSP_AG | SPA_BT_PROFILE_HFP_AG), SPA_BT_PROFILE_HEADSET_AUDIO = (SPA_BT_PROFILE_HEADSET_HEAD_UNIT | SPA_BT_PROFILE_HEADSET_AUDIO_GATEWAY), - SPA_BT_PROFILE_MEDIA_SINK = (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_BAP_SINK), - SPA_BT_PROFILE_MEDIA_SOURCE = (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_BAP_SOURCE), + SPA_BT_PROFILE_MEDIA_SINK = (SPA_BT_PROFILE_A2DP_SINK | SPA_BT_PROFILE_BAP_SINK | + SPA_BT_PROFILE_BAP_BROADCAST_SINK), + SPA_BT_PROFILE_MEDIA_SOURCE = (SPA_BT_PROFILE_A2DP_SOURCE | SPA_BT_PROFILE_BAP_SOURCE | + SPA_BT_PROFILE_BAP_BROADCAST_SOURCE), }; static inline enum spa_bt_profile spa_bt_profile_from_uuid(const char *uuid) @@ -206,6 +216,10 @@ return SPA_BT_PROFILE_BAP_SINK; else if (strcasecmp(uuid, SPA_BT_UUID_BAP_SOURCE) == 0) return SPA_BT_PROFILE_BAP_SOURCE; + else if (strcasecmp(uuid, SPA_BT_UUID_BAP_BROADCAST_SOURCE) == 0) + return SPA_BT_PROFILE_BAP_BROADCAST_SOURCE; + else if (strcasecmp(uuid, SPA_BT_UUID_BAP_BROADCAST_SINK) == 0) + return SPA_BT_PROFILE_BAP_BROADCAST_SINK; else return 0; } @@ -307,8 +321,10 @@ case SPA_BT_PROFILE_HEADSET_AUDIO: return "headset-audio"; case SPA_BT_PROFILE_BAP_SOURCE: + case SPA_BT_PROFILE_BAP_BROADCAST_SOURCE: return "bap-source"; case SPA_BT_PROFILE_BAP_SINK: + case SPA_BT_PROFILE_BAP_BROADCAST_SINK: return "bap-sink"; case SPA_BT_PROFILE_BAP_DUPLEX: return "bap-duplex"; @@ -349,6 +365,7 @@ unsigned int le_audio_supported:1; unsigned int has_adapter1_interface:1; unsigned int has_media1_interface:1; + unsigned int le_audio_bcast_supported:1; }; enum spa_bt_form_factor { @@ -630,6 +647,8 @@ unsigned int latency_us; uint8_t bap_cig; uint8_t bap_cis; + uint8_t bap_big; + uint8_t bap_bis; uint32_t bap_interval; struct spa_bt_iso_io *iso_io;
View file
pipewire-0.3.77.tar.gz/spa/plugins/bluez5/iso-io.c -> pipewire-0.3.79.tar.gz/spa/plugins/bluez5/iso-io.c
Changed
@@ -315,7 +315,14 @@ int block_size = 0; struct spa_audio_info format = { 0 }; int res; - bool sink = (t->profile & SPA_BT_PROFILE_BAP_SINK) != 0; + bool sink; + if((t->profile == SPA_BT_PROFILE_BAP_SINK) || + (t->profile == SPA_BT_PROFILE_BAP_BROADCAST_SINK)) { + sink = true; + } else { + sink = false; + } + if (!t->media_codec->bap) { res = -EINVAL;
View file
pipewire-0.3.77.tar.gz/spa/plugins/support/evl-system.c -> pipewire-0.3.79.tar.gz/spa/plugins/support/evl-system.c
Changed
@@ -18,6 +18,7 @@ #include <spa/support/log.h> #include <spa/support/system.h> #include <spa/support/plugin.h> +#include <spa/utils/names.h> #include <spa/utils/type.h> #include <spa/utils/result.h> #include <spa/utils/string.h> @@ -133,7 +134,7 @@ e->fd = fd; e->events = events; e->data = data; - return evl_add_pollfd(pfd, fd, e->events); + return evl_add_pollfd(pfd, fd, e->events, evl_nil); } static int impl_pollfd_mod(void *object, int pfd, int fd, uint32_t events, void *data) @@ -147,7 +148,7 @@ e->events = events; e->data = data; - return evl_mod_pollfd(pfd, fd, e->events); + return evl_mod_pollfd(pfd, fd, e->events, evl_nil); } static int impl_pollfd_del(void *object, int pfd, int fd) @@ -248,10 +249,8 @@ } static int impl_timerfd_read(void *object, int fd, uint64_t *expirations) { - uint32_t ticks; - if (oob_read(fd, &ticks, sizeof(ticks)) != sizeof(ticks)) + if (oob_read(fd, expirations, sizeof(uint64_t)) != sizeof(uint64_t)) return -errno; - *expirations = ticks; return 0; } @@ -259,17 +258,18 @@ static int impl_eventfd_create(void *object, int flags) { struct impl *impl = object; - int res; + int res, fl; + + fl = EVL_CLONE_PRIVATE; + if (flags & SPA_FD_NONBLOCK) + fl |= EVL_CLONE_NONBLOCK; - res = evl_new_xbuf(1024, 1024, "xbuf-%d-%p-%d", impl->pid, impl, impl->n_xbuf); + res = evl_create_xbuf(1024, 1024, fl, "xbuf-%d-%p-%d", impl->pid, impl, impl->n_xbuf); if (res < 0) return res; impl->n_xbuf++; - if (flags & SPA_FD_NONBLOCK) - fcntl(res, F_SETFL, fcntl(res, F_GETFL) | O_NONBLOCK); - return res; }
View file
pipewire-0.3.77.tar.gz/spa/plugins/support/logger.c -> pipewire-0.3.79.tar.gz/spa/plugins/support/logger.c
Changed
@@ -295,6 +295,7 @@ struct spa_loop *loop = NULL; const char *str, *dest = ""; bool linebuf = false; + bool force_colors = false; spa_return_val_if_fail(factory != NULL, -EINVAL); spa_return_val_if_fail(handle != NULL, -EINVAL); @@ -333,8 +334,14 @@ this->timestamp = spa_atob(str); if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LINE)) != NULL) this->line = spa_atob(str); - if ((str = spa_dict_lookup(info, SPA_KEY_LOG_COLORS)) != NULL) - this->colors = spa_atob(str); + if ((str = spa_dict_lookup(info, SPA_KEY_LOG_COLORS)) != NULL) { + if (spa_streq(str, "force")) { + this->colors = true; + force_colors = true; + } else { + this->colors = spa_atob(str); + } + } if ((str = spa_dict_lookup(info, SPA_KEY_LOG_LEVEL)) != NULL) this->log.level = atoi(str); if ((str = spa_dict_lookup(info, SPA_KEY_LOG_FILE)) != NULL) { @@ -363,8 +370,9 @@ if (linebuf) setlinebuf(this->file); - if (!isatty(fileno(this->file))) + if (!isatty(fileno(this->file)) && !force_colors) { this->colors = false; + } spa_ringbuffer_init(&this->trace_rb);
View file
pipewire-0.3.77.tar.gz/spa/plugins/support/meson.build -> pipewire-0.3.79.tar.gz/spa/plugins/support/meson.build
Changed
@@ -24,9 +24,9 @@ spa_support_dep = declare_dependency(link_with: spa_support_lib) if get_option('evl').allowed() - evl_inc = include_directories('/usr/evl/include') + evl_inc = include_directories('/usr/include') evl_lib = cc.find_library('evl', - dirs: '/usr/evl/lib/', + dirs: '/usr/lib/', required: get_option('evl')) spa_evl_sources = 'evl-system.c', 'evl-plugin.c'
View file
pipewire-0.3.77.tar.gz/spa/plugins/v4l2/v4l2-udev.c -> pipewire-0.3.79.tar.gz/spa/plugins/v4l2/v4l2-udev.c
Changed
@@ -393,6 +393,19 @@ } } +static int stop_inotify(struct device *dev) +{ + struct impl *impl = dev->impl; + if (dev->notify.fd == -1) + return 0; + spa_log_info(impl->log, "stop inotify for /dev/video%u", dev->id); + spa_loop_remove_source(impl->main_loop, &dev->notify); + close(dev->notify.fd); + dev->notify.fd = -1; + return 0; +} + + static void impl_on_notify_events(struct spa_source *source) { struct device *dev = source->data; @@ -402,7 +415,12 @@ struct inotify_event e; /* for appropriate alignment */ } buf; - while (true) { + if (source->rmask & (SPA_IO_ERR | SPA_IO_HUP)) { + spa_log_warn(impl->log, "notify error on /dev/video%u", dev->id); + stop_inotify(dev); + return; + } + while (source->rmask & SPA_IO_IN) { ssize_t len; const struct inotify_event *event; void *p, *e; @@ -469,18 +487,6 @@ return 0; } -static int stop_inotify(struct device *dev) -{ - struct impl *impl = dev->impl; - if (dev->notify.fd == -1) - return 0; - spa_log_info(impl->log, "stop inotify for /dev/video%u", dev->id); - spa_loop_remove_source(impl->main_loop, &dev->notify); - close(dev->notify.fd); - dev->notify.fd = -1; - return 0; -} - static void impl_on_fd_events(struct spa_source *source) { struct impl *impl = source->data;
View file
pipewire-0.3.77.tar.gz/src/daemon/client-rt.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/client-rt.conf.in
Changed
@@ -94,13 +94,33 @@ #dither.noise = 0 } +stream.rules = + { matches = + { + # all keys must match the value. ! negates. ~ starts regex. + #application.name = "pw-cat" + #node.name = "~Google Chrome$" + } + + actions = { + update-props = { + #node.latency = 512/48000 + } + } + } + + alsa.properties = { - #alsa.format = 0 - #alsa.rate = 0 - #alsa.channels = 0 - #alsa.period-bytes = 0 - #alsa.buffer-bytes = 0 - #alsa.volume-method = cubic # linear, cubic + # ALSA params take a single value, an array of values + # or a range { min=.. max=... } + #alsa.access = MMAP_INTERLEAVED MMAP_NONINTERLEAVED RW_INTERLEAVED RW_NONINTERLEAVED + #alsa.format = FLOAT S32 S24 S24_3 S16 U8 + #alsa.rate = { min=1 max=384000 } # or 44100 48000 .. + #alsa.channels = { min=1 max=64 } # or 2 4 6 .. + #alsa.period-bytes = { min=128 max=2097152 } # or 128 256 1024 .. + #alsa.buffer-bytes = { min=256 max=4194304 } # or 256 512 4096 .. + + #alsa.volume-method = cubic # linear, cubic } # client specific properties
View file
pipewire-0.3.77.tar.gz/src/daemon/jack.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/jack.conf.in
Changed
@@ -95,7 +95,7 @@ jack.rules = { matches = { - # all keys must match the value. ~ starts regex. + # all keys must match the value. ! negates. ~ starts regex. #client.name = "Carla" #application.process.binary = "jack_simple_client" #application.name = "~jack_simple_client.*"
View file
pipewire-0.3.77.tar.gz/src/daemon/pipewire-pulse.conf.in -> pipewire-0.3.79.tar.gz/src/daemon/pipewire-pulse.conf.in
Changed
@@ -116,7 +116,7 @@ { matches = { - # all keys must match the value. ~ starts regex. + # all keys must match the value. ! negates. ~ starts regex. #client.name = "Firefox" #application.process.binary = "teams" #application.name = "~speech-dispatcher.*"
View file
pipewire-0.3.77.tar.gz/src/gst/gstpipewiredeviceprovider.c -> pipewire-0.3.79.tar.gz/src/gst/gstpipewiredeviceprovider.c
Changed
@@ -665,11 +665,16 @@ { GstPipeWireDeviceProvider *self = GST_PIPEWIRE_DEVICE_PROVIDER (provider); - pw_thread_loop_lock (self->core->loop); + /* core might be NULL if we failed to connect in _start. */ + if (self->core != NULL) { + pw_thread_loop_lock (self->core->loop); + } GST_DEBUG_OBJECT (self, "stopping provider"); g_clear_pointer ((struct pw_proxy**)&self->registry, pw_proxy_destroy); - pw_thread_loop_unlock (self->core->loop); + if (self->core != NULL) { + pw_thread_loop_unlock (self->core->loop); + } g_clear_pointer (&self->core, gst_pipewire_core_release); }
View file
pipewire-0.3.77.tar.gz/src/modules/meson.build -> pipewire-0.3.79.tar.gz/src/modules/meson.build
Changed
@@ -356,6 +356,8 @@ 'module-protocol-pulse/stream.c', 'module-protocol-pulse/utils.c', 'module-protocol-pulse/volume.c', + 'module-protocol-pulse/modules/module-alsa-sink.c', + 'module-protocol-pulse/modules/module-alsa-source.c', 'module-protocol-pulse/modules/module-always-sink.c', 'module-protocol-pulse/modules/module-combine-sink.c', 'module-protocol-pulse/modules/module-echo-cancel.c',
View file
pipewire-0.3.77.tar.gz/src/modules/module-combine-stream.c -> pipewire-0.3.79.tar.gz/src/modules/module-combine-stream.c
Changed
@@ -93,7 +93,7 @@ * # any of the items in matches needs to match, if one does, * # actions are emited. * { - * # all keys must match the value. ~ in value starts regex. + * # all keys must match the value. ! negates. ~ starts regex. * #node.name = "~alsa_input.*" * media.class = "Audio/Sink" * }
View file
pipewire-0.3.77.tar.gz/src/modules/module-profiler.c -> pipewire-0.3.79.tar.gz/src/modules/module-profiler.c
Changed
@@ -104,7 +104,11 @@ struct spa_source *flush_event; unsigned int listening:1; +#ifdef max_align_t alignas(max_align_t) +#else + alignas(64) +#endif uint8_t flushFLUSH_BUFFER + sizeof(struct spa_pod_struct); };
View file
pipewire-0.3.77.tar.gz/src/modules/module-protocol-pulse/manager.c -> pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/manager.c
Changed
@@ -641,9 +641,10 @@ o->this.removing = true; - if (!o->this.creating) + if (!o->this.creating) { + o->this.change_mask = ~0; manager_emit_removed(m, &o->this); - + } object_destroy(o); }
View file
pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/modules/module-alsa-sink.c
Added
@@ -0,0 +1,239 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#include <pipewire/pipewire.h> + +#include "../manager.h" +#include "../module.h" + +#define NAME "alsa-sink" + +#define DEFAULT_DEVICE "default" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct module_alsa_sink_data { + struct pw_core *core; + struct spa_hook core_listener; + + struct pw_proxy *proxy; + struct spa_hook proxy_listener; +}; + +static void module_alsa_sink_proxy_removed(void *data) +{ + struct module *module = data; + struct module_alsa_sink_data *d = module->user_data; + pw_proxy_destroy(d->proxy); +} + +static void module_alsa_sink_proxy_destroy(void *data) +{ + struct module *module = data; + struct module_alsa_sink_data *d = module->user_data; + + pw_log_info("proxy %p destroy", d->proxy); + + spa_hook_remove(&d->proxy_listener); + d->proxy = NULL; + + module_schedule_unload(module); +} + +static void module_alsa_sink_proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) +{ + struct module *module = data; + struct module_alsa_sink_data *d = module->user_data; + + pw_log_info("proxy %p bound", d->proxy); + + module_emit_loaded(module, 0); +} + +static void module_alsa_sink_proxy_error(void *data, int seq, int res, const char *message) +{ + struct module *module = data; + struct module_alsa_sink_data *d = module->user_data; + + pw_log_info("proxy %p error %d", d->proxy, res); + + pw_proxy_destroy(d->proxy); +} + +static const struct pw_proxy_events proxy_events = { + PW_VERSION_PROXY_EVENTS, + .removed = module_alsa_sink_proxy_removed, + .bound_props = module_alsa_sink_proxy_bound_props, + .error = module_alsa_sink_proxy_error, + .destroy = module_alsa_sink_proxy_destroy, +}; + +static void module_alsa_sink_core_error(void *data, uint32_t id, int seq, int res, const char *message) +{ + struct module *module = data; + + pw_log_warn("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + + if (id == PW_ID_CORE && res == -EPIPE) + module_schedule_unload(module); +} + +static const struct pw_core_events core_events = { + PW_VERSION_CORE_EVENTS, + .error = module_alsa_sink_core_error, +}; + +static int module_alsa_sink_load(struct module *module) +{ + struct module_alsa_sink_data *d = module->user_data; + + d->core = pw_context_connect(module->impl->context, NULL, 0); + if (d->core == NULL) + return -errno; + + pw_core_add_listener(d->core, &d->core_listener, &core_events, module); + + pw_properties_setf(module->props, "pulse.module.id", "%u", module->index); + + d->proxy = pw_core_create_object(d->core, + "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, + module->props ? &module->props->dict : NULL, 0); + if (d->proxy == NULL) + return -errno; + + pw_proxy_add_listener(d->proxy, &d->proxy_listener, &proxy_events, module); + + return SPA_RESULT_RETURN_ASYNC(0); +} + +static int module_alsa_sink_unload(struct module *module) +{ + struct module_alsa_sink_data *d = module->user_data; + + if (d->proxy != NULL) { + spa_hook_remove(&d->proxy_listener); + pw_proxy_destroy(d->proxy); + d->proxy = NULL; + } + + if (d->core != NULL) { + spa_hook_remove(&d->core_listener); + pw_core_disconnect(d->core); + d->core = NULL; + } + + return 0; +} + +static const struct spa_dict_item module_alsa_sink_info = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "An ALSA sink" }, + { PW_KEY_MODULE_USAGE, + "name=<name of the sink, to be prefixed> " + "sink_name=<name for the sink> " + "sink_properties=<properties for the sink> " + "namereg_fail=<when false attempt to synthesise new sink_name if it is already taken> " + "device=<ALSA device> " + "device_id=<ALSA card index> " + "format=<sample format> " + "rate=<sample rate> " + "alternate_rate=<alternate sample rate> " + "channels=<number of channels> " + "channel_map=<channel map> " + "fragments=<number of fragments> " + "fragment_size=<fragment size> " + "mmap=<enable memory mapping?> " + "tsched=<enable system timer based scheduling mode?> " + "tsched_buffer_size=<buffer size when using timer based scheduling> " + "tsched_buffer_watermark=<lower fill watermark> " + "ignore_dB=<ignore dB information from the device?> " + "control=<name of mixer control, or name and index separated by a comma> " + "rewind_safeguard=<number of bytes that cannot be rewound> " + "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> " + "deferred_volume_safety_margin=<usec adjustment depending on volume direction> " + "deferred_volume_extra_delay=<usec adjustment to HW volume changes> " + "fixed_latency_range=<disable latency range changes on underrun?>" }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +static int module_alsa_sink_prepare(struct module * const module) +{ + struct pw_properties * const props = module->props; + const char *str, *dev_id; + struct spa_audio_info_raw info = { 0 }; + + PW_LOG_TOPIC_INIT(mod_topic); + + dev_id = pw_properties_get(props, "device_id"); + if (dev_id == NULL) + dev_id = pw_properties_get(props, "device"); + if (dev_id == NULL) + dev_id = DEFAULT_DEVICE; + + pw_properties_set(props, "api.alsa.path", dev_id); + + if ((str = pw_properties_get(props, "sink_name")) != NULL) { + pw_properties_set(props, PW_KEY_NODE_NAME, str); + pw_properties_set(props, "sink_name", NULL); + } + else if ((str = pw_properties_get(props, "name")) != NULL) { + pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", str); + pw_properties_set(props, "name", NULL); + } + else { + pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", dev_id); + } + + if ((str = pw_properties_get(props, "sink_properties")) != NULL) { + module_args_add_props(props, str); + pw_properties_set(props, "sink_properties", NULL); + } + + if ((str = pw_properties_get(props, "fragments")) != NULL) { + pw_properties_set(props, "api.alsa.period-num", str); + pw_properties_set(props, "fragments", NULL); + } + if ((str = pw_properties_get(props, "fragment_size")) != NULL) { + pw_properties_set(props, "api.alsa.period-size", str); + pw_properties_set(props, "fragment_size", NULL); + } + if ((str = pw_properties_get(props, "mmap")) != NULL) { + pw_properties_setf(props, "api.alsa.disable-mmap", + spa_atob(str) ? "false" : "true"); + pw_properties_set(props, "mmap", NULL); + } + + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) + return -EINVAL; + + audioinfo_to_properties(&info, props); + + if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) + pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + + if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL) + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "ALSA Sink on %s", dev_id); + + pw_properties_set(props, PW_KEY_FACTORY_NAME, "api.alsa.pcm.sink"); + + if (pw_properties_get(props, "monitor.channel-volumes") == NULL) + pw_properties_set(props, "monitor.channel-volumes", "true"); + if (pw_properties_get(props, "node.suspend-on-idle") == NULL) + pw_properties_set(props, "node.suspend-on-idle", "true"); + + return 0; +} + +DEFINE_MODULE_INFO(module_alsa_sink) = { + .name = "module-alsa-sink", + .prepare = module_alsa_sink_prepare, + .load = module_alsa_sink_load, + .unload = module_alsa_sink_unload, + .properties = &SPA_DICT_INIT_ARRAY(module_alsa_sink_info), + .data_size = sizeof(struct module_alsa_sink_data), +};
View file
pipewire-0.3.79.tar.gz/src/modules/module-protocol-pulse/modules/module-alsa-source.c
Added
@@ -0,0 +1,239 @@ +/* PipeWire */ +/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans <wim.taymans@gmail.com> */ +/* SPDX-License-Identifier: MIT */ + +#include <pipewire/pipewire.h> + +#include "../manager.h" +#include "../module.h" + +#define NAME "alsa-source" + +#define DEFAULT_DEVICE "default" + +PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); +#define PW_LOG_TOPIC_DEFAULT mod_topic + +struct module_alsa_source_data { + struct pw_core *core; + struct spa_hook core_listener; + + struct pw_proxy *proxy; + struct spa_hook proxy_listener; +}; + +static void module_alsa_source_proxy_removed(void *data) +{ + struct module *module = data; + struct module_alsa_source_data *d = module->user_data; + pw_proxy_destroy(d->proxy); +} + +static void module_alsa_source_proxy_destroy(void *data) +{ + struct module *module = data; + struct module_alsa_source_data *d = module->user_data; + + pw_log_info("proxy %p destroy", d->proxy); + + spa_hook_remove(&d->proxy_listener); + d->proxy = NULL; + + module_schedule_unload(module); +} + +static void module_alsa_source_proxy_bound_props(void *data, uint32_t global_id, const struct spa_dict *props) +{ + struct module *module = data; + struct module_alsa_source_data *d = module->user_data; + + pw_log_info("proxy %p bound", d->proxy); + + module_emit_loaded(module, 0); +} + +static void module_alsa_source_proxy_error(void *data, int seq, int res, const char *message) +{ + struct module *module = data; + struct module_alsa_source_data *d = module->user_data; + + pw_log_info("proxy %p error %d", d->proxy, res); + + pw_proxy_destroy(d->proxy); +} + +static const struct pw_proxy_events proxy_events = { + PW_VERSION_PROXY_EVENTS, + .removed = module_alsa_source_proxy_removed, + .bound_props = module_alsa_source_proxy_bound_props, + .error = module_alsa_source_proxy_error, + .destroy = module_alsa_source_proxy_destroy, +}; + +static void module_alsa_source_core_error(void *data, uint32_t id, int seq, int res, const char *message) +{ + struct module *module = data; + + pw_log_warn("error id:%u seq:%d res:%d (%s): %s", + id, seq, res, spa_strerror(res), message); + + if (id == PW_ID_CORE && res == -EPIPE) + module_schedule_unload(module); +} + +static const struct pw_core_events core_events = { + PW_VERSION_CORE_EVENTS, + .error = module_alsa_source_core_error, +}; + +static int module_alsa_source_load(struct module *module) +{ + struct module_alsa_source_data *d = module->user_data; + + d->core = pw_context_connect(module->impl->context, NULL, 0); + if (d->core == NULL) + return -errno; + + pw_core_add_listener(d->core, &d->core_listener, &core_events, module); + + pw_properties_setf(module->props, "pulse.module.id", "%u", module->index); + + d->proxy = pw_core_create_object(d->core, + "adapter", PW_TYPE_INTERFACE_Node, PW_VERSION_NODE, + module->props ? &module->props->dict : NULL, 0); + if (d->proxy == NULL) + return -errno; + + pw_proxy_add_listener(d->proxy, &d->proxy_listener, &proxy_events, module); + + return SPA_RESULT_RETURN_ASYNC(0); +} + +static int module_alsa_source_unload(struct module *module) +{ + struct module_alsa_source_data *d = module->user_data; + + if (d->proxy != NULL) { + spa_hook_remove(&d->proxy_listener); + pw_proxy_destroy(d->proxy); + d->proxy = NULL; + } + + if (d->core != NULL) { + spa_hook_remove(&d->core_listener); + pw_core_disconnect(d->core); + d->core = NULL; + } + + return 0; +} + +static const struct spa_dict_item module_alsa_source_info = { + { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, + { PW_KEY_MODULE_DESCRIPTION, "An ALSA source" }, + { PW_KEY_MODULE_USAGE, + "name=<name of the source, to be prefixed> " + "source_name=<name for the source> " + "source_properties=<properties for the source> " + "namereg_fail=<when false attempt to synthesise new source_name if it is already taken> " + "device=<ALSA device> " + "device_id=<ALSA card index> " + "format=<sample format> " + "rate=<sample rate> " + "alternate_rate=<alternate sample rate> " + "channels=<number of channels> " + "channel_map=<channel map> " + "fragments=<number of fragments> " + "fragment_size=<fragment size> " + "mmap=<enable memory mapping?> " + "tsched=<enable system timer based scheduling mode?> " + "tsched_buffer_size=<buffer size when using timer based scheduling> " + "tsched_buffer_watermark=<lower fill watermark> " + "ignore_dB=<ignore dB information from the device?> " + "control=<name of mixer control, or name and index separated by a comma> " + "rewind_safeguard=<number of bytes that cannot be rewound> " + "deferred_volume=<Synchronize software and hardware volume changes to avoid momentary jumps?> " + "deferred_volume_safety_margin=<usec adjustment depending on volume direction> " + "deferred_volume_extra_delay=<usec adjustment to HW volume changes> " + "fixed_latency_range=<disable latency range changes on underrun?>" }, + { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, +}; + +static int module_alsa_source_prepare(struct module * const module) +{ + struct pw_properties * const props = module->props; + const char *str, *dev_id; + struct spa_audio_info_raw info = { 0 }; + + PW_LOG_TOPIC_INIT(mod_topic); + + dev_id = pw_properties_get(props, "device_id"); + if (dev_id == NULL) + dev_id = pw_properties_get(props, "device"); + if (dev_id == NULL) + dev_id = DEFAULT_DEVICE; + + pw_properties_set(props, "api.alsa.path", dev_id); + + if ((str = pw_properties_get(props, "source_name")) != NULL) { + pw_properties_set(props, PW_KEY_NODE_NAME, str); + pw_properties_set(props, "source_name", NULL); + } + else if ((str = pw_properties_get(props, "name")) != NULL) { + pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", str); + pw_properties_set(props, "name", NULL); + } + else { + pw_properties_setf(props, PW_KEY_NODE_NAME, "alsa_output.%s", dev_id); + } + + if ((str = pw_properties_get(props, "source_properties")) != NULL) { + module_args_add_props(props, str); + pw_properties_set(props, "source_properties", NULL); + } + + if ((str = pw_properties_get(props, "fragments")) != NULL) { + pw_properties_set(props, "api.alsa.period-num", str); + pw_properties_set(props, "fragments", NULL); + } + if ((str = pw_properties_get(props, "fragment_size")) != NULL) { + pw_properties_set(props, "api.alsa.period-size", str); + pw_properties_set(props, "fragment_size", NULL); + } + if ((str = pw_properties_get(props, "mmap")) != NULL) { + pw_properties_setf(props, "api.alsa.disable-mmap", + spa_atob(str) ? "false" : "true"); + pw_properties_set(props, "mmap", NULL); + } + + if (module_args_to_audioinfo_keys(module->impl, props, + "format", "rate", "channels", "channel_map", &info) < 0) + return -EINVAL; + + audioinfo_to_properties(&info, props); + + if (pw_properties_get(props, PW_KEY_MEDIA_CLASS) == NULL) + pw_properties_set(props, PW_KEY_MEDIA_CLASS, "Audio/Source"); + + if ((str = pw_properties_get(props, PW_KEY_NODE_DESCRIPTION)) == NULL) + pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION, + "ALSA Source on %s", dev_id); + + pw_properties_set(props, PW_KEY_FACTORY_NAME, "api.alsa.pcm.source"); + + if (pw_properties_get(props, "monitor.channel-volumes") == NULL) + pw_properties_set(props, "monitor.channel-volumes", "true"); + if (pw_properties_get(props, "node.suspend-on-idle") == NULL) + pw_properties_set(props, "node.suspend-on-idle", "true"); + + return 0; +} + +DEFINE_MODULE_INFO(module_alsa_source) = { + .name = "module-alsa-source", + .prepare = module_alsa_source_prepare, + .load = module_alsa_source_load, + .unload = module_alsa_source_unload, + .properties = &SPA_DICT_INIT_ARRAY(module_alsa_source_info), + .data_size = sizeof(struct module_alsa_source_data), +};
View file
pipewire-0.3.77.tar.gz/src/modules/module-rtp-sap.c -> pipewire-0.3.79.tar.gz/src/modules/module-rtp-sap.c
Changed
@@ -75,7 +75,7 @@ * { matches = * # any of the items in matches needs to match, if one does, * # actions are emited. - * { # all keys must match the value. ~ in value starts regex. + * { # all keys must match the value. ! negates. ~ starts regex. * #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0" * #rtp.payload = "127" * #rtp.fmt = "L16/48000/2" @@ -91,7 +91,7 @@ * } * } * { matches = - * { # all keys must match the value. ~ in value starts regex. + * { # all keys must match the value. ! negates. ~ starts regex. * #rtp.origin = "wim 3883629975 0 IN IP4 0.0.0.0" * #rtp.payload = "127" * #rtp.fmt = "L16/48000/2" @@ -1435,6 +1435,7 @@ uint32_t port; const char *str; int res = 0; + char addr64; PW_LOG_TOPIC_INIT(mod_topic); @@ -1484,7 +1485,15 @@ res = ioctl(fd, SIOCGIFADDR, &req); if (res < 0) pw_log_warn("SIOCGIFADDR %s failed: %m", impl->ifname); - str = inet_ntoa(((struct sockaddr_in *)&req.ifr_addr)->sin_addr); + str = inet_ntop(req.ifr_addr.sa_family, + &((struct sockaddr_in *)&req.ifr_addr)->sin_addr, + addr, sizeof(addr)); + if (str == NULL) { + pw_log_warn("can't parse interface ip: %m"); + str = DEFAULT_SOURCE_IP; + } else { + pw_log_info("interface %s IP: %s", impl->ifname, str); + } close(fd); } }
View file
pipewire-0.3.77.tar.gz/src/modules/module-vban/audio.c -> pipewire-0.3.79.tar.gz/src/modules/module-vban/audio.c
Changed
@@ -103,7 +103,7 @@ hlen = VBAN_HEADER_SIZE; plen = len - hlen; - samples = SPA_MIN(hdr->format_nbs, plen / stride); + samples = SPA_MIN(hdr->format_nbs+1, plen / stride); n_frames = hdr->n_frames; if (impl->have_sync && impl->n_frames != n_frames) { @@ -132,7 +132,7 @@ filled = impl->target_buffer; spa_dll_init(&impl->dll); - spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 128, impl->rate); + spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, 128, impl->rate); memset(impl->buffer, 0, BUFFER_SIZE); impl->have_sync = true; } else if (expected_write != write) { @@ -145,7 +145,7 @@ BUFFER_SIZE / stride); impl->have_sync = false; } else { - pw_log_debug("got samples:%u", samples); + pw_log_trace("got samples:%u", samples); spa_ringbuffer_write_data(&impl->ring, impl->buffer, BUFFER_SIZE,
View file
pipewire-0.3.77.tar.gz/src/modules/module-vban/stream.c -> pipewire-0.3.79.tar.gz/src/modules/module-vban/stream.c
Changed
@@ -393,7 +393,7 @@ pw_properties_setf(props, "vban.channels", "%u", impl->info.info.raw.channels); spa_dll_init(&impl->dll); - spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MIN, 128, impl->rate); + spa_dll_set_bw(&impl->dll, SPA_DLL_BW_MAX, 128, impl->rate); impl->corr = 1.0; impl->stream = pw_stream_new(core, "vban-session", props);
View file
pipewire-0.3.77.tar.gz/src/pipewire/conf.c -> pipewire-0.3.79.tar.gz/src/pipewire/conf.c
Changed
@@ -586,6 +586,7 @@ /* * { * # all keys must match the value. ~ in value starts regex. + * # ! as the first char of the value negates the match * <key> = <value> * ... * } @@ -598,7 +599,7 @@ char key256, val1024; const char *str, *value; int match = 0, fail = 0; - int len; + int len, skip = 0; while (spa_json_get_string(&it0, key, sizeof(key)) > 0) { bool success = false; @@ -615,18 +616,28 @@ continue; value = val; len = strlen(val); + if (len > 0 && value0 == '!') { + success = !success; + skip++; + } } if (str != NULL) { - if (value0 == '~') { + if (valueskip == '~') { regex_t preg; - if (regcomp(&preg, value+1, REG_EXTENDED | REG_NOSUB) == 0) { + int res; + skip++; + if ((res = regcomp(&preg, value+skip, REG_EXTENDED | REG_NOSUB)) != 0) { + char errbuf1024; + regerror(res, &preg, errbuf, sizeof(errbuf)); + pw_log_warn("invalid regex %s: %s", value+skip, errbuf); + } else { if (regexec(&preg, str, 0, NULL, 0) == 0) - success = true; + success = !success; regfree(&preg); } - } else if (strncmp(str, value, len) == 0 && - strlen(str) == (size_t)len) { - success = true; + } else if (strncmp(str, value+skip, len-skip) == 0 && + strlen(str) == (size_t)(len-skip)) { + success = !success; } } if (success) { @@ -634,6 +645,7 @@ pw_log_debug("'%s' match '%s' < > '%.*s'", key, str, len, value); } else { + pw_log_debug("'%s' fail '%s' < > '%.*s'", key, str, len, value); fail++; break; } @@ -1075,7 +1087,7 @@ * # any of the items in matches needs to match, if one does, * # actions are emited. * { - * # all keys must match the value. ~ in value starts regex. + * # all keys must match the value. ! negates. ~ starts regex. * <key> = <value> * ... * }
View file
pipewire-0.3.77.tar.gz/src/pipewire/context.c -> pipewire-0.3.79.tar.gz/src/pipewire/context.c
Changed
@@ -787,44 +787,46 @@ return pw_impl_node_set_state(node, state); } -/* From a node (that is runnable) follow all prepared links and groups to - * active nodes up to the driver and make them recursively runnable as well. - * - * We stop at driver nodes so that other paths linked to the driver will stay - * unrunnable when no other runnable path exists. +/* From a node (that is runnable) follow all prepared links in the given direction + * 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) +static inline int run_nodes(struct pw_context *context, struct pw_impl_node *node, + struct spa_list *nodes, enum pw_direction direction) { struct pw_impl_node *t; struct pw_impl_port *p; struct pw_impl_link *l; - pw_log_debug("node %p: '%s'", node, node->name); + pw_log_debug("node %p: '%s' direction:%s", node, node->name, + pw_direction_as_string(direction)); - spa_list_for_each(p, &node->input_ports, link) { - spa_list_for_each(l, &p->links, input_link) { - t = l->output->node; + SPA_FLAG_SET(node->checked, 1u<<direction); - if (!t->active || !l->prepared || t->runnable) - continue; + if (direction == PW_DIRECTION_INPUT) { + spa_list_for_each(p, &node->input_ports, link) { + spa_list_for_each(l, &p->links, input_link) { + t = l->output->node; - pw_log_debug(" peer %p: '%s'", t, t->name); - t->runnable = true; - if (!t->driving) - run_nodes(context, t, nodes); + if (!t->active || !l->prepared || (!t->driving && t->runnable)) + continue; + + pw_log_debug(" peer %p: '%s'", t, t->name); + t->runnable = true; + run_nodes(context, t, nodes, direction); + } } - } - spa_list_for_each(p, &node->output_ports, link) { - spa_list_for_each(l, &p->links, output_link) { - t = l->input->node; + } else { + spa_list_for_each(p, &node->output_ports, link) { + spa_list_for_each(l, &p->links, output_link) { + t = l->input->node; - if (!t->active || !l->prepared || t->runnable) - continue; + if (!t->active || !l->prepared || (!t->driving && t->runnable)) + continue; - pw_log_debug(" peer %p: '%s'", t, t->name); - t->runnable = true; - if (!t->driving) - run_nodes(context, t, nodes); + pw_log_debug(" peer %p: '%s'", t, t->name); + t->runnable = true; + run_nodes(context, t, nodes, direction); + } } } /* now go through all the nodes that have the same link group and @@ -834,7 +836,8 @@ * them. */ if (node->link_group != NULL) { spa_list_for_each(t, nodes, sort_link) { - if (t->exported || !t->active || t->runnable) + if (t->exported || !t->active || + SPA_FLAG_IS_SET(t->checked, 1u<<direction)) continue; if (!spa_streq(t->link_group, node->link_group)) continue; @@ -842,7 +845,7 @@ pw_log_debug(" group %p: '%s'", t, t->name); t->runnable = true; if (!t->driving) - run_nodes(context, t, nodes); + run_nodes(context, t, nodes, direction); } } return 0; @@ -944,8 +947,10 @@ pw_log_debug(" next node %p: '%s' runnable:%u", n, n->name, n->runnable); } spa_list_for_each(n, collect, sort_link) - if (!n->driving && n->runnable) - run_nodes(context, n, collect); + if (!n->driving && n->runnable) { + run_nodes(context, n, collect, PW_DIRECTION_OUTPUT); + run_nodes(context, n, collect, PW_DIRECTION_INPUT); + } return 0; } @@ -1199,6 +1204,7 @@ /* clean up the flags first */ spa_list_for_each(n, &context->node_list, link) { n->visited = false; + n->checked = 0; n->runnable = n->always_process && n->active; }
View file
pipewire-0.3.77.tar.gz/src/pipewire/impl-node.c -> pipewire-0.3.79.tar.gz/src/pipewire/impl-node.c
Changed
@@ -445,6 +445,17 @@ node_deactivate(this); + pw_log_debug("%p: suspend node driving:%d driver:%d added:%d", this, + this->driving, this->driver, this->added); + + res = spa_node_send_command(this->node, + &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend)); + if (res == -ENOTSUP) + res = spa_node_send_command(this->node, + &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause)); + if (res < 0 && res != -EIO) + pw_log_warn("%p: suspend node error %s", this, spa_strerror(res)); + spa_list_for_each(p, &this->input_ports, link) { if ((res = pw_impl_port_set_param(p, SPA_PARAM_Format, 0, NULL)) < 0) pw_log_warn("%p: error unset format input: %s", @@ -461,17 +472,6 @@ p->state = PW_IMPL_PORT_STATE_CONFIGURE; } - pw_log_debug("%p: suspend node driving:%d driver:%d added:%d", this, - this->driving, this->driver, this->added); - - res = spa_node_send_command(this->node, - &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Suspend)); - if (res == -ENOTSUP) - res = spa_node_send_command(this->node, - &SPA_NODE_COMMAND_INIT(SPA_NODE_COMMAND_Pause)); - if (res < 0 && res != -EIO) - pw_log_warn("%p: suspend node error %s", this, spa_strerror(res)); - node_update_state(this, PW_NODE_STATE_SUSPENDED, 0, NULL); return res; @@ -1796,7 +1796,12 @@ * help drivers that don't support this yet */ if (SPA_UNLIKELY(node->rt.position->clock.duration != node->rt.position->clock.target_duration || node->rt.position->clock.rate.denom != node->rt.position->clock.target_rate.denom)) { - pw_log_warn("driver %s did not update duration/rate", node->name); + pw_log_warn("driver %s did not update duration/rate (%"PRIu64"/%"PRIu64" %u/%u)", + node->name, + node->rt.position->clock.duration, + node->rt.position->clock.target_duration, + node->rt.position->clock.rate.denom, + node->rt.position->clock.target_rate.denom); node->rt.position->clock.duration = node->rt.position->clock.target_duration; node->rt.position->clock.rate = node->rt.position->clock.target_rate; }
View file
pipewire-0.3.77.tar.gz/src/pipewire/pipewire.c -> pipewire-0.3.79.tar.gz/src/pipewire/pipewire.c
Changed
@@ -598,8 +598,11 @@ char *patterns = NULL; n_items = 0; - if (!support->no_color) - itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_COLORS, "true"); + if (!support->no_color) { + if ((str = getenv("PIPEWIRE_LOG_COLOR")) == NULL) + str = "true"; + itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_COLORS, str); + } itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_TIMESTAMP, "true"); if ((str = getenv("PIPEWIRE_LOG_LINE")) == NULL || spa_atob(str)) itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_LOG_LINE, "true");
View file
pipewire-0.3.77.tar.gz/src/pipewire/private.h -> pipewire-0.3.79.tar.gz/src/pipewire/private.h
Changed
@@ -676,6 +676,7 @@ unsigned int trigger:1; /**< has the TRIGGER property and needs an extra * trigger to start processing. */ unsigned int can_suspend:1; + unsigned int checked; /**< for sorting */ uint32_t port_user_data_size; /**< extra size for port user data */
View file
pipewire-0.3.77.tar.gz/src/pipewire/stream.h -> pipewire-0.3.79.tar.gz/src/pipewire/stream.h
Changed
@@ -226,10 +226,12 @@ * value, and pw_time.ticks, were captured at pw_time.now and can be extrapolated * to the current time like this: * + *\code{.c} * struct timespec ts; * clock_gettime(CLOCK_MONOTONIC, &ts); * int64_t diff = SPA_TIMESPEC_TO_NSEC(&ts) - pw_time.now; * int64_t elapsed = (pw_time.rate.denom * diff) / (pw_time.rate.num * SPA_NSEC_PER_SEC); + *\endcode * * pw_time.delay contains the total delay that a signal will travel through the * graph. This includes the delay caused by filters in the graph as well as delays @@ -255,15 +257,21 @@ * in milliseconds for the first sample in the newly queued buffer to be played * by the hardware can be calculated as: * + *\code{.unparsed} * (pw_time.buffered * 1000 / stream.samplerate) + * (pw_time.queued * 1000 / app.rate) + * ((pw_time.delay - elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom) + *\endcode * * The current extrapolated time (in ms) in the source or sink can be calculated as: * + *\code{.unparsed} * (pw_time.ticks + elapsed) * 1000 * pw_time.rate.num / pw_time.rate.denom + *\endcode * + * Below is an overview of the different timing values: * + *\code{.unparsed} * stream time domain graph time domain * /-----------------------\/-----------------------------\ * @@ -275,6 +283,7 @@ * latency latency * \--------/\-------------/\-----------------------------/ * queued buffered delay + *\endcode */ struct pw_time { int64_t now; /**< the monotonic time in nanoseconds. This is the time
View file
pipewire-0.3.77.tar.gz/src/tools/pw-mon.c -> pipewire-0.3.79.tar.gz/src/tools/pw-mon.c
Changed
@@ -757,7 +757,7 @@ setlinebuf(stdout); - if (isatty(STDERR_FILENO) && getenv("NO_COLOR") == NULL) + if (isatty(STDOUT_FILENO) && getenv("NO_COLOR") == NULL) colors = true; while ((c = getopt_long(argc, argv, "hVr:NC", long_options, NULL)) != -1) {
View file
pipewire-0.3.77.tar.gz/src/tools/pw-top.c -> pipewire-0.3.79.tar.gz/src/tools/pw-top.c
Changed
@@ -82,6 +82,9 @@ unsigned pending_refresh:1; WINDOW *win; + + unsigned int batch_mode:1; + int iterations; }; struct point { @@ -89,6 +92,22 @@ struct driver info; }; +static SPA_PRINTF_FUNC(4, 5) void print_mode_dependent(struct data *d, int y, int x, const char *fmt, ...) +{ + va_list argp; + if (!d->batch_mode) + mvwprintw(d->win, y, x, "%s", ""); + + va_start(argp, fmt); + if (d->batch_mode) { + vprintf(fmt, argp); + printf("\n"); + } else + vw_printw(d->win, fmt, argp); + va_end(argp); +} + + static int process_info(struct data *d, const struct spa_pod *pod, struct driver *info) { return spa_pod_parse_struct(pod, @@ -144,7 +163,7 @@ .destroy = on_node_destroy, }; -static void do_refresh(struct data *d); +static void do_refresh(struct data *d, bool force_refresh); static void node_info(void *data, const struct pw_node_info *info) { @@ -152,7 +171,7 @@ if (n->state != info->state) { n->state = info->state; - do_refresh(n->data); + do_refresh(n->data, !n->data->batch_mode); } } @@ -259,7 +278,7 @@ break; } done: - do_refresh(n->data); + do_refresh(n->data, !n->data->batch_mode); } static const struct pw_node_events node_events = { @@ -296,7 +315,8 @@ } spa_list_append(&d->node_list, &n->link); d->n_nodes++; - d->pending_refresh = true; + if (!d->batch_mode) + d->pending_refresh = true; return n; } @@ -307,7 +327,8 @@ pw_proxy_destroy(n->proxy); spa_list_remove(&n->link); d->n_nodes--; - d->pending_refresh = true; + if (!d->batch_mode) + d->pending_refresh = true; free(n); } @@ -462,7 +483,7 @@ else busy = -1; - mvwprintw(d->win, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %16.16s %s%s", + print_mode_dependent(d, y, 0, "%s %4.1u %6.1u %6.1u %s %s %s %s %3.1u %16.16s %s%s", state_as_string(n->state), n->id, frac.num, frac.denom, @@ -484,23 +505,31 @@ spa_zero(n->info); } -static void do_refresh(struct data *d) +#define HEADER "S ID QUANT RATE WAIT BUSY W/Q B/Q ERR FORMAT NAME " + +static void do_refresh(struct data *d, bool force_refresh) { struct node *n, *t, *f; int y = 1; - 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 FORMAT NAME "); - wattroff(d->win, A_REVERSE); - wprintw(d->win, "\n"); + if (!d->pending_refresh && !force_refresh) + return; + + if (!d->batch_mode) { + wclear(d->win); + wattron(d->win, A_REVERSE); + wprintw(d->win, "%-*.*s", COLS, COLS, HEADER); + wattroff(d->win, A_REVERSE); + wprintw(d->win, "\n"); + } else + printf(HEADER "\n"); spa_list_for_each_safe(n, t, &d->node_list, link) { if (n->driver != n) continue; print_node(d, &n->info, n, y++); - if(y > LINES) + if(!d->batch_mode && y > LINES) break; spa_list_for_each(f, &d->node_list, link) { @@ -517,19 +546,28 @@ } } - // Clear from last line to the end of the window to hide text wrapping from the last node - wmove(d->win, y, 0); - wclrtobot(d->win); + if (!d->batch_mode) { + // Clear from last line to the end of the window to hide text wrapping from the last node + wmove(d->win, y, 0); + wclrtobot(d->win); + + wrefresh(d->win); + } - wrefresh(d->win); d->pending_refresh = false; + + if (d->iterations > 0) + d->iterations--; + + if (d->iterations == 0) + pw_main_loop_quit(d->loop); } static void do_timeout(void *data, uint64_t expirations) { struct data *d = data; d->generation++; - do_refresh(d); + do_refresh(d, true); } static void profiler_profile(void *data, const struct spa_pod *pod) @@ -568,8 +606,8 @@ if (res < 0) continue; } - if (d->pending_refresh) - do_refresh(d); + + do_refresh(d, false); } static const struct pw_profiler_events profiler_events = { @@ -608,8 +646,8 @@ d->profiler = proxy; pw_proxy_add_object_listener(proxy, &d->profiler_listener, &profiler_events, d); } - if (d->pending_refresh) - do_refresh(d); + + do_refresh(d, false); return; error_proxy: @@ -623,8 +661,8 @@ struct node *n; if ((n = find_node(d, id)) != NULL) remove_node(d, n); - if (d->pending_refresh) - do_refresh(d); + + do_refresh(d, false); } static const struct pw_registry_events registry_events = { @@ -662,7 +700,7 @@ pw_log_error("no Profiler Interface found, please load one in the server"); pw_main_loop_quit(d->loop); } else { - do_refresh(d); + do_refresh(d, true); } } } @@ -681,10 +719,14 @@ static void show_help(const char *name, bool error) { - fprintf(error ? stderr : stdout, "%s options\n" + fprintf(error ? stderr : stdout, "Usage:\n%s options\n\n" + "Options:\n" + " -b, --batch-mode run in non-interactive batch_mode mode\n" + " -n, --iterations = NUMBER exit on maximum iterations NUMBER\n" + " -r, --remote Remote daemon name\n" + "\n" " -h, --help Show this help\n" - " --version Show version\n" - " -r, --remote Remote daemon name\n", + " -V --version Show version\n", name); } @@ -713,7 +755,7 @@ pw_main_loop_quit(d->loop); break; default: - do_refresh(d); + do_refresh(d, !d->batch_mode); break; } } @@ -725,9 +767,11 @@ struct pw_loop *l; const char *opt_remote = NULL; static const struct option long_options = { + { "batch-mode", no_argument, NULL, 'b' }, + { "iterations", required_argument, NULL, 'n' }, + { "remote", required_argument, NULL, 'r' }, { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, - { "remote", required_argument, NULL, 'r' }, { NULL, 0, NULL, 0} }; int c; @@ -737,9 +781,11 @@ setlocale(LC_ALL, ""); pw_init(&argc, &argv); + data.iterations = -1; + spa_list_init(&data.node_list); - while ((c = getopt_long(argc, argv, "hVr:o:", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "hVr:o:bn:", long_options, NULL)) != -1) { switch (c) { case 'h': show_help(argv0, false); @@ -755,6 +801,12 @@ case 'r': opt_remote = optarg; break; + case 'b': + data.batch_mode = 1; + break; + case 'n': + spa_atoi32(optarg, &data.iterations, 10); + break; default: show_help(argv0, true); return -1; @@ -767,6 +819,9 @@ return -1; } + if (!data.batch_mode) + data.iterations = -1; + l = pw_main_loop_get_loop(data.loop); pw_loop_add_signal(l, SIGINT, do_quit, &data); pw_loop_add_signal(l, SIGTERM, do_quit, &data); @@ -800,9 +855,10 @@ data.check_profiler = pw_core_sync(data.core, 0, 0); - terminal_start(); - - data.win = newwin(LINES, COLS, 0, 0); + if (!data.batch_mode) { + terminal_start(); + data.win = newwin(LINES, COLS, 0, 0); + } data.timer = pw_loop_add_timer(l, do_timeout, &data); value.tv_sec = 1; @@ -811,15 +867,16 @@ interval.tv_nsec = 0; pw_loop_update_timer(l, data.timer, &value, &interval, false); - pw_loop_add_io(l, fileno(stdin), SPA_IO_IN, false, do_handle_io, &data); + if (!data.batch_mode) + pw_loop_add_io(l, fileno(stdin), SPA_IO_IN, false, do_handle_io, &data); pw_main_loop_run(data.loop); - terminal_stop(); + if (!data.batch_mode) + terminal_stop(); spa_list_consume(n, &data.node_list, link) remove_node(&data, n); - if (data.profiler) { spa_hook_remove(&data.profiler_listener); pw_proxy_destroy((struct pw_proxy*)data.profiler);
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
.