Projects
Essentials
pipewire-aptx
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 60
View file
pipewire-aptx.changes
Changed
@@ -1,4 +1,9 @@ ------------------------------------------------------------------- +Sat Nov 15 13:00:32 UTC 2025 - Bjørn Lie <zaitor@opensuse.org> + +- Update to version 1.5.83 + +------------------------------------------------------------------- Sun Nov 2 11:28:58 UTC 2025 - Bjørn Lie <zaitor@opensuse.org> - Update to version 1.5.81
View file
pipewire-aptx.spec
Changed
@@ -8,7 +8,7 @@ %define minimum_version 1.5.0 Name: pipewire-aptx -Version: 1.5.81 +Version: 1.5.83 Release: 0 Summary: PipeWire Bluetooth aptX codec plugin License: MIT
View file
_service:download_files:pipewire-1.5.81.tar.bz2/.gitlab-ci.yml -> _service:download_files:pipewire-1.5.83.tar.bz2/.gitlab-ci.yml
Changed
@@ -38,7 +38,7 @@ .fedora: variables: # Update this tag when you want to trigger a rebuild - FDO_DISTRIBUTION_TAG: '2025-10-15.0' + FDO_DISTRIBUTION_TAG: '2025-10-22.0' FDO_DISTRIBUTION_VERSION: '42' FDO_DISTRIBUTION_PACKAGES: >- alsa-lib-devel @@ -48,6 +48,7 @@ dbus-devel doxygen fdk-aac-free-devel + file findutils gcc gcc-c++
View file
_service:download_files:pipewire-1.5.81.tar.bz2/NEWS -> _service:download_files:pipewire-1.5.83.tar.bz2/NEWS
Changed
@@ -1,3 +1,76 @@ +# PipeWire 1.5.83 (2025-11-06) + +This is the third 1.6 release candidate that is API and ABI +compatible with previous 1.4.x, 1.2.x and 1.0.x releases. + +Changes since the last pre-release: + +## Highlights + - Include the NEWS and updated version number. + + +Older versions: + +# PipeWire 1.5.82 (2025-11-06) + +This is the second 1.6 release candidate that is API and ABI +compatible with previous 1.4.x, 1.2.x and 1.0.x releases. + +Changes since the last pre-release: + +## Highlights + - The max channel limit is now a compile time option. + - The SAP and RTP module have seen some robustness improvements. + - Add audio.layout propperty. + - Cleanups to the code here and there. + +## PipeWire + - Handle Tags more like Latency with a NULL param when no ports are linked + and some sort of (empty) Tag when the ports are linked. + +## Modules + - Improve the echo-cancel module to keep the streams more aligned + and cause less latency. + - Improve format parsing errors in most modules. + - The RTP module now has extra code for better network robustness, including + cases when network interfaces are not yet up and running, and multicast + sockets are silently kicked out of IGMP groups. + - The direct timestamp mode in the RTP module was effectively broken and is + now fixed. + - Add support for audio.layout. + - Add multichannel support to ROC. + +## SPA + - Rework the maximum number of channel handling. Because this is a + potential ABI break, it is now a compile time option with new + functions to handle more than the previous 64 channels. + - The 64 channel limit was removed from the noise shaper. + - spa_strbuf is used in more places instead of custom snprintf code. + - The volume ramp code was simplified. + - The driver node now has properties to configure the clock. + - The adapter will try to renegotiate when the driver changes. + - Fix relaxed array parsing with od number of elements. (#4944) + - audio.layout was added to set the channel positions to some + predefined layouts. + - Added more POD choice checks to ensure the right amount of values + are present in the choice. + - Fix __has_attribute usage. (#4962) + - Thread RESET_ON_FORK is now disabled for JACK application so that + forking will preserve any real-time thread priorities, like JACK. + (#4966) + - Fix some compilation issues. (#4960 and #4961). + +## Pulse-server + - Fix missing subscription events on device port changes. + - Increase min.quantum to 256/48000. (#4875) + +## GStreamer + - Avoid overflow in clock time calculations. + - Fix renegotiation. + +## Docs + - Swap the name and id of device.product + # PipeWire 1.5.81 (2025-10-16) This is the first 1.6 release candidate that is API and ABI @@ -166,8 +239,11 @@ ## Bluetooth - Telephony improvements. - ASHA support was added. - - Add packet loss correction with spandsp for some codecs. - - Synchronisation between ISO streams in the same group. + - Packet loss concealment was added. + - Improved synchronisation between LE Audio streams in the same group. + - Improved LE Audio device compatibility. + - LC3-24kHz voice codec was added (used by Airpods) + - LDAC decoding support added (requires separate decoder library) ## Pulse-server - The SUSPEND event is now correctly generated. fail-on-suspend is @@ -193,9 +269,6 @@ ## Docs - Document the client-node flow a bit more. - -Older versions: - # PipeWire 1.4.0 (2025-03-06) This is the 1.4 release that is API and ABI compatible with previous
View file
_service:download_files:pipewire-1.5.81.tar.bz2/doc/dox/api/spa-pod.dox -> _service:download_files:pipewire-1.5.83.tar.bz2/doc/dox/api/spa-pod.dox
Changed
@@ -33,7 +33,7 @@ - `SPA_TYPE_Bytes`: A byte array. - `SPA_TYPE_Rectangle`: A rectangle with width and height. - `SPA_TYPE_Fraction`: A fraction with numerator and denominator. -- `SPA_TYPE_Bitmap`: An array of bits. +- `SPA_TYPE_Bitmap`: An array of bits. Deprecated and unused. POD's can be grouped together in these container types: @@ -435,10 +435,11 @@ \endcode `spa_pod_get_values()` is a useful function. It returns a -`struct spa_pod*` with and array of values. For normal POD's -and choice none values, it simply returns the POD and one value. -For other choice values it returns the choice type and an array -of values: +`struct spa_pod*` with and array of values. For invalid PODs +it returns the POD and no values. For normal PODs it returns +the POD and one value. For choice values it returns the choice +type and an array of values. If the choice doesn't fit even a +single value, the array will have no values. \code{.c} struct spa_pod *value;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/doc/dox/config/pipewire-props.7.md -> _service:download_files:pipewire-1.5.83.tar.bz2/doc/dox/config/pipewire-props.7.md
Changed
@@ -174,12 +174,12 @@ @PAR@ device-prop device.product.id # integer \parblock -\copydoc PW_KEY_DEVICE_PRODUCT_NAME +\copydoc PW_KEY_DEVICE_PRODUCT_ID \endparblock @PAR@ device-prop device.product.name # string \parblock -\copydoc PW_KEY_DEVICE_PRODUCT_ID +\copydoc PW_KEY_DEVICE_PRODUCT_NAME \endparblock @PAR@ device-prop device.class # string @@ -843,6 +843,9 @@ @PAR@ node-prop audio.position # JSON array of strings The audio position of the channels in the device. This is auto detected based on the profile. You can configure an array of channel positions, like " FL, FR ". +@PAR@ node-prop audio.layout # string +The audio layout of the channels in the device. You can use any of the predefined layouts, like "Stereo", "5.1" etc. + @PAR@ node-prop audio.allowed-rates # JSON array of integers \parblock The allowed audio rates to open the device with. Default is " ", which means the device can be opened in any supported rate.
View file
_service:download_files:pipewire-1.5.81.tar.bz2/meson.build -> _service:download_files:pipewire-1.5.83.tar.bz2/meson.build
Changed
@@ -1,5 +1,5 @@ project('pipewire', 'c' , - version : '1.5.81', + version : '1.5.83', license : 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' , meson_version : '>= 0.61.1', default_options : 'warning_level=3', @@ -115,10 +115,11 @@ '-Werror=old-style-definition', '-Werror=missing-parameter-type', '-Werror=strict-prototypes', + '-DSPA_AUDIO_MAX_CHANNELS=128u', add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c') - -cc_flags_native = cc_native.get_supported_arguments(cc_flags) +add_project_arguments(cc_native.get_supported_arguments(cc_flags), + language: 'c', native: true) have_cpp = add_languages('cpp', native: false, required : false)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c -> _service:download_files:pipewire-1.5.83.tar.bz2/pipewire-alsa/alsa-plugins/ctl_pipewire.c
Changed
@@ -22,9 +22,11 @@ #define VOLUME_MIN ((uint32_t) 0U) #define VOLUME_MAX ((uint32_t) 0x10000U) +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + struct volume { uint32_t channels; - long valuesSPA_AUDIO_MAX_CHANNELS; + long valuesMAX_CHANNELS; }; typedef struct { @@ -498,7 +500,7 @@ spa_pod_builder_push_object(b, &f0, SPA_TYPE_OBJECT_Props, SPA_PARAM_Props); if (volume) { - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; uint32_t i, n_volumes = 0; n_volumes = volume->channels; @@ -850,11 +852,11 @@ break; case SPA_PROP_channelVolumes: { - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; uint32_t n_volumes, i; n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - volumes, SPA_AUDIO_MAX_CHANNELS); + volumes, SPA_N_ELEMENTS(volumes)); g->node.channel_volume.channels = n_volumes; for (i = 0; i < n_volumes; i++)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/pipewire-alsa/alsa-plugins/pcm_pipewire.c -> _service:download_files:pipewire-1.5.83.tar.bz2/pipewire-alsa/alsa-plugins/pcm_pipewire.c
Changed
@@ -31,6 +31,7 @@ #define MAX_BUFFERS 64u #define MAX_RATE (48000*8) +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define MIN_PERIOD 64 @@ -642,7 +643,7 @@ #define _FORMAT_BE(p, fmt) p ? SPA_AUDIO_FORMAT_UNKNOWN : SPA_AUDIO_FORMAT_ ## fmt ## _OE #endif -static int set_default_channels(uint32_t channels, uint32_t positionSPA_AUDIO_MAX_CHANNELS) +static int set_default_channels(uint32_t channels, uint32_t positionMAX_CHANNELS) { switch (channels) { case 8: @@ -915,12 +916,16 @@ default: return -EINVAL; } + if (map->channels > MAX_CHANNELS) + return -ENOTSUP; + for (i = 0; i < map->channels; i++) { + char buf8; positioni = chmap_to_channel(map->posi); pw_log_debug("map %d: %s / %s", i, snd_pcm_chmap_name(map->posi), - spa_debug_type_find_short_name(spa_type_audio_channel, - positioni)); + spa_type_audio_channel_make_short_name(positioni, + buf, sizeof(buf), "UNK")); } return 1; } @@ -1097,7 +1102,7 @@ { "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, SPA_AUDIO_MAX_CHANNELS }, 2, collect_int }, + { 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,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/pipewire-jack/src/pipewire-jack.c -> _service:download_files:pipewire-1.5.83.tar.bz2/pipewire-jack/src/pipewire-jack.c
Changed
@@ -4299,6 +4299,7 @@ client->props = pw_properties_new( PW_KEY_LOOP_CANCEL, "true", + SPA_KEY_THREAD_RESET_ON_FORK, "false", PW_KEY_REMOTE_NAME, client->server_name, PW_KEY_CLIENT_NAME, client_name, PW_KEY_CLIENT_API, "jack",
View file
_service:download_files:pipewire-1.5.81.tar.bz2/po/tr.po -> _service:download_files:pipewire-1.5.83.tar.bz2/po/tr.po
Changed
@@ -1,46 +1,51 @@ # Turkish translation for PipeWire. -# Copyright (C) 2014-2024 PipeWire's COPYRIGHT HOLDER +# Copyright (C) 2014-2025 PipeWire's COPYRIGHT HOLDER # This file is distributed under the same license as the PipeWire package. # # Necdet Yücel <necdetyucel@gmail.com>, 2014. # Kaan Özdinçer <kaanozdincer@gmail.com>, 2014. # Muhammet Kara <muhammetk@gmail.com>, 2015, 2016, 2017. # Oğuz Ersen <oguz@ersen.moe>, 2021-2022. -# Sabri Ünal <libreajans@gmail.com>, 2024. +# Sabri Ünal <yakushabb@gmail.com>, 2024, 2025. # msgid "" msgstr "" "Project-Id-Version: PipeWire master\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2024-02-25 03:43+0300\n" -"PO-Revision-Date: 2024-02-25 03:49+0300\n" -"Last-Translator: Sabri Ünal <libreajans@gmail.com>\n" +"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" +"issues\n" +"POT-Creation-Date: 2025-10-24 15:37+0000\n" +"PO-Revision-Date: 2025-10-24 20:15+0300\n" +"Last-Translator: Sabri Ünal <yakushabb@gmail.com>\n" "Language-Team: Türkçe <takim@gnome.org.tr>\n" "Language: tr\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=1; plural=0;\n" -"X-Generator: Poedit 3.4.2\n" +"X-Generator: Poedit 3.8\n" -#: src/daemon/pipewire.c:26 +#: src/daemon/pipewire.c:29 #, c-format msgid "" "%s options\n" " -h, --help Show this help\n" +" -v, --verbose Increase verbosity by one level\n" " --version Show version\n" " -c, --config Load config (Default %s)\n" +" -P --properties Set context properties\n" msgstr "" "%s seçenekler\n" " -h, --help Bu yardımı göster\n" +" -v, --verbose Ayrıntı düzeyini bir düzey artır\n" " --version Sürümü göster\n" " -c, --config Yapılandırmayı yükle (Öntanımlı %s)\n" +" -P --properties Bağlam özelliklerini ayarla\n" -#: src/daemon/pipewire.desktop.in:4 +#: src/daemon/pipewire.desktop.in:3 msgid "PipeWire Media System" msgstr "PipeWire Ortam Sistemi" -#: src/daemon/pipewire.desktop.in:5 +#: src/daemon/pipewire.desktop.in:4 msgid "Start the PipeWire Media System" msgstr "PipeWire Ortam Sistemini Başlat" @@ -54,26 +59,26 @@ msgid "Dummy Output" msgstr "Temsili Çıkış" -#: src/modules/module-pulse-tunnel.c:774 +#: src/modules/module-pulse-tunnel.c:760 #, c-format msgid "Tunnel for %s@%s" msgstr "%s@%s için tünel" -#: src/modules/module-zeroconf-discover.c:315 +#: src/modules/module-zeroconf-discover.c:320 msgid "Unknown device" msgstr "Bilinmeyen aygıt" -#: src/modules/module-zeroconf-discover.c:327 +#: src/modules/module-zeroconf-discover.c:332 #, c-format msgid "%s on %s@%s" msgstr "%s, %s@%s" -#: src/modules/module-zeroconf-discover.c:331 +#: src/modules/module-zeroconf-discover.c:336 #, c-format msgid "%s on %s" msgstr "%s, %s" -#: src/tools/pw-cat.c:991 +#: src/tools/pw-cat.c:1096 #, c-format msgid "" "%s options <file>|-\n" @@ -88,7 +93,7 @@ " -v, --verbose Ayrıntılı işlemleri etkinleştir\n" "\n" -#: src/tools/pw-cat.c:998 +#: src/tools/pw-cat.c:1103 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -122,7 +127,7 @@ " -P --properties Düğüm özelliklerini ayarla\n" "\n" -#: src/tools/pw-cat.c:1016 +#: src/tools/pw-cat.c:1121 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -139,6 +144,10 @@ " --volume Stream volume 0-1.0 (default %.3f)\n" " -q --quality Resampler quality (0 - 15) (default " "%d)\n" +" -a, --raw RAW mode\n" +" -M, --force-midi Force midi format, one of \"midi\" " +"or \"ump\", (default ump)\n" +" -n, --sample-count COUNT Stop after COUNT samples\n" "\n" msgstr "" " --rate Örnekleme oranı (kayıt için gerekli) " @@ -156,15 +165,21 @@ "%.3f)\n" " -q --quality Yeniden örnekleyici kalitesi (0 - " "15) (öntanımlı %d)\n" +" -a, --raw HAM kipi\n" +" -M, --force-midi Midi biçimini zorla, ikisinden " +"birisi \"midi\" ya da\"ump\", (öntanımlı ump)\n" +" -n, --sample-count COUNT COUNT örnekleme sonrası dur\n" "\n" -#: src/tools/pw-cat.c:1033 +#: src/tools/pw-cat.c:1141 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" +" -s, --sysex SysEx mode\n" +" -c, --midi-clip MIDI clip mode\n" "\n" msgstr "" " -p, --playback Çalma kipi\n" @@ -172,9 +187,11 @@ " -m, --midi Midi kipi\n" " -d, --dsd DSD kipi\n" " -o, --encoded Kodlanmış kip\n" +" -s, --sysex SysEx kipi\n" +" -c, --midi-clip MIDI klip kipi\n" "\n" -#: src/tools/pw-cli.c:2252 +#: src/tools/pw-cli.c:2386 #, c-format msgid "" "%s options command\n" @@ -193,195 +210,203 @@ " -r, --remote Uzak arka plan programı adı\n" " -m, --monitor Etkinliği izle\n" -#: spa/plugins/alsa/acp/acp.c:327 +#: spa/plugins/alsa/acp/acp.c:361 msgid "Pro Audio" msgstr "Profesyonel Ses" -#: spa/plugins/alsa/acp/acp.c:488 spa/plugins/alsa/acp/alsa-mixer.c:4633 -#: spa/plugins/bluez5/bluez5-device.c:1701 +#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699 +#: spa/plugins/bluez5/bluez5-device.c:1976 msgid "Off" msgstr "Kapalı" -#: spa/plugins/alsa/acp/alsa-mixer.c:2652 +#: spa/plugins/alsa/acp/acp.c:620 +#, c-format +msgid "%s ALSA UCM error" +msgstr "%s ALSA UCM hatası" + +#: spa/plugins/alsa/acp/alsa-mixer.c:2721 msgid "Input" msgstr "Giriş" -#: spa/plugins/alsa/acp/alsa-mixer.c:2653 +#: spa/plugins/alsa/acp/alsa-mixer.c:2722 msgid "Docking Station Input" msgstr "Yerleştirme İstasyonu Girişi" -#: spa/plugins/alsa/acp/alsa-mixer.c:2654 +#: spa/plugins/alsa/acp/alsa-mixer.c:2723 msgid "Docking Station Microphone" msgstr "Yerleştirme İstasyonu Mikrofonu" -#: spa/plugins/alsa/acp/alsa-mixer.c:2655 +#: spa/plugins/alsa/acp/alsa-mixer.c:2724 msgid "Docking Station Line In" msgstr "Yerleştirme İstasyonu Hat Girişi" -#: spa/plugins/alsa/acp/alsa-mixer.c:2656 -#: spa/plugins/alsa/acp/alsa-mixer.c:2747 +#: spa/plugins/alsa/acp/alsa-mixer.c:2725 +#: spa/plugins/alsa/acp/alsa-mixer.c:2816 msgid "Line In" msgstr "Hat Girişi" -#: spa/plugins/alsa/acp/alsa-mixer.c:2657 -#: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:1989 +#: spa/plugins/alsa/acp/alsa-mixer.c:2726 +#: spa/plugins/alsa/acp/alsa-mixer.c:2810 +#: spa/plugins/bluez5/bluez5-device.c:2374 msgid "Microphone" msgstr "Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2658 -#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +#: spa/plugins/alsa/acp/alsa-mixer.c:2727 +#: spa/plugins/alsa/acp/alsa-mixer.c:2811 msgid "Front Microphone" msgstr "Ön Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2659 -#: spa/plugins/alsa/acp/alsa-mixer.c:2743 +#: spa/plugins/alsa/acp/alsa-mixer.c:2728 +#: spa/plugins/alsa/acp/alsa-mixer.c:2812 msgid "Rear Microphone" msgstr "Arka Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2660 +#: spa/plugins/alsa/acp/alsa-mixer.c:2729 msgid "External Microphone" msgstr "Harici Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2661 -#: spa/plugins/alsa/acp/alsa-mixer.c:2745 +#: spa/plugins/alsa/acp/alsa-mixer.c:2730 +#: spa/plugins/alsa/acp/alsa-mixer.c:2814 msgid "Internal Microphone" msgstr "Dahili Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2662 -#: spa/plugins/alsa/acp/alsa-mixer.c:2748 +#: spa/plugins/alsa/acp/alsa-mixer.c:2731 +#: spa/plugins/alsa/acp/alsa-mixer.c:2817 msgid "Radio" msgstr "Radyo" -#: spa/plugins/alsa/acp/alsa-mixer.c:2663 -#: spa/plugins/alsa/acp/alsa-mixer.c:2749 +#: spa/plugins/alsa/acp/alsa-mixer.c:2732 +#: spa/plugins/alsa/acp/alsa-mixer.c:2818 msgid "Video" msgstr "Video" -#: spa/plugins/alsa/acp/alsa-mixer.c:2664 +#: spa/plugins/alsa/acp/alsa-mixer.c:2733 msgid "Automatic Gain Control" msgstr "Otomatik Kazanç Denetimi" -#: spa/plugins/alsa/acp/alsa-mixer.c:2665 +#: spa/plugins/alsa/acp/alsa-mixer.c:2734 msgid "No Automatic Gain Control" msgstr "Otomatik Kazanç Denetimi Yok" -#: spa/plugins/alsa/acp/alsa-mixer.c:2666 +#: spa/plugins/alsa/acp/alsa-mixer.c:2735 msgid "Boost" msgstr "Artır" -#: spa/plugins/alsa/acp/alsa-mixer.c:2667 +#: spa/plugins/alsa/acp/alsa-mixer.c:2736 msgid "No Boost" msgstr "Artırma Yok" -#: spa/plugins/alsa/acp/alsa-mixer.c:2668 +#: spa/plugins/alsa/acp/alsa-mixer.c:2737 msgid "Amplifier" msgstr "Yükseltici" -#: spa/plugins/alsa/acp/alsa-mixer.c:2669 +#: spa/plugins/alsa/acp/alsa-mixer.c:2738 msgid "No Amplifier" msgstr "Yükseltici Yok" -#: spa/plugins/alsa/acp/alsa-mixer.c:2670 +#: spa/plugins/alsa/acp/alsa-mixer.c:2739 msgid "Bass Boost" msgstr "Bas Artır" -#: spa/plugins/alsa/acp/alsa-mixer.c:2671 +#: spa/plugins/alsa/acp/alsa-mixer.c:2740 msgid "No Bass Boost" msgstr "Bas Artırma Yok" -#: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:1995 +#: spa/plugins/alsa/acp/alsa-mixer.c:2741 +#: spa/plugins/bluez5/bluez5-device.c:2380 msgid "Speaker" msgstr "Hoparlör" -#: spa/plugins/alsa/acp/alsa-mixer.c:2673 -#: spa/plugins/alsa/acp/alsa-mixer.c:2751 +#. Don't call it "headset", the HF one has the mic +#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +#: spa/plugins/alsa/acp/alsa-mixer.c:2820 +#: spa/plugins/bluez5/bluez5-device.c:2386 +#: spa/plugins/bluez5/bluez5-device.c:2453 msgid "Headphones" msgstr "Kulaklık" -#: spa/plugins/alsa/acp/alsa-mixer.c:2740 +#: spa/plugins/alsa/acp/alsa-mixer.c:2809 msgid "Analog Input" msgstr "Analog Giriş" -#: spa/plugins/alsa/acp/alsa-mixer.c:2744 +#: spa/plugins/alsa/acp/alsa-mixer.c:2813 msgid "Dock Microphone" msgstr "Yapışık Mikrofon" -#: spa/plugins/alsa/acp/alsa-mixer.c:2746 +#: spa/plugins/alsa/acp/alsa-mixer.c:2815 msgid "Headset Microphone" msgstr "Mikrofonlu Kulaklık" -#: spa/plugins/alsa/acp/alsa-mixer.c:2750 +#: spa/plugins/alsa/acp/alsa-mixer.c:2819 msgid "Analog Output" msgstr "Analog Çıkış" -#: spa/plugins/alsa/acp/alsa-mixer.c:2752 +#: spa/plugins/alsa/acp/alsa-mixer.c:2821 msgid "Headphones 2" msgstr "Kulaklık 2" -#: spa/plugins/alsa/acp/alsa-mixer.c:2753 +#: spa/plugins/alsa/acp/alsa-mixer.c:2822 msgid "Headphones Mono Output" msgstr "Kulaklık Tek Kanallı Çıkış" -#: spa/plugins/alsa/acp/alsa-mixer.c:2754 +#: spa/plugins/alsa/acp/alsa-mixer.c:2823 msgid "Line Out" msgstr "Hat Çıkışı" -#: spa/plugins/alsa/acp/alsa-mixer.c:2755 +#: spa/plugins/alsa/acp/alsa-mixer.c:2824 msgid "Analog Mono Output" msgstr "Analog Tek Kanallı Çıkış" -#: spa/plugins/alsa/acp/alsa-mixer.c:2756 +#: spa/plugins/alsa/acp/alsa-mixer.c:2825 msgid "Speakers" msgstr "Hoparlörler" -#: spa/plugins/alsa/acp/alsa-mixer.c:2757 +#: spa/plugins/alsa/acp/alsa-mixer.c:2826 msgid "HDMI / DisplayPort" msgstr "HDMI / DisplayPort" -#: spa/plugins/alsa/acp/alsa-mixer.c:2758 +#: spa/plugins/alsa/acp/alsa-mixer.c:2827 msgid "Digital Output (S/PDIF)" msgstr "Sayısal Çıkış (S/PDIF)" -#: spa/plugins/alsa/acp/alsa-mixer.c:2759 +#: spa/plugins/alsa/acp/alsa-mixer.c:2828 msgid "Digital Input (S/PDIF)" msgstr "Sayısal Giriş (S/PDIF)" -#: spa/plugins/alsa/acp/alsa-mixer.c:2760 +#: spa/plugins/alsa/acp/alsa-mixer.c:2829 msgid "Multichannel Input" msgstr "Çok Kanallı Giriş" -#: spa/plugins/alsa/acp/alsa-mixer.c:2761 +#: spa/plugins/alsa/acp/alsa-mixer.c:2830 msgid "Multichannel Output" msgstr "Çok Kanallı Çıkış" -#: spa/plugins/alsa/acp/alsa-mixer.c:2762 +#: spa/plugins/alsa/acp/alsa-mixer.c:2831 msgid "Game Output" msgstr "Oyun Çıkışı" -#: spa/plugins/alsa/acp/alsa-mixer.c:2763 -#: spa/plugins/alsa/acp/alsa-mixer.c:2764 +#: spa/plugins/alsa/acp/alsa-mixer.c:2832 +#: spa/plugins/alsa/acp/alsa-mixer.c:2833 msgid "Chat Output" msgstr "Sohbet Çıkışı" -#: spa/plugins/alsa/acp/alsa-mixer.c:2765 +#: spa/plugins/alsa/acp/alsa-mixer.c:2834 msgid "Chat Input" msgstr "Sohbet Girişi" -#: spa/plugins/alsa/acp/alsa-mixer.c:2766 +#: spa/plugins/alsa/acp/alsa-mixer.c:2835 msgid "Virtual Surround 7.1" msgstr "Sanal Çevresel Ses 7.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4456 +#: spa/plugins/alsa/acp/alsa-mixer.c:4522 msgid "Analog Mono" msgstr "Analog Tek Kanallı" -#: spa/plugins/alsa/acp/alsa-mixer.c:4457 +#: spa/plugins/alsa/acp/alsa-mixer.c:4523 msgid "Analog Mono (Left)" msgstr "Analog Tek Kanallı (Sol)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4458 +#: spa/plugins/alsa/acp/alsa-mixer.c:4524 msgid "Analog Mono (Right)" msgstr "Analog Tek Kanallı (Sağ)" @@ -390,147 +415,147 @@ #. * here would lead to the source name to become "Analog Stereo Input #. * Input". The same logic applies to analog-stereo-output, #. * multichannel-input and multichannel-output. -#: spa/plugins/alsa/acp/alsa-mixer.c:4459 -#: spa/plugins/alsa/acp/alsa-mixer.c:4467 -#: spa/plugins/alsa/acp/alsa-mixer.c:4468 +#: spa/plugins/alsa/acp/alsa-mixer.c:4525 +#: spa/plugins/alsa/acp/alsa-mixer.c:4533 +#: spa/plugins/alsa/acp/alsa-mixer.c:4534 msgid "Analog Stereo" msgstr "Analog Stereo" -#: spa/plugins/alsa/acp/alsa-mixer.c:4460 +#: spa/plugins/alsa/acp/alsa-mixer.c:4526 msgid "Mono" msgstr "Tek Kanallı" -#: spa/plugins/alsa/acp/alsa-mixer.c:4461 +#: spa/plugins/alsa/acp/alsa-mixer.c:4527 msgid "Stereo" msgstr "Stereo" -#: spa/plugins/alsa/acp/alsa-mixer.c:4469 -#: spa/plugins/alsa/acp/alsa-mixer.c:4627 -#: spa/plugins/bluez5/bluez5-device.c:1977 +#: spa/plugins/alsa/acp/alsa-mixer.c:4535 +#: spa/plugins/alsa/acp/alsa-mixer.c:4693 +#: spa/plugins/bluez5/bluez5-device.c:2362 msgid "Headset" msgstr "Kulaklık" -#: spa/plugins/alsa/acp/alsa-mixer.c:4470 -#: spa/plugins/alsa/acp/alsa-mixer.c:4628 +#: spa/plugins/alsa/acp/alsa-mixer.c:4536 +#: spa/plugins/alsa/acp/alsa-mixer.c:4694 msgid "Speakerphone" msgstr "Hoparlör" -#: spa/plugins/alsa/acp/alsa-mixer.c:4471 -#: spa/plugins/alsa/acp/alsa-mixer.c:4472 +#: spa/plugins/alsa/acp/alsa-mixer.c:4537 +#: spa/plugins/alsa/acp/alsa-mixer.c:4538 msgid "Multichannel" msgstr "Çok kanallı" -#: spa/plugins/alsa/acp/alsa-mixer.c:4473 +#: spa/plugins/alsa/acp/alsa-mixer.c:4539 msgid "Analog Surround 2.1" msgstr "Analog Çevresel Ses 2.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4474 +#: spa/plugins/alsa/acp/alsa-mixer.c:4540 msgid "Analog Surround 3.0" msgstr "Analog Çevresel Ses 3.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4475 +#: spa/plugins/alsa/acp/alsa-mixer.c:4541 msgid "Analog Surround 3.1" msgstr "Analog Çevresel Ses 3.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4476 +#: spa/plugins/alsa/acp/alsa-mixer.c:4542 msgid "Analog Surround 4.0" msgstr "Analog Çevresel Ses 4.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4477 +#: spa/plugins/alsa/acp/alsa-mixer.c:4543 msgid "Analog Surround 4.1" msgstr "Analog Çevresel Ses 4.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4478 +#: spa/plugins/alsa/acp/alsa-mixer.c:4544 msgid "Analog Surround 5.0" msgstr "Analog Çevresel Ses 5.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4479 +#: spa/plugins/alsa/acp/alsa-mixer.c:4545 msgid "Analog Surround 5.1" msgstr "Analog Çevresel Ses 5.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4480 +#: spa/plugins/alsa/acp/alsa-mixer.c:4546 msgid "Analog Surround 6.0" msgstr "Analog Çevresel Ses 6.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4481 +#: spa/plugins/alsa/acp/alsa-mixer.c:4547 msgid "Analog Surround 6.1" msgstr "Analog Çevresel Ses 6.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4482 +#: spa/plugins/alsa/acp/alsa-mixer.c:4548 msgid "Analog Surround 7.0" msgstr "Analog Çevresel Ses 7.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4483 +#: spa/plugins/alsa/acp/alsa-mixer.c:4549 msgid "Analog Surround 7.1" msgstr "Analog Çevresel Ses 7.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4484 +#: spa/plugins/alsa/acp/alsa-mixer.c:4550 msgid "Digital Stereo (IEC958)" msgstr "Sayısal Stereo (IEC958)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4485 +#: spa/plugins/alsa/acp/alsa-mixer.c:4551 msgid "Digital Surround 4.0 (IEC958/AC3)" msgstr "Sayısal Çevresel Ses 4.0 (IEC958/AC3)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4486 +#: spa/plugins/alsa/acp/alsa-mixer.c:4552 msgid "Digital Surround 5.1 (IEC958/AC3)" msgstr "Sayısal Çevresel Ses 5.1 (IEC958/AC3)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4487 +#: spa/plugins/alsa/acp/alsa-mixer.c:4553 msgid "Digital Surround 5.1 (IEC958/DTS)" msgstr "Sayısal Çevresel Ses 5.1 (IEC958/DTS)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4488 +#: spa/plugins/alsa/acp/alsa-mixer.c:4554 msgid "Digital Stereo (HDMI)" msgstr "Sayısal Stereo (HDMI)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4489 +#: spa/plugins/alsa/acp/alsa-mixer.c:4555 msgid "Digital Surround 5.1 (HDMI)" msgstr "Sayısal Çevresel Ses 5.1 (HDMI)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4490 +#: spa/plugins/alsa/acp/alsa-mixer.c:4556 msgid "Chat" msgstr "Sohbet" -#: spa/plugins/alsa/acp/alsa-mixer.c:4491 +#: spa/plugins/alsa/acp/alsa-mixer.c:4557 msgid "Game" msgstr "Oyun" -#: spa/plugins/alsa/acp/alsa-mixer.c:4625 +#: spa/plugins/alsa/acp/alsa-mixer.c:4691 msgid "Analog Mono Duplex" msgstr "Analog Tek Kanallı İkili" -#: spa/plugins/alsa/acp/alsa-mixer.c:4626 +#: spa/plugins/alsa/acp/alsa-mixer.c:4692 msgid "Analog Stereo Duplex" msgstr "Analog İkili Stereo" -#: spa/plugins/alsa/acp/alsa-mixer.c:4629 +#: spa/plugins/alsa/acp/alsa-mixer.c:4695 msgid "Digital Stereo Duplex (IEC958)" msgstr "Sayısal İkili Stereo (IEC958)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4630 +#: spa/plugins/alsa/acp/alsa-mixer.c:4696 msgid "Multichannel Duplex" msgstr "Çok Kanallı İkili" -#: spa/plugins/alsa/acp/alsa-mixer.c:4631 +#: spa/plugins/alsa/acp/alsa-mixer.c:4697 msgid "Stereo Duplex" msgstr "İkili Stereo" -#: spa/plugins/alsa/acp/alsa-mixer.c:4632 +#: spa/plugins/alsa/acp/alsa-mixer.c:4698 msgid "Mono Chat + 7.1 Surround" msgstr "Tek Kanallı Sohbet + 7.1 Çevresel Ses" -#: spa/plugins/alsa/acp/alsa-mixer.c:4733 +#: spa/plugins/alsa/acp/alsa-mixer.c:4799 #, c-format msgid "%s Output" msgstr "%s Çıkışı" -#: spa/plugins/alsa/acp/alsa-mixer.c:4741 +#: spa/plugins/alsa/acp/alsa-mixer.c:4807 #, c-format msgid "%s Input" msgstr "%s Girişi" -#: spa/plugins/alsa/acp/alsa-util.c:1220 spa/plugins/alsa/acp/alsa-util.c:1314 +#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327 #, c-format msgid "" "snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu " @@ -547,16 +572,16 @@ "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA " "geliştiricilerine bildirin." -#: spa/plugins/alsa/acp/alsa-util.c:1286 +#: spa/plugins/alsa/acp/alsa-util.c:1299 #, 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 "" @@ -564,7 +589,7 @@ "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA " "geliştiricilerine bildirin." -#: spa/plugins/alsa/acp/alsa-util.c:1333 +#: spa/plugins/alsa/acp/alsa-util.c:1346 #, c-format msgid "" "snd_pcm_avail_delay() returned strange values: delay %lu is less than avail " @@ -577,7 +602,7 @@ "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA " "geliştiricilerine bildirin." -#: spa/plugins/alsa/acp/alsa-util.c:1376 +#: spa/plugins/alsa/acp/alsa-util.c:1389 #, c-format msgid "" "snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte " @@ -595,112 +620,112 @@ "Büyük ihtimalle bu bir ALSA sürücüsü '%s' hatasıdır. Lütfen bu sorunu ALSA " "geliştiricilerine bildirin." -#: spa/plugins/alsa/acp/channelmap.h:457 +#: spa/plugins/alsa/acp/channelmap.h:460 msgid "(invalid)" msgstr "(geçersiz)" -#: spa/plugins/alsa/acp/compat.c:193 +#: spa/plugins/alsa/acp/compat.c:194 msgid "Built-in Audio" msgstr "Dahili Ses" -#: spa/plugins/alsa/acp/compat.c:198 +#: spa/plugins/alsa/acp/compat.c:199 msgid "Modem" msgstr "Modem" -#: spa/plugins/bluez5/bluez5-device.c:1712 +#: spa/plugins/bluez5/bluez5-device.c:1987 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "Ses Geçidi (A2DP Kaynak & HSP/HFP AG)" -#: spa/plugins/bluez5/bluez5-device.c:1760 +#: spa/plugins/bluez5/bluez5-device.c:2016 +msgid "Audio Streaming for Hearing Aids (ASHA Sink)" +msgstr "İşitme Aygıtları İçin Ses Akışı (ASHA Alıcı)" + +#: spa/plugins/bluez5/bluez5-device.c:2059 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "Yüksek Kaliteli Çalma (A2DP Alıcı, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1763 +#: spa/plugins/bluez5/bluez5-device.c:2062 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "Yüksek Kaliteli İkili (A2DP Kaynak/Alıcı, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1771 +#: spa/plugins/bluez5/bluez5-device.c:2070 msgid "High Fidelity Playback (A2DP Sink)" msgstr "Yüksek Kaliteli Çalma (A2DP Alıcı)" -#: spa/plugins/bluez5/bluez5-device.c:1773 +#: spa/plugins/bluez5/bluez5-device.c:2072 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "Yüksek Kaliteli İkili (A2DP Kaynak/Alıcı)" -#: spa/plugins/bluez5/bluez5-device.c:1823 +#: spa/plugins/bluez5/bluez5-device.c:2146 #, c-format msgid "High Fidelity Playback (BAP Sink, codec %s)" msgstr "Yüksek Kaliteli Çalma (BAP Alıcı, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1828 +#: spa/plugins/bluez5/bluez5-device.c:2151 #, c-format msgid "High Fidelity Input (BAP Source, codec %s)" msgstr "Yüksek Kaliteli Giriş (BAP Kaynak, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1832 +#: spa/plugins/bluez5/bluez5-device.c:2155 #, c-format msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)" msgstr "Yüksek Kaliteli İkili (BAP Kaynak/Alıcı, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1841 +#: spa/plugins/bluez5/bluez5-device.c:2164 msgid "High Fidelity Playback (BAP Sink)" msgstr "Yüksek Kaliteli Çalma (BAP Alıcı)" -#: spa/plugins/bluez5/bluez5-device.c:1845 +#: spa/plugins/bluez5/bluez5-device.c:2168 msgid "High Fidelity Input (BAP Source)" msgstr "Yüksek Kaliteli Giriş (BAP Kaynak)" -#: spa/plugins/bluez5/bluez5-device.c:1848 +#: spa/plugins/bluez5/bluez5-device.c:2171 msgid "High Fidelity Duplex (BAP Source/Sink)" msgstr "Yüksek Kaliteli İkili (BAP Kaynak/Alıcı)" -#: spa/plugins/bluez5/bluez5-device.c:1897 +#: spa/plugins/bluez5/bluez5-device.c:2211 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "Kulaklık Ana Birimi (HSP/HFP, çözücü %s)" -#: spa/plugins/bluez5/bluez5-device.c:1978 -#: spa/plugins/bluez5/bluez5-device.c:1983 -#: spa/plugins/bluez5/bluez5-device.c:1990 -#: spa/plugins/bluez5/bluez5-device.c:1996 -#: spa/plugins/bluez5/bluez5-device.c:2002 -#: spa/plugins/bluez5/bluez5-device.c:2008 -#: spa/plugins/bluez5/bluez5-device.c:2014 -#: spa/plugins/bluez5/bluez5-device.c:2020 -#: spa/plugins/bluez5/bluez5-device.c:2026 +#: spa/plugins/bluez5/bluez5-device.c:2363 +#: spa/plugins/bluez5/bluez5-device.c:2368 +#: spa/plugins/bluez5/bluez5-device.c:2375 +#: spa/plugins/bluez5/bluez5-device.c:2381 +#: spa/plugins/bluez5/bluez5-device.c:2387 +#: spa/plugins/bluez5/bluez5-device.c:2393 +#: spa/plugins/bluez5/bluez5-device.c:2399 +#: spa/plugins/bluez5/bluez5-device.c:2405 +#: spa/plugins/bluez5/bluez5-device.c:2411 msgid "Handsfree" msgstr "Ahizesiz" -#: spa/plugins/bluez5/bluez5-device.c:1984 +#: spa/plugins/bluez5/bluez5-device.c:2369 msgid "Handsfree (HFP)" msgstr "Ahizesiz (HFP)" -#: spa/plugins/bluez5/bluez5-device.c:2001 -msgid "Headphone" -msgstr "Kulaklık" - -#: spa/plugins/bluez5/bluez5-device.c:2007 +#: spa/plugins/bluez5/bluez5-device.c:2392 msgid "Portable" msgstr "Taşınabilir" -#: spa/plugins/bluez5/bluez5-device.c:2013 +#: spa/plugins/bluez5/bluez5-device.c:2398 msgid "Car" msgstr "Araba" -#: spa/plugins/bluez5/bluez5-device.c:2019 +#: spa/plugins/bluez5/bluez5-device.c:2404 msgid "HiFi" msgstr "Yüksek Kalite" -#: spa/plugins/bluez5/bluez5-device.c:2025 +#: spa/plugins/bluez5/bluez5-device.c:2410 msgid "Phone" msgstr "Telefon" -#: spa/plugins/bluez5/bluez5-device.c:2032 +#: spa/plugins/bluez5/bluez5-device.c:2417 msgid "Bluetooth" msgstr "Bluetooth" -#: spa/plugins/bluez5/bluez5-device.c:2033 +#: spa/plugins/bluez5/bluez5-device.c:2418 msgid "Bluetooth (HFP)" msgstr "Bluetooth (HFP)"
View file
_service:download_files:pipewire-1.5.81.tar.bz2/po/zh_CN.po -> _service:download_files:pipewire-1.5.83.tar.bz2/po/zh_CN.po
Changed
@@ -13,8 +13,8 @@ "Project-Id-Version: pipewire.master-tx\n" "Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/" "issues\n" -"POT-Creation-Date: 2025-09-21 15:33+0000\n" -"PO-Revision-Date: 2025-09-22 08:53+0800\n" +"POT-Creation-Date: 2025-11-04 15:35+0000\n" +"PO-Revision-Date: 2025-11-05 07:47+0800\n" "Last-Translator: lumingzh <lumingzh@qq.com>\n" "Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n" "Language: zh_CN\n" @@ -60,7 +60,7 @@ msgid "Dummy Output" msgstr "虚拟输出" -#: src/modules/module-pulse-tunnel.c:760 +#: src/modules/module-pulse-tunnel.c:761 #, c-format msgid "Tunnel for %s@%s" msgstr "用于 %s@%s 的隧道" @@ -79,7 +79,7 @@ msgid "%s on %s" msgstr "%2$s 上的 %1$s" -#: src/tools/pw-cat.c:1084 +#: src/tools/pw-cat.c:1096 #, c-format msgid "" "%s options <file>|-\n" @@ -94,7 +94,7 @@ " -v, --verbose 输出详细操作\n" "\n" -#: src/tools/pw-cat.c:1091 +#: src/tools/pw-cat.c:1103 #, c-format msgid "" " -R, --remote Remote daemon name\n" @@ -126,7 +126,7 @@ " -P --properties 设置节点属性\n" "\n" -#: src/tools/pw-cat.c:1109 +#: src/tools/pw-cat.c:1121 #, c-format msgid "" " --rate Sample rate (req. for rec) (default " @@ -166,7 +166,7 @@ " -n, --sample-count COUNT 计数采样后停止\n" "\n" -#: src/tools/pw-cat.c:1129 +#: src/tools/pw-cat.c:1141 msgid "" " -p, --playback Playback mode\n" " -r, --record Recording mode\n" @@ -204,203 +204,203 @@ " -m, --monitor 监视器活动\n" "\n" -#: spa/plugins/alsa/acp/acp.c:351 +#: spa/plugins/alsa/acp/acp.c:361 msgid "Pro Audio" msgstr "专业音频" -#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635 -#: spa/plugins/bluez5/bluez5-device.c:1974 +#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699 +#: spa/plugins/bluez5/bluez5-device.c:1976 msgid "Off" msgstr "关" -#: spa/plugins/alsa/acp/acp.c:610 +#: spa/plugins/alsa/acp/acp.c:620 #, c-format msgid "%s ALSA UCM error" msgstr "%s ALSA UCM 错误" -#: spa/plugins/alsa/acp/alsa-mixer.c:2652 +#: spa/plugins/alsa/acp/alsa-mixer.c:2721 msgid "Input" msgstr "输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2653 +#: spa/plugins/alsa/acp/alsa-mixer.c:2722 msgid "Docking Station Input" msgstr "扩展坞输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2654 +#: spa/plugins/alsa/acp/alsa-mixer.c:2723 msgid "Docking Station Microphone" msgstr "扩展坞话筒" -#: spa/plugins/alsa/acp/alsa-mixer.c:2655 +#: spa/plugins/alsa/acp/alsa-mixer.c:2724 msgid "Docking Station Line In" msgstr "扩展坞线输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2656 -#: spa/plugins/alsa/acp/alsa-mixer.c:2747 +#: spa/plugins/alsa/acp/alsa-mixer.c:2725 +#: spa/plugins/alsa/acp/alsa-mixer.c:2816 msgid "Line In" msgstr "输入插孔" -#: spa/plugins/alsa/acp/alsa-mixer.c:2657 -#: spa/plugins/alsa/acp/alsa-mixer.c:2741 -#: spa/plugins/bluez5/bluez5-device.c:2372 +#: spa/plugins/alsa/acp/alsa-mixer.c:2726 +#: spa/plugins/alsa/acp/alsa-mixer.c:2810 +#: spa/plugins/bluez5/bluez5-device.c:2374 msgid "Microphone" msgstr "话筒" -#: spa/plugins/alsa/acp/alsa-mixer.c:2658 -#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +#: spa/plugins/alsa/acp/alsa-mixer.c:2727 +#: spa/plugins/alsa/acp/alsa-mixer.c:2811 msgid "Front Microphone" msgstr "前麦克风" -#: spa/plugins/alsa/acp/alsa-mixer.c:2659 -#: spa/plugins/alsa/acp/alsa-mixer.c:2743 +#: spa/plugins/alsa/acp/alsa-mixer.c:2728 +#: spa/plugins/alsa/acp/alsa-mixer.c:2812 msgid "Rear Microphone" msgstr "后麦克风" -#: spa/plugins/alsa/acp/alsa-mixer.c:2660 +#: spa/plugins/alsa/acp/alsa-mixer.c:2729 msgid "External Microphone" msgstr "外部话筒" -#: spa/plugins/alsa/acp/alsa-mixer.c:2661 -#: spa/plugins/alsa/acp/alsa-mixer.c:2745 +#: spa/plugins/alsa/acp/alsa-mixer.c:2730 +#: spa/plugins/alsa/acp/alsa-mixer.c:2814 msgid "Internal Microphone" msgstr "内部话筒" -#: spa/plugins/alsa/acp/alsa-mixer.c:2662 -#: spa/plugins/alsa/acp/alsa-mixer.c:2748 +#: spa/plugins/alsa/acp/alsa-mixer.c:2731 +#: spa/plugins/alsa/acp/alsa-mixer.c:2817 msgid "Radio" msgstr "无线电" -#: spa/plugins/alsa/acp/alsa-mixer.c:2663 -#: spa/plugins/alsa/acp/alsa-mixer.c:2749 +#: spa/plugins/alsa/acp/alsa-mixer.c:2732 +#: spa/plugins/alsa/acp/alsa-mixer.c:2818 msgid "Video" msgstr "视频" -#: spa/plugins/alsa/acp/alsa-mixer.c:2664 +#: spa/plugins/alsa/acp/alsa-mixer.c:2733 msgid "Automatic Gain Control" msgstr "自动增益控制" -#: spa/plugins/alsa/acp/alsa-mixer.c:2665 +#: spa/plugins/alsa/acp/alsa-mixer.c:2734 msgid "No Automatic Gain Control" msgstr "无自动增益控制" -#: spa/plugins/alsa/acp/alsa-mixer.c:2666 +#: spa/plugins/alsa/acp/alsa-mixer.c:2735 msgid "Boost" msgstr "增强" -#: spa/plugins/alsa/acp/alsa-mixer.c:2667 +#: spa/plugins/alsa/acp/alsa-mixer.c:2736 msgid "No Boost" msgstr "无增强" -#: spa/plugins/alsa/acp/alsa-mixer.c:2668 +#: spa/plugins/alsa/acp/alsa-mixer.c:2737 msgid "Amplifier" msgstr "功放" -#: spa/plugins/alsa/acp/alsa-mixer.c:2669 +#: spa/plugins/alsa/acp/alsa-mixer.c:2738 msgid "No Amplifier" msgstr "无功放" -#: spa/plugins/alsa/acp/alsa-mixer.c:2670 +#: spa/plugins/alsa/acp/alsa-mixer.c:2739 msgid "Bass Boost" msgstr "重低音增强" -#: spa/plugins/alsa/acp/alsa-mixer.c:2671 +#: spa/plugins/alsa/acp/alsa-mixer.c:2740 msgid "No Bass Boost" msgstr "无重低音增强" -#: spa/plugins/alsa/acp/alsa-mixer.c:2672 -#: spa/plugins/bluez5/bluez5-device.c:2378 +#: spa/plugins/alsa/acp/alsa-mixer.c:2741 +#: spa/plugins/bluez5/bluez5-device.c:2380 msgid "Speaker" msgstr "扬声器" #. Don't call it "headset", the HF one has the mic -#: spa/plugins/alsa/acp/alsa-mixer.c:2673 -#: spa/plugins/alsa/acp/alsa-mixer.c:2751 -#: spa/plugins/bluez5/bluez5-device.c:2384 -#: spa/plugins/bluez5/bluez5-device.c:2451 +#: spa/plugins/alsa/acp/alsa-mixer.c:2742 +#: spa/plugins/alsa/acp/alsa-mixer.c:2820 +#: spa/plugins/bluez5/bluez5-device.c:2386 +#: spa/plugins/bluez5/bluez5-device.c:2453 msgid "Headphones" msgstr "模拟耳机" -#: spa/plugins/alsa/acp/alsa-mixer.c:2740 +#: spa/plugins/alsa/acp/alsa-mixer.c:2809 msgid "Analog Input" msgstr "模拟输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2744 +#: spa/plugins/alsa/acp/alsa-mixer.c:2813 msgid "Dock Microphone" msgstr "扩展坞麦克风" -#: spa/plugins/alsa/acp/alsa-mixer.c:2746 +#: spa/plugins/alsa/acp/alsa-mixer.c:2815 msgid "Headset Microphone" msgstr "头挂麦克风" -#: spa/plugins/alsa/acp/alsa-mixer.c:2750 +#: spa/plugins/alsa/acp/alsa-mixer.c:2819 msgid "Analog Output" msgstr "模拟输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2752 +#: spa/plugins/alsa/acp/alsa-mixer.c:2821 msgid "Headphones 2" msgstr "模拟耳机 2" -#: spa/plugins/alsa/acp/alsa-mixer.c:2753 +#: spa/plugins/alsa/acp/alsa-mixer.c:2822 msgid "Headphones Mono Output" msgstr "模拟单声道输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2754 +#: spa/plugins/alsa/acp/alsa-mixer.c:2823 msgid "Line Out" msgstr "线缆输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2755 +#: spa/plugins/alsa/acp/alsa-mixer.c:2824 msgid "Analog Mono Output" msgstr "模拟单声道输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2756 +#: spa/plugins/alsa/acp/alsa-mixer.c:2825 msgid "Speakers" msgstr "扬声器" -#: spa/plugins/alsa/acp/alsa-mixer.c:2757 +#: spa/plugins/alsa/acp/alsa-mixer.c:2826 msgid "HDMI / DisplayPort" msgstr "HDMI / DisplayPort" -#: spa/plugins/alsa/acp/alsa-mixer.c:2758 +#: spa/plugins/alsa/acp/alsa-mixer.c:2827 msgid "Digital Output (S/PDIF)" msgstr "数字输出 (S/PDIF)" -#: spa/plugins/alsa/acp/alsa-mixer.c:2759 +#: spa/plugins/alsa/acp/alsa-mixer.c:2828 msgid "Digital Input (S/PDIF)" msgstr "数字输入 (S/PDIF)" -#: spa/plugins/alsa/acp/alsa-mixer.c:2760 +#: spa/plugins/alsa/acp/alsa-mixer.c:2829 msgid "Multichannel Input" msgstr "多声道输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2761 +#: spa/plugins/alsa/acp/alsa-mixer.c:2830 msgid "Multichannel Output" msgstr "多声道输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2762 +#: spa/plugins/alsa/acp/alsa-mixer.c:2831 msgid "Game Output" msgstr "游戏输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2763 -#: spa/plugins/alsa/acp/alsa-mixer.c:2764 +#: spa/plugins/alsa/acp/alsa-mixer.c:2832 +#: spa/plugins/alsa/acp/alsa-mixer.c:2833 msgid "Chat Output" msgstr "语音输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:2765 +#: spa/plugins/alsa/acp/alsa-mixer.c:2834 msgid "Chat Input" msgstr "语音输入" -#: spa/plugins/alsa/acp/alsa-mixer.c:2766 +#: spa/plugins/alsa/acp/alsa-mixer.c:2835 msgid "Virtual Surround 7.1" msgstr "虚拟环绕 7.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4458 +#: spa/plugins/alsa/acp/alsa-mixer.c:4522 msgid "Analog Mono" msgstr "模拟单声道" -#: spa/plugins/alsa/acp/alsa-mixer.c:4459 +#: spa/plugins/alsa/acp/alsa-mixer.c:4523 msgid "Analog Mono (Left)" msgstr "模拟单声道 (左声道)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4460 +#: spa/plugins/alsa/acp/alsa-mixer.c:4524 msgid "Analog Mono (Right)" msgstr "模拟单声道 (右声道)" @@ -409,142 +409,142 @@ #. * here would lead to the source name to become "Analog Stereo Input #. * Input". The same logic applies to analog-stereo-output, #. * multichannel-input and multichannel-output. -#: spa/plugins/alsa/acp/alsa-mixer.c:4461 -#: spa/plugins/alsa/acp/alsa-mixer.c:4469 -#: spa/plugins/alsa/acp/alsa-mixer.c:4470 +#: spa/plugins/alsa/acp/alsa-mixer.c:4525 +#: spa/plugins/alsa/acp/alsa-mixer.c:4533 +#: spa/plugins/alsa/acp/alsa-mixer.c:4534 msgid "Analog Stereo" msgstr "模拟立体声" -#: spa/plugins/alsa/acp/alsa-mixer.c:4462 +#: spa/plugins/alsa/acp/alsa-mixer.c:4526 msgid "Mono" msgstr "单声道" -#: spa/plugins/alsa/acp/alsa-mixer.c:4463 +#: spa/plugins/alsa/acp/alsa-mixer.c:4527 msgid "Stereo" msgstr "立体声" -#: spa/plugins/alsa/acp/alsa-mixer.c:4471 -#: spa/plugins/alsa/acp/alsa-mixer.c:4629 -#: spa/plugins/bluez5/bluez5-device.c:2360 +#: spa/plugins/alsa/acp/alsa-mixer.c:4535 +#: spa/plugins/alsa/acp/alsa-mixer.c:4693 +#: spa/plugins/bluez5/bluez5-device.c:2362 msgid "Headset" msgstr "耳机" -#: spa/plugins/alsa/acp/alsa-mixer.c:4472 -#: spa/plugins/alsa/acp/alsa-mixer.c:4630 +#: spa/plugins/alsa/acp/alsa-mixer.c:4536 +#: spa/plugins/alsa/acp/alsa-mixer.c:4694 msgid "Speakerphone" msgstr "扬声麦克风" -#: spa/plugins/alsa/acp/alsa-mixer.c:4473 -#: spa/plugins/alsa/acp/alsa-mixer.c:4474 +#: spa/plugins/alsa/acp/alsa-mixer.c:4537 +#: spa/plugins/alsa/acp/alsa-mixer.c:4538 msgid "Multichannel" msgstr "多声道" -#: spa/plugins/alsa/acp/alsa-mixer.c:4475 +#: spa/plugins/alsa/acp/alsa-mixer.c:4539 msgid "Analog Surround 2.1" msgstr "模拟环绕 2.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4476 +#: spa/plugins/alsa/acp/alsa-mixer.c:4540 msgid "Analog Surround 3.0" msgstr "模拟环绕 3.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4477 +#: spa/plugins/alsa/acp/alsa-mixer.c:4541 msgid "Analog Surround 3.1" msgstr "模拟环绕 3.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4478 +#: spa/plugins/alsa/acp/alsa-mixer.c:4542 msgid "Analog Surround 4.0" msgstr "模拟环绕 4.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4479 +#: spa/plugins/alsa/acp/alsa-mixer.c:4543 msgid "Analog Surround 4.1" msgstr "模拟环绕 4.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4480 +#: spa/plugins/alsa/acp/alsa-mixer.c:4544 msgid "Analog Surround 5.0" msgstr "模拟环绕 5.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4481 +#: spa/plugins/alsa/acp/alsa-mixer.c:4545 msgid "Analog Surround 5.1" msgstr "模拟环绕 5.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4482 +#: spa/plugins/alsa/acp/alsa-mixer.c:4546 msgid "Analog Surround 6.0" msgstr "模拟环绕 6.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4483 +#: spa/plugins/alsa/acp/alsa-mixer.c:4547 msgid "Analog Surround 6.1" msgstr "模拟环绕 6.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4484 +#: spa/plugins/alsa/acp/alsa-mixer.c:4548 msgid "Analog Surround 7.0" msgstr "模拟环绕 7.0" -#: spa/plugins/alsa/acp/alsa-mixer.c:4485 +#: spa/plugins/alsa/acp/alsa-mixer.c:4549 msgid "Analog Surround 7.1" msgstr "模拟环绕 7.1" -#: spa/plugins/alsa/acp/alsa-mixer.c:4486 +#: spa/plugins/alsa/acp/alsa-mixer.c:4550 msgid "Digital Stereo (IEC958)" msgstr "数字立体声 (IEC958)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4487 +#: spa/plugins/alsa/acp/alsa-mixer.c:4551 msgid "Digital Surround 4.0 (IEC958/AC3)" msgstr "数字环绕 4.0 (IEC958/AC3)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4488 +#: spa/plugins/alsa/acp/alsa-mixer.c:4552 msgid "Digital Surround 5.1 (IEC958/AC3)" msgstr "数字环绕 5.1 (IEC958/AC3)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4489 +#: spa/plugins/alsa/acp/alsa-mixer.c:4553 msgid "Digital Surround 5.1 (IEC958/DTS)" msgstr "数字环绕 5.1 (IEC958/DTS)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4490 +#: spa/plugins/alsa/acp/alsa-mixer.c:4554 msgid "Digital Stereo (HDMI)" msgstr "数字立体声 (HDMI)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4491 +#: spa/plugins/alsa/acp/alsa-mixer.c:4555 msgid "Digital Surround 5.1 (HDMI)" msgstr "数字环绕 5.1 (HDMI)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4492 +#: spa/plugins/alsa/acp/alsa-mixer.c:4556 msgid "Chat" msgstr "语音" -#: spa/plugins/alsa/acp/alsa-mixer.c:4493 +#: spa/plugins/alsa/acp/alsa-mixer.c:4557 msgid "Game" msgstr "游戏" -#: spa/plugins/alsa/acp/alsa-mixer.c:4627 +#: spa/plugins/alsa/acp/alsa-mixer.c:4691 msgid "Analog Mono Duplex" msgstr "模拟单声道双工" -#: spa/plugins/alsa/acp/alsa-mixer.c:4628 +#: spa/plugins/alsa/acp/alsa-mixer.c:4692 msgid "Analog Stereo Duplex" msgstr "模拟立体声双工" -#: spa/plugins/alsa/acp/alsa-mixer.c:4631 +#: spa/plugins/alsa/acp/alsa-mixer.c:4695 msgid "Digital Stereo Duplex (IEC958)" msgstr "数字立体声双工 (IEC958)" -#: spa/plugins/alsa/acp/alsa-mixer.c:4632 +#: spa/plugins/alsa/acp/alsa-mixer.c:4696 msgid "Multichannel Duplex" msgstr "多声道双工" -#: spa/plugins/alsa/acp/alsa-mixer.c:4633 +#: spa/plugins/alsa/acp/alsa-mixer.c:4697 msgid "Stereo Duplex" msgstr "模拟立体声双工" -#: spa/plugins/alsa/acp/alsa-mixer.c:4634 +#: spa/plugins/alsa/acp/alsa-mixer.c:4698 msgid "Mono Chat + 7.1 Surround" msgstr "单声道语音 + 7.1 环绕声" -#: spa/plugins/alsa/acp/alsa-mixer.c:4735 +#: spa/plugins/alsa/acp/alsa-mixer.c:4799 #, c-format msgid "%s Output" msgstr "%s 输出" -#: spa/plugins/alsa/acp/alsa-mixer.c:4743 +#: spa/plugins/alsa/acp/alsa-mixer.c:4807 #, c-format msgid "%s Input" msgstr "%s 输入" @@ -608,7 +608,7 @@ "snd_pcm_mmap_begin() 返回的值非常大:%lu 字节(%lu ms)。\n" "这很可能是由 ALSA 驱动程序 %s 的缺陷导致的。请向 ALSA 开发者报告这个问题。" -#: spa/plugins/alsa/acp/channelmap.h:457 +#: spa/plugins/alsa/acp/channelmap.h:460 msgid "(invalid)" msgstr "(无效)" @@ -620,103 +620,103 @@ msgid "Modem" msgstr "调制解调器" -#: spa/plugins/bluez5/bluez5-device.c:1985 +#: spa/plugins/bluez5/bluez5-device.c:1987 msgid "Audio Gateway (A2DP Source & HSP/HFP AG)" msgstr "音频网关 (A2DP 信源 或 HSP/HFP 网关)" -#: spa/plugins/bluez5/bluez5-device.c:2014 +#: spa/plugins/bluez5/bluez5-device.c:2016 msgid "Audio Streaming for Hearing Aids (ASHA Sink)" msgstr "助听器音频流 (ASHA 信宿)" -#: spa/plugins/bluez5/bluez5-device.c:2057 +#: spa/plugins/bluez5/bluez5-device.c:2059 #, c-format msgid "High Fidelity Playback (A2DP Sink, codec %s)" msgstr "高保真回放 (A2DP 信宿, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2060 +#: spa/plugins/bluez5/bluez5-device.c:2062 #, c-format msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)" msgstr "高保真双工 (A2DP 信源/信宿, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2068 +#: spa/plugins/bluez5/bluez5-device.c:2070 msgid "High Fidelity Playback (A2DP Sink)" msgstr "高保真回放 (A2DP 信宿)" -#: spa/plugins/bluez5/bluez5-device.c:2070 +#: spa/plugins/bluez5/bluez5-device.c:2072 msgid "High Fidelity Duplex (A2DP Source/Sink)" msgstr "高保真双工 (A2DP 信源/信宿)" -#: spa/plugins/bluez5/bluez5-device.c:2144 +#: spa/plugins/bluez5/bluez5-device.c:2146 #, c-format msgid "High Fidelity Playback (BAP Sink, codec %s)" msgstr "高保真回放 (BAP 信宿, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2149 +#: spa/plugins/bluez5/bluez5-device.c:2151 #, c-format msgid "High Fidelity Input (BAP Source, codec %s)" msgstr "高保真输入 (BAP 信源, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2153 +#: spa/plugins/bluez5/bluez5-device.c:2155 #, c-format msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)" msgstr "高保真双工 (BAP 信源/信宿, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2162 +#: spa/plugins/bluez5/bluez5-device.c:2164 msgid "High Fidelity Playback (BAP Sink)" msgstr "高保真回放 (BAP 信宿)" -#: spa/plugins/bluez5/bluez5-device.c:2166 +#: spa/plugins/bluez5/bluez5-device.c:2168 msgid "High Fidelity Input (BAP Source)" msgstr "高保真输入 (BAP 信源)" -#: spa/plugins/bluez5/bluez5-device.c:2169 +#: spa/plugins/bluez5/bluez5-device.c:2171 msgid "High Fidelity Duplex (BAP Source/Sink)" msgstr "高保真双工 (BAP 信源/信宿)" -#: spa/plugins/bluez5/bluez5-device.c:2209 +#: spa/plugins/bluez5/bluez5-device.c:2211 #, c-format msgid "Headset Head Unit (HSP/HFP, codec %s)" msgstr "头戴式耳机单元 (HSP/HFP, 编码 %s)" -#: spa/plugins/bluez5/bluez5-device.c:2361 -#: spa/plugins/bluez5/bluez5-device.c:2366 -#: spa/plugins/bluez5/bluez5-device.c:2373 -#: spa/plugins/bluez5/bluez5-device.c:2379 -#: spa/plugins/bluez5/bluez5-device.c:2385 -#: spa/plugins/bluez5/bluez5-device.c:2391 -#: spa/plugins/bluez5/bluez5-device.c:2397 -#: spa/plugins/bluez5/bluez5-device.c:2403 -#: spa/plugins/bluez5/bluez5-device.c:2409 +#: spa/plugins/bluez5/bluez5-device.c:2363 +#: spa/plugins/bluez5/bluez5-device.c:2368 +#: spa/plugins/bluez5/bluez5-device.c:2375 +#: spa/plugins/bluez5/bluez5-device.c:2381 +#: spa/plugins/bluez5/bluez5-device.c:2387 +#: spa/plugins/bluez5/bluez5-device.c:2393 +#: spa/plugins/bluez5/bluez5-device.c:2399 +#: spa/plugins/bluez5/bluez5-device.c:2405 +#: spa/plugins/bluez5/bluez5-device.c:2411 msgid "Handsfree" -msgstr "免手操作" +msgstr "免提" -#: spa/plugins/bluez5/bluez5-device.c:2367 +#: spa/plugins/bluez5/bluez5-device.c:2369 msgid "Handsfree (HFP)" -msgstr "免手操作 (HFP)" +msgstr "免提(HFP)" -#: spa/plugins/bluez5/bluez5-device.c:2390 +#: spa/plugins/bluez5/bluez5-device.c:2392 msgid "Portable" msgstr "便携式" -#: spa/plugins/bluez5/bluez5-device.c:2396 +#: spa/plugins/bluez5/bluez5-device.c:2398 msgid "Car" msgstr "车内" -#: spa/plugins/bluez5/bluez5-device.c:2402 +#: spa/plugins/bluez5/bluez5-device.c:2404 msgid "HiFi" msgstr "高保真" -#: spa/plugins/bluez5/bluez5-device.c:2408 +#: spa/plugins/bluez5/bluez5-device.c:2410 msgid "Phone" msgstr "电话" -#: spa/plugins/bluez5/bluez5-device.c:2415 +#: spa/plugins/bluez5/bluez5-device.c:2417 msgid "Bluetooth" msgstr "蓝牙" -#: spa/plugins/bluez5/bluez5-device.c:2416 -msgid "Bluetooth (HFP)" -msgstr "蓝牙 (HFP)" +#: spa/plugins/bluez5/bluez5-device.c:2418 +msgid "Bluetooth Handsfree" +msgstr "蓝牙免提" #~ msgid "Headphone" #~ msgstr "头戴耳机"
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/examples/adapter-control.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/examples/adapter-control.c
Changed
@@ -578,7 +578,7 @@ SPA_PARAM_PORT_CONFIG_direction, SPA_POD_Id(SPA_DIRECTION_OUTPUT), SPA_PARAM_PORT_CONFIG_mode, SPA_POD_Id(SPA_PARAM_PORT_CONFIG_MODE_dsp), SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); - if ((res = spa_node_set_param(data->source_node, SPA_PARAM_PortConfig, 0, param) < 0)) { + if ((res = spa_node_set_param(data->source_node, SPA_PARAM_PortConfig, 0, param)) < 0) { printf("can't setup source node %d\n", res); return res; } @@ -647,7 +647,7 @@ SPA_PARAM_PORT_CONFIG_format, SPA_POD_Pod(param)); - if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param) < 0)) { + if ((res = spa_node_set_param(data->sink_node, SPA_PARAM_PortConfig, 0, param)) < 0) { printf("can't setup sink node %d\n", res); return res; } @@ -987,7 +987,7 @@ setlocale(LC_ALL, ""); - while ((c = getopt_long(argc, argv, "hdmstiac:", long_options, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "hd:m:s:t:i:a:c:", long_options, NULL)) != -1) { switch (c) { case 'h': show_help(&data, argv0, false);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/debug/format.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/debug/format.h
Changed
@@ -164,8 +164,7 @@ type = val->type; size = val->size; - if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1 || - size < spa_pod_type_size(type)) + if (type < SPA_TYPE_None || type >= _SPA_TYPE_LAST || n_vals < 1) continue; vals = SPA_POD_BODY(val);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/dsd-utils.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/dsd-utils.h
Changed
@@ -42,7 +42,7 @@ SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); if (position == NULL || - !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) + !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position))) SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); return res;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/format-utils.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/format-utils.h
Changed
@@ -46,20 +46,61 @@ #endif #endif +SPA_API_AUDIO_FORMAT_UTILS bool +spa_format_audio_ext_valid_size(uint32_t media_subtype, size_t size) +{ + switch (media_subtype) { + case SPA_MEDIA_SUBTYPE_raw: + return size >= offsetof(struct spa_audio_info, info.raw) && + SPA_AUDIO_INFO_RAW_VALID_SIZE(size - offsetof(struct spa_audio_info, info.raw)); + +#define _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(format) \ + case SPA_MEDIA_SUBTYPE_ ## format: \ + return size >= offsetof(struct spa_audio_info, info.format) + sizeof(struct spa_audio_info_ ## format); + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(dsp) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(iec958) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(dsd) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(mp3) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(aac) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(vorbis) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(wma) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(ra) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(amr) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(alac) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(flac) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(ape) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(ac3) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(eac3) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(truehd) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(dts) + _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE(mpegh) +#undef _SPA_FORMAT_AUDIO_EXT_VALID_SIZE_CASE + } + return false; +} + SPA_API_AUDIO_FORMAT_UTILS int -spa_format_audio_parse(const struct spa_pod *format, struct spa_audio_info *info) +spa_format_audio_ext_parse(const struct spa_pod *format, struct spa_audio_info *info, size_t size) { int res; + uint32_t media_type, media_subtype; - if ((res = spa_format_parse(format, &info->media_type, &info->media_subtype)) < 0) + if ((res = spa_format_parse(format, &media_type, &media_subtype)) < 0) return res; - if (info->media_type != SPA_MEDIA_TYPE_audio) + if (media_type != SPA_MEDIA_TYPE_audio) return -EINVAL; - switch (info->media_subtype) { + if (!spa_format_audio_ext_valid_size(media_subtype, size)) + return -EINVAL; + + info->media_type = media_type; + info->media_subtype = media_subtype; + + switch (media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - return spa_format_audio_raw_parse(format, &info->info.raw); + return spa_format_audio_raw_ext_parse(format, &info->info.raw, + size - offsetof(struct spa_audio_info, info.raw)); case SPA_MEDIA_SUBTYPE_dsp: return spa_format_audio_dsp_parse(format, &info->info.dsp); case SPA_MEDIA_SUBTYPE_iec958: @@ -98,13 +139,25 @@ return -ENOTSUP; } +SPA_API_AUDIO_FORMAT_UTILS int +spa_format_audio_parse(const struct spa_pod *format, struct spa_audio_info *info) +{ + return spa_format_audio_ext_parse(format, info, sizeof(*info)); +} + SPA_API_AUDIO_FORMAT_UTILS struct spa_pod * -spa_format_audio_build(struct spa_pod_builder *builder, uint32_t id, - const struct spa_audio_info *info) +spa_format_audio_ext_build(struct spa_pod_builder *builder, uint32_t id, + const struct spa_audio_info *info, size_t size) { + if (!spa_format_audio_ext_valid_size(info->media_subtype, size)) { + errno = EINVAL; + return NULL; + } + switch (info->media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - return spa_format_audio_raw_build(builder, id, &info->info.raw); + return spa_format_audio_raw_ext_build(builder, id, &info->info.raw, + size - offsetof(struct spa_audio_info, info.raw)); case SPA_MEDIA_SUBTYPE_dsp: return spa_format_audio_dsp_build(builder, id, &info->info.dsp); case SPA_MEDIA_SUBTYPE_iec958: @@ -143,6 +196,13 @@ errno = ENOTSUP; return NULL; } + +SPA_API_AUDIO_FORMAT_UTILS struct spa_pod * +spa_format_audio_build(struct spa_pod_builder *builder, uint32_t id, + const struct spa_audio_info *info) +{ + return spa_format_audio_ext_build(builder, id, info, sizeof(*info)); +} /** * \} */
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/format.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/format.h
Changed
@@ -59,6 +59,8 @@ struct spa_audio_info_dts dts; struct spa_audio_info_mpegh mpegh; } info; + + /* padding follows here when info has flexible size */ }; /**
View file
_service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/layout-types.h
Added
@@ -0,0 +1,118 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2025 Wim Taymans */ +/* SPDX-License-Identifier: MIT */ + +#ifndef SPA_AUDIO_LAYOUT_TYPES_H +#define SPA_AUDIO_LAYOUT_TYPES_H + +#include <spa/utils/type.h> +#include <spa/utils/string.h> +#include <spa/param/audio/layout.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup spa_param + * \{ + */ + +#ifndef SPA_API_AUDIO_LAYOUT_TYPES + #ifdef SPA_API_IMPL + #define SPA_API_AUDIO_LAYOUT_TYPES SPA_API_IMPL + #else + #define SPA_API_AUDIO_LAYOUT_TYPES static inline + #endif +#endif + +static const struct spa_type_audio_layout_info { + const char *name; + struct spa_audio_layout_info layout; +} spa_type_audio_layout_info = { + { "Mono", { SPA_AUDIO_LAYOUT_Mono } }, + { "Stereo", { SPA_AUDIO_LAYOUT_Stereo } }, + { "Quad", { SPA_AUDIO_LAYOUT_Quad } }, + { "Pentagonal", { SPA_AUDIO_LAYOUT_Pentagonal } }, + { "Hexagonal", { SPA_AUDIO_LAYOUT_Hexagonal } }, + { "Octagonal", { SPA_AUDIO_LAYOUT_Octagonal } }, + { "Cube", { SPA_AUDIO_LAYOUT_Cube } }, + { "MPEG-1.0", { SPA_AUDIO_LAYOUT_MPEG_1_0 } }, + { "MPEG-2.0", { SPA_AUDIO_LAYOUT_MPEG_2_0 } }, + { "MPEG-3.0A", { SPA_AUDIO_LAYOUT_MPEG_3_0A } }, + { "MPEG-3.0B", { SPA_AUDIO_LAYOUT_MPEG_3_0B } }, + { "MPEG-4.0A", { SPA_AUDIO_LAYOUT_MPEG_4_0A } }, + { "MPEG-4.0B", { SPA_AUDIO_LAYOUT_MPEG_4_0B } }, + { "MPEG-5.0A", { SPA_AUDIO_LAYOUT_MPEG_5_0A } }, + { "MPEG-5.0B", { SPA_AUDIO_LAYOUT_MPEG_5_0B } }, + { "MPEG-5.0C", { SPA_AUDIO_LAYOUT_MPEG_5_0C } }, + { "MPEG-5.0D", { SPA_AUDIO_LAYOUT_MPEG_5_0D } }, + { "MPEG-5.1A", { SPA_AUDIO_LAYOUT_MPEG_5_1A } }, + { "MPEG-5.1B", { SPA_AUDIO_LAYOUT_MPEG_5_1B } }, + { "MPEG-5.1C", { SPA_AUDIO_LAYOUT_MPEG_5_1C } }, + { "MPEG-5.1D", { SPA_AUDIO_LAYOUT_MPEG_5_1D } }, + { "MPEG-6.1A", { SPA_AUDIO_LAYOUT_MPEG_6_1A } }, + { "MPEG-7.1A", { SPA_AUDIO_LAYOUT_MPEG_7_1A } }, + { "MPEG-7.1B", { SPA_AUDIO_LAYOUT_MPEG_7_1B } }, + { "MPEG-7.1C", { SPA_AUDIO_LAYOUT_MPEG_7_1C } }, + { "2.1", { SPA_AUDIO_LAYOUT_2_1 } }, + { "2RC", { SPA_AUDIO_LAYOUT_2RC } }, + { "2FC", { SPA_AUDIO_LAYOUT_2FC } }, + { "3.1", { SPA_AUDIO_LAYOUT_3_1 } }, + { "4.0", { SPA_AUDIO_LAYOUT_4_0 } }, + { "2.2", { SPA_AUDIO_LAYOUT_2_2 } }, + { "4.1", { SPA_AUDIO_LAYOUT_4_1 } }, + { "5.0", { SPA_AUDIO_LAYOUT_5_0 } }, + { "5.0R", { SPA_AUDIO_LAYOUT_5_0R } }, + { "5.1", { SPA_AUDIO_LAYOUT_5_1 } }, + { "5.1R", { SPA_AUDIO_LAYOUT_5_1R } }, + { "6.0", { SPA_AUDIO_LAYOUT_6_0 } }, + { "6.0F", { SPA_AUDIO_LAYOUT_6_0F } }, + { "6.1", { SPA_AUDIO_LAYOUT_6_1 } }, + { "6.1F", { SPA_AUDIO_LAYOUT_6_1F } }, + { "7.0", { SPA_AUDIO_LAYOUT_7_0 } }, + { "7.0F", { SPA_AUDIO_LAYOUT_7_0F } }, + { "7.1", { SPA_AUDIO_LAYOUT_7_1 } }, + { "7.1W", { SPA_AUDIO_LAYOUT_7_1W } }, + { "7.1WR", { SPA_AUDIO_LAYOUT_7_1WR } }, + { NULL, }, +}; + +SPA_API_AUDIO_LAYOUT_TYPES int +spa_audio_layout_info_parse_name(struct spa_audio_layout_info *layout, size_t size, + const char *name) +{ + uint32_t max_position = SPA_AUDIO_LAYOUT_INFO_MAX_POSITION(size); + if (spa_strstartswith(name, "AUX")) { + uint32_t i, n_pos; + if (spa_atou32(name+3, &n_pos, 10)) { + if (n_pos > max_position) + return -ECHRNG; + for (i = 0; i < 0x1000 && i < n_pos; i++) + layout->positioni = SPA_AUDIO_CHANNEL_AUX0 + i; + for (; i < n_pos; i++) + layout->positioni = SPA_AUDIO_CHANNEL_UNKNOWN; + layout->n_channels = n_pos; + return n_pos; + } + } + SPA_FOR_EACH_ELEMENT_VAR(spa_type_audio_layout_info, i) { + if (spa_streq(name, i->name)) { + if (i->layout.n_channels > max_position) + return -ECHRNG; + *layout = i->layout; + return i->layout.n_channels; + } + } + return -ENOTSUP; +} + +/** + * \} + */ + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* SPA_AUDIO_LAYOUT_TYPES_H */
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/layout.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/layout.h
Changed
@@ -21,8 +21,11 @@ struct spa_audio_layout_info { uint32_t n_channels; uint32_t positionSPA_AUDIO_MAX_CHANNELS; + /* padding may follow to allow more channels */ }; +#define SPA_AUDIO_LAYOUT_INFO_MAX_POSITION(size) (((size)-offsetof(struct spa_audio_layout_info,position))/sizeof(uint32_t)) + #define SPA_AUDIO_LAYOUT_Mono 1, { SPA_AUDIO_CHANNEL_MONO, } #define SPA_AUDIO_LAYOUT_Stereo 2, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, } #define SPA_AUDIO_LAYOUT_Quad 4, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ @@ -37,7 +40,7 @@ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_RC, \ SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, } -#define SPA_AUDIO_LAYOUT_Cube 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR }, \ +#define SPA_AUDIO_LAYOUT_Cube 8, { SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, \ SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, \ SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, \ SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR, }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/raw-json.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/raw-json.h
Changed
@@ -9,6 +9,7 @@ #include <spa/utils/json.h> #include <spa/param/audio/raw.h> #include <spa/param/audio/raw-types.h> +#include <spa/param/audio/layout-types.h> #ifdef __cplusplus extern "C" { @@ -28,8 +29,8 @@ #endif SPA_API_AUDIO_RAW_JSON int -spa_audio_parse_position(const char *str, size_t len, - uint32_t *position, uint32_t *n_channels) +spa_audio_parse_position_n(const char *str, size_t len, + uint32_t *position, uint32_t max_position, uint32_t *n_channels) { struct spa_json iter; char v256; @@ -38,18 +39,46 @@ if (spa_json_begin_array_relax(&iter, str, len) <= 0) return 0; - while (spa_json_get_string(&iter, v, sizeof(v)) > 0 && - channels < SPA_AUDIO_MAX_CHANNELS) { - positionchannels++ = spa_type_audio_channel_from_short_name(v); + while (spa_json_get_string(&iter, v, sizeof(v)) > 0) { + if (channels < max_position) + positionchannels = spa_type_audio_channel_from_short_name(v); + channels++; } *n_channels = channels; return channels; } SPA_API_AUDIO_RAW_JSON int -spa_audio_info_raw_update(struct spa_audio_info_raw *info, const char *key, const char *val, bool force) +spa_audio_parse_position(const char *str, size_t len, + uint32_t *position, uint32_t *n_channels) +{ + return spa_audio_parse_position_n(str, len, position, SPA_AUDIO_MAX_CHANNELS, n_channels); +} + +SPA_API_AUDIO_RAW_JSON int +spa_audio_parse_layout(const char *str, uint32_t *position, uint32_t max_position, + uint32_t *n_channels) +{ + struct spa_audio_layout_info l; + uint32_t i; + if (spa_audio_layout_info_parse_name(&l, sizeof(l), str) <= 0) + return 0; + for (i = 0; i < l.n_channels && i < max_position; i++) + positioni = l.positioni; + *n_channels = l.n_channels; + return l.n_channels; +} + +SPA_API_AUDIO_RAW_JSON int +spa_audio_info_raw_ext_update(struct spa_audio_info_raw *info, size_t size, + const char *key, const char *val, bool force) { uint32_t v; + uint32_t max_position = SPA_AUDIO_INFO_RAW_MAX_POSITION(size); + + if (!SPA_AUDIO_INFO_RAW_VALID_SIZE(size)) + return -EINVAL; + if (spa_streq(key, SPA_KEY_AUDIO_FORMAT)) { if (force || info->format == 0) info->format = (enum spa_audio_format)spa_type_audio_format_from_short_name(val); @@ -57,43 +86,99 @@ if (spa_atou32(val, &v, 0) && (force || info->rate == 0)) info->rate = v; } else if (spa_streq(key, SPA_KEY_AUDIO_CHANNELS)) { - if (spa_atou32(val, &v, 0) && (force || info->channels == 0)) - info->channels = SPA_MIN(v, SPA_AUDIO_MAX_CHANNELS); + if (spa_atou32(val, &v, 0) && (force || info->channels == 0)) { + if (v > max_position) + return -ECHRNG; + info->channels = v; + } + } else if (spa_streq(key, SPA_KEY_AUDIO_LAYOUT)) { + if (force || info->channels == 0) { + if (spa_audio_parse_layout(val, info->position, max_position, &v) > 0) { + if (v > max_position) + return -ECHRNG; + info->channels = v; + SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); + } + } } else if (spa_streq(key, SPA_KEY_AUDIO_POSITION)) { if (force || info->channels == 0) { - if (spa_audio_parse_position(val, strlen(val), info->position, &info->channels) > 0) + if (spa_audio_parse_position_n(val, strlen(val), info->position, + max_position, &v) > 0) { + if (v > max_position) + return -ECHRNG; + info->channels = v; SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); + } } } return 0; } -SPA_API_AUDIO_RAW_JSON int SPA_SENTINEL -spa_audio_info_raw_init_dict_keys(struct spa_audio_info_raw *info, +SPA_API_AUDIO_RAW_JSON int +spa_audio_info_raw_update(struct spa_audio_info_raw *info, + const char *key, const char *val, bool force) +{ + return spa_audio_info_raw_ext_update(info, sizeof(*info), key, val, force); +} + +SPA_API_AUDIO_RAW_JSON int +spa_audio_info_raw_ext_init_dict_keys_va(struct spa_audio_info_raw *info, size_t size, const struct spa_dict *defaults, - const struct spa_dict *dict, ...) + const struct spa_dict *dict, va_list args) { - spa_zero(*info); + int res; + + if (!SPA_AUDIO_INFO_RAW_VALID_SIZE(size)) + return -EINVAL; + + memset(info, 0, size); SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); if (dict) { const char *val, *key; - va_list args; - va_start(args, dict); while ((key = va_arg(args, const char *))) { if ((val = spa_dict_lookup(dict, key)) == NULL) continue; - spa_audio_info_raw_update(info, key, val, true); + if ((res = spa_audio_info_raw_ext_update(info, size, + key, val, true)) < 0) + return res; } - va_end(args); } if (defaults) { const struct spa_dict_item *it; spa_dict_for_each(it, defaults) - spa_audio_info_raw_update(info, it->key, it->value, false); + if ((res = spa_audio_info_raw_ext_update(info, size, + it->key, it->value, false)) < 0) + return res; } return 0; } +SPA_API_AUDIO_RAW_JSON int SPA_SENTINEL +spa_audio_info_raw_ext_init_dict_keys(struct spa_audio_info_raw *info, size_t size, + const struct spa_dict *defaults, + const struct spa_dict *dict, ...) +{ + va_list args; + int res; + va_start(args, dict); + res = spa_audio_info_raw_ext_init_dict_keys_va(info, size, defaults, dict, args); + va_end(args); + return res; +} + +SPA_API_AUDIO_RAW_JSON int SPA_SENTINEL +spa_audio_info_raw_init_dict_keys(struct spa_audio_info_raw *info, + const struct spa_dict *defaults, + const struct spa_dict *dict, ...) +{ + va_list args; + int res; + va_start(args, dict); + res = spa_audio_info_raw_ext_init_dict_keys_va(info, sizeof(*info), defaults, dict, args); + va_end(args); + return res; +} + /** * \} */
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/raw-types.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/raw-types.h
Changed
@@ -267,12 +267,34 @@ SPA_API_AUDIO_RAW_TYPES uint32_t spa_type_audio_channel_from_short_name(const char *name) { - return spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN); + uint32_t res; + if (spa_strstartswith(name, "AUX")) { + if (spa_atou32(name+3, &res, 10) && res < 0x1000) + res = SPA_AUDIO_CHANNEL_AUX0 + res; + else + res = SPA_AUDIO_CHANNEL_UNKNOWN; + } else { + res = spa_type_from_short_name(name, spa_type_audio_channel, SPA_AUDIO_CHANNEL_UNKNOWN); + } + return res; } SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_to_short_name(uint32_t type) { return spa_type_to_short_name(type, spa_type_audio_channel, "UNK"); } +SPA_API_AUDIO_RAW_TYPES const char * spa_type_audio_channel_make_short_name(uint32_t type, + char *buf, size_t size, const char *unknown) +{ + if (SPA_AUDIO_CHANNEL_IS_AUX(type)) { + snprintf(buf, size, "AUX%u", type - SPA_AUDIO_CHANNEL_AUX0); + } else { + const char *str = spa_type_to_short_name(type, spa_type_audio_channel, NULL); + if (str == NULL) + return unknown; + snprintf(buf, size, "%.7s", str); + } + return buf; +} #define SPA_TYPE_INFO_AudioVolumeRampScale SPA_TYPE_INFO_ENUM_BASE "AudioVolumeRampScale" #define SPA_TYPE_INFO_AUDIO_VOLUME_RAMP_SCALE_BASE SPA_TYPE_INFO_AudioVolumeRampScale ":" @@ -292,4 +314,4 @@ } /* extern "C" */ #endif -#endif /* SPA_AUDIO_RAW_RAW_TYPES_H */ +#endif /* SPA_AUDIO_RAW_TYPES_H */
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/raw-utils.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/raw-utils.h
Changed
@@ -29,10 +29,15 @@ #endif SPA_API_AUDIO_RAW_UTILS int -spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info) +spa_format_audio_raw_ext_parse(const struct spa_pod *format, struct spa_audio_info_raw *info, size_t size) { struct spa_pod *position = NULL; int res; + uint32_t max_position = SPA_AUDIO_INFO_RAW_MAX_POSITION(size); + + if (!SPA_AUDIO_INFO_RAW_VALID_SIZE(size)) + return -EINVAL; + info->flags = 0; res = spa_pod_parse_object(format, SPA_TYPE_OBJECT_Format, NULL, @@ -40,18 +45,33 @@ SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate), SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels), SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position)); + if (info->channels > max_position) + return -ECHRNG; if (position == NULL || - !spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_AUDIO_MAX_CHANNELS)) + spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED); return res; } +SPA_API_AUDIO_RAW_UTILS int +spa_format_audio_raw_parse(const struct spa_pod *format, struct spa_audio_info_raw *info) +{ + return spa_format_audio_raw_ext_parse(format, info, sizeof(*info)); +} + SPA_API_AUDIO_RAW_UTILS struct spa_pod * -spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, - const struct spa_audio_info_raw *info) +spa_format_audio_raw_ext_build(struct spa_pod_builder *builder, uint32_t id, + const struct spa_audio_info_raw *info, size_t size) { struct spa_pod_frame f; + uint32_t max_position = SPA_AUDIO_INFO_RAW_MAX_POSITION(size); + + if (!SPA_AUDIO_INFO_RAW_VALID_SIZE(size)) { + errno = EINVAL; + return NULL; + } + spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_Format, id); spa_pod_builder_add(builder, SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), @@ -66,7 +86,10 @@ if (info->channels != 0) { spa_pod_builder_add(builder, SPA_FORMAT_AUDIO_channels, SPA_POD_Int(info->channels), 0); - if (!SPA_FLAG_IS_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { + /* we drop the positions here when we can't read all of them. This is + * really a malformed spa_audio_info structure. */ + if (!SPA_FLAG_IS_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED) && + info->channels <= max_position) { spa_pod_builder_add(builder, SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, info->channels, info->position), 0); @@ -75,6 +98,13 @@ return (struct spa_pod*)spa_pod_builder_pop(builder, &f); } +SPA_API_AUDIO_RAW_UTILS struct spa_pod * +spa_format_audio_raw_build(struct spa_pod_builder *builder, uint32_t id, + const struct spa_audio_info_raw *info) +{ + return spa_format_audio_raw_ext_build(builder, id, info, sizeof(*info)); +} + /** * \} */
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/raw.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/raw.h
Changed
@@ -18,7 +18,11 @@ * \{ */ -#define SPA_AUDIO_MAX_CHANNELS 128u +/* This is the max number of channels, changing this will change the + * size of some helper structures. This value should be at least 64 */ +#ifndef SPA_AUDIO_MAX_CHANNELS +#define SPA_AUDIO_MAX_CHANNELS 64u +#endif enum spa_audio_format { SPA_AUDIO_FORMAT_UNKNOWN, @@ -259,6 +263,8 @@ SPA_AUDIO_CHANNEL_START_Custom = 0x10000, }; +#define SPA_AUDIO_CHANNEL_IS_AUX(ch) ((ch)>=SPA_AUDIO_CHANNEL_START_Aux && (ch)<=SPA_AUDIO_CHANNEL_LAST_Aux) + enum spa_audio_volume_ramp_scale { SPA_AUDIO_VOLUME_RAMP_INVALID, SPA_AUDIO_VOLUME_RAMP_LINEAR, @@ -269,23 +275,34 @@ #define SPA_AUDIO_FLAG_NONE (0) /*< no valid flag */ #define SPA_AUDIO_FLAG_UNPOSITIONED (1 << 0) /*< the position array explicitly * contains unpositioned channels. */ -/** Audio information description */ +/** Audio information description. You can assume when you receive this structure + * that there is enought padding to accomodate all channel positions in case the + * channel count is more than SPA_AUDIO_MAX_CHANNELS. */ struct spa_audio_info_raw { enum spa_audio_format format; /*< format, one of enum spa_audio_format */ uint32_t flags; /*< extra flags */ uint32_t rate; /*< sample rate */ - uint32_t channels; /*< number of channels */ + uint32_t channels; /*< number of channels. This can be more than SPA_AUDIO_MAX_CHANNELS + * and you may assume there is enough padding for the extra + * channel positions. */ uint32_t positionSPA_AUDIO_MAX_CHANNELS; /*< channel position from enum spa_audio_channel */ + /* padding follows here when channels > SPA_AUDIO_MAX_CHANNELS */ }; #define SPA_AUDIO_INFO_RAW_INIT(...) ((struct spa_audio_info_raw) { __VA_ARGS__ }) +#define SPA_AUDIO_INFO_RAW_MAX_POSITION(size) (((size)-offsetof(struct spa_audio_info_raw,position))/sizeof(uint32_t)) + +#define SPA_AUDIO_INFO_RAW_VALID_SIZE(size) ((size) >= offsetof(struct spa_audio_info_raw, position)) + + #define SPA_KEY_AUDIO_FORMAT "audio.format" /**< an audio format as string, * Ex. "S16LE" */ #define SPA_KEY_AUDIO_CHANNEL "audio.channel" /**< an audio channel as string, * Ex. "FL" */ #define SPA_KEY_AUDIO_CHANNELS "audio.channels" /**< an audio channel count as int */ #define SPA_KEY_AUDIO_RATE "audio.rate" /**< an audio sample rate as int */ +#define SPA_KEY_AUDIO_LAYOUT "audio.layout" /**< channel positions as predefined layout */ #define SPA_KEY_AUDIO_POSITION "audio.position" /**< channel positions as comma separated list * of channels ex. "FL,FR" */ #define SPA_KEY_AUDIO_ALLOWED_RATES "audio.allowed-rates" /**< a list of allowed samplerates
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/audio/type-info.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/audio/type-info.h
Changed
@@ -6,6 +6,7 @@ #define SPA_AUDIO_TYPES_H #include <spa/param/audio/raw-types.h> +#include <spa/param/audio/layout-types.h> #include <spa/param/audio/iec958-types.h> #include <spa/param/audio/mp3-types.h> #include <spa/param/audio/aac-types.h>
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/props-types.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/props-types.h
Changed
@@ -40,6 +40,9 @@ { SPA_PROP_quality, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "quality", NULL }, { SPA_PROP_bluetoothAudioCodec, SPA_TYPE_Id, SPA_TYPE_INFO_PROPS_BASE "bluetoothAudioCodec", spa_type_bluetooth_audio_codec }, { SPA_PROP_bluetoothOffloadActive, SPA_TYPE_Bool, SPA_TYPE_INFO_PROPS_BASE "bluetoothOffloadActive", NULL }, + { SPA_PROP_clockId, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "clockId", NULL }, + { SPA_PROP_clockDevice, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "clockDevice", NULL }, + { SPA_PROP_clockInterface, SPA_TYPE_String, SPA_TYPE_INFO_PROPS_BASE "clockInterface", NULL }, { SPA_PROP_waveType, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "waveType", NULL }, { SPA_PROP_frequency, SPA_TYPE_Int, SPA_TYPE_INFO_PROPS_BASE "frequency", NULL },
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/param/props.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/param/props.h
Changed
@@ -55,6 +55,9 @@ SPA_PROP_quality, SPA_PROP_bluetoothAudioCodec, SPA_PROP_bluetoothOffloadActive, + SPA_PROP_clockId, + SPA_PROP_clockDevice, + SPA_PROP_clockInterface, SPA_PROP_START_Audio = 0x10000, /**< audio related properties */ SPA_PROP_waveType,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/pod/body.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/body.h
Changed
@@ -78,6 +78,36 @@ return 0; } +SPA_API_POD_BODY int spa_pod_choice_n_values(uint32_t choice_type, uint32_t *min, uint32_t *max) +{ + switch (choice_type) { + case SPA_CHOICE_Enum: + *min = 2; + *max = UINT32_MAX; + break; + case SPA_CHOICE_Range: + *min = *max = 3; + break; + case SPA_CHOICE_Step: + *min = *max = 4; + break; + case SPA_CHOICE_None: + case SPA_CHOICE_Flags: + *min = *max = 1; + break; + default: + /* + * This must always return at least 1, because callers + * assume that n_vals >= spa_pod_choice_n_values() + * mean that n_vals is at least 1. + */ + *min = 1; + *max = UINT32_MAX; + return 0; + } + return 1; +} + SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size, struct spa_pod *pod, const void **body) { @@ -243,9 +273,9 @@ SPA_API_POD_BODY int spa_pod_body_get_pointer(const struct spa_pod *pod, const void *body, uint32_t *type, const void **value) { + struct spa_pod_pointer_body b; if (!spa_pod_is_pointer(pod)) return -EINVAL; - struct spa_pod_pointer_body b; SPA_POD_BODY_LOAD_FIELD_ONCE(&b, body, type); SPA_POD_BODY_LOAD_FIELD_ONCE(&b, body, value); *type = b.type; @@ -333,6 +363,8 @@ *n_values = child_size ? (arr->pod.size - sizeof(arr->body)) / child_size : 0; *val_size = child_size; *val_type = arr->body.child.type; + if (*val_size < spa_pod_type_size(*val_type)) + *n_values = 0; return body; } @@ -366,13 +398,16 @@ const void *body, uint32_t *n_values, uint32_t *choice, uint32_t *val_size, uint32_t *val_type) { - uint32_t child_size = pod->body.child.size; + uint32_t child_size = pod->body.child.size, min, max; *val_size = child_size; *val_type = pod->body.child.type; *n_values = child_size ? (pod->pod.size - sizeof(pod->body)) / child_size : 0; *choice = pod->body.type; - if (*choice == SPA_CHOICE_None) - *n_values = SPA_MIN(1u, *n_values); + spa_pod_choice_n_values(*choice, &min, &max); + if (*n_values < min || *val_size < spa_pod_type_size(*val_type)) + *n_values = 0; + else if (*n_values > max) + *n_values = max; return body; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/pod/filter.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/filter.h
Changed
@@ -82,7 +82,7 @@ v1 = spa_pod_get_values(&p1->value, &nalt1, &p1c); v2 = spa_pod_get_values(&p2->value, &nalt2, &p2c); - /* empty choices */ + /* empty/invalid choices */ if (nalt1 < 1 || nalt2 < 1) return -EINVAL; @@ -95,8 +95,6 @@ /* incompatible property types */ if (type != v2->type || size != v2->size || p1->key != p2->key) return -EINVAL; - if (size < spa_pod_type_size(type)) - return -EINVAL; /* start with copying the property */ spa_pod_builder_prop(b, p1->key, p1->flags & p2->flags); @@ -406,7 +404,7 @@ struct spa_pod *v = spa_pod_get_values(&res->value, &nvals, &choice); const void *vals = SPA_POD_BODY(v); - if (v->size < spa_pod_type_size(v->type)) + if (nvals < 1) continue; if (spa_pod_compare_is_valid_choice(v->type, v->size,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/pod/iter.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/iter.h
Changed
@@ -228,7 +228,7 @@ spa_pod_choice_body_get_values(p, SPA_POD_BODY_CONST(p), n_vals, choice, &size, &type); return (struct spa_pod*)&p->body.child; } else { - *n_vals = 1; + *n_vals = pod->size < spa_pod_type_size(pod->type) ? 0 : 1; *choice = SPA_CHOICE_None; return (struct spa_pod*)pod; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/pod/parser.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/parser.h
Changed
@@ -90,13 +90,14 @@ /* Cast to uint64_t to avoid wraparound. */ const uint64_t long_offset = (uint64_t)offset + header_size; if (long_offset <= size && (offset & 7) == 0) { + struct spa_pod *pod; /* a barrier around the memcpy to make sure it is not moved around or - * duplicated after the size check below. We need to to work on shared - * memory while there could be updates happening while we read. */ + * duplicated after the size check below. We need to work on shared + * memory and so there could be updates happening while we read. */ SPA_BARRIER; memcpy(header, SPA_PTROFF(parser->data, offset, void), header_size); SPA_BARRIER; - struct spa_pod *pod = SPA_PTROFF(header, pod_offset, struct spa_pod); + pod = SPA_PTROFF(header, pod_offset, struct spa_pod); /* Check that the size (rounded to the next multiple of 8) is in bounds. */ if (long_offset + SPA_ROUND_UP_N((uint64_t)pod->size, SPA_POD_ALIGN) <= size) { *body = SPA_PTROFF(parser->data, long_offset, void);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/pod/vararg.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/pod/vararg.h
Changed
@@ -28,7 +28,7 @@ #define SPA_CHOICE_RANGE(def,min,max) 3,(def),(min),(max) #define SPA_CHOICE_STEP(def,min,max,step) 4,(def),(min),(max),(step) -#define SPA_CHOICE_ENUM(n_vals,...) (n_vals),##__VA_ARGS__ +#define SPA_CHOICE_ENUM(n_vals,def,alt1,...) (n_vals),(def),(alt1),##__VA_ARGS__ #define SPA_CHOICE_FLAGS(flags) 1, (flags) #define SPA_CHOICE_FEATURES(features) 1, (features) #define SPA_CHOICE_BOOL(def) 3,(def),(def),!(def)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/support/thread.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/support/thread.h
Changed
@@ -117,6 +117,8 @@ #define SPA_KEY_THREAD_STACK_SIZE "thread.stack-size" /* the stack size of the thread */ #define SPA_KEY_THREAD_AFFINITY "thread.affinity" /* array of CPUs for this thread */ #define SPA_KEY_THREAD_CREATOR "thread.creator" /* platform specific thread creator function */ +#define SPA_KEY_THREAD_RESET_ON_FORK "thread.reset-on-fork" /* reset priority and policy for real-time threads + on fork. Default true */ /** * \}
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/utils/cleanup.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/cleanup.h
Changed
@@ -46,9 +46,13 @@ /* ========================================================================== */ -#if defined(__has_attribute) && __has_attribute(__cleanup__) - +#ifdef __has_attribute +#if __has_attribute(__cleanup__) #define spa_cleanup(func) __attribute__((__cleanup__(func))) +#endif +#endif + +#ifdef spa_cleanup #define SPA_DEFINE_AUTO_CLEANUP(name, type, ...) \ typedef __typeof__(type) _spa_auto_cleanup_type_ ## name; \
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/utils/json-core.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/json-core.h
Changed
@@ -54,6 +54,15 @@ { *iter = SPA_JSON_INIT(data, size); } + +#define SPA_JSON_INIT_RELAX(type,data,size) \ + ((struct spa_json) { (data), (data)+(size), NULL, (uint32_t)((type) == '' ? 0x10 : 0x0), 0 }) + +SPA_API_JSON void spa_json_init_relax(struct spa_json * iter, char type, const char *data, size_t size) +{ + *iter = SPA_JSON_INIT_RELAX(type, data, size); +} + #define SPA_JSON_ENTER(iter) ((struct spa_json) { (iter)->cur, (iter)->end, (iter), (iter)->state & 0xff0, 0 }) SPA_API_JSON void spa_json_enter(struct spa_json * iter, struct spa_json * sub)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/utils/json.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/json.h
Changed
@@ -105,7 +105,7 @@ spa_json_init(iter, data, size); res = spa_json_enter_container(iter, iter, type); if (res == -EPROTO && relax) - spa_json_init(iter, data, size); + spa_json_init_relax(iter, type, data, size); else if (res <= 0) return res; return 1;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/include/spa/utils/string.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/include/spa/utils/string.h
Changed
@@ -10,6 +10,7 @@ #include <errno.h> #include <stdlib.h> #include <locale.h> +#include <sys/types.h> #include <spa/utils/defs.h>
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/lib/lib.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/lib/lib.c
Changed
@@ -1,4 +1,6 @@ +#undef SPA_AUDIO_MAX_CHANNELS + #define SPA_API_IMPL SPA_EXPORT #include <spa/utils/defs.h> #include <spa/buffer/alloc.h> @@ -61,6 +63,7 @@ #include <spa/param/audio/iec958-types.h> #include <spa/param/audio/iec958-utils.h> #include <spa/param/audio/layout.h> +#include <spa/param/audio/layout-types.h> #include <spa/param/audio/mp3.h> #include <spa/param/audio/mp3-types.h> #include <spa/param/audio/mp3-utils.h> @@ -165,9 +168,3 @@ #include <spa/utils/string.h> #include <spa/utils/type.h> #include <spa/utils/type-info.h> - - - - - -
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/alsa/acp/acp.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/alsa/acp/acp.c
Changed
@@ -245,7 +245,7 @@ pa_proplist_update(dev->proplist, PA_UPDATE_REPLACE, m->input_proplist); } if (m->split) { - char pos2048; + char posPA_CHANNELS_MAX*8; struct spa_strbuf b; int i; @@ -1142,8 +1142,9 @@ pa_proplist_unset(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED); } else { uint32_t positionseld.lpcm_channels; - char position64; - int i = 0, pos = 0; + char positioneld.lpcm_channels * 8; + struct spa_strbuf b; + int i = 0; if (eld.speakers & 0x01) { positionsi++ = ACP_CHANNEL_FL; @@ -1172,16 +1173,14 @@ if (eld.speakers & 0x10) { positionsi++ = ACP_CHANNEL_RC; } - while (i < eld.lpcm_channels) positionsi++ = ACP_CHANNEL_UNKNOWN; - for (i = 0, pos = 0; i < eld.lpcm_channels; i++) { - pos += snprintf(&positionpos, sizeof(position) - pos, "%s,", channel_namespositionsi); - } - - /* Overwrite trailing , */ - positionpos - 1 = 0; + spa_strbuf_init(&b, position, sizeof(position)); + spa_strbuf_append(&b, ""); + for (i = 0; i < eld.lpcm_channels; i++) + spa_strbuf_append(&b, "%s%s", i ? "," : "", channel_namespositionsi); + spa_strbuf_append(&b, ""); changed |= (old_position == NULL) || (!spa_streq(old_position, position)); pa_proplist_sets(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED, position);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/alsa/acp/channelmap.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/alsa/acp/channelmap.h
Changed
@@ -27,7 +27,11 @@ extern "C" { #endif +#ifdef SPA_AUDIO_MAX_CHANNELS +#define PA_CHANNELS_MAX ((int)SPA_AUDIO_MAX_CHANNELS) +#else #define PA_CHANNELS_MAX 64 +#endif #define PA_CHANNEL_MAP_SNPRINT_MAX (PA_CHANNELS_MAX * 32) @@ -451,7 +455,6 @@ static inline char* pa_channel_map_snprint(char *s, size_t l, const pa_channel_map *map) { unsigned channel; - bool first = true; char *e; if (!pa_channel_map_valid(map)) { pa_snprintf(s, l, "%s", _("(invalid)")); @@ -460,12 +463,10 @@ *(e = s) = 0; for (channel = 0; channel < map->channels && l > 1; channel++) { l -= pa_snprintf(e, l, "%s%s", - first ? "" : ",", + channel == 0 ? "" : ",", pa_channel_position_to_string(map->mapchannel)); e = strchr(e, 0); - first = false; } - return s; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/alsa/alsa-acp-device.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/alsa/alsa-acp-device.c
Changed
@@ -38,6 +38,7 @@ extern struct spa_i18n *acp_i18n; #define MAX_POLL 16 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define DEFAULT_DEVICE "hw:0" #define DEFAULT_AUTO_PROFILE true @@ -155,12 +156,13 @@ const struct acp_dict_item *it; uint32_t n_items, i; char device_name128, path210, channels16, ch12, routes16; - char card_index16, card_name64, *p; - char positionsSPA_AUDIO_MAX_CHANNELS * 12; + char card_index16, card_name64; + char positionsMAX_CHANNELS * 12; char codecs512; struct spa_device_object_info info; struct acp_card *card = this->card; const char *stream, *card_id, *bus; + struct spa_strbuf b; info = SPA_DEVICE_OBJECT_INFO_INIT(); info.type = SPA_TYPE_INTERFACE_Node; @@ -199,11 +201,13 @@ snprintf(channels, sizeof(channels), "%d", dev->format.channels); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_CHANNELS, channels); - p = positions; + spa_strbuf_init(&b, positions, sizeof(positions)); + spa_strbuf_append(&b, ""); for (i = 0; i < dev->format.channels; i++) { - p += snprintf(p, 12, "%s%s", i == 0 ? "" : ",", + spa_strbuf_append(&b, "%s%s", i == 0 ? " " : ", ", acp_channel_str(ch, sizeof(ch), dev->format.mapi)); } + spa_strbuf_append(&b, " "); itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_AUDIO_POSITION, positions); if (dev->n_codecs > 0) { @@ -673,8 +677,8 @@ struct spa_pod_prop *prop; struct spa_pod_object *obj = (struct spa_pod_object *) props; int changed = 0; - float volumesSPA_AUDIO_MAX_CHANNELS; - uint32_t channelsSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; + uint32_t channelsMAX_CHANNELS; uint32_t n_volumes = 0; if (!spa_pod_is_object_type(props, SPA_TYPE_OBJECT_Props)) @@ -696,13 +700,13 @@ break; case SPA_PROP_channelVolumes: if ((n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { + volumes, SPA_N_ELEMENTS(volumes))) > 0) { changed++; } break; case SPA_PROP_channelMap: if (spa_pod_copy_array(&prop->value, SPA_TYPE_Id, - channels, SPA_AUDIO_MAX_CHANNELS) > 0) { + channels, SPA_N_ELEMENTS(channels)) > 0) { changed++; } break;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/alsa/alsa-pcm.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/alsa/alsa-pcm.c
Changed
@@ -163,10 +163,10 @@ int fmt_change = 0; if (spa_streq(k, SPA_KEY_AUDIO_CHANNELS)) { state->default_channels = atoi(s); - if (state->default_channels > SPA_AUDIO_MAX_CHANNELS) { + if (state->default_channels > MAX_CHANNELS) { spa_log_warn(state->log, "%p: %s: %s > %d, clamping", - state, k, s, SPA_AUDIO_MAX_CHANNELS); - state->default_channels = SPA_AUDIO_MAX_CHANNELS; + state, k, s, MAX_CHANNELS); + state->default_channels = MAX_CHANNELS; } fmt_change++; } else if (spa_streq(k, SPA_KEY_AUDIO_RATE)) { @@ -240,35 +240,33 @@ static int position_to_string(struct channel_map *map, char *val, size_t len) { - uint32_t i, o = 0; - int r; - o += snprintf(val, len, " "); - for (i = 0; i < map->channels; i++) { - r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ", - spa_debug_type_find_short_name(spa_type_audio_channel, - map->posi)); - if (r < 0 || o + r >= len) - return -ENOSPC; - o += r; + uint32_t i; + char pos8; + struct spa_strbuf b; + + spa_strbuf_init(&b, val, len); + spa_strbuf_append(&b, ""); + for (i = 0; i < map->n_pos; i++) { + spa_strbuf_append(&b, "%s%s", i == 0 ? " " : ", ", + spa_type_audio_channel_make_short_name(map->posi, + pos, sizeof(pos), "UNK")); } - if (len > o) - o += snprintf(val+o, len-o, " "); + if (spa_strbuf_append(&b, " ") < 2) + return -ENOSPC; return 0; } static int uint32_array_to_string(uint32_t *vals, uint32_t n_vals, char *val, size_t len) { - uint32_t i, o = 0; - int r; - o += snprintf(val, len, " "); - for (i = 0; i < n_vals; i++) { - r = snprintf(val+o, len-o, "%s%d", i == 0 ? "" : ", ", valsi); - if (r < 0 || o + r >= len) - return -ENOSPC; - o += r; - } - if (len > o) - o += snprintf(val+o, len-o, " "); + uint32_t i; + struct spa_strbuf b; + + spa_strbuf_init(&b, val, len); + spa_strbuf_append(&b, ""); + for (i = 0; i < n_vals; i++) + spa_strbuf_append(&b, "%s%d", i == 0 ? " " : ", ", valsi); + if (spa_strbuf_append(&b, " ") < 2) + return -ENOSPC; return 0; } @@ -775,7 +773,7 @@ snd_ctl_elem_id_alloca(&bound_id); snd_ctl_elem_value_alloca(&old_value); - while ((err = snd_ctl_read(state->ctl, ev) > 0)) { + while ((err = snd_ctl_read(state->ctl, ev)) > 0) { bool changed = false; if (snd_ctl_event_get_type(ev) != SND_CTL_EVENT_ELEM) @@ -1584,8 +1582,8 @@ spa_log_debug(state->log, "channels (%d %d) default:%d all:%d", min, max, state->default_channels, all); - min = SPA_MIN(min, SPA_AUDIO_MAX_CHANNELS); - max = SPA_MIN(max, SPA_AUDIO_MAX_CHANNELS); + min = SPA_MIN(min, MAX_CHANNELS); + max = SPA_MIN(max, MAX_CHANNELS); if (state->default_channels != 0 && !all) { if (min > state->default_channels || @@ -1645,7 +1643,7 @@ } else { const struct channel_map *map = NULL; spa_pod_builder_int(b, min); - if (state->default_pos.channels == min) { + if (state->default_pos.n_pos == min) { map = &state->default_pos; spa_log_debug(state->log, "%p: using provided default", state); } else if (min <= 8) { @@ -1655,7 +1653,7 @@ if (map) { spa_pod_builder_prop(b, SPA_FORMAT_AUDIO_position, 0); spa_pod_builder_push_array(b, &f0); - for (i = 0; i < map->channels; i++) { + for (i = 0; i < map->n_pos; i++) { spa_log_debug(state->log, "%p: position %zd %d", state, i, map->posi); spa_pod_builder_id(b, map->posi); }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/alsa/alsa-pcm.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/alsa/alsa-pcm.h
Changed
@@ -36,6 +36,7 @@ #endif #define MAX_RATES 16 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define DEFAULT_PERIOD 1024u #define DEFAULT_RATE 48000u @@ -71,8 +72,8 @@ #define BW_PERIOD (3 * SPA_NSEC_PER_SEC) struct channel_map { - uint32_t channels; - uint32_t posSPA_AUDIO_MAX_CHANNELS; + uint32_t n_pos; + uint32_t posMAX_CHANNELS; }; struct card { @@ -314,7 +315,7 @@ static inline void spa_alsa_parse_position(struct channel_map *map, const char *val, size_t len) { - spa_audio_parse_position(val, len, map->pos, &map->channels); + spa_audio_parse_position_n(val, len, map->pos, SPA_N_ELEMENTS(map->pos), &map->n_pos); } static inline uint32_t spa_alsa_parse_rates(uint32_t *rates, uint32_t max, const char *val, size_t len)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/audioadapter.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/audioadapter.c
Changed
@@ -808,6 +808,7 @@ if (spa_format_audio_parse(param, &info) < 0) { spa_log_error(this->log, "%p: cannot set Format param: " "parsing the POD failed", this); + spa_debug_log_pod(this->log, SPA_LOG_LEVEL_ERROR, 0, NULL, param); return -EINVAL; } if (info.media_subtype != SPA_MEDIA_SUBTYPE_raw) { @@ -841,6 +842,7 @@ SPA_PARAM_PORT_CONFIG_format, SPA_POD_OPT_Pod(&format)) < 0) { spa_log_error(this->log, "%p: cannot set PortConfig param: " "parsing the POD failed", this); + spa_debug_log_pod(this->log, SPA_LOG_LEVEL_ERROR, 0, NULL, param); return -EINVAL; } @@ -848,8 +850,12 @@ struct spa_audio_info info; spa_zero(info); - if ((res = spa_format_audio_parse(format, &info)) < 0) + if ((res = spa_format_audio_parse(format, &info)) < 0) { + spa_log_error(this->log, "%p: cannot set PortConfig param: " + "parsing format failed: %s", this, spa_strerror(res)); + spa_debug_log_pod(this->log, SPA_LOG_LEVEL_ERROR, 0, NULL, format); return res; + } if (info.media_subtype == SPA_MEDIA_SUBTYPE_raw) { info.info.raw.rate = 0; @@ -1213,6 +1219,9 @@ case SPA_PARAM_Tag: idx = IDX_Tag; break; + case SPA_PARAM_EnumFormat: + idx = IDX_EnumFormat; + break; default: continue; } @@ -1240,6 +1249,11 @@ spa_log_debug(this->log, "tag: %d (%s)", res, spa_strerror(res)); } + if (idx == IDX_EnumFormat) { + spa_log_info(this->log, "new EnumFormat from converter"); + /* we will renegotiate when restarting */ + this->recheck_format = true; + } spa_log_debug(this->log, "param %d changed", info->paramsi.id); } } @@ -1438,7 +1452,7 @@ spa_strerror(res)); } if (idx == IDX_EnumFormat) { - spa_log_debug(this->log, "new formats"); + spa_log_debug(this->log, "new EnumFormat from follower"); /* we will renegotiate when restarting */ this->recheck_format = true; } @@ -2046,11 +2060,12 @@ return -ENOENT; if (format.media_subtype == SPA_MEDIA_SUBTYPE_raw) { + uint32_t n_pos = SPA_MIN(SPA_N_ELEMENTS(format.info.raw.position), format.info.raw.channels); if (position == POSITION_AUX) { - for (i = 0; i < format.info.raw.channels; i++) + for (i = 0; i < n_pos; i++) format.info.raw.positioni = SPA_AUDIO_CHANNEL_START_Aux + i; } else if (position == POSITION_UNKNOWN) { - for (i = 0; i < format.info.raw.channels; i++) + for (i = 0; i < n_pos; i++) format.info.raw.positioni = SPA_AUDIO_CHANNEL_UNKNOWN; } }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/audioconvert.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/audioconvert.c
Changed
@@ -47,10 +47,11 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define MAX_ALIGN FMT_OPS_MAX_ALIGN #define MAX_BUFFERS 32 -#define MAX_DATAS SPA_AUDIO_MAX_CHANNELS -#define MAX_PORTS (SPA_AUDIO_MAX_CHANNELS+1) +#define MAX_DATAS MAX_CHANNELS +#define MAX_PORTS (MAX_CHANNELS+1) #define MAX_STAGES 64 #define MAX_GRAPH 9 /* 8 active + 1 replacement slot */ @@ -62,7 +63,7 @@ struct volumes { bool mute; uint32_t n_volumes; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; }; static void init_volumes(struct volumes *vol) @@ -70,7 +71,7 @@ uint32_t i; vol->mute = DEFAULT_MUTE; vol->n_volumes = 0; - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) vol->volumesi = DEFAULT_VOLUME; } @@ -91,7 +92,7 @@ float max_volume; float prev_volume; uint32_t n_channels; - uint32_t channel_mapSPA_AUDIO_MAX_CHANNELS; + uint32_t channel_mapMAX_CHANNELS; struct volumes channel; struct volumes soft; struct volumes monitor; @@ -112,7 +113,7 @@ props->min_volume = DEFAULT_MIN_VOLUME; props->max_volume = DEFAULT_MAX_VOLUME; props->n_channels = 0; - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) props->channel_mapi = SPA_AUDIO_CHANNEL_UNKNOWN; init_volumes(&props->channel); init_volumes(&props->soft); @@ -241,9 +242,9 @@ struct spa_filter_graph *graph; struct spa_hook listener; uint32_t n_inputs; - uint32_t inputs_positionSPA_AUDIO_MAX_CHANNELS; + uint32_t inputs_positionMAX_CHANNELS; uint32_t n_outputs; - uint32_t outputs_positionSPA_AUDIO_MAX_CHANNELS; + uint32_t outputs_positionMAX_CHANNELS; uint32_t latency; bool removing; bool setup; @@ -281,6 +282,7 @@ struct props props; + struct spa_io_clock *io_clock; struct spa_io_position *io_position; struct spa_io_rate_match *io_rate_match; @@ -423,7 +425,6 @@ uint32_t position, bool is_dsp, bool is_monitor, bool is_control) { struct port *port = GET_PORT(this, direction, port_id); - const char *name; spa_assert(port_id < MAX_PORTS); @@ -438,8 +439,7 @@ port->latencySPA_DIRECTION_INPUT = SPA_LATENCY_INFO(SPA_DIRECTION_INPUT); port->latencySPA_DIRECTION_OUTPUT = SPA_LATENCY_INFO(SPA_DIRECTION_OUTPUT); - name = spa_debug_type_find_short_name(spa_type_audio_channel, position); - snprintf(port->position, sizeof(port->position), "%s", name ? name : "UNK"); + spa_type_audio_channel_make_short_name(position, port->position, sizeof(port->position), "UNK"); port->info = SPA_PORT_INFO_INIT(); port->info.change_mask = port->info_all = SPA_PORT_CHANGE_MASK_FLAGS | @@ -1006,12 +1006,43 @@ spa_log_debug(this->log, "%p: io %d %p/%zd", this, id, data, size); switch (id) { + case SPA_IO_Clock: + this->io_clock = data; + break; case SPA_IO_Position: + { + struct port *p; + uint32_t i; + this->io_position = data; + + if (this->io_position && this->io_clock && + this->io_position->clock.target_rate.denom != this->io_clock->target_rate.denom && + !this->props.resample_disabled) { + spa_log_warn(this->log, "driver %d changed rate:%u -> %u", this->io_position->clock.id, + this->io_clock->target_rate.denom, + this->io_position->clock.target_rate.denom); + + this->io_clock->target_rate = this->io_position->clock.target_rate; + for (i = 0; i < this->dirSPA_DIRECTION_INPUT.n_ports; i++) { + if ((p = GET_IN_PORT(this, i)) && p->valid && !p->is_dsp && !p->is_control) { + p->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; + p->paramsIDX_EnumFormat.user++; + } + } + for (i = 0; i < this->dirSPA_DIRECTION_OUTPUT.n_ports; i++) { + if ((p = GET_OUT_PORT(this, i)) && p->valid && !p->is_dsp && !p->is_control) { + p->info.change_mask |= SPA_PORT_CHANGE_MASK_PARAMS; + p->paramsIDX_EnumFormat.user++; + } + } + } break; + } default: return -ENOENT; } + emit_info(this, false); return 0; } @@ -1103,11 +1134,11 @@ else if (spa_streq(k, "n_outputs")) spa_atou32(s, &g->n_outputs, 0); else if (spa_streq(k, "inputs.audio.position")) - spa_audio_parse_position(s, strlen(s), - g->inputs_position, &g->n_inputs); + spa_audio_parse_position_n(s, strlen(s), g->inputs_position, + SPA_N_ELEMENTS(g->inputs_position), &g->n_inputs); else if (spa_streq(k, "outputs.audio.position")) - spa_audio_parse_position(s, strlen(s), - g->outputs_position, &g->n_outputs); + spa_audio_parse_position_n(s, strlen(s), g->outputs_position, + SPA_N_ELEMENTS(g->outputs_position), &g->n_outputs); else if (spa_streq(k, "latency")) { double latency; if (spa_atod(s, &latency)) @@ -1539,8 +1570,6 @@ samples = (vrp->volume_ramp_time * vrp->rate) / 1000; spa_log_info(this->log, "volume ramp samples calculated from time is %d", samples); } - if (!samples) - samples = -1; return samples; } @@ -1551,12 +1580,10 @@ if (vrp->volume_ramp_step_samples) samples = vrp->volume_ramp_step_samples; else if (vrp->volume_ramp_step_time) { - /* convert the step time which is in nano seconds to seconds */ - samples = (vrp->volume_ramp_step_time/1000) * (vrp->rate/1000); + /* convert the step time which is in nano seconds to seconds, round up */ + samples = SPA_MAX(1u, vrp->volume_ramp_step_time/1000) * (vrp->rate/1000); spa_log_debug(this->log, "volume ramp step samples calculated from time is %d", samples); } - if (!samples) - samples = -1; return samples; } @@ -1569,76 +1596,52 @@ return 0.0; } -static struct spa_pod *generate_ramp_up_seq(struct impl *this, struct volume_ramp_params *vrp, +static struct spa_pod *generate_ramp_seq(struct impl *this, struct volume_ramp_params *vrp, void *buffer, size_t size) { struct spa_pod_dynamic_builder b; struct spa_pod_frame f1; - float start = vrp->start, end = vrp->end, volume_accum = start; - int ramp_samples = get_ramp_samples(this, vrp); - int ramp_step_samples = get_ramp_step_samples(this, vrp); - float volume_step = ((end - start) / (ramp_samples / ramp_step_samples)); - uint32_t volume_offs = 0; + float start = vrp->start, end = vrp->end; + int samples = get_ramp_samples(this, vrp); + int step = get_ramp_step_samples(this, vrp); + int offs = 0; + + if (samples < 0 || step < 0 || (samples > 0 && step == 0)) + return NULL; spa_pod_dynamic_builder_init(&b, buffer, size, 4096); spa_pod_builder_push_sequence(&b.b, &f0, 0); - spa_log_info(this->log, "generating ramp up sequence from %f to %f with a" - " step value %f at scale %d", start, end, volume_step, vrp->scale); - do { - float vas = get_volume_at_scale(vrp, volume_accum); - spa_log_trace(this->log, "volume accum %f", vas); - spa_pod_builder_control(&b.b, volume_offs, SPA_CONTROL_Properties); - spa_pod_builder_add_object(&b.b, - SPA_TYPE_OBJECT_Props, 0, - SPA_PROP_volume, SPA_POD_Float(vas)); - volume_accum += volume_step; - volume_offs += ramp_step_samples; - } while (volume_accum < end); - return spa_pod_builder_pop(&b.b, &f0); -} + spa_log_info(this->log, "generating ramp sequence from %f to %f with " + "step %d/%d at scale %d", start, end, step, samples, vrp->scale); -static struct spa_pod *generate_ramp_down_seq(struct impl *this, struct volume_ramp_params *vrp, - void *buffer, size_t size) -{ - struct spa_pod_dynamic_builder b; - struct spa_pod_frame f1; - int ramp_samples = get_ramp_samples(this, vrp); - int ramp_step_samples = get_ramp_step_samples(this, vrp); - float start = vrp->start, end = vrp->end, volume_accum = start; - float volume_step = ((start - end) / (ramp_samples / ramp_step_samples)); - uint32_t volume_offs = 0; + while (1) { + float pos = (samples == 0) ? end : + SPA_CLAMP(start + (end - start) * offs / samples, + SPA_MIN(start, end), SPA_MAX(start, end)); + float vas = get_volume_at_scale(vrp, pos); - spa_pod_dynamic_builder_init(&b, buffer, size, 4096); - - spa_pod_builder_push_sequence(&b.b, &f0, 0); - spa_log_info(this->log, "generating ramp down sequence from %f to %f with a" - " step value %f at scale %d", start, end, volume_step, vrp->scale); - do { - float vas = get_volume_at_scale(vrp, volume_accum); - spa_log_trace(this->log, "volume accum %f", vas); - spa_pod_builder_control(&b.b, volume_offs, SPA_CONTROL_Properties); + spa_log_trace(this->log, "volume %d accum %f", offs, vas); + spa_pod_builder_control(&b.b, offs, SPA_CONTROL_Properties); spa_pod_builder_add_object(&b.b, SPA_TYPE_OBJECT_Props, 0, SPA_PROP_volume, SPA_POD_Float(vas)); - volume_accum -= volume_step; - volume_offs += ramp_step_samples; - } while (volume_accum > end); + if (offs >= samples) + break; + + offs = SPA_MIN(samples, offs + step); + } + return spa_pod_builder_pop(&b.b, &f0); } static void generate_volume_ramp(struct impl *this, struct volume_ramp_params *vrp, void *buffer, size_t size) { - void *sequence = NULL; - if (vrp->start == vrp->end) - spa_log_error(this->log, "no change in volume, cannot ramp volume"); - else if (vrp->end > vrp->start) - sequence = generate_ramp_up_seq(this, vrp, buffer, size); - else - sequence = generate_ramp_down_seq(this, vrp, buffer, size); + void *sequence; + sequence = generate_ramp_seq(this, vrp, buffer, size); if (!sequence) spa_log_error(this->log, "unable to generate sequence"); @@ -1748,7 +1751,7 @@ case SPA_PROP_channelVolumes: if (!p->lock_volumes && (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - p->channel.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { + p->channel.volumes, SPA_N_ELEMENTS(p->channel.volumes))) > 0) { have_channel_volume = true; p->channel.n_volumes = n; changed++; @@ -1756,7 +1759,7 @@ break; case SPA_PROP_channelMap: if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, - p->channel_map, SPA_AUDIO_MAX_CHANNELS)) > 0) { + p->channel_map, SPA_N_ELEMENTS(p->channel_map))) > 0) { p->n_channels = n; changed++; } @@ -1771,7 +1774,7 @@ case SPA_PROP_softVolumes: if (!p->lock_volumes && (n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - p->soft.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { + p->soft.volumes, SPA_N_ELEMENTS(p->soft.volumes))) > 0) { have_soft_volume = true; p->soft.n_volumes = n; changed++; @@ -1783,7 +1786,7 @@ break; case SPA_PROP_monitorVolumes: if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - p->monitor.volumes, SPA_AUDIO_MAX_CHANNELS)) > 0) { + p->monitor.volumes, SPA_N_ELEMENTS(p->monitor.volumes))) > 0) { p->monitor.n_volumes = n; changed++; } @@ -1895,10 +1898,11 @@ this->dirSPA_DIRECTION_OUTPUT.n_ports = dir->n_ports + 1; for (i = 0; i < dir->n_ports; i++) { - init_port(this, direction, i, info->info.raw.positioni, true, false, false); + uint32_t pos = info->info.raw.positioni; + init_port(this, direction, i, pos, true, false, false); if (this->monitor && direction == SPA_DIRECTION_INPUT) init_port(this, SPA_DIRECTION_OUTPUT, i+1, - info->info.raw.positioni, true, true, false); + pos, true, true, false); } break; } @@ -1966,7 +1970,7 @@ return -EINVAL; if (info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels > MAX_CHANNELS) return -EINVAL; infop = &info; @@ -2056,22 +2060,24 @@ dst_info.info.raw.rate); qsort(dst_info.info.raw.position, dst_info.info.raw.channels, - sizeof(uint32_t), int32_cmp); + sizeof(uint32_t), int32_cmp); for (i = 0; i < src_info.info.raw.channels; i++) { for (j = 0; j < dst_info.info.raw.channels; j++) { - if (src_info.info.raw.positioni != - dst_info.info.raw.positionj) + uint32_t pi, pj; + char b18, b28; + + pi = src_info.info.raw.positioni; + pj = dst_info.info.raw.positionj; + if (pi != pj) continue; in->remapi = j; if (i != j) remap = true; spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, i, in->remapi, j, - spa_debug_type_find_short_name(spa_type_audio_channel, - src_info.info.raw.positioni), - spa_debug_type_find_short_name(spa_type_audio_channel, - dst_info.info.raw.positionj)); + spa_type_audio_channel_make_short_name(pi, b1, 8, "UNK"), + spa_type_audio_channel_make_short_name(pj, b2, 8, "UNK")); dst_info.info.raw.positionj = -1; break; } @@ -2120,9 +2126,10 @@ for (i = 0; i < p->n_channels; i++) { for (j = i; j < target; j++) { + uint32_t pj = info->info.raw.positionj; spa_log_debug(this->log, "%d %d: %d <-> %d", i, j, - p->channel_mapi, info->info.raw.positionj); - if (p->channel_mapi != info->info.raw.positionj) + p->channel_mapi, pj); + if (p->channel_mapi != pj) continue; if (i != j) { SPA_SWAP(p->channel_mapi, p->channel_mapj); @@ -2153,7 +2160,7 @@ { struct volumes *vol; uint32_t i; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; struct dir *dir = &this->dirthis->direction; spa_log_debug(this->log, "%p set volume %f have_format:%d", this, this->props.volume, dir->have_format); @@ -2184,10 +2191,11 @@ static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position) { uint32_t i, idx = 0; + char buf8; for (i = 0; i < channels; i++) idx += snprintf(str + idx, len - idx, "%s%s", i == 0 ? "" : " ", - spa_debug_type_find_short_name(spa_type_audio_channel, - positioni)); + spa_type_audio_channel_make_short_name(positioni, + buf, sizeof(buf), "UNK")); return str; } @@ -2344,12 +2352,16 @@ dst_info.info.raw.rate); qsort(src_info.info.raw.position, src_info.info.raw.channels, - sizeof(uint32_t), int32_cmp); + sizeof(uint32_t), int32_cmp); for (i = 0; i < src_info.info.raw.channels; i++) { for (j = 0; j < dst_info.info.raw.channels; j++) { - if (src_info.info.raw.positioni != - dst_info.info.raw.positionj) + uint32_t pi, pj; + char b18, b28; + + pi = src_info.info.raw.positioni; + pj = dst_info.info.raw.positionj; + if (pi != pj) continue; out->remapi = j; if (i != j) @@ -2357,10 +2369,9 @@ spa_log_debug(this->log, "%p: channel %d (%d) -> %d (%s -> %s)", this, i, out->remapi, j, - spa_debug_type_find_short_name(spa_type_audio_channel, - src_info.info.raw.positioni), - spa_debug_type_find_short_name(spa_type_audio_channel, - dst_info.info.raw.positionj)); + spa_type_audio_channel_make_short_name(pi, b1, 8, "UNK"), + spa_type_audio_channel_make_short_name(pj, b2, 8, "UNK")); + dst_info.info.raw.positionj = -1; break; } @@ -2671,7 +2682,7 @@ } spa_pod_builder_add(b, SPA_FORMAT_AUDIO_channels, SPA_POD_CHOICE_RANGE_Int( - DEFAULT_CHANNELS, 1, SPA_AUDIO_MAX_CHANNELS), + DEFAULT_CHANNELS, 1, MAX_CHANNELS), 0); *param = spa_pod_builder_pop(b, &f0); } @@ -3064,7 +3075,7 @@ if (info.info.raw.format == 0 || (!this->props.resample_disabled && info.info.raw.rate == 0) || info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) { + info.info.raw.channels > MAX_CHANNELS) { spa_log_error(this->log, "invalid format:%d rate:%d channels:%d", info.info.raw.format, info.info.raw.rate, info.info.raw.channels); @@ -4295,9 +4306,18 @@ this->direction = SPA_DIRECTION_INPUT; } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { - if (s != NULL) - spa_audio_parse_position(s, strlen(s), this->props.channel_map, - &this->props.n_channels); + if (s == NULL) + continue; + spa_audio_parse_position_n(s, strlen(s), + this->props.channel_map, SPA_N_ELEMENTS(this->props.channel_map), + &this->props.n_channels); + } + else if (spa_streq(k, SPA_KEY_AUDIO_LAYOUT)) { + if (s == NULL) + continue; + spa_audio_parse_layout(s, + this->props.channel_map, SPA_N_ELEMENTS(this->props.channel_map), + &this->props.n_channels); } else if (spa_streq(k, SPA_KEY_PORT_IGNORE_LATENCY)) this->port_ignore_latency = spa_atob(s);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/channelmix-ops.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/channelmix-ops.c
Changed
@@ -142,29 +142,29 @@ } static void distribute_mix(struct channelmix *mix, - float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + float matrixMAX_CHANNELSMAX_CHANNELS, uint64_t mask) { uint32_t i, ch = mask_to_ch(mix, mask); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixich= 1.0f; } static void average_mix(struct channelmix *mix, - float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + float matrixMAX_CHANNELSMAX_CHANNELS, uint64_t mask) { uint32_t i, ch = mask_to_ch(mix, mask); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixchi= 1.0f; } -static void pair_mix(float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS) +static void pair_mix(float matrixMAX_CHANNELSMAX_CHANNELS) { uint32_t i; - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixii= 1.0f; } static bool match_mix(struct channelmix *mix, - float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS, + float matrixMAX_CHANNELSMAX_CHANNELS, uint64_t src_mask, uint64_t dst_mask) { bool matched = false; @@ -181,7 +181,7 @@ static int make_matrix(struct channelmix *mix) { - float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS = {{ 0.0f }}; + float matrixMAX_CHANNELSMAX_CHANNELS = {{ 0.0f }}; uint64_t src_mask = mix->src_mask, src_paired; uint64_t dst_mask = mix->dst_mask, dst_paired; uint32_t src_chan = mix->src_chan; @@ -293,7 +293,7 @@ keep &= ~STEREO; } else if (dst_mask & _MASK(MONO)){ spa_log_info(mix->log, "assign FC to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixi_CH(FC)= 1.0f; normalize = true; } else { @@ -313,7 +313,7 @@ keep &= ~FRONT; } else if ((dst_mask & _MASK(MONO))){ spa_log_info(mix->log, "assign STEREO to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) { matrixi_CH(FL)= 1.0f; matrixi_CH(FR)= 1.0f; } @@ -352,7 +352,7 @@ _MATRIX(FC,RC) += slev * SQRT1_2; } else if (dst_mask & _MASK(MONO)){ spa_log_info(mix->log, "assign RC to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixi_CH(RC)= 1.0f; normalize = true; } else { @@ -398,7 +398,7 @@ _MATRIX(FC,RR)+= slev * SQRT1_2; } else if (dst_mask & _MASK(MONO)){ spa_log_info(mix->log, "assign RL+RR to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) { matrixi_CH(RL)= 1.0f; matrixi_CH(RR)= 1.0f; } @@ -450,7 +450,7 @@ _MATRIX(FC,SR) += slev * SQRT1_2; } else if (dst_mask & _MASK(MONO)){ spa_log_info(mix->log, "assign SL+SR to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) { matrixi_CH(SL)= 1.0f; matrixi_CH(SR)= 1.0f; } @@ -471,7 +471,7 @@ _MATRIX(FC,FRC)+= SQRT1_2; } else if (dst_mask & _MASK(MONO)){ spa_log_info(mix->log, "assign FLC+FRC to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) { matrixi_CH(FLC)= 1.0f; matrixi_CH(FRC)= 1.0f; } @@ -492,7 +492,7 @@ _MATRIX(FR,LFE) += llev * SQRT1_2; } else if ((dst_mask & _MASK(MONO))){ spa_log_info(mix->log, "assign LFE to MONO (%f)", 1.0f); - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) + for (i = 0; i < MAX_CHANNELS; i++) matrixi_CH(LFE)= 1.0f; normalize = true; } else { @@ -690,7 +690,7 @@ static void impl_channelmix_set_volume(struct channelmix *mix, float volume, bool mute, uint32_t n_channel_volumes, float *channel_volumes) { - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; float vol = mute ? 0.0f : volume, t; uint32_t i, j; uint32_t src_chan = mix->src_chan; @@ -760,8 +760,8 @@ { const struct channelmix_info *info; - if (mix->src_chan > SPA_AUDIO_MAX_CHANNELS || - mix->dst_chan > SPA_AUDIO_MAX_CHANNELS) + if (mix->src_chan > MAX_CHANNELS || + mix->dst_chan > MAX_CHANNELS) return -EINVAL; info = find_channelmix_info(mix->src_chan, mix->src_mask, mix->dst_chan, mix->dst_mask,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/channelmix-ops.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/channelmix-ops.h
Changed
@@ -24,6 +24,7 @@ #define BUFFER_SIZE 4096 #define MAX_TAPS 255u +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define CHANNELMIX_OPS_MAX_ALIGN 16 @@ -50,8 +51,8 @@ #define CHANNELMIX_FLAG_EQUAL (1<<2) /**< all values are equal */ #define CHANNELMIX_FLAG_COPY (1<<3) /**< 1 on diagonal, can be nxm */ uint32_t flags; - float matrix_origSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS; - float matrixSPA_AUDIO_MAX_CHANNELSSPA_AUDIO_MAX_CHANNELS; + float matrix_origMAX_CHANNELSMAX_CHANNELS; + float matrixMAX_CHANNELSMAX_CHANNELS; float freq; /* sample frequency */ float lfe_cutoff; /* in Hz, 0 is disabled */ @@ -59,7 +60,7 @@ float rear_delay; /* in ms, 0 is disabled */ float widen; /* stereo widen. 0 is disabled */ uint32_t hilbert_taps; /* to phase shift, 0 disabled */ - struct lr4 lr4SPA_AUDIO_MAX_CHANNELS; + struct lr4 lr4MAX_CHANNELS; float buffer_mem2 * BUFFER_SIZE*2 + CHANNELMIX_OPS_MAX_ALIGN/4; float *buffer2;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/fmt-ops.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/fmt-ops.c
Changed
@@ -551,7 +551,7 @@ const struct dither_info *dinfo; const struct noise_info *ninfo; const struct clear_info *cinfo; - uint32_t i, conv_flags, data_size3; + uint32_t i, conv_flags, data_size4; /* we generate int32 bits of random values. With this scale * factor, we bring this in the -1.0, 1.0 range */ @@ -615,15 +615,17 @@ data_size0 = SPA_ROUND_UP(conv->noise_size * sizeof(float), FMT_OPS_MAX_ALIGN); data_size1 = SPA_ROUND_UP(RANDOM_SIZE * sizeof(uint32_t), FMT_OPS_MAX_ALIGN); data_size2 = SPA_ROUND_UP(RANDOM_SIZE * sizeof(int32_t), FMT_OPS_MAX_ALIGN); + data_size3 = SPA_ROUND_UP(conv->n_channels * sizeof(struct shaper), FMT_OPS_MAX_ALIGN); conv->data = calloc(FMT_OPS_MAX_ALIGN + - data_size0 + data_size1 + data_size2, 1); + data_size0 + data_size1 + data_size2 + data_size3, 1); if (conv->data == NULL) return -errno; conv->noise = SPA_PTR_ALIGN(conv->data, FMT_OPS_MAX_ALIGN, float); conv->random = SPA_PTROFF(conv->noise, data_size0, uint32_t); conv->prev = SPA_PTROFF(conv->random, data_size1, int32_t); + conv->shaper = SPA_PTROFF(conv->prev, data_size2, struct shaper); for (i = 0; i < RANDOM_SIZE; i++) conv->randomi = random();
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/fmt-ops.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/fmt-ops.h
Changed
@@ -236,7 +236,7 @@ uint32_t noise_size; const float *ns; uint32_t n_ns; - struct shaper shaper64; + struct shaper *shaper; void (*update_noise) (struct convert *conv, float *noise, uint32_t n_samples); void (*process) (struct convert *conv, void * SPA_RESTRICT dst, const void * SPA_RESTRICT src,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/meson.build -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/meson.build
Changed
@@ -125,7 +125,7 @@ sparesampledumpcoeffs = executable( 'spa-resample-dump-coeffs', sparesampledumpcoeffs_sources, - c_args : cc_flags_native, '-DRESAMPLE_DISABLE_PRECOMP' , + c_args : '-DRESAMPLE_DISABLE_PRECOMP' , dependencies : spa_dep, mathlib_native , install : false, native : true,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/audioconvert/test-audioconvert.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/audioconvert/test-audioconvert.c
Changed
@@ -25,7 +25,8 @@ extern const struct spa_handle_factory test_source_factory; -#define MAX_PORTS (SPA_AUDIO_MAX_CHANNELS+1) +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS +#define MAX_PORTS (MAX_CHANNELS+1) struct context { struct spa_handle *convert_handle;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/avb/avb-pcm.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/avb/avb-pcm.c
Changed
@@ -40,7 +40,13 @@ state->default_format = spa_type_audio_format_from_short_name(s); fmt_change++; } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { - spa_audio_parse_position(s, strlen(s), state->default_pos.pos, + spa_audio_parse_position_n(s, strlen(s), state->default_pos.pos, + SPA_N_ELEMENTS(state->default_pos.pos), + &state->default_pos.channels); + fmt_change++; + } else if (spa_streq(k, SPA_KEY_AUDIO_LAYOUT)) { + spa_audio_parse_layout(s, state->default_pos.pos, + SPA_N_ELEMENTS(state->default_pos.pos), &state->default_pos.channels); fmt_change++; } else if (spa_streq(k, SPA_KEY_AUDIO_ALLOWED_RATES)) { @@ -85,11 +91,12 @@ { uint32_t i, o = 0; int r; + char pos8; o += snprintf(val, len, " "); for (i = 0; i < map->channels; i++) { r = snprintf(val+o, len-o, "%s%s", i == 0 ? "" : ", ", - spa_debug_type_find_short_name(spa_type_audio_channel, - map->posi)); + spa_type_audio_channel_make_short_name(map->posi, + pos, sizeof(pos), "UNK")); if (r < 0 || o + r >= len) return -ENOSPC; o += r;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/avb/avb-pcm.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/avb/avb-pcm.h
Changed
@@ -109,6 +109,7 @@ return str; } +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define MAX_BUFFERS 32 struct buffer { @@ -127,7 +128,7 @@ struct channel_map { uint32_t channels; - uint32_t posSPA_AUDIO_MAX_CHANNELS; + uint32_t posMAX_CHANNELS; }; struct port {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-aac.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-aac.c
Changed
@@ -200,7 +200,7 @@ a2dp_aac_t conf; struct spa_pod_frame f2; struct spa_pod_choice *choice; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; uint32_t i = 0; if (caps_size < sizeof(conf))
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-aptx.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-aptx.c
Changed
@@ -205,7 +205,7 @@ a2dp_aptx_t conf; struct spa_pod_frame f2; struct spa_pod_choice *choice; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; uint32_t i = 0; if (caps_size < sizeof(conf))
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-faststream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-faststream.c
Changed
@@ -114,7 +114,7 @@ a2dp_faststream_t conf; struct spa_pod_frame f2; struct spa_pod_choice *choice; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; uint32_t i = 0; if (caps_size < sizeof(conf))
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-lc3plus.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-lc3plus.c
Changed
@@ -175,7 +175,7 @@ a2dp_lc3plus_hr_t conf; struct spa_pod_frame f2; struct spa_pod_choice *choice; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; uint32_t i = 0; if (caps_size < sizeof(conf))
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-ldac.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-ldac.c
Changed
@@ -158,7 +158,7 @@ struct spa_pod_frame f2; struct spa_pod_choice *choice; uint32_t i = 0; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; if (caps_size < sizeof(conf)) return -EINVAL;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus-g.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus-g.c
Changed
@@ -164,7 +164,7 @@ { a2dp_opus_g_t conf; struct spa_pod_frame f1; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; int channels; if (caps_size < sizeof(conf))
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-opus.c
Changed
@@ -58,6 +58,8 @@ #define BITRATE_DUPLEX_BIDI 160000 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + #define OPUS_05_MAX_BYTES (15 * 1024) struct props { @@ -251,14 +253,8 @@ static uint32_t bt_channel_from_name(const char *name) { size_t i; - enum spa_audio_channel position = SPA_AUDIO_CHANNEL_UNKNOWN; + enum spa_audio_channel position = spa_type_audio_channel_from_short_name(name); - for (i = 0; spa_type_audio_channeli.name; i++) { - if (spa_streq(name, spa_debug_type_short_name(spa_type_audio_channeli.name))) { - position = spa_type_audio_channeli.type; - break; - } - } for (i = 0; i < SPA_N_ELEMENTS(audio_locations); i++) { if (position == audio_locationsi.position) return audio_locationsi.mask; @@ -313,14 +309,14 @@ return; if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.channels"), &v, 0)) - props->channels = SPA_CLAMP(v, 1u, SPA_AUDIO_MAX_CHANNELS); + props->channels = SPA_CLAMP(v, 1u, MAX_CHANNELS); if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.max-bitrate"), &v, 0)) props->max_bitrate = SPA_MAX(v, (uint32_t)BITRATE_MIN); if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.coupled-streams"), &v, 0)) props->coupled_streams = SPA_CLAMP(v, 0u, props->channels / 2); if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.bidi.channels"), &v, 0)) - props->bidi_channels = SPA_CLAMP(v, 0u, SPA_AUDIO_MAX_CHANNELS); + props->bidi_channels = SPA_CLAMP(v, 0u, MAX_CHANNELS); if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.bidi.max-bitrate"), &v, 0)) props->bidi_max_bitrate = SPA_MAX(v, (uint32_t)BITRATE_MIN); if (spa_atou32(spa_dict_lookup(settings, "bluez5.a2dp.opus.pro.bidi.coupled-streams"), &v, 0)) @@ -503,7 +499,7 @@ const uint8_t *permutation = NULL; size_t i, j; - if (channels > SPA_AUDIO_MAX_CHANNELS) + if (channels > MAX_CHANNELS) return -EINVAL; if (2 * coupled_streams > channels) return -EINVAL; @@ -542,10 +538,9 @@ const struct audio_location loc = audio_locationsi; if (location & loc.mask) { - if (permutation) - positionspermutationj++ = loc.position; - else - positionsj++ = loc.position; + uint32_t idx = permutation ? permutationj : j; + positionsidx = loc.position; + j++; } } for (i = SPA_AUDIO_CHANNEL_START_Aux; j < channels; ++i, ++j) @@ -561,7 +556,7 @@ a2dp_opus_05_t a2dp_opus_05 = { .info = codec->vendor, .main = { - .channels = SPA_MIN(255u, SPA_AUDIO_MAX_CHANNELS), + .channels = SPA_MIN(255u, MAX_CHANNELS), .frame_duration = (OPUS_05_FRAME_DURATION_25 | OPUS_05_FRAME_DURATION_50 | OPUS_05_FRAME_DURATION_100 | @@ -571,7 +566,7 @@ OPUS_05_INIT_BITRATE(0) }, .bidi = { - .channels = SPA_MIN(255u, SPA_AUDIO_MAX_CHANNELS), + .channels = SPA_MIN(255u, MAX_CHANNELS), .frame_duration = (OPUS_05_FRAME_DURATION_25 | OPUS_05_FRAME_DURATION_50 | OPUS_05_FRAME_DURATION_100 | @@ -771,7 +766,7 @@ a2dp_opus_05_t conf; a2dp_opus_05_direction_t *dir; struct spa_pod_frame f1; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t positionMAX_CHANNELS; if (caps_size < sizeof(conf)) return -EINVAL; @@ -835,7 +830,8 @@ } info->info.raw.channels = dir1->channels; - if (get_mapping(codec, dir1, surround_encoder, NULL, NULL, NULL, info->info.raw.position) < 0) + if (get_mapping(codec, dir1, surround_encoder, NULL, NULL, NULL, + info->info.raw.position) < 0) return -EINVAL; if (get_mapping(codec, dir2, surround_encoder, NULL, NULL, NULL, NULL) < 0) return -EINVAL;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/a2dp-codec-sbc.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/a2dp-codec-sbc.c
Changed
@@ -346,7 +346,7 @@ struct spa_pod_frame f2; struct spa_pod_choice *choice; uint32_t i = 0; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t position2; if (caps_size < sizeof(conf)) return -EINVAL;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/bap-codec-lc3.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bap-codec-lc3.c
Changed
@@ -901,12 +901,12 @@ return conf_cmp(&conf1, res1, &conf2, res2); } -static uint8_t channels_to_positions(uint32_t channels, uint32_t *position) +static uint8_t channels_to_positions(uint32_t channels, uint32_t *position, uint32_t max_position) { uint32_t n_channels = get_channel_count(channels); uint8_t n_positions = 0; - spa_assert(n_channels <= SPA_AUDIO_MAX_CHANNELS); + spa_assert(n_channels <= max_position); if (channels == 0) { position0 = SPA_AUDIO_CHANNEL_MONO; @@ -932,7 +932,7 @@ bap_lc3_t conf; struct spa_pod_frame f2; struct spa_pod_choice *choice; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t positionLC3_MAX_CHANNELS; uint32_t i = 0; uint8_t res; @@ -990,7 +990,7 @@ if (i == 0) return -EINVAL; - res = channels_to_positions(conf.channels, position); + res = channels_to_positions(conf.channels, position, SPA_N_ELEMENTS(position)); if (res == 0) return -EINVAL; spa_pod_builder_add(b, @@ -1044,7 +1044,8 @@ return -EINVAL; } - res = channels_to_positions(conf.channels, info->info.raw.position); + res = channels_to_positions(conf.channels, info->info.raw.position, + SPA_N_ELEMENTS(info->info.raw.position)); if (res == 0) return -EINVAL; info->info.raw.channels = res;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/bluez5-dbus.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bluez5-dbus.c
Changed
@@ -35,6 +35,7 @@ #include <spa/utils/string.h> #include <spa/utils/json.h> #include <spa-private/dbus-helpers.h> +#include <spa/param/audio/raw-utils.h> #include <spa/param/audio/raw-json.h> #include "codec-loader.h" @@ -5037,6 +5038,10 @@ spa_log_error(monitor->log, "invalid transport configuration"); return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } + if (info.info.raw.channels > MAX_CHANNELS) { + spa_log_error(monitor->log, "too many channels in transport"); + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + } transport->n_channels = info.info.raw.channels; memcpy(transport->channels, info.info.raw.position, transport->n_channels * sizeof(uint32_t)); @@ -6850,7 +6855,7 @@ const char *key, uint32_t *value) { const char *str; - uint32_t positionSPA_AUDIO_MAX_CHANNELS; + uint32_t positionMAX_CHANNELS; uint32_t n_channels; uint32_t locations; unsigned int i, j; @@ -6861,7 +6866,8 @@ if (spa_atou32(str, value, 0)) return; - if (!spa_audio_parse_position(str, strlen(str), position, &n_channels)) { + if (!spa_audio_parse_position_n(str, strlen(str), position, + SPA_N_ELEMENTS(position), &n_channels)) { spa_log_error(this->log, "property %s '%s' is not valid position array", key, str); return; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/bluez5-device.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/bluez5-device.c
Changed
@@ -26,6 +26,7 @@ #include <spa/pod/parser.h> #include <spa/param/param.h> #include <spa/param/audio/raw.h> +#include <spa/param/audio/raw-utils.h> #include <spa/param/bluetooth/audio.h> #include <spa/param/bluetooth/type-info.h> #include <spa/debug/pod.h> @@ -38,7 +39,7 @@ #undef SPA_LOG_TOPIC_DEFAULT #define SPA_LOG_TOPIC_DEFAULT &log_topic -#define MAX_NODES (2*SPA_AUDIO_MAX_CHANNELS) +#define MAX_NODES (2*MAX_CHANNELS) #define DEVICE_ID_SOURCE 0 #define DEVICE_ID_SINK 1 @@ -99,9 +100,9 @@ unsigned int offload_acquired:1; uint32_t n_channels; int64_t latency_offset; - uint32_t channelsSPA_AUDIO_MAX_CHANNELS; - float volumesSPA_AUDIO_MAX_CHANNELS; - float soft_volumesSPA_AUDIO_MAX_CHANNELS; + uint32_t channelsMAX_CHANNELS; + float volumesMAX_CHANNELS; + float soft_volumesMAX_CHANNELS; }; struct dynamic_node @@ -129,8 +130,8 @@ bool leader; uint32_t sinks; uint32_t sources; - struct device_set_member sinkSPA_AUDIO_MAX_CHANNELS; - struct device_set_member sourceSPA_AUDIO_MAX_CHANNELS; + struct device_set_member sinkMAX_CHANNELS; + struct device_set_member sourceMAX_CHANNELS; }; struct impl { @@ -182,7 +183,7 @@ spa_zero(*node); node->id = id; - for (i = 0; i < SPA_AUDIO_MAX_CHANNELS; i++) { + for (i = 0; i < MAX_CHANNELS; i++) { node->volumesi = 1.0f; node->soft_volumesi = 1.0f; } @@ -476,6 +477,7 @@ *n_channels = info.info.raw.channels; memcpy(channels, info.info.raw.position, info.info.raw.channels * sizeof(uint32_t)); + } static const char *get_channel_name(uint32_t channel) @@ -546,7 +548,7 @@ if (node->channelsk == t->channelsj) break; } - if (k == node->n_channels && node->n_channels < SPA_AUDIO_MAX_CHANNELS) + if (k == node->n_channels && node->n_channels < MAX_CHANNELS) node->channelsnode->n_channels++ = t->channelsj; } } @@ -2413,7 +2415,7 @@ default: name_prefix = "bluetooth"; description = _("Bluetooth"); - hfp_description = _("Bluetooth (HFP)"); + hfp_description = _("Bluetooth Handsfree"); port_type = "bluetooth"; break; } @@ -2946,8 +2948,8 @@ struct spa_pod_prop *prop; struct spa_pod_object *obj = (struct spa_pod_object *) props; int changed = 0; - float volumesSPA_AUDIO_MAX_CHANNELS; - uint32_t channelsSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; + uint32_t channelsMAX_CHANNELS; uint32_t n_volumes = 0, SPA_UNUSED n_channels = 0; int64_t latency_offset = 0; @@ -2972,11 +2974,11 @@ break; case SPA_PROP_channelVolumes: n_volumes = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - volumes, SPA_AUDIO_MAX_CHANNELS); + volumes, SPA_N_ELEMENTS(volumes)); break; case SPA_PROP_channelMap: n_channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, - channels, SPA_AUDIO_MAX_CHANNELS); + channels, SPA_N_ELEMENTS(channels)); break; case SPA_PROP_latencyOffsetNsec: if (spa_pod_get_long(&prop->value, &latency_offset) == 0) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/defs.h -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/defs.h
Changed
@@ -157,6 +157,8 @@ #define SPA_BT_NO_BATTERY ((uint8_t)255) +#define MAX_CHANNELS (SPA_AUDIO_MAX_CHANNELS) + enum spa_bt_media_direction { SPA_BT_MEDIA_SOURCE, SPA_BT_MEDIA_SINK, @@ -678,7 +680,7 @@ struct spa_list bap_transport_linked; uint32_t n_channels; - uint32_t channelsSPA_AUDIO_MAX_CHANNELS; + uint32_t channelsMAX_CHANNELS; struct spa_bt_transport_volume volumesSPA_BT_VOLUME_ID_TERM;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/hfp-codec-cvsd.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/hfp-codec-cvsd.c
Changed
@@ -34,7 +34,7 @@ struct spa_pod_builder *b, struct spa_pod **param) { struct spa_pod_frame f1; - const uint32_t positionSPA_AUDIO_MAX_CHANNELS = { SPA_AUDIO_CHANNEL_MONO }; + const uint32_t position1 = { SPA_AUDIO_CHANNEL_MONO }; const int channels = 1; spa_assert(caps == NULL && caps_size == 0); @@ -47,7 +47,7 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_S16_LE), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_ENUM_Int(1, 8000), + SPA_FORMAT_AUDIO_rate, SPA_POD_Int(8000), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(channels), SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position),
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/hfp-codec-lc3-a127.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/hfp-codec-lc3-a127.c
Changed
@@ -39,7 +39,7 @@ struct spa_pod_builder *b, struct spa_pod **param) { struct spa_pod_frame f1; - const uint32_t positionSPA_AUDIO_MAX_CHANNELS = { SPA_AUDIO_CHANNEL_MONO }; + const uint32_t position1 = { SPA_AUDIO_CHANNEL_MONO }; const int channels = 1; spa_assert(caps == NULL && caps_size == 0); @@ -52,7 +52,7 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_F32), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_ENUM_Int(1, 24000), + SPA_FORMAT_AUDIO_rate, SPA_POD_Int(24000), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(channels), SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position),
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/hfp-codec-lc3-swb.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/hfp-codec-lc3-swb.c
Changed
@@ -42,7 +42,7 @@ struct spa_pod_builder *b, struct spa_pod **param) { struct spa_pod_frame f1; - const uint32_t positionSPA_AUDIO_MAX_CHANNELS = { SPA_AUDIO_CHANNEL_MONO }; + const uint32_t position1 = { SPA_AUDIO_CHANNEL_MONO }; const int channels = 1; spa_assert(caps == NULL && caps_size == 0); @@ -55,7 +55,7 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_F32), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_ENUM_Int(1, 32000), + SPA_FORMAT_AUDIO_rate, SPA_POD_Int(32000), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(channels), SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position),
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/hfp-codec-msbc.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/hfp-codec-msbc.c
Changed
@@ -49,7 +49,7 @@ struct spa_pod_builder *b, struct spa_pod **param) { struct spa_pod_frame f1; - const uint32_t positionSPA_AUDIO_MAX_CHANNELS = { SPA_AUDIO_CHANNEL_MONO }; + const uint32_t position1 = { SPA_AUDIO_CHANNEL_MONO }; const int channels = 1; spa_assert(caps == NULL && caps_size == 0); @@ -62,7 +62,7 @@ SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_audio), SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_raw), SPA_FORMAT_AUDIO_format, SPA_POD_Id(SPA_AUDIO_FORMAT_S16), - SPA_FORMAT_AUDIO_rate, SPA_POD_CHOICE_ENUM_Int(1, 16000), + SPA_FORMAT_AUDIO_rate, SPA_POD_Int(16000), SPA_FORMAT_AUDIO_channels, SPA_POD_Int(channels), SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, channels, position),
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/media-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/media-sink.c
Changed
@@ -2139,7 +2139,7 @@ if (info.info.raw.rate == 0 || info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels > MAX_CHANNELS) return -EINVAL; if (this->transport && this->transport->iso_io) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/bluez5/media-source.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/bluez5/media-source.c
Changed
@@ -1439,7 +1439,7 @@ if (info.info.raw.rate == 0 || info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels > MAX_CHANNELS) return -EINVAL; port->frame_size = info.info.raw.channels;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/filter-graph/filter-graph.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/filter-graph/filter-graph.c
Changed
@@ -39,6 +39,7 @@ SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.filter-graph"); #define MAX_HNDL 64 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define DEFAULT_RATE 48000 @@ -154,15 +155,15 @@ struct volume { bool mute; uint32_t n_volumes; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; uint32_t n_ports; - struct port *portsSPA_AUDIO_MAX_CHANNELS; - float minSPA_AUDIO_MAX_CHANNELS; - float maxSPA_AUDIO_MAX_CHANNELS; + struct port *portsMAX_CHANNELS; + float minMAX_CHANNELS; + float maxMAX_CHANNELS; #define SCALE_LINEAR 0 #define SCALE_CUBIC 1 - int scaleSPA_AUDIO_MAX_CHANNELS; + int scaleMAX_CHANNELS; }; struct graph { @@ -194,9 +195,9 @@ uint32_t n_inputs; uint32_t n_outputs; - uint32_t inputs_positionSPA_AUDIO_MAX_CHANNELS; + uint32_t inputs_positionMAX_CHANNELS; uint32_t n_inputs_position; - uint32_t outputs_positionSPA_AUDIO_MAX_CHANNELS; + uint32_t outputs_positionMAX_CHANNELS; uint32_t n_outputs_position; float min_latency; @@ -231,16 +232,18 @@ float *discard_data; }; -static inline void print_channels(char *buffer, size_t max_size, uint32_t n_channels, uint32_t *positions) +static inline void print_channels(char *buffer, size_t max_size, uint32_t n_positions, uint32_t *positions) { uint32_t i; struct spa_strbuf buf; + char pos8; spa_strbuf_init(&buf, buffer, max_size); spa_strbuf_append(&buf, ""); - for (i = 0; i < n_channels; i++) { + for (i = 0; i < n_positions; i++) { spa_strbuf_append(&buf, "%s%s", i ? "," : "", - spa_type_audio_channel_to_short_name(positionsi)); + spa_type_audio_channel_make_short_name(positionsi, + pos, sizeof(pos), "UNK")); } spa_strbuf_append(&buf, ""); } @@ -256,8 +259,8 @@ char n_inputs64, n_outputs64, latency64; struct spa_dict_item items6; struct spa_dict dict = SPA_DICT(items, 0); - char in_posSPA_AUDIO_MAX_CHANNELS * 8; - char out_posSPA_AUDIO_MAX_CHANNELS * 8; + char in_posMAX_CHANNELS * 8; + char out_posMAX_CHANNELS * 8; snprintf(n_inputs, sizeof(n_inputs), "%d", impl->graph.n_inputs); snprintf(n_outputs, sizeof(n_outputs), "%d", impl->graph.n_outputs); @@ -745,10 +748,10 @@ case SPA_PROP_channelVolumes: { uint32_t i, n_vols; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, vols, - SPA_AUDIO_MAX_CHANNELS)) > 0) { + SPA_N_ELEMENTS(vols))) > 0) { if (vol->n_volumes != n_vols) do_volume = true; vol->n_volumes = n_vols; @@ -772,7 +775,7 @@ } } if (do_volume && vol->n_ports != 0) { - float soft_volsSPA_AUDIO_MAX_CHANNELS; + float soft_volsMAX_CHANNELS; uint32_t i; for (i = 0; i < vol->n_volumes; i++) @@ -1264,7 +1267,7 @@ spa_log_error(impl->log, "unknown control port %s", control); return -ENOENT; } - if (vol->n_ports >= SPA_AUDIO_MAX_CHANNELS) { + if (vol->n_ports >= MAX_CHANNELS) { spa_log_error(impl->log, "too many volume controls"); return -ENOSPC; } @@ -2118,8 +2121,9 @@ spa_log_error(impl->log, "%s expects an array", key); return -EINVAL; } - spa_audio_parse_position(val, len, graph->inputs_position, - &graph->n_inputs_position); + spa_audio_parse_position_n(val, len, graph->inputs_position, + SPA_N_ELEMENTS(graph->inputs_position), + &graph->n_inputs_position); impl->info.n_inputs = graph->n_inputs_position; } else if (spa_streq("outputs.audio.position", key)) { @@ -2128,8 +2132,9 @@ spa_log_error(impl->log, "%s expects an array", key); return -EINVAL; } - spa_audio_parse_position(val, len, graph->outputs_position, - &graph->n_outputs_position); + spa_audio_parse_position_n(val, len, graph->outputs_position, + SPA_N_ELEMENTS(graph->outputs_position), + &graph->n_outputs_position); impl->info.n_outputs = graph->n_outputs_position; } else if (spa_streq("nodes", key)) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/support/node-driver.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/support/node-driver.c
Changed
@@ -26,6 +26,8 @@ #include <spa/node/io.h> #include <spa/node/utils.h> #include <spa/param/param.h> +#include <spa/pod/filter.h> +#include <spa/pod/parser.h> SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.driver"); @@ -48,12 +50,16 @@ #define BW_PERIOD (3 * SPA_NSEC_PER_SEC) #define MAX_ERROR_MS 1 +#define CLOCK_NAME_MAX 64 + struct props { bool freewheel; - char clock_name64; + char clock_nameCLOCK_NAME_MAX; clockid_t clock_id; uint32_t freewheel_wait; float resync_ms; + char clock_deviceCLOCK_NAME_MAX; + char clock_interfaceCLOCK_NAME_MAX; }; struct clock_offset { @@ -73,7 +79,10 @@ uint64_t info_all; struct spa_node_info info; - struct spa_param_info params1; +#define NODE_PropInfo 0 +#define NODE_Props 1 +#define N_NODE_PARAMS 2 + struct spa_param_info paramsN_NODE_PARAMS; struct spa_hook_list hooks; struct spa_callbacks callbacks; @@ -99,13 +108,20 @@ struct clock_offset nsec_offset; }; +static void reset_props_strings(struct props *props) +{ + spa_zero(props->clock_name); + spa_zero(props->clock_device); + spa_zero(props->clock_interface); +} + static void reset_props(struct props *props) { props->freewheel = DEFAULT_FREEWHEEL; - spa_zero(props->clock_name); props->clock_id = CLOCK_MONOTONIC; props->freewheel_wait = DEFAULT_FREEWHEEL_WAIT; props->resync_ms = DEFAULT_RESYNC_MS; + reset_props_strings(props); } static const struct clock_info { @@ -598,10 +614,280 @@ return SPA_STATUS_HAVE_DATA | SPA_STATUS_NEED_DATA; } +static int impl_node_enum_params(void *object, int seq, + uint32_t id, uint32_t start, uint32_t num, + const struct spa_pod *filter) +{ + struct impl *this = object; + struct spa_pod *param; + struct spa_pod_builder b = { 0 }; + uint8_t buffer4096; + struct spa_result_node_params result; + uint32_t count = 0; + + spa_return_val_if_fail(this != NULL, -EINVAL); + spa_return_val_if_fail(num != 0, -EINVAL); + + result.id = id; + result.next = start; +next: + result.index = result.next++; + + spa_pod_builder_init(&b, buffer, sizeof(buffer)); + + switch (id) { + case SPA_PARAM_PropInfo: + { + struct props *p = &this->props; + + switch (result.index) { + case 0: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_clockId), + SPA_PROP_INFO_description, SPA_POD_String("The clock id (monotonic, realtime, etc.)"), + SPA_PROP_INFO_type, SPA_POD_String(clock_id_to_name(p->clock_id))); + break; + case 1: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_clockDevice), + SPA_PROP_INFO_description, SPA_POD_String("The clock device (eg. /dev/ptp0)"), + SPA_PROP_INFO_type, SPA_POD_Stringn(p->clock_device, sizeof(p->clock_device))); + break; + case 2: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_PropInfo, id, + SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_clockInterface), + SPA_PROP_INFO_description, SPA_POD_String("The clock network interface (eg. eth0)"), + SPA_PROP_INFO_type, SPA_POD_Stringn(p->clock_interface, sizeof(p->clock_interface))); + break; + default: + return 0; + } + + break; + } + + case SPA_PARAM_Props: + { + struct props *p = &this->props; + + switch (result.index) { + case 0: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, id, + SPA_PROP_clockId, SPA_POD_String(clock_id_to_name(p->clock_id)) + ); + break; + case 1: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, id, + SPA_PROP_clockDevice, SPA_POD_Stringn(p->clock_device, sizeof(p->clock_device)) + ); + break; + case 2: + param = spa_pod_builder_add_object(&b, + SPA_TYPE_OBJECT_Props, id, + SPA_PROP_clockInterface, SPA_POD_Stringn(p->clock_interface, sizeof(p->clock_interface)) + ); + break; + default: + return 0; + } + + break; + } + + default: + return -ENOENT; + } + + if (spa_pod_filter(&b, &result.param, param, filter) < 0) + goto next; + + spa_node_emit_result(&this->hooks, seq, 0, SPA_RESULT_TYPE_NODE_PARAMS, &result); + + if (++count != num) + goto next; + + return 0; +} + +static int get_phc_index(struct spa_system *s, const char *name) { +#ifdef ETHTOOL_GET_TS_INFO + struct ethtool_ts_info info = {0}; + struct ifreq ifr = {0}; + int fd, err; + + info.cmd = ETHTOOL_GET_TS_INFO; + strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); + ifr.ifr_data = (char *) &info; + + fd = socket(AF_INET, SOCK_DGRAM, 0); + if (fd < 0) + return -errno; + + err = spa_system_ioctl(s, fd, SIOCETHTOOL, &ifr); + close(fd); + if (err < 0) + return -errno; + + return info.phc_index; +#else + return -ENOTSUP; +#endif +} + +static bool parse_clock_id(struct impl *this, const char *s) +{ + int id = clock_name_to_id(s); + if (id == -1) { + spa_log_info(this->log, "unknown clock id '%s'", s); + return false; + } + this->props.clock_id = id; + if (this->clock_fd >= 0) { + close(this->clock_fd); + this->clock_fd = -1; + } + return true; +} + +static bool parse_clock_device(struct impl *this, const char *s) +{ + int fd = open(s, O_RDONLY); + if (fd == -1) { + spa_log_info(this->log, "failed to open clock device '%s': %m", s); + return false; + } + if (this->clock_fd >= 0) { + close(this->clock_fd); + } + this->clock_fd = fd; + this->props.clock_id = FD_TO_CLOCKID(this->clock_fd); + return true; +} + +static bool parse_clock_interface(struct impl *this, const char *s) +{ + int phc_index = get_phc_index(this->data_system, s); + if (phc_index < 0) { + spa_log_info(this->log, "failed to get phc device index for interface '%s': %s", + s, spa_strerror(phc_index)); + return false; + } else { + char dev19; + spa_scnprintf(dev, sizeof(dev), "/dev/ptp%d", phc_index); + if (!parse_clock_device(this, dev)) { + spa_log_info(this->log, "failed to open clock device '%s' " + "for interface '%s': %m", dev, s); + return false; + } + } + return true; +} + +static void ensure_clock_name(struct impl *this) +{ + struct props *p = &this->props; + if (p->clock_name0 == '\0') { + const char *name = clock_id_to_name(p->clock_id); + if (p->clock_device0) + name = p->clock_device; + if (p->clock_interface0) + name = p->clock_interface; + spa_scnprintf(p->clock_name, sizeof(p->clock_name), + "%s.%s", DEFAULT_CLOCK_PREFIX, name); + } +} + +static int impl_node_set_param(void *object, uint32_t id, uint32_t flags, + const struct spa_pod *param) +{ + struct impl *this = object; + + spa_return_val_if_fail(this != NULL, -EINVAL); + + switch (id) { + case SPA_PARAM_Props: + { + struct props *p = &this->props; + bool notify = false; + char bufferCLOCK_NAME_MAX; + int count; + + if (param == NULL) { + return 0; + } + + /* Note that the length passed to SPA_POD_OPT_Stringn() also + * includes room for the null terminator, so the content of the + * buffer variable is always guaranteed to be null terminated. */ + + spa_zero(buffer); + count = spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_clockId, SPA_POD_OPT_Stringn(buffer, sizeof(buffer)) + ); + if (count && parse_clock_id(this, buffer)) + { + reset_props_strings(p); + notify = true; + } + + spa_zero(buffer); + count = spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_clockDevice, SPA_POD_OPT_Stringn(buffer, sizeof(buffer)) + ); + if (count && parse_clock_device(this, buffer)) + { + reset_props_strings(p); + strncpy(p->clock_device, buffer, sizeof(p->clock_device)); + notify = true; + } + + spa_zero(buffer); + count = spa_pod_parse_object(param, + SPA_TYPE_OBJECT_Props, NULL, + SPA_PROP_clockInterface, SPA_POD_OPT_Stringn(buffer, sizeof(buffer)) + ); + if (count && parse_clock_interface(this, buffer)) + { + reset_props_strings(p); + strncpy(p->clock_interface, buffer, sizeof(p->clock_interface)); + notify = true; + } + + if (notify) + { + ensure_clock_name(this); + spa_log_info(this->log, "%p: setting clock to '%s'", this, p->clock_name); + if (this->started) { + do_stop(this); + do_start(this); + } + emit_node_info(this, true); + } + + break; + } + + default: + return -ENOENT; + break; + } + + return 0; +} + static const struct spa_node_methods impl_node = { SPA_VERSION_NODE_METHODS, .add_listener = impl_node_add_listener, .set_callbacks = impl_node_set_callbacks, + .enum_params = impl_node_enum_params, + .set_param = impl_node_set_param, .set_io = impl_node_set_io, .send_command = impl_node_send_command, .process = impl_node_process, @@ -655,31 +941,6 @@ return sizeof(struct impl); } -static int get_phc_index(struct spa_system *s, const char *name) { -#ifdef ETHTOOL_GET_TS_INFO - struct ethtool_ts_info info = {0}; - struct ifreq ifr = {0}; - int fd, err; - - info.cmd = ETHTOOL_GET_TS_INFO; - strncpy(ifr.ifr_name, name, IFNAMSIZ - 1); - ifr.ifr_data = (char *) &info; - - fd = socket(AF_INET, SOCK_DGRAM, 0); - if (fd < 0) - return -errno; - - err = spa_system_ioctl(s, fd, SIOCETHTOOL, &ifr); - close(fd); - if (err < 0) - return -errno; - - return info.phc_index; -#else - return -ENOTSUP; -#endif -} - static int impl_init(const struct spa_handle_factory *factory, struct spa_handle *handle, @@ -727,9 +988,10 @@ this->info.max_input_ports = 0; this->info.max_output_ports = 0; this->info.flags = SPA_NODE_FLAG_RT; - this->params0 = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE); + this->paramsNODE_PropInfo = SPA_PARAM_INFO(SPA_PARAM_PropInfo, SPA_PARAM_INFO_READ); + this->paramsNODE_Props = SPA_PARAM_INFO(SPA_PARAM_Props, SPA_PARAM_INFO_READWRITE); this->info.params = this->params; - this->info.n_params = 0; + this->info.n_params = N_NODE_PARAMS; reset_props(&this->props); @@ -742,37 +1004,17 @@ spa_scnprintf(this->props.clock_name, sizeof(this->props.clock_name), "%s", s); } else if (spa_streq(k, "clock.id") && this->clock_fd < 0) { - this->props.clock_id = clock_name_to_id(s); - if (this->props.clock_id == -1) { - spa_log_warn(this->log, "unknown clock id '%s'", s); - this->props.clock_id = DEFAULT_CLOCK_ID; - } + if (parse_clock_id(this, s)) + reset_props_strings(&this->props); } else if (spa_streq(k, "clock.device")) { - if (this->clock_fd >= 0) { - close(this->clock_fd); - } - this->clock_fd = open(s, O_RDONLY); - - if (this->clock_fd == -1) { - spa_log_warn(this->log, "failed to open clock device '%s': %m", s); - } else { - this->props.clock_id = FD_TO_CLOCKID(this->clock_fd); + if (parse_clock_device(this, s)) { + reset_props_strings(&this->props); + strncpy(this->props.clock_device, s, sizeof(this->props.clock_device)-1); } } else if (spa_streq(k, "clock.interface") && this->clock_fd < 0) { - int phc_index = get_phc_index(this->data_system, s); - if (phc_index < 0) { - spa_log_warn(this->log, "failed to get phc device index for interface '%s': %s", - s, spa_strerror(phc_index)); - } else { - char dev19; - spa_scnprintf(dev, sizeof(dev), "/dev/ptp%d", phc_index); - this->clock_fd = open(dev, O_RDONLY); - if (this->clock_fd == -1) { - spa_log_warn(this->log, "failed to open clock device '%s' " - "for interface '%s': %m", dev, s); - } else { - this->props.clock_id = FD_TO_CLOCKID(this->clock_fd); - } + if (parse_clock_interface(this, s)) { + reset_props_strings(&this->props); + strncpy(this->props.clock_interface, s, sizeof(this->props.clock_interface)-1); } } else if (spa_streq(k, "freewheel.wait")) { this->props.freewheel_wait = atoi(s); @@ -785,6 +1027,7 @@ "%s.%s", DEFAULT_CLOCK_PREFIX, clock_id_to_name(this->props.clock_id)); } + ensure_clock_name(this); this->tracking = !clock_for_timerfd(this->props.clock_id); this->timer_clockid = this->tracking ? CLOCK_MONOTONIC : this->props.clock_id;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/support/null-audio-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/support/null-audio-sink.c
Changed
@@ -35,12 +35,13 @@ SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.null-audio-sink"); #define DEFAULT_CLOCK_NAME "clock.system.monotonic" +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS struct props { uint32_t format; uint32_t channels; uint32_t rate; - uint32_t posSPA_AUDIO_MAX_CHANNELS; + uint32_t posMAX_CHANNELS; char clock_name64; unsigned int debug:1; unsigned int driver:1; @@ -636,7 +637,7 @@ if (info.info.raw.rate == 0 || info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels > MAX_CHANNELS) return -EINVAL; if (this->props.format != 0) { @@ -949,7 +950,11 @@ } else if (spa_streq(k, SPA_KEY_NODE_DRIVER)) { this->props.driver = spa_atob(s); } else if (spa_streq(k, SPA_KEY_AUDIO_POSITION)) { - spa_audio_parse_position(s, strlen(s), this->props.pos, &this->props.channels); + spa_audio_parse_position_n(s, strlen(s), this->props.pos, + SPA_N_ELEMENTS(this->props.pos), &this->props.channels); + } else if (spa_streq(k, SPA_KEY_AUDIO_LAYOUT)) { + spa_audio_parse_layout(s, this->props.pos, + SPA_N_ELEMENTS(this->props.pos), &this->props.channels); } else if (spa_streq(k, "clock.name")) { spa_scnprintf(this->props.clock_name, sizeof(this->props.clock_name),
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/v4l2/v4l2-utils.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/v4l2/v4l2-utils.c
Changed
@@ -1486,7 +1486,7 @@ spa_pod_builder_push_object(&b.b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); spa_pod_builder_add(&b.b, SPA_PROP_INFO_id, SPA_POD_Id(prop_id), - SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, (int32_t)queryctrl.default_value), + SPA_PROP_INFO_type, SPA_POD_Int((int32_t)queryctrl.default_value), SPA_PROP_INFO_description, SPA_POD_String(queryctrl.name), 0);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/videoconvert/videoadapter.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/videoconvert/videoadapter.c
Changed
@@ -900,6 +900,7 @@ switch (id) { case SPA_IO_Position: this->io_position = data; + this->recheck_format = true; break; default: break;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/spa/plugins/volume/volume.c -> _service:download_files:pipewire-1.5.83.tar.bz2/spa/plugins/volume/volume.c
Changed
@@ -454,8 +454,7 @@ return -EINVAL; if (info.info.raw.format != SPA_AUDIO_FORMAT_S16 || - info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels == 0) return -EINVAL; this->bpf = 2 * info.info.raw.channels;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/daemon/pipewire-pulse.conf.in -> _service:download_files:pipewire-1.5.83.tar.bz2/src/daemon/pipewire-pulse.conf.in
Changed
@@ -109,12 +109,12 @@ #server.dbus-name = "org.pulseaudio.Server" #pulse.allow-module-loading = true - #pulse.min.req = 128/48000 # 2.7ms + #pulse.min.req = 256/48000 # 5.3ms #pulse.default.req = 960/48000 # 20 milliseconds - #pulse.min.frag = 128/48000 # 2.7ms + #pulse.min.frag = 256/48000 # 5.3ms #pulse.default.frag = 96000/48000 # 2 seconds #pulse.default.tlength = 96000/48000 # 2 seconds - #pulse.min.quantum = 128/48000 # 2.7ms + #pulse.min.quantum = 256/48000 # 5.3ms #pulse.idle.timeout = 0 # don't pause after underruns #pulse.default.format = F32 #pulse.default.position = FL FR
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/examples/export-source.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/examples/export-source.c
Changed
@@ -268,8 +268,7 @@ d->format.format != SPA_AUDIO_FORMAT_F32) return -EINVAL; if (d->format.rate == 0 || - d->format.channels == 0 || - d->format.channels > SPA_AUDIO_MAX_CHANNELS) + d->format.channels == 0) return -EINVAL; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/gst/gstpipewireclock.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/gst/gstpipewireclock.c
Changed
@@ -45,7 +45,7 @@ t.rate.denom == 0) return pclock->last_time; - result = gst_util_uint64_scale_int (t.ticks, GST_SECOND * t.rate.num, t.rate.denom); + result = gst_util_uint64_scale (t.ticks, GST_SECOND * t.rate.num, t.rate.denom); result += now - t.now; result += pclock->time_offset;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/gst/gstpipewireformat.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/gst/gstpipewireformat.c
Changed
@@ -649,7 +649,7 @@ static void set_default_channels (struct spa_pod_builder *b, uint32_t channels) { - uint32_t positionSPA_AUDIO_MAX_CHANNELS = {0}; + uint32_t position8 = {0}; gboolean ok = TRUE; switch (channels) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/gst/gstpipewiresrc.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/gst/gstpipewiresrc.c
Changed
@@ -769,7 +769,7 @@ GST_BUFFER_DTS (buf) = b->time - pwsrc->delay; } - if (pwsrc->is_video) { + if (pwsrc->media_type == SPA_MEDIA_TYPE_video) { if (pwsrc->video_info.fps_n) { GST_BUFFER_DURATION (buf) = gst_util_uint64_scale (GST_SECOND, pwsrc->video_info.fps_d, pwsrc->video_info.fps_n); @@ -912,7 +912,7 @@ * must handle the clock lost message in it's bus handler by pausing * the pipeline and then setting it back to playing. */ - if (current_state == GST_STATE_PLAYING && !pwsrc->is_video) + if (current_state == GST_STATE_PLAYING && pwsrc->media_type == SPA_MEDIA_TYPE_audio) gst_element_post_message (GST_ELEMENT_CAST (pwsrc), gst_message_new_clock_lost (GST_OBJECT_CAST (pwsrc), GST_CLOCK_CAST (pwsrc->stream->clock))); @@ -1265,7 +1265,7 @@ if (param == NULL) { GST_DEBUG_OBJECT (pwsrc, "clear format"); pwsrc->negotiated = FALSE; - pwsrc->is_video = FALSE; + pwsrc->media_type = SPA_MEDIA_TYPE_unknown; return; } @@ -1303,7 +1303,7 @@ structure = gst_caps_get_structure (pwsrc->caps, 0); if (g_str_has_prefix (gst_structure_get_name (structure), "video/") || g_str_has_prefix (gst_structure_get_name (structure), "image/")) { - pwsrc->is_video = TRUE; + pwsrc->media_type = SPA_MEDIA_TYPE_video; #ifdef HAVE_GSTREAMER_DMA_DRM if (gst_video_is_dma_drm_caps (pwsrc->caps)) { @@ -1342,10 +1342,12 @@ * application/user */ if (pwsrc->use_bufferpool != USE_BUFFERPOOL_YES) pwsrc->use_bufferpool = USE_BUFFERPOOL_NO; + + pwsrc->media_type = SPA_MEDIA_TYPE_audio; } } else { pwsrc->negotiated = FALSE; - pwsrc->is_video = FALSE; + pwsrc->media_type = SPA_MEDIA_TYPE_unknown; pwsrc->is_rawvideo = FALSE; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/gst/gstpipewiresrc.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/gst/gstpipewiresrc.h
Changed
@@ -15,6 +15,7 @@ #include <gst/video/video.h> #include <pipewire/pipewire.h> +#include <spa/param/format.h> #include <gst/gstpipewirepool.h> #include <gst/gstpipewirecore.h> @@ -63,7 +64,7 @@ GstCaps *caps; GstCaps *possible_caps; - gboolean is_video; + enum spa_media_type media_type; gboolean is_rawvideo; GstVideoInfo video_info; #ifdef HAVE_GSTREAMER_DMA_DRM
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-avb/stream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-avb/stream.c
Changed
@@ -484,7 +484,7 @@ pw_log_warn("short packet received (%d < %d)", len, (int)sizeof(struct avb_packet_header)); } else { - struct avb_frame_header *h = (void*)buffer; + struct avb_ethernet_header *h = (void*)buffer; struct avb_packet_iec61883 *p = SPA_PTROFF(h, sizeof(*h), void); if (memcmp(h->dest, stream->addr, 6) != 0 ||
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-combine-stream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-combine-stream.c
Changed
@@ -64,6 +64,7 @@ * * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -76,9 +77,10 @@ * ## Stream options * * - `audio.position`: Set the stream channel map. By default this is the same channel - * map as the combine stream. + * map as the combine stream. You can also use audio.layout * - `combine.audio.position`: map the combine audio positions to the stream positions. * combine input channels are mapped one-by-one to stream output channels. + * You can also use combine.audio.layout. * * ## Example configuration * @@ -231,9 +233,9 @@ "( stream.props=<properties> ) " \ "( stream.rules=<properties> ) " +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define DELAYBUF_MAX_SIZE (20 * sizeof(float) * 96000) - static const struct spa_dict_item module_props = { { PW_KEY_MODULE_AUTHOR, "Wim Taymans <wim.taymans@gmail.com>" }, { PW_KEY_MODULE_DESCRIPTION, "Combine multiple streams into a single stream" }, @@ -312,10 +314,10 @@ struct spa_latency_info latency; struct spa_audio_info_raw info; - uint32_t remapSPA_AUDIO_MAX_CHANNELS; + uint32_t remapMAX_CHANNELS; void *delaybuf; - struct ringbuffer delaySPA_AUDIO_MAX_CHANNELS; + struct ringbuffer delayMAX_CHANNELS; int64_t delay_samples; /* for main loop */ int64_t data_delay_samples; /* for data loop */ @@ -326,14 +328,15 @@ unsigned int have_latency:1; }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P"), SPA_DICT_ITEM(SPA_KEY_AUDIO_POSITION, DEFAULT_POSITION)), &props->dict, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -509,7 +512,7 @@ struct replace_delay_info { struct stream *stream; void *buf; - struct ringbuffer delaySPA_AUDIO_MAX_CHANNELS; + struct ringbuffer delayMAX_CHANNELS; }; static int do_replace_delay(struct spa_loop *loop, bool async, uint32_t seq, @@ -866,13 +869,21 @@ s->info = impl->info; if ((str = pw_properties_get(info->stream_props, SPA_KEY_AUDIO_POSITION)) != NULL) - spa_audio_parse_position(str, strlen(str), s->info.position, &s->info.channels); + spa_audio_parse_position_n(str, strlen(str), s->info.position, + SPA_N_ELEMENTS(s->info.position), &s->info.channels); + if ((str = pw_properties_get(info->stream_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) + spa_audio_parse_layout(str, s->info.position, + SPA_N_ELEMENTS(s->info.position), &s->info.channels); if (s->info.channels == 0) s->info = impl->info; spa_zero(remap_info); if ((str = pw_properties_get(info->stream_props, "combine.audio.position")) != NULL) - spa_audio_parse_position(str, strlen(str), remap_info.position, &remap_info.channels); + spa_audio_parse_position_n(str, strlen(str), remap_info.position, + SPA_N_ELEMENTS(remap_info.position), &remap_info.channels); + if ((str = pw_properties_get(info->stream_props, "combine.audio.layout")) != NULL) + spa_audio_parse_layout(str, remap_info.position, + SPA_N_ELEMENTS(remap_info.position), &remap_info.channels); if (remap_info.channels == 0) remap_info = s->info; @@ -880,7 +891,10 @@ for (i = 0; i < remap_info.channels; i++) { s->remapi = i; for (j = 0; j < tmp_info.channels; j++) { - if (tmp_info.positionj == remap_info.positioni) { + uint32_t pj, pi; + pj = tmp_info.positionj; + pi = remap_info.positioni; + if (pj == pi) { s->remapi = j; break; } @@ -1228,7 +1242,7 @@ struct pw_buffer *in, *out; struct stream *s; bool delay_changed = false; - bool mixSPA_AUDIO_MAX_CHANNELS; + bool mixMAX_CHANNELS; if ((out = pw_stream_dequeue_buffer(impl->combine)) == NULL) { pw_log_debug("%p: out of output buffers: %m", impl); @@ -1622,6 +1636,7 @@ copy_props(props, impl->combine_props, PW_KEY_NODE_LOOP_NAME); copy_props(props, impl->combine_props, PW_KEY_AUDIO_CHANNELS); + copy_props(props, impl->combine_props, SPA_KEY_AUDIO_LAYOUT); copy_props(props, impl->combine_props, SPA_KEY_AUDIO_POSITION); copy_props(props, impl->combine_props, PW_KEY_NODE_NAME); copy_props(props, impl->combine_props, PW_KEY_NODE_DESCRIPTION); @@ -1633,7 +1648,10 @@ copy_props(props, impl->combine_props, "resample.prefill"); copy_props(props, impl->combine_props, "resample.disable"); - parse_audio_info(impl->combine_props, &impl->info); + if ((res = parse_audio_info(impl->combine_props, &impl->info)) < 0) { + pw_log_error( "can't create format: %s", spa_strerror(res)); + goto error; + } copy_props(props, impl->stream_props, PW_KEY_NODE_LOOP_NAME); copy_props(props, impl->stream_props, PW_KEY_NODE_GROUP);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-echo-cancel.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-echo-cancel.c
Changed
@@ -105,6 +105,7 @@ * * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_CLASS * - \ref PW_KEY_NODE_LATENCY @@ -154,6 +155,7 @@ #define DEFAULT_RATE 48000 #define DEFAULT_POSITION " FL FR " +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS /* Hopefully this is enough for any combination of AEC engine and resampler * input requirement for rate matching */ @@ -203,7 +205,7 @@ struct spa_hook source_listener; struct spa_audio_info_raw source_info; - void *rec_bufferSPA_AUDIO_MAX_CHANNELS; + void *rec_bufferMAX_CHANNELS; uint32_t rec_ringsize; struct spa_ringbuffer rec_ring; @@ -215,21 +217,23 @@ struct pw_properties *sink_props; struct pw_stream *sink; struct spa_hook sink_listener; - void *play_bufferSPA_AUDIO_MAX_CHANNELS; + void *play_bufferMAX_CHANNELS; uint32_t play_ringsize; struct spa_ringbuffer play_ring; struct spa_ringbuffer play_delayed_ring; struct spa_audio_info_raw sink_info; - void *out_bufferSPA_AUDIO_MAX_CHANNELS; + void *out_bufferMAX_CHANNELS; uint32_t out_ringsize; struct spa_ringbuffer out_ring; struct spa_audio_aec *aec; uint32_t aec_blocksize; - unsigned int capture_ready:1; - unsigned int sink_ready:1; + struct spa_io_position *capture_position; + struct spa_io_position *sink_position; + uint32_t capture_cycle; + uint32_t sink_cycle; unsigned int do_disconnect:1; @@ -306,13 +310,24 @@ const float *play_delayedimpl->play_info.channels; float *outimpl->out_info.channels; struct spa_data *dd; - uint32_t i, size; - uint32_t rindex, pindex, oindex, pdindex, avail; + uint32_t i; + uint32_t rindex, pindex, oindex, pdindex, size; + int32_t avail, pavail, pdavail; size = impl->aec_blocksize; - /* First read a block from the playback and capture ring buffers */ - spa_ringbuffer_get_read_index(&impl->rec_ring, &rindex); + /* First read a block from the capture ring buffer */ + avail = spa_ringbuffer_get_read_index(&impl->rec_ring, &rindex); + while (avail >= (int32_t)size * 2) { + /* drop samples that are not needed this or next cycle. Note + * that samples are kept in the ringbuffer until next cycle if + * size is not equal to or divisible by quantum, to avoid + * discontinuity */ + pw_log_debug("avail %d", avail); + spa_ringbuffer_read_update(&impl->rec_ring, rindex + size); + avail = spa_ringbuffer_get_read_index(&impl->rec_ring, &rindex); + pw_log_debug("new avail %d, size %u", avail, size); + } for (i = 0; i < impl->rec_info.channels; i++) { /* captured samples, with echo from sink */ @@ -330,19 +345,34 @@ outi = &out_bufi0; } - spa_ringbuffer_get_read_index(&impl->play_ring, &pindex); - spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &pdindex); + pavail = spa_ringbuffer_get_read_index(&impl->play_ring, &pindex); + pdavail = spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &pdindex); if (impl->playback != NULL && (pout = pw_stream_dequeue_buffer(impl->playback)) == NULL) { pw_log_debug("out of playback buffers: %m"); /* playback stream may not yet be in streaming state, drop play * data to avoid introducing additional playback latency */ - spa_ringbuffer_read_update(&impl->play_ring, pindex + size); - spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + size); + spa_ringbuffer_read_update(&impl->play_ring, pindex + pavail); + spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + pdavail); goto done; } + if (pavail > avail) { + /* drop too old samples from previous graph cycles */ + pw_log_debug("pavail %d, dropping %d", pavail, pavail - avail); + spa_ringbuffer_read_update(&impl->play_ring, pindex + pavail - avail); + pavail = spa_ringbuffer_get_read_index(&impl->play_ring, &pindex); + pw_log_debug("new pavail %d, avail %d", pavail, avail); + } + if (pdavail > avail) { + /* drop too old samples from previous graph cycles */ + pw_log_debug("pdavail %d, dropping %d", pdavail, pdavail - avail); + spa_ringbuffer_read_update(&impl->play_delayed_ring, pdindex + pdavail - avail); + pdavail = spa_ringbuffer_get_read_index(&impl->play_delayed_ring, &pdindex); + pw_log_debug("new pdavail %d, avail %d", pdavail, avail); + } + for (i = 0; i < impl->play_info.channels; i++) { /* echo from sink */ playi = &play_bufi0; @@ -430,32 +460,31 @@ * available on the source */ avail = spa_ringbuffer_get_read_index(&impl->out_ring, &oindex); - while (avail >= size) { - if ((cout = pw_stream_dequeue_buffer(impl->source)) == NULL) { + while (avail >= (int32_t)size) { + if ((cout = pw_stream_dequeue_buffer(impl->source)) != NULL) { + for (i = 0; i < impl->out_info.channels; i++) { + dd = &cout->buffer->datasi; + spa_ringbuffer_read_data(&impl->out_ring, impl->out_bufferi, + impl->out_ringsize, oindex % impl->out_ringsize, + (void *)dd->data, size); + dd->chunk->offset = 0; + dd->chunk->size = size; + dd->chunk->stride = sizeof(float); + } + pw_stream_queue_buffer(impl->source, cout); + } else { + /* drop data as to not cause delay */ pw_log_debug("out of source buffers: %m"); - break; - } - - for (i = 0; i < impl->out_info.channels; i++) { - dd = &cout->buffer->datasi; - spa_ringbuffer_read_data(&impl->out_ring, impl->out_bufferi, - impl->out_ringsize, oindex % impl->out_ringsize, - (void *)dd->data, size); - dd->chunk->offset = 0; - dd->chunk->size = size; - dd->chunk->stride = sizeof(float); } - pw_stream_queue_buffer(impl->source, cout); - oindex += size; spa_ringbuffer_read_update(&impl->out_ring, oindex); avail -= size; } done: - impl->sink_ready = false; - impl->capture_ready = false; + impl->capture_cycle = 0; + impl->sink_cycle = 0; } static void reset_buffers(struct impl *impl) @@ -479,8 +508,8 @@ spa_ringbuffer_get_read_index(&impl->play_ring, &index); spa_ringbuffer_read_update(&impl->play_ring, index + (sizeof(float) * (impl->buffer_delay))); - impl->sink_ready = false; - impl->capture_ready = false; + impl->capture_cycle = 0; + impl->sink_cycle = 0; } static void capture_destroy(void *d) @@ -546,8 +575,11 @@ spa_ringbuffer_write_update(&impl->rec_ring, index + size); if (avail + size >= impl->aec_blocksize) { - impl->capture_ready = true; - if (impl->sink_ready) + if (impl->capture_position) + impl->capture_cycle = impl->capture_position->clock.cycle; + else + pw_log_warn("no capture position"); + if (impl->capture_cycle == impl->sink_cycle) process(impl); } @@ -740,12 +772,26 @@ } } +static void capture_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + + switch (id) { + case SPA_IO_Position: + impl->capture_position = area; + break; + default: + break; + } +} + static const struct pw_stream_events capture_events = { PW_VERSION_STREAM_EVENTS, .destroy = capture_destroy, .state_changed = capture_state_changed, .process = capture_process, - .param_changed = input_param_changed + .param_changed = input_param_changed, + .io_changed = capture_io_changed }; static void source_destroy(void *d) @@ -930,10 +976,15 @@ SPA_PTROFF(d->data, offs, void), size); } spa_ringbuffer_write_update(&impl->play_ring, index + size); + spa_ringbuffer_get_write_index(&impl->play_delayed_ring, &index); + spa_ringbuffer_write_update(&impl->play_delayed_ring, index + size); if (avail + size >= impl->aec_blocksize) { - impl->sink_ready = true; - if (impl->capture_ready) + if (impl->sink_position) + impl->sink_cycle = impl->sink_position->clock.cycle; + else + pw_log_warn("no sink position"); + if (impl->capture_cycle == impl->sink_cycle) process(impl); } @@ -955,12 +1006,27 @@ .state_changed = playback_state_changed, .param_changed = output_param_changed }; + +static void sink_io_changed(void *data, uint32_t id, void *area, uint32_t size) +{ + struct impl *impl = data; + + switch (id) { + case SPA_IO_Position: + impl->sink_position = area; + break; + default: + break; + } +} + static const struct pw_stream_events sink_events = { PW_VERSION_STREAM_EVENTS, .destroy = sink_destroy, .process = sink_process, .state_changed = sink_state_changed, - .param_changed = output_param_changed + .param_changed = output_param_changed, + .io_changed = sink_io_changed }; #define MAX_PARAMS 512u @@ -1203,9 +1269,9 @@ .destroy = module_destroy, }; -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P"), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -1213,6 +1279,7 @@ &props->dict, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1291,7 +1358,10 @@ if (pw_properties_get(props, "resample.prefill") == NULL) pw_properties_set(props, "resample.prefill", "true"); - parse_audio_info(props, &info); + if ((res = parse_audio_info(props, &info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->capture_info = info; impl->source_info = info; @@ -1348,6 +1418,7 @@ copy_props(impl, props, PW_KEY_NODE_LINK_GROUP); copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, SPA_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, "resample.prefill"); @@ -1371,24 +1442,41 @@ } if ((str = pw_properties_get(impl->capture_props, SPA_KEY_AUDIO_POSITION)) != NULL) { - spa_audio_parse_position(str, strlen(str), - impl->capture_info.position, &impl->capture_info.channels); + spa_audio_parse_position_n(str, strlen(str), impl->capture_info.position, + SPA_N_ELEMENTS(impl->capture_info.position), &impl->capture_info.channels); + } + if ((str = pw_properties_get(impl->capture_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) { + spa_audio_parse_layout(str, impl->capture_info.position, + SPA_N_ELEMENTS(impl->capture_info.position), &impl->capture_info.channels); } if ((str = pw_properties_get(impl->source_props, SPA_KEY_AUDIO_POSITION)) != NULL) { - spa_audio_parse_position(str, strlen(str), - impl->source_info.position, &impl->source_info.channels); + spa_audio_parse_position_n(str, strlen(str), impl->source_info.position, + SPA_N_ELEMENTS(impl->source_info.position), &impl->source_info.channels); + } + if ((str = pw_properties_get(impl->source_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) { + spa_audio_parse_layout(str, impl->source_info.position, + SPA_N_ELEMENTS(impl->source_info.position), &impl->source_info.channels); } if ((str = pw_properties_get(impl->sink_props, SPA_KEY_AUDIO_POSITION)) != NULL) { - spa_audio_parse_position(str, strlen(str), - impl->sink_info.position, &impl->sink_info.channels); + spa_audio_parse_position_n(str, strlen(str), impl->sink_info.position, + SPA_N_ELEMENTS(impl->sink_info.position), &impl->sink_info.channels); + impl->playback_info = impl->sink_info; + } + if ((str = pw_properties_get(impl->sink_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) { + spa_audio_parse_layout(str, impl->sink_info.position, + SPA_N_ELEMENTS(impl->sink_info.position), &impl->sink_info.channels); impl->playback_info = impl->sink_info; } if ((str = pw_properties_get(impl->playback_props, SPA_KEY_AUDIO_POSITION)) != NULL) { - spa_audio_parse_position(str, strlen(str), - impl->playback_info.position, &impl->playback_info.channels); - if (impl->playback_info.channels != impl->sink_info.channels) - impl->playback_info = impl->sink_info; + spa_audio_parse_position_n(str, strlen(str), impl->playback_info.position, + SPA_N_ELEMENTS(impl->playback_info.position), &impl->playback_info.channels); } + if ((str = pw_properties_get(impl->playback_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) { + spa_audio_parse_layout(str, impl->playback_info.position, + SPA_N_ELEMENTS(impl->playback_info.position), &impl->playback_info.channels); + } + if (impl->playback_info.channels != impl->sink_info.channels) + impl->playback_info = impl->sink_info; if ((str = pw_properties_get(props, "aec.method")) != NULL) pw_log_warn("aec.method is not supported anymore use library.name");
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-example-filter.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-example-filter.c
Changed
@@ -46,6 +46,7 @@ * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -298,8 +299,7 @@ if (spa_format_audio_raw_parse(param, &info) < 0) return; if (info.rate == 0 || - info.channels == 0 || - info.channels > SPA_AUDIO_MAX_CHANNELS) + info.channels == 0) return; break; } @@ -468,15 +468,16 @@ .destroy = module_destroy, }; -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P"), SPA_DICT_ITEM(SPA_KEY_AUDIO_POSITION, DEFAULT_POSITION)), &props->dict, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -549,6 +550,7 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); copy_props(impl, props, PW_KEY_NODE_GROUP); @@ -574,8 +576,11 @@ if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL) pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str); - parse_audio_info(impl->capture_props, &impl->capture_info); - parse_audio_info(impl->playback_props, &impl->playback_info); + if ((res = parse_audio_info(impl->capture_props, &impl->capture_info)) < 0 || + (res = parse_audio_info(impl->playback_props, &impl->playback_info)) < 0) { + pw_log_error( "can't parse formats: %s", spa_strerror(res)); + goto error; + } if (!impl->capture_info.rate && !impl->playback_info.rate) { if (pw_properties_get(impl->playback_props, "resample.disable") == NULL)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-example-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-example-sink.c
Changed
@@ -52,6 +52,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -273,9 +274,9 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -284,6 +285,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -387,6 +389,7 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); @@ -395,7 +398,10 @@ copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - parse_audio_info(impl->stream_props, &impl->info); + if ((res = parse_audio_info(impl->stream_props, &impl->info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->frame_size = calc_frame_size(&impl->info); if (impl->frame_size == 0) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-example-source.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-example-source.c
Changed
@@ -52,6 +52,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -279,9 +280,9 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -290,6 +291,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -393,6 +395,7 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); @@ -401,7 +404,10 @@ copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - parse_audio_info(impl->stream_props, &impl->info); + if ((res = parse_audio_info(impl->stream_props, &impl->info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->frame_size = calc_frame_size(&impl->info); if (impl->frame_size == 0) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-ffado-driver.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-ffado-driver.c
Changed
@@ -66,6 +66,7 @@ * Options with well-known behavior. * * - \ref PW_KEY_REMOTE_NAME + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -112,6 +113,7 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define MAX_PORTS 128 #define FFADO_RT_PRIORITY_PACKETIZER_RELATIVE 5 @@ -179,7 +181,7 @@ struct volume { bool mute; uint32_t n_volumes; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; }; struct stream { @@ -760,7 +762,7 @@ struct port *port = s->portsi; char channel32; - snprintf(channel, sizeof(channel), "AUX%u", n_channels % SPA_AUDIO_MAX_CHANNELS); + snprintf(channel, sizeof(channel), "AUX%u", n_channels); switch (port->stream_type) { case ffado_stream_type_audio: @@ -873,9 +875,9 @@ case SPA_PROP_channelVolumes: { uint32_t n; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { s->volume.n_volumes = n; for (n = 0; n < s->volume.n_volumes; n++) s->volume.volumesn = volsn; @@ -1227,8 +1229,9 @@ impl->source.portsi = port; } if (impl->source.info.channels != n_channels) { - impl->source.info.channels = n_channels; - for (i = 0; i < SPA_MIN(impl->source.info.channels, SPA_AUDIO_MAX_CHANNELS); i++) + uint32_t n_pos = SPA_MIN(n_channels, SPA_N_ELEMENTS(impl->source.info.position)); + impl->source.info.channels = n_pos; + for (i = 0; i < n_pos; i++) impl->source.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } @@ -1253,8 +1256,9 @@ impl->sink.portsi = port; } if (impl->sink.info.channels != n_channels) { - impl->sink.info.channels = n_channels; - for (i = 0; i < SPA_MIN(impl->sink.info.channels, SPA_AUDIO_MAX_CHANNELS); i++) + uint32_t n_pos = SPA_MIN(n_channels, SPA_N_ELEMENTS(impl->sink.info.position)); + impl->sink.info.channels = n_pos; + for (i = 0; i < n_pos; i++) impl->sink.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } @@ -1426,14 +1430,15 @@ } } -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P"), SPA_DICT_ITEM(SPA_KEY_AUDIO_POSITION, DEFAULT_POSITION)), &props->dict, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1579,8 +1584,11 @@ copy_props(impl, props, PW_KEY_NODE_VIRTUAL); copy_props(impl, props, PW_KEY_NODE_PAUSE_ON_IDLE); - parse_audio_info(impl->source.props, &impl->source.info); - parse_audio_info(impl->sink.props, &impl->sink.info); + if ((res = parse_audio_info(impl->source.props, &impl->source.info)) < 0 || + (res = parse_audio_info(impl->sink.props, &impl->sink.info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); if (impl->core == NULL) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-filter-chain.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-filter-chain.c
Changed
@@ -995,6 +995,7 @@ * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -1832,14 +1833,15 @@ .destroy = module_destroy, }; -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P")), &props->dict, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1918,6 +1920,7 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); copy_props(impl, props, PW_KEY_NODE_GROUP); @@ -1927,8 +1930,11 @@ copy_props(impl, props, PW_KEY_MEDIA_NAME); copy_props(impl, props, "resample.prefill"); - parse_audio_info(impl->capture_props, &impl->capture_info); - parse_audio_info(impl->playback_props, &impl->playback_info); + if ((res = parse_audio_info(impl->capture_props, &impl->capture_info)) < 0 || + (res = parse_audio_info(impl->playback_props, &impl->playback_info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } if (!impl->capture_info.rate && !impl->playback_info.rate) { if (pw_properties_get(impl->playback_props, "resample.disable") == NULL)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-jack-tunnel.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-jack-tunnel.c
Changed
@@ -72,6 +72,7 @@ * * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -115,6 +116,7 @@ PW_LOG_TOPIC_STATIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define MAX_PORTS 128 #define DEFAULT_CLIENT_NAME "PipeWire" @@ -157,7 +159,7 @@ struct volume { bool mute; uint32_t n_volumes; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; }; struct stream { @@ -513,6 +515,7 @@ for (i = 0; i < s->n_ports; i++) { struct port *port = s->portsi; char *link_port = NULL; + char pos8; if (port != NULL) { s->portsi = NULL; @@ -522,8 +525,8 @@ } if (i < s->info.channels) { - str = spa_debug_type_find_short_name(spa_type_audio_channel, - s->info.positioni); + str = spa_type_audio_channel_make_short_name( + s->info.positioni, pos, sizeof(pos), NULL); if (str) snprintf(name, sizeof(name), "%s_%s", prefix, str); else @@ -624,9 +627,9 @@ case SPA_PROP_channelVolumes: { uint32_t n; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { s->volume.n_volumes = n; for (n = 0; n < s->volume.n_volumes; n++) s->volume.volumesn = volsn; @@ -1050,14 +1053,15 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P"), SPA_DICT_ITEM(SPA_KEY_AUDIO_POSITION, DEFAULT_POSITION)), &props->dict, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1167,6 +1171,7 @@ pw_properties_update_string(impl->source.props, str, strlen(str)); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_ALWAYS_PROCESS); copy_props(impl, props, PW_KEY_NODE_GROUP); @@ -1175,8 +1180,11 @@ copy_props(impl, props, "jack.connect-audio"); copy_props(impl, props, "jack.connect-midi"); - parse_audio_info(impl->source.props, &impl->source.info); - parse_audio_info(impl->sink.props, &impl->sink.info); + if ((res = parse_audio_info(impl->source.props, &impl->source.info)) < 0 || + (res = parse_audio_info(impl->sink.props, &impl->sink.info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->source.n_midi = pw_properties_get_uint32(impl->source.props, "midi.ports", DEFAULT_MIDI_PORTS);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-loopback.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-loopback.c
Changed
@@ -51,6 +51,7 @@ * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_NODE_LATENCY @@ -538,8 +539,7 @@ spa_zero(info); if (param != NULL) { if (spa_format_audio_raw_parse(param, &info) < 0 || - info.channels == 0 || - info.channels > SPA_AUDIO_MAX_CHANNELS) + info.channels == 0) return; if ((impl->info.format != 0 && impl->info.format != info.format) || @@ -839,14 +839,15 @@ .destroy = module_destroy, }; -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P")), &props->dict, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -928,6 +929,7 @@ copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); copy_props(impl, props, PW_KEY_NODE_GROUP); @@ -953,9 +955,12 @@ if (pw_properties_get(impl->playback_props, PW_KEY_NODE_DESCRIPTION) == NULL) pw_properties_set(impl->playback_props, PW_KEY_NODE_DESCRIPTION, str); - parse_audio_info(props, &impl->info); - parse_audio_info(impl->capture_props, &impl->capture_info); - parse_audio_info(impl->playback_props, &impl->playback_info); + if ((res = parse_audio_info(props, &impl->info)) < 0 || + (res = parse_audio_info(impl->capture_props, &impl->capture_info)) < 0 || + (res = parse_audio_info(impl->playback_props, &impl->playback_info)) < 0) { + pw_log_error( "can't parse formats: %s", spa_strerror(res)); + goto error; + } if (!impl->capture_info.rate && !impl->playback_info.rate) { if (pw_properties_get(impl->playback_props, "resample.disable") == NULL)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-netjack2-driver.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-netjack2-driver.c
Changed
@@ -99,6 +99,7 @@ * * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -441,11 +442,11 @@ } if (i < s->info.channels) { - str = spa_debug_type_find_short_name(spa_type_audio_channel, - s->info.positioni % SPA_AUDIO_MAX_CHANNELS); + str = spa_type_audio_channel_make_short_name( + s->info.positioni, name, sizeof(name), "UNK"); props = pw_properties_new( PW_KEY_FORMAT_DSP, "32 bit float mono audio", - PW_KEY_AUDIO_CHANNEL, str ? str : "UNK", + PW_KEY_AUDIO_CHANNEL, str, PW_KEY_PORT_PHYSICAL, "true", NULL); @@ -512,9 +513,9 @@ case SPA_PROP_channelVolumes: { uint32_t n; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { s->volume.n_volumes = n; for (n = 0; n < s->volume.n_volumes; n++) s->volume.volumesn = volsn; @@ -863,7 +864,7 @@ } impl->sink.info.rate = peer->params.sample_rate; if ((uint32_t)peer->params.send_audio_channels != impl->sink.info.channels) { - impl->sink.info.channels = SPA_MIN(peer->params.send_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); + impl->sink.info.channels = peer->params.send_audio_channels; for (i = 0; i < impl->sink.info.channels; i++) impl->sink.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } @@ -874,7 +875,7 @@ } impl->source.info.rate = peer->params.sample_rate; if ((uint32_t)peer->params.recv_audio_channels != impl->source.info.channels) { - impl->source.info.channels = SPA_MIN(peer->params.recv_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); + impl->source.info.channels = peer->params.recv_audio_channels; for (i = 0; i < impl->source.info.channels; i++) impl->source.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } @@ -1218,13 +1219,14 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P")), &props->dict, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1329,6 +1331,7 @@ copy_props(impl, props, PW_KEY_NODE_LOOP_NAME); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_ALWAYS_PROCESS); copy_props(impl, props, PW_KEY_NODE_GROUP); @@ -1336,8 +1339,11 @@ copy_props(impl, props, "midi.ports"); copy_props(impl, props, "audio.ports"); - parse_audio_info(impl->source.props, &impl->source.info); - parse_audio_info(impl->sink.props, &impl->sink.info); + if ((res = parse_audio_info(impl->source.props, &impl->source.info)) < 0 || + (res = parse_audio_info(impl->sink.props, &impl->sink.info)) < 0) { + pw_log_error( "can't parse format: %s", spa_strerror(res)); + goto error; + } impl->source.wanted_n_midi = pw_properties_get_int32(impl->source.props, "midi.ports", DEFAULT_MIDI_PORTS);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-netjack2-manager.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-netjack2-manager.c
Changed
@@ -94,6 +94,7 @@ * * - \ref PW_KEY_REMOTE_NAME * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -181,7 +182,7 @@ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info); +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info); struct port { enum spa_direction direction; @@ -601,12 +602,11 @@ } if (i < s->info.channels) { - str = spa_debug_type_find_short_name(spa_type_audio_channel, - s->info.positioni); - + str = spa_type_audio_channel_make_short_name( + s->info.positioni, name, sizeof(name), "UNK"); props = pw_properties_new( PW_KEY_FORMAT_DSP, "32 bit float mono audio", - PW_KEY_AUDIO_CHANNEL, str ? str : "UNK", + PW_KEY_AUDIO_CHANNEL, str, PW_KEY_PORT_PHYSICAL, "true", NULL); @@ -677,9 +677,9 @@ case SPA_PROP_channelVolumes: { uint32_t n; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { s->volume.n_volumes = n; for (n = 0; n < s->volume.n_volumes; n++) s->volume.volumesn = volsn; @@ -969,8 +969,11 @@ follower->sink.direction = PW_DIRECTION_INPUT; follower->sink.props = pw_properties_copy(impl->sink_props); - parse_audio_info(follower->source.props, &follower->source.info); - parse_audio_info(follower->sink.props, &follower->sink.info); + if ((res = parse_audio_info(follower->source.props, &follower->source.info)) < 0 || + (res = parse_audio_info(follower->sink.props, &follower->sink.info)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + return res; + } follower->source.n_audio = pw_properties_get_uint32(follower->source.props, "audio.ports", follower->source.info.channels ? @@ -1026,14 +1029,14 @@ follower->source.n_ports = peer->params.recv_audio_channels + peer->params.recv_midi_channels; follower->source.info.rate = peer->params.sample_rate; if ((uint32_t)peer->params.recv_audio_channels != follower->source.info.channels) { - follower->source.info.channels = SPA_MIN(peer->params.recv_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); + follower->source.info.channels = peer->params.recv_audio_channels; for (i = 0; i < follower->source.info.channels; i++) follower->source.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } follower->sink.n_ports = peer->params.send_audio_channels + peer->params.send_midi_channels; follower->sink.info.rate = peer->params.sample_rate; if ((uint32_t)peer->params.send_audio_channels != follower->sink.info.channels) { - follower->sink.info.channels = SPA_MIN(peer->params.send_audio_channels, (int)SPA_AUDIO_MAX_CHANNELS); + follower->sink.info.channels = peer->params.send_audio_channels; for (i = 0; i < follower->sink.info.channels; i++) follower->sink.info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; } @@ -1290,13 +1293,14 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, "F32P")), &props->dict, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1415,6 +1419,7 @@ copy_props(impl, props, PW_KEY_NODE_LOCK_QUANTUM); copy_props(impl, props, PW_KEY_NODE_LOCK_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, "audio.ports"); copy_props(impl, props, "midi.ports");
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-netjack2/peer.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-netjack2/peer.c
Changed
@@ -7,10 +7,12 @@ #include <opus/opus_custom.h> #endif +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + struct volume { bool mute; uint32_t n_volumes; - float volumesSPA_AUDIO_MAX_CHANNELS; + float volumesMAX_CHANNELS; }; static inline float bswap_f32(float f)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-parametric-equalizer.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-parametric-equalizer.c
Changed
@@ -70,6 +70,7 @@ * Options with well-known behaviour: * * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_REMOTE_NAME *
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-pipe-tunnel.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-pipe-tunnel.c
Changed
@@ -79,6 +79,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_LATENCY * - \ref PW_KEY_NODE_NAME @@ -745,9 +746,9 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -756,6 +757,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -886,6 +888,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); @@ -896,7 +899,10 @@ copy_props(impl, props, PW_KEY_TARGET_OBJECT); copy_props(impl, props, "pipe.filename"); - parse_audio_info(impl->stream_props, &impl->info); + if ((res = parse_audio_info(impl->stream_props, &impl->info)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + goto error; + } impl->frame_size = calc_frame_size(&impl->info); if (impl->frame_size == 0) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse.c
Changed
@@ -67,12 +67,12 @@ * * #server.dbus-name = "org.pulseaudio.Server" * #pulse.allow-module-loading = true - * #pulse.min.req = 128/48000 # 2.7ms + * #pulse.min.req = 256/48000 # 5.3ms * #pulse.default.req = 960/48000 # 20 milliseconds - * #pulse.min.frag = 128/48000 # 2.7ms + * #pulse.min.frag = 256/48000 # 5.3ms * #pulse.default.frag = 96000/48000 # 2 seconds * #pulse.default.tlength = 96000/48000 # 2 seconds - * #pulse.min.quantum = 128/48000 # 2.7ms + * #pulse.min.quantum = 256/48000 # 5.3ms * #pulse.default.format = F32 * #pulse.default.position = FL FR * #pulse.idle.timeout = 0 @@ -140,7 +140,7 @@ * ### Playback buffering options * *\code{.unparsed} - * pulse.min.req = 128/48000 # 2.7ms + * pulse.min.req = 256/48000 # 5.3ms *\endcode * * The minimum amount of data to request for clients. The client requested @@ -166,7 +166,7 @@ * ### Record buffering options * *\code{.unparsed} - * pulse.min.frag = 128/48000 # 2.7ms + * pulse.min.frag = 256/48000 # 5.3ms *\endcode * * The minimum allowed size of the capture buffer before it is sent to a client. @@ -184,7 +184,7 @@ * ### Scheduling options * *\code{.unparsed} - * pulse.min.quantum = 128/48000 # 2.7ms + * pulse.min.quantum = 256/48000 # 5.3ms *\endcode * * The minimum quantum (buffer size in samples) to use for pulseaudio clients.
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/collect.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/collect.c
Changed
@@ -169,7 +169,7 @@ SPA_PARAM_PROFILE_description, SPA_POD_OPT_String(&pi->description), SPA_PARAM_PROFILE_priority, SPA_POD_OPT_Int(&pi->priority), SPA_PARAM_PROFILE_available, SPA_POD_OPT_Id(&pi->available), - SPA_PARAM_PROFILE_classes, SPA_POD_OPT_Pod(&classes)) < 0) { + SPA_PARAM_PROFILE_classes, SPA_POD_OPT_PodStruct(&classes)) < 0) { continue; } if (pi->description == NULL) @@ -233,6 +233,7 @@ struct device_info *dev_info, bool monitor, struct defs *defs) { struct pw_manager_param *p; + dev_info->active_port_name = NULL; if (card) { spa_list_for_each(p, &card->param_list, link) { @@ -246,7 +247,7 @@ SPA_TYPE_OBJECT_ParamRoute, NULL, SPA_PARAM_ROUTE_index, SPA_POD_Int(&index), SPA_PARAM_ROUTE_device, SPA_POD_Int(&dev), - SPA_PARAM_ROUTE_props, SPA_POD_OPT_Pod(&props)) < 0) + SPA_PARAM_ROUTE_props, SPA_POD_OPT_PodObject(&props)) < 0) continue; if (dev != dev_info->device) continue; @@ -256,6 +257,30 @@ dev_info->have_volume = true; } } + + /* Look up the port name for the active port */ + if (dev_info->active_port != SPA_ID_INVALID) { + spa_list_for_each(p, &card->param_list, link) { + uint32_t index, direction; + const char *name = NULL; + + if (p->id != SPA_PARAM_EnumRoute) + continue; + + if (spa_pod_parse_object(p->param, + SPA_TYPE_OBJECT_ParamRoute, NULL, + SPA_PARAM_ROUTE_index, SPA_POD_Int(&index), + SPA_PARAM_ROUTE_direction, SPA_POD_Id(&direction), + SPA_PARAM_ROUTE_name, SPA_POD_String(&name)) < 0) + continue; + + if (index == dev_info->active_port && + direction == dev_info->direction) { + dev_info->active_port_name = name; + break; + } + } + } } spa_list_for_each(p, &device->param_list, link) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/format.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/format.c
Changed
@@ -12,6 +12,8 @@ #include "format.h" +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + static const struct format audio_formats = { SAMPLE_U8 = { SAMPLE_U8, SPA_AUDIO_FORMAT_U8, "u8", 1 }, SAMPLE_ALAW = { SAMPLE_ALAW, SPA_AUDIO_FORMAT_ALAW, "alaw", 1 }, @@ -296,9 +298,9 @@ return audio_channelschannel.channel; } -const char *channel_id2name(uint32_t channel) +const char *channel_id2name(uint32_t channel, char *buf, size_t size) { - return spa_type_audio_channel_to_short_name(channel); + return spa_type_audio_channel_make_short_name(channel, buf, size, "UNK"); } uint32_t channel_name2id(const char *name) @@ -346,9 +348,9 @@ } -void channel_map_to_positions(const struct channel_map *map, uint32_t *pos) +void channel_map_to_positions(const struct channel_map *map, uint32_t *pos, uint32_t max_pos) { - uint32_t i, channels = SPA_MIN(map->channels, SPA_AUDIO_MAX_CHANNELS); + uint32_t i, channels = SPA_MIN(map->channels, max_pos); for (i = 0; i < channels; i++) posi = map->mapi; } @@ -448,8 +450,9 @@ void channel_map_parse_position(const char *str, struct channel_map *map) { - uint32_t channels = 0, positionSPA_AUDIO_MAX_CHANNELS; - spa_audio_parse_position(str, strlen(str), position, &channels); + uint32_t channels = 0, positionCHANNELS_MAX; + spa_audio_parse_position_n(str, strlen(str), position, + SPA_N_ELEMENTS(position), &channels); positions_to_channel_map(position, channels, map); } @@ -532,8 +535,7 @@ info.info.raw.rate = 48000; if (info.info.raw.format == 0 || info.info.raw.rate == 0 || - info.info.raw.channels == 0 || - info.info.raw.channels > SPA_AUDIO_MAX_CHANNELS) + info.info.raw.channels == 0) return -ENOTSUP; } break; @@ -631,8 +633,8 @@ SPA_FORMAT_AUDIO_channels, SPA_POD_Int(spec->channels), 0); if (map && map->channels == spec->channels) { - uint32_t positionsSPA_AUDIO_MAX_CHANNELS; - channel_map_to_positions(map, positions); + uint32_t positionsspec->channels; + channel_map_to_positions(map, positions, spec->channels); spa_pod_builder_add(b, SPA_FORMAT_AUDIO_position, SPA_POD_Array(sizeof(uint32_t), SPA_TYPE_Id, spec->channels, positions), 0);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/format.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/format.h
Changed
@@ -190,13 +190,13 @@ struct spa_dict *props); uint32_t channel_pa2id(enum channel_position channel); -const char *channel_id2name(uint32_t channel); +const char *channel_id2name(uint32_t channel, char *buf, size_t size); uint32_t channel_name2id(const char *name); enum channel_position channel_id2pa(uint32_t id, uint32_t *aux); const char *channel_id2paname(uint32_t id, uint32_t *aux); uint32_t channel_paname2id(const char *name, size_t size); -void channel_map_to_positions(const struct channel_map *map, uint32_t *pos); +void channel_map_to_positions(const struct channel_map *map, uint32_t *pos, uint32_t max_pos); void channel_map_parse(const char *str, struct channel_map *map); bool channel_map_valid(const struct channel_map *map); void channel_map_parse_position(const char *str, struct channel_map *map);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/message.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/message.c
Changed
@@ -761,11 +761,13 @@ case TAG_CHANNEL_MAP: { struct channel_map map; + char pos8; if ((res = read_channel_map(m, &map)) < 0) return res; pw_log(level, "%s %u: channelmap: channels:%u", prefix, o, map.channels); for (i = 0; i < map.channels; i++) - pw_log(level, "%s %d: %s", prefix, i, channel_id2name(map.mapi)); + pw_log(level, "%s %d: %s", prefix, i, + channel_id2name(map.mapi, pos, sizeof(pos))); break; } case TAG_CVOLUME:
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/module.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/module.c
Changed
@@ -12,6 +12,7 @@ #include <spa/utils/list.h> #include <spa/utils/hook.h> #include <spa/utils/string.h> +#include <spa/param/audio/raw-utils.h> #include <pipewire/log.h> #include <pipewire/map.h> #include <pipewire/properties.h> @@ -226,14 +227,15 @@ info->channels, map.channels); return -EINVAL; } - channel_map_to_positions(&map, info->position); + channel_map_to_positions(&map, info->position, SPA_N_ELEMENTS(info->position)); pw_properties_set(props, key_channel_map, NULL); } else { if (info->channels == 0) info->channels = impl->defs.sample_spec.channels; if (info->channels == impl->defs.channel_map.channels) { - channel_map_to_positions(&impl->defs.channel_map, info->position); + channel_map_to_positions(&impl->defs.channel_map, + info->position, SPA_N_ELEMENTS(info->position)); } else if (info->channels == 1) { info->position0 = SPA_AUDIO_CHANNEL_MONO; } else if (info->channels == 2) { @@ -281,14 +283,14 @@ if (info->rate) pw_properties_setf(props, SPA_KEY_AUDIO_RATE, "%u", info->rate); if (info->channels) { - char *s, *p; + char *s, *p, pos8; pw_properties_setf(props, SPA_KEY_AUDIO_CHANNELS, "%u", info->channels); p = s = alloca(info->channels * 8); for (i = 0; i < info->channels; i++) p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ", ", - channel_id2name(info->positioni)); + channel_id2name(info->positioni, pos, sizeof(pos))); pw_properties_setf(props, SPA_KEY_AUDIO_POSITION, " %s ", s); } }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/modules/module-stream-restore.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/modules/module-stream-restore.c
Changed
@@ -295,9 +295,11 @@ fprintf(f, " "); } if (map.channels > 0) { + char pos8; fprintf(f, ", \"channels\": "); for (i = 0; i < map.channels; i++) - fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "), channel_id2name(map.mapi)); + fprintf(f, "%s\"%s\"", (i == 0 ? " ":", "), + channel_id2name(map.mapi, pos, sizeof(pos))); fprintf(f, " "); } if (device_name != NULL && device_name0 &&
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/pulse-server.c
Changed
@@ -57,12 +57,12 @@ #include "volume.h" #define DEFAULT_ALLOW_MODULE_LOADING "true" -#define DEFAULT_MIN_REQ "128/48000" +#define DEFAULT_MIN_REQ "256/48000" #define DEFAULT_DEFAULT_REQ "960/48000" -#define DEFAULT_MIN_FRAG "128/48000" +#define DEFAULT_MIN_FRAG "256/48000" #define DEFAULT_DEFAULT_FRAG "96000/48000" #define DEFAULT_DEFAULT_TLENGTH "96000/48000" -#define DEFAULT_MIN_QUANTUM "128/48000" +#define DEFAULT_MIN_QUANTUM "256/48000" #define DEFAULT_FORMAT "F32" #define DEFAULT_POSITION " FL FR " #define DEFAULT_IDLE_TIMEOUT "0"
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-pulse/volume.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-pulse/volume.c
Changed
@@ -53,7 +53,7 @@ if (monitor) continue; info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - info->volume.values, CHANNELS_MAX); + info->volume.values, SPA_N_ELEMENTS(info->volume.values)); SPA_FLAG_UPDATE(info->flags, VOLUME_HW_VOLUME, prop->flags & SPA_POD_PROP_FLAG_HARDWARE); break; @@ -68,7 +68,7 @@ if (!monitor) continue; info->volume.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - info->volume.values, CHANNELS_MAX); + info->volume.values, SPA_N_ELEMENTS(info->volume.values)); SPA_FLAG_CLEAR(info->flags, VOLUME_HW_VOLUME); break; case SPA_PROP_volumeBase: @@ -84,7 +84,7 @@ } case SPA_PROP_channelMap: info->map.channels = spa_pod_copy_array(&prop->value, SPA_TYPE_Id, - info->map.map, CHANNELS_MAX); + info->map.map, SPA_N_ELEMENTS(info->map.map)); break; default: break;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-protocol-simple.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-protocol-simple.c
Changed
@@ -72,6 +72,7 @@ * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_LATENCY * - \ref PW_KEY_NODE_RATE @@ -815,13 +816,14 @@ case SPA_AUDIO_FORMAT_F64_OE: return res * 8; default: - return 0; + return -ENOTSUP; } } static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + int res; + if ((res = spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -830,7 +832,9 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, - SPA_KEY_AUDIO_POSITION, NULL); + SPA_KEY_AUDIO_LAYOUT, + SPA_KEY_AUDIO_POSITION, NULL)) < 0) + return res; return calc_frame_size(info); } @@ -851,6 +855,7 @@ const char *str; struct spa_json it1; char value512; + int res; pw_properties_fetch_bool(impl->props, "capture", &impl->capture); pw_properties_fetch_bool(impl->props, "playback", &impl->playback); @@ -885,6 +890,7 @@ copy_props(impl, PW_KEY_AUDIO_FORMAT); copy_props(impl, PW_KEY_AUDIO_RATE); copy_props(impl, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, SPA_KEY_AUDIO_POSITION); copy_props(impl, PW_KEY_NODE_RATE); copy_props(impl, PW_KEY_NODE_NAME); @@ -894,19 +900,20 @@ copy_props(impl, PW_KEY_NODE_VIRTUAL); copy_props(impl, PW_KEY_NODE_NETWORK); - impl->capture_frame_size = parse_audio_info(impl->capture_props, &impl->capture_info); - if (impl->capture_frame_size == 0) { + if ((res = parse_audio_info(impl->capture_props, &impl->capture_info)) <= 0) { pw_log_error("unsupported capture audio format:%d channels:%d", impl->capture_info.format, impl->capture_info.channels); return -EINVAL; } + impl->capture_frame_size = res; - impl->playback_frame_size = parse_audio_info(impl->playback_props, &impl->playback_info); - if (impl->playback_frame_size == 0) { + if ((res = parse_audio_info(impl->playback_props, &impl->playback_info)) <= 0) { pw_log_error("unsupported playback audio format:%d channels:%d", impl->playback_info.format, impl->playback_info.channels); return -EINVAL; } + impl->playback_frame_size = res; + if (impl->capture_info.rate != 0 && pw_properties_get(impl->capture_props, PW_KEY_NODE_RATE) == NULL) pw_properties_setf(impl->capture_props, PW_KEY_NODE_RATE,
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-pulse-tunnel.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-pulse-tunnel.c
Changed
@@ -72,6 +72,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_LATENCY * - \ref PW_KEY_NODE_NAME @@ -117,6 +118,8 @@ #define DEFAULT_CHANNELS 2 #define DEFAULT_POSITION " FL FR " +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + #define MODULE_USAGE "( remote.name=<remote> " \ "( node.latency=<latency as fraction> " \ "( node.name=<name of the nodes> " \ @@ -295,10 +298,10 @@ { struct pa_cvolume volume; uint32_t n; - float volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; if ((n = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { volume.channels = SPA_MIN(PA_CHANNELS_MAX, n); for (n = 0; n < volume.channels; n++) volume.valuesn = pa_sw_volume_from_linear(volsn); @@ -752,7 +755,8 @@ map.channels = impl->info.channels; for (i = 0; i < map.channels; i++) - map.mapi = (pa_channel_position_t)channel_id2pa(impl->info.positioni, &aux); + map.mapi = (pa_channel_position_t)channel_id2pa( + impl->info.positioni, &aux); snprintf(stream_name, sizeof(stream_name), _("Tunnel for %s@%s"), pw_get_user_name(), pw_get_host_name()); @@ -832,10 +836,10 @@ struct spa_pod_frame f1; struct spa_pod *param; uint32_t i, channels; - float volsSPA_AUDIO_MAX_CHANNELS; - float soft_volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS; + float soft_volsMAX_CHANNELS; - channels = SPA_MIN(impl->volume.channels, SPA_AUDIO_MAX_CHANNELS); + channels = SPA_MIN(impl->volume.channels, MAX_CHANNELS); for (i = 0; i < channels; i++) { volsi = (float)pa_sw_volume_to_linear(impl->volume.valuesi); soft_volsi = 1.0f; @@ -1045,9 +1049,9 @@ .destroy = module_destroy, }; -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -1056,6 +1060,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -1180,6 +1185,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); @@ -1189,7 +1195,10 @@ copy_props(impl, props, PW_KEY_NODE_NETWORK); copy_props(impl, props, PW_KEY_MEDIA_CLASS); - parse_audio_info(impl->stream_props, &impl->info); + if ((res = parse_audio_info(impl->stream_props, &impl->info)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + goto error; + } impl->frame_size = calc_frame_size(&impl->info); if (impl->frame_size == 0) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-raop-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-raop-sink.c
Changed
@@ -82,6 +82,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -158,6 +159,7 @@ #define RAOP_LATENCY_MS 250 #define DEFAULT_LATENCY_MS 1500 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define VOLUME_MAX 0.0 #define VOLUME_MIN -30.0 #define VOLUME_MUTE -144.0 @@ -1612,11 +1614,11 @@ case SPA_PROP_channelVolumes: { uint32_t i, n_vols; - float volsSPA_AUDIO_MAX_CHANNELS, volume; - float soft_volsSPA_AUDIO_MAX_CHANNELS; + float volsMAX_CHANNELS, volume; + float soft_volsMAX_CHANNELS; if ((n_vols = spa_pod_copy_array(&prop->value, SPA_TYPE_Float, - vols, SPA_AUDIO_MAX_CHANNELS)) > 0) { + vols, SPA_N_ELEMENTS(vols))) > 0) { volume = 0.0f; for (i = 0; i < n_vols; i++) { volume += volsi; @@ -1900,6 +1902,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_DEVICE_ICON_NAME); copy_props(impl, props, PW_KEY_NODE_NAME);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-roc-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-roc-sink.c
Changed
@@ -12,6 +12,7 @@ #include <spa/utils/hook.h> #include <spa/utils/result.h> #include <spa/param/audio/format-utils.h> +#include <spa/param/audio/raw-json.h> #include <roc/config.h> #include <roc/log.h> @@ -52,7 +53,10 @@ * * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION - * - \ref PW_KEY_MEDIA_NAME + * - \ref PW_KEY_NODE_VIRTUAL + * - \ref PW_KEY_MEDIA_CLASS + * - \ref SPA_KEY_AUDIO_POSITION + * * ## Example configuration *\code{.unparsed} @@ -70,6 +74,7 @@ * sink.props = { * node.name = "roc-sink" * } + * audio.position = FL FR * } * } * @@ -264,18 +269,34 @@ spa_zero(sender_config); sender_config.frame_encoding.rate = data->rate; - sender_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_STEREO; sender_config.frame_encoding.format = ROC_FORMAT_PCM_FLOAT32; - sender_config.packet_encoding = ROC_PACKET_ENCODING_AVP_L16_STEREO; sender_config.fec_encoding = data->fec_code; - info.rate = data->rate; - /* Fixed to be the same as ROC sender config above */ - info.channels = 2; + info.rate = data->rate; info.format = SPA_AUDIO_FORMAT_F32; - info.position0 = SPA_AUDIO_CHANNEL_FL; - info.position1 = SPA_AUDIO_CHANNEL_FR; + + const char* positions = pw_properties_get(data->capture_props, SPA_KEY_AUDIO_POSITION); + int channels = spa_audio_parse_position_n(positions, strlen(positions), info.position, SPA_N_ELEMENTS(info.position), &info.channels); + + if(channels == 2) { + sender_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_STEREO; + sender_config.packet_encoding = ROC_PACKET_ENCODING_AVP_L16_STEREO; + } else { + sender_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_MULTITRACK; + sender_config.frame_encoding.tracks = channels; + + res = roc_context_register_encoding(data->context, PW_ROC_MULTITRACK_ENCODING_ID, &sender_config.frame_encoding); + if(res) { + pw_log_error("failed to register encoding: %d", res); + return -EINVAL; + } + sender_config.packet_encoding = PW_ROC_MULTITRACK_ENCODING_ID; + + // As of v0.4.0, roc generates packets bigger than it can handle if many channels are used + // (see github.com/roc-streaming/roc-toolkit/issues/821) + sender_config.packet_length = PW_ROC_DEFAULT_PACKET_LENGTH * 2 / channels; + } pw_properties_setf(data->capture_props, PW_KEY_NODE_RATE, "1/%d", info.rate); @@ -360,6 +381,7 @@ "( remote.source.port=<remote receiver port for source packets> ) " "( remote.repair.port=<remote receiver port for repair packets> ) " "( remote.control.port=<remote receiver port for control packets> ) " + "( audio.position=<channel map, default:"PW_ROC_STEREO_POSITIONS"> ) " "( sink.props= { key=val ... } ) " }, { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; @@ -418,6 +440,12 @@ if ((str = pw_properties_get(capture_props, PW_KEY_MEDIA_CLASS)) == NULL) pw_properties_set(capture_props, PW_KEY_MEDIA_CLASS, "Audio/Sink"); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) { + pw_properties_set(capture_props, SPA_KEY_AUDIO_POSITION, str); + } else { + pw_properties_set(capture_props, SPA_KEY_AUDIO_POSITION, PW_ROC_STEREO_POSITIONS); + } + data->rate = pw_properties_get_uint32(capture_props, PW_KEY_AUDIO_RATE, 0); if (data->rate == 0) data->rate = PW_ROC_DEFAULT_RATE;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-roc-source.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-roc-source.c
Changed
@@ -12,6 +12,7 @@ #include <spa/utils/hook.h> #include <spa/utils/result.h> #include <spa/param/audio/format-utils.h> +#include <spa/param/audio/raw-json.h> #include <roc/config.h> #include <roc/log.h> @@ -62,7 +63,9 @@ * * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION - * - \ref PW_KEY_MEDIA_NAME + * - \ref PW_KEY_NODE_VIRTUAL + * - \ref PW_KEY_MEDIA_CLASS + * - \ref SPA_KEY_AUDIO_POSITION * * ## Example configuration *\code{.unparsed} @@ -85,6 +88,7 @@ * source.props = { * node.name = "roc-source" * } + * audio.position = FL FR * } * } * @@ -285,20 +289,33 @@ spa_zero(receiver_config); receiver_config.frame_encoding.rate = data->rate; - receiver_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_STEREO; receiver_config.frame_encoding.format = ROC_FORMAT_PCM_FLOAT32; receiver_config.resampler_profile = data->resampler_profile; receiver_config.resampler_backend = data->resampler_backend; receiver_config.latency_tuner_backend = data->latency_tuner_backend; receiver_config.latency_tuner_profile = data->latency_tuner_profile; - info.rate = data->rate; /* Fixed to be the same as ROC receiver config above */ - info.channels = 2; + info.rate = data->rate; info.format = SPA_AUDIO_FORMAT_F32; - info.position0 = SPA_AUDIO_CHANNEL_FL; - info.position1 = SPA_AUDIO_CHANNEL_FR; + + const char* positions = pw_properties_get(data->playback_props, SPA_KEY_AUDIO_POSITION); + int channels = spa_audio_parse_position_n(positions, strlen(positions), info.position, SPA_N_ELEMENTS(info.position), &info.channels); + + if(channels == 2) { + receiver_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_STEREO; + } else { + receiver_config.frame_encoding.channels = ROC_CHANNEL_LAYOUT_MULTITRACK; + receiver_config.frame_encoding.tracks = channels; + + res = roc_context_register_encoding(data->context, PW_ROC_MULTITRACK_ENCODING_ID, &receiver_config.frame_encoding); + if(res) { + pw_log_error("failed to register encoding: %d", res); + return -EINVAL; + } + } + data->stride = info.channels * sizeof(float); pw_properties_setf(data->playback_props, PW_KEY_NODE_RATE, "1/%d", info.rate); @@ -403,6 +420,7 @@ "( local.source.port=<local receiver port for source packets> ) " "( local.repair.port=<local receiver port for repair packets> ) " "( local.control.port=<local receiver port for control packets> ) " + "( audio.position=<channel map, default:"PW_ROC_STEREO_POSITIONS"> ) " "( source.props= { key=value ... } ) " }, { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; @@ -459,6 +477,12 @@ if (pw_properties_get(playback_props, PW_KEY_NODE_NETWORK) == NULL) pw_properties_set(playback_props, PW_KEY_NODE_NETWORK, "true"); + if ((str = pw_properties_get(props, SPA_KEY_AUDIO_POSITION)) != NULL) { + pw_properties_set(playback_props, SPA_KEY_AUDIO_POSITION, str); + } else { + pw_properties_set(playback_props, SPA_KEY_AUDIO_POSITION, PW_ROC_STEREO_POSITIONS); + } + data->rate = pw_properties_get_uint32(playback_props, PW_KEY_AUDIO_RATE, 0); if (data->rate == 0) data->rate = PW_ROC_DEFAULT_RATE;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-roc/common.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-roc/common.h
Changed
@@ -13,6 +13,10 @@ #define PW_ROC_DEFAULT_SESS_LATENCY 200 #define PW_ROC_DEFAULT_RATE 44100 #define PW_ROC_DEFAULT_CONTROL_PROTO ROC_PROTO_RTCP +#define PW_ROC_DEFAULT_PACKET_LENGTH 5000000 // 5ms in ns + +#define PW_ROC_MULTITRACK_ENCODING_ID 100 +#define PW_ROC_STEREO_POSITIONS " FL FR " static inline int pw_roc_parse_fec_encoding(roc_fec_encoding *out, const char *str) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rt.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rt.c
Changed
@@ -650,8 +650,8 @@ static int acquire_rt_sched(struct spa_thread *thread, int priority) { - int err, min, max; - struct sched_param sp; + int err, min, max, new_policy, old_policy; + struct sched_param new_sched_params, old_sched_params; pthread_t pt = (pthread_t)thread; min = max = 0; @@ -663,10 +663,18 @@ priority, min, max, REALTIME_POLICY); priority = SPA_CLAMP(priority, min, max); } + if ((err = pthread_getschedparam(pt, &old_policy, &old_sched_params)) != 0) { + pw_log_warn("Failed to get scheduling params: %s", strerror(err)); + old_policy = SCHED_RESET_ON_FORK; + } - spa_zero(sp); - sp.sched_priority = priority; - if ((err = pthread_setschedparam(pt, REALTIME_POLICY | SCHED_RESET_ON_FORK, &sp)) != 0) { + spa_zero(new_sched_params); + new_sched_params.sched_priority = priority; + new_policy = REALTIME_POLICY; + if ((old_policy & SCHED_RESET_ON_FORK) != 0) + new_policy |= SCHED_RESET_ON_FORK; + + if ((err = pthread_setschedparam(pt, new_policy, &new_sched_params)) != 0) { pw_log_warn("could not make thread %p realtime: %s", thread, strerror(err)); return -err; } @@ -677,12 +685,21 @@ static int impl_drop_rt_generic(void *object, struct spa_thread *thread) { - struct sched_param sp; + struct sched_param new_sched_params, old_sched_params; pthread_t pt = (pthread_t)thread; - int err; + int err, new_policy, old_policy; + + if ((err = pthread_getschedparam(pt, &old_policy, &old_sched_params)) != 0) { + pw_log_warn("Failed to get scheduling params: %s", strerror(err)); + old_policy = SCHED_RESET_ON_FORK; + } + + spa_zero(new_sched_params); + new_policy = SCHED_OTHER; + if (SPA_FLAG_IS_SET(old_policy, SCHED_RESET_ON_FORK)) + new_policy |= SCHED_RESET_ON_FORK; - spa_zero(sp); - if ((err = pthread_setschedparam(pt, SCHED_OTHER | SCHED_RESET_ON_FORK, &sp)) != 0) { + if ((err = pthread_setschedparam(pt, new_policy, &new_sched_params)) != 0) { pw_log_debug("thread %p: SCHED_OTHER|SCHED_RESET_ON_FORK failed: %s", thread, strerror(err)); return -err;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp-sap.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-sap.c
Changed
@@ -156,6 +156,7 @@ #define DEFAULT_LOOP false #define MAX_SDP 2048 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS #define USAGE "( local.ifname=<local interface name to use> ) " \ "( sap.ip=<SAP IP address to send announce, default:"DEFAULT_SAP_IP"> ) " \ @@ -247,6 +248,16 @@ struct session *session; }; +struct igmp_recovery { + struct pw_timer timer; + int socket_fd; + struct sockaddr_storage mcast_addr; + socklen_t mcast_len; + uint32_t if_index; + bool is_ipv6; + uint32_t deadline; +}; + struct impl { struct pw_properties *props; @@ -264,7 +275,11 @@ struct pw_registry *registry; struct spa_hook registry_listener; - struct pw_timer timer; + struct pw_timer sap_send_timer; + + /* This timer is used when the first start_sap() call fails because + * of an ENODEV error (see the start_sap() code for details) */ + struct pw_timer start_sap_retry_timer; char *ifname; uint32_t ttl; @@ -280,6 +295,10 @@ struct spa_source *sap_source; uint32_t cleanup_interval; + /* IGMP recovery (triggers when no SAP packets are + * received after the recovery deadline is reached) */ + struct igmp_recovery igmp_recovery; + uint32_t max_sessions; uint32_t n_sessions; struct spa_list sessions; @@ -287,7 +306,7 @@ char *extra_attrs_preamble; char *extra_attrs_end; - char *ptp_mgmt_socket; + char *ptp_mgmt_socket_path; int ptp_fd; uint32_t ptp_seq; uint8_t clock_id8; @@ -321,6 +340,7 @@ return NULL; } +static int start_sap(struct impl *impl); static int send_sap(struct impl *impl, struct session *sess, bool bye); @@ -382,7 +402,7 @@ return false; } -static int make_unix_socket(const char *path) { +static int make_unix_ptp_mgmt_socket(const char *path) { struct sockaddr_un addr; spa_autoclose int fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); @@ -418,7 +438,7 @@ af = src->ss_family; if ((fd = socket(af, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) { - pw_log_error("socket failed: %m"); + pw_log_error("socket() failed: %m"); return -errno; } if (bind(fd, (struct sockaddr*)src, src_len) < 0) { @@ -450,6 +470,9 @@ pw_log_warn("setsockopt(IPV6_MULTICAST_HOPS) failed: %m"); } } + + pw_log_info("sender socket up and running"); + return fd; error: close(fd); @@ -457,7 +480,7 @@ } static int make_recv_socket(struct sockaddr_storage *sa, socklen_t salen, - char *ifname) + char *ifname, struct igmp_recovery *igmp_recovery) { int af, fd, val, res; struct ifreq req; @@ -467,13 +490,13 @@ af = sa->ss_family; if ((fd = socket(af, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)) < 0) { - pw_log_error("socket failed: %m"); + pw_log_error("socket() failed: %m"); return -errno; } val = 1; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)) < 0) { res = -errno; - pw_log_error("setsockopt failed: %m"); + pw_log_error("setsockopt() failed: %m"); goto error; } spa_zero(req); @@ -527,6 +550,16 @@ goto error; } + /* Store multicast info for recovery */ + igmp_recovery->socket_fd = fd; + igmp_recovery->mcast_addr = ba; + igmp_recovery->mcast_len = salen; + igmp_recovery->if_index = req.ifr_ifindex; + igmp_recovery->is_ipv6 = (af == AF_INET6); + pw_log_debug("stored %s multicast info: socket_fd=%d, " + "if_index=%d", igmp_recovery->is_ipv6 ? + "IPv6" : "IPv4", fd, req.ifr_ifindex); + if (bind(fd, (struct sockaddr*)&ba, salen) < 0) { res = -errno; pw_log_error("bind() failed: %m"); @@ -539,6 +572,9 @@ goto error; } } + + pw_log_info("receiver socket up and running"); + return fd; error: close(fd); @@ -547,8 +583,13 @@ static bool update_ts_refclk(struct impl *impl) { - if (!impl->ptp_mgmt_socket || impl->ptp_fd < 0) + if (!impl->ptp_mgmt_socket_path) return false; + if (impl->ptp_fd < 0) { + impl->ptp_fd = make_unix_ptp_mgmt_socket(impl->ptp_mgmt_socket_path); + if (impl->ptp_fd < 0) + return false; + } // Read if something is left in the socket int avail; @@ -580,6 +621,12 @@ if (write(impl->ptp_fd, &req, sizeof(req)) == -1) { pw_log_warn("Failed to send PTP management request: %m"); + if (errno != ENOTCONN) + return false; + close(impl->ptp_fd); + impl->ptp_fd = make_unix_ptp_mgmt_socket(impl->ptp_mgmt_socket_path); + if (impl->ptp_fd > -1) + pw_log_info("Reopened PTP management socket"); return false; } @@ -921,7 +968,98 @@ return res; } -static void on_timer_event(void *data) +static void on_igmp_recovery_timer_event(void *data) +{ + struct impl *impl = data; + char addr128; + int res = 0; + + /* Only attempt recovery if we have a valid socket and multicast address */ + if (impl->igmp_recovery.socket_fd < 0) { + pw_log_debug("no socket, skipping IGMP recovery"); + goto finish; + } + + pw_net_get_ip(&impl->igmp_recovery.mcast_addr, addr, sizeof(addr), NULL, NULL); + pw_log_info("IGMP recovery triggered for %s", addr); + + /* Force IGMP membership refresh by leaving the group first, then rejoin */ + if (impl->igmp_recovery.is_ipv6) { + struct ipv6_mreq mr6; + memset(&mr6, 0, sizeof(mr6)); + mr6.ipv6mr_multiaddr = ((struct sockaddr_in6*)&impl->igmp_recovery.mcast_addr)->sin6_addr; + mr6.ipv6mr_interface = impl->igmp_recovery.if_index; + + /* Leave the group first */ + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mr6, sizeof(mr6)); + if (SPA_LIKELY(res == 0)) { + pw_log_info("left IPv6 multicast group"); + } else { + if (errno == EADDRNOTAVAIL) { + pw_log_info("attempted to leave IPv6 multicast group, but " + "membership was already silently dropped"); + } else { + pw_log_warn("failed to leave IPv6 multicast group: %m"); + } + } + + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mr6, sizeof(mr6)); + if (res < 0) { + pw_log_warn("failed to re-join IPv6 multicast group: %m"); + } else { + pw_log_info("re-joined IPv6 multicast group successfully"); + } + } else { + struct ip_mreqn mr4; + memset(&mr4, 0, sizeof(mr4)); + mr4.imr_multiaddr = ((struct sockaddr_in*)&impl->igmp_recovery.mcast_addr)->sin_addr; + mr4.imr_ifindex = impl->igmp_recovery.if_index; + + /* Leave the group first */ + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, + &mr4, sizeof(mr4)); + if (SPA_LIKELY(res == 0)) { + pw_log_info("left IPv4 multicast group"); + } else { + if (errno == EADDRNOTAVAIL) { + pw_log_info("attempted to leave IPv4 multicast group, but " + "membership was already silently dropped"); + } else { + pw_log_warn("failed to leave IPv4 multicast group: %m"); + } + } + + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mr4, sizeof(mr4)); + if (res < 0) { + pw_log_warn("failed to re-join IPv4 multicast group: %m"); + } else { + pw_log_info("re-joined IPv4 multicast group successfully"); + } + } + +finish: + /* If rejoining failed, try again in 1 second. This can happen + * for example when the network interface went down, and is not + * yet up and running again, and ENODEV is returned as a result. + * Otherwise, continue with the usual deadline. */ + pw_timer_queue_add(impl->timer_queue, &impl->igmp_recovery.timer, + &impl->igmp_recovery.timer.timeout, + ((res == 0) ? impl->igmp_recovery.deadline : 1) * SPA_NSEC_PER_SEC, + on_igmp_recovery_timer_event, impl); +} + +static void rearm_igmp_recovery_timer(struct impl *impl) +{ + pw_timer_queue_cancel(&impl->igmp_recovery.timer); + pw_timer_queue_add(impl->timer_queue, &impl->igmp_recovery.timer, + NULL, impl->igmp_recovery.deadline * SPA_NSEC_PER_SEC, + on_igmp_recovery_timer_event, impl); +} + +static void on_sap_send_timer_event(void *data) { struct impl *impl = data; struct session *sess, *tmp; @@ -955,9 +1093,16 @@ } } - pw_timer_queue_add(impl->timer_queue, &impl->timer, - &impl->timer.timeout, SAP_INTERVAL_SEC * SPA_NSEC_PER_SEC, - on_timer_event, impl); + pw_timer_queue_add(impl->timer_queue, &impl->sap_send_timer, + &impl->sap_send_timer.timeout, SAP_INTERVAL_SEC * SPA_NSEC_PER_SEC, + on_sap_send_timer_event, impl); +} + +static void on_start_sap_retry_timer_event(void *data) +{ + struct impl *impl = data; + pw_log_debug("trying again to start SAP send after previous attempt failed with ENODEV"); + start_sap(impl); } static struct session *session_find(struct impl *impl, const struct sdp_info *info) @@ -1404,7 +1549,7 @@ cstrcspn(c, " ") = '\0'; uint32_t channels; - if (sscanf(c, "%u", &channels) != 1 || channels <= 0 || channels > SPA_AUDIO_MAX_CHANNELS) + if (sscanf(c, "%u", &channels) != 1 || channels <= 0 || channels > MAX_CHANNELS) return 0; c += strcspn(c, "\0"); @@ -1645,23 +1790,70 @@ bufferlen = 0; if ((res = parse_sap(impl, buffer, len)) < 0) pw_log_warn("error parsing SAP: %s", spa_strerror(res)); + + rearm_igmp_recovery_timer(impl); } } static int start_sap(struct impl *impl) { - int fd = -1, res; + int fd = -1, res = 0; char addr128 = "invalid"; - pw_log_info("starting SAP timer"); - if ((res = pw_timer_queue_add(impl->timer_queue, &impl->timer, + pw_log_info("starting SAP send timer"); + /* start_sap() might be called more than once. See the make_recv_socket() + * call below for why that can happen. In such a case, the timer was + * started already. The easiest way of handling it is to just cancel it. + * Such cases are not expected to occur often, so canceling and then + * adding the timer again is acceptable. */ + pw_timer_queue_cancel(&impl->sap_send_timer); + if ((res = pw_timer_queue_add(impl->timer_queue, &impl->sap_send_timer, NULL, SAP_INTERVAL_SEC * SPA_NSEC_PER_SEC, - on_timer_event, impl)) < 0) { - pw_log_error("can't add timer: %s", spa_strerror(res)); + on_sap_send_timer_event, impl)) < 0) { + pw_log_error("can't add SAP send timer: %s", spa_strerror(res)); goto error; } - if ((fd = make_recv_socket(&impl->sap_addr, impl->sap_len, impl->ifname)) < 0) - return fd; + if ((fd = make_recv_socket(&impl->sap_addr, impl->sap_len, impl->ifname, + &(impl->igmp_recovery))) < 0) { + /* If make_recv_socket() tries to create a socket and join to a multicast + * group while the network interfaces are not ready yet to do so + * (usually because a network manager component is still setting up + * those network interfaces), ENODEV will be returned. This is essentially + * a race condition. There is no discernible way to be notified when the + * network interfaces are ready for that operation, so the next best + * approach is to essentially do a form of polling by retrying the + * start_sap() call after some time. The start_sap_retry_timer exists + * precisely for that purpose. This means that ENODEV is not treated as + * an error, but instead, it triggers the creation of that timer. */ + if (fd == -ENODEV) { + pw_log_warn("failed to create receiver socket because network device " + "is not ready and present yet; will try again"); + + pw_timer_queue_cancel(&impl->start_sap_retry_timer); + /* Use a 1-second retry interval. The network interfaces + * are likely to be up and running then. */ + pw_timer_queue_add(impl->timer_queue, &impl->start_sap_retry_timer, + NULL, 1 * SPA_NSEC_PER_SEC, + on_start_sap_retry_timer_event, impl); + + /* It is important to return 0 in this case. Otherwise, the nonzero return + * value will later be propagated through the core as an error. */ + res = 0; + goto finish; + } else { + pw_log_error("failed to create socket: %s", spa_strerror(-fd)); + /* If ENODEV was returned earlier, and the start_sap_retry_timer + * was consequently created, but then a non-ENODEV error occurred, + * the timer must be stopped and removed. */ + pw_timer_queue_cancel(&impl->start_sap_retry_timer); + res = fd; + goto error; + } + } + + /* Cleanup the timer in case ENODEV occurred earlier, and this time, + * the socket creation succeeded. */ + pw_timer_queue_cancel(&impl->start_sap_retry_timer); pw_net_get_ip(&impl->sap_addr, addr, sizeof(addr), NULL, NULL); pw_log_info("starting SAP listener on %s", addr); @@ -1672,11 +1864,15 @@ goto error; } - return 0; + rearm_igmp_recovery_timer(impl); + +finish: + return res; + error: if (fd > 0) close(fd); - return res; + goto finish; } static void node_event_info(void *data, const struct pw_node_info *info) @@ -1806,7 +2002,9 @@ if (impl->core && impl->do_disconnect) pw_core_disconnect(impl->core); - pw_timer_queue_cancel(&impl->timer); + pw_timer_queue_cancel(&impl->sap_send_timer); + pw_timer_queue_cancel(&impl->start_sap_retry_timer); + pw_timer_queue_cancel(&impl->igmp_recovery.timer); if (impl->sap_source) pw_loop_destroy_source(impl->loop, impl->sap_source); @@ -1820,7 +2018,7 @@ free(impl->extra_attrs_preamble); free(impl->extra_attrs_end); - free(impl->ptp_mgmt_socket); + free(impl->ptp_mgmt_socket_path); free(impl->ifname); free(impl); } @@ -1873,6 +2071,9 @@ impl->ptp_fd = -1; spa_list_init(&impl->sessions); + impl->igmp_recovery.socket_fd = -1; + impl->igmp_recovery.if_index = -1; + if (args == NULL) args = ""; @@ -1892,11 +2093,11 @@ impl->ifname = str ? strdup(str) : NULL; str = pw_properties_get(props, "ptp.management-socket"); - impl->ptp_mgmt_socket = str ? strdup(str) : NULL; + impl->ptp_mgmt_socket_path = str ? strdup(str) : NULL; // TODO: support UDP management access as well - if (impl->ptp_mgmt_socket) - impl->ptp_fd = make_unix_socket(impl->ptp_mgmt_socket); + if (impl->ptp_mgmt_socket_path) + impl->ptp_fd = make_unix_ptp_mgmt_socket(impl->ptp_mgmt_socket_path); if ((str = pw_properties_get(props, "sap.ip")) == NULL) str = DEFAULT_SAP_IP; @@ -1908,6 +2109,11 @@ impl->cleanup_interval = pw_properties_get_uint32(impl->props, "sap.cleanup.sec", DEFAULT_CLEANUP_SEC); + /* We will use half of the cleanup interval for IGMP deadline, minimum 1 second */ + impl->igmp_recovery.deadline = SPA_MAX(impl->cleanup_interval / 2, 1u); + pw_log_info("using IGMP deadline of %" PRIu32 " second(s)", + impl->igmp_recovery.deadline); + impl->ttl = pw_properties_get_uint32(props, "net.ttl", DEFAULT_TTL); impl->mcast_loop = pw_properties_get_bool(props, "net.loop", DEFAULT_LOOP); impl->max_sessions = pw_properties_get_uint32(props, "sap.max-sessions", DEFAULT_MAX_SESSIONS);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp-session.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-session.c
Changed
@@ -82,6 +82,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -148,6 +149,7 @@ "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) "\ "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ + "( audio.layout=<layout name, default:"DEFAULT_LAYOUT"> ) " \ "( stream.props= { key=value ... } ) " static const struct spa_dict_item module_info = { @@ -1043,8 +1045,11 @@ if (sess == NULL) goto unknown_ssrc; - if (sess->data_ready && sess->receiving) - rtp_stream_receive_packet(sess->recv, buffer, len); + if (sess->data_ready && sess->receiving) { + uint64_t current_time = rtp_stream_get_nsec(sess->recv); + rtp_stream_receive_packet(sess->recv, buffer, len, + current_time); + } } } return; @@ -1326,6 +1331,12 @@ } else if (spa_streq(key, "channels")) { k = PW_KEY_AUDIO_CHANNELS; mask |= 1<<3; + } else if (spa_streq(key, "position")) { + pw_properties_set(props, + SPA_KEY_AUDIO_POSITION, value); + } else if (spa_streq(key, "layout")) { + pw_properties_set(props, + SPA_KEY_AUDIO_LAYOUT, value); } else if (spa_streq(key, "channelnames")) { pw_properties_set(props, PW_KEY_NODE_CHANNELNAMES, value); @@ -1584,6 +1595,8 @@ txt = avahi_string_list_add_pair(txt, "channels", str); if ((str = pw_properties_get(impl->stream_props, SPA_KEY_AUDIO_POSITION)) != NULL) txt = avahi_string_list_add_pair(txt, "position", str); + if ((str = pw_properties_get(impl->stream_props, SPA_KEY_AUDIO_LAYOUT)) != NULL) + txt = avahi_string_list_add_pair(txt, "layout", str); if ((str = pw_properties_get(impl->stream_props, PW_KEY_NODE_CHANNELNAMES)) != NULL) txt = avahi_string_list_add_pair(txt, "channelnames", str); if (impl->ts_refclk != NULL) { @@ -1699,6 +1712,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp-sink.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-sink.c
Changed
@@ -77,6 +77,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -150,6 +151,7 @@ "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \ "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ + "( audio.layout=<channel layout, default:"DEFAULT_LAYOUT"> ) " \ "( aes67.driver-group=<driver driving the PTP send> ) " \ "( stream.props= { key=value ... } ) " @@ -578,6 +580,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp-source.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp-source.c
Changed
@@ -15,6 +15,7 @@ #include <net/if.h> #include <ctype.h> +#include <spa/utils/atomic.h> #include <spa/utils/hook.h> #include <spa/utils/result.h> #include <spa/utils/ringbuffer.h> @@ -71,6 +72,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_MEDIA_CLASS @@ -156,6 +158,9 @@ PW_LOG_TOPIC(mod_topic, "mod." NAME); #define PW_LOG_TOPIC_DEFAULT mod_topic +#define DEFAULT_IGMP_CHECK_INTERVAL_SEC 5 +#define DEFAULT_IGMP_DEADLINE_SEC 30 + #define DEFAULT_CLEANUP_SEC 60 #define DEFAULT_SOURCE_IP "224.0.0.56" @@ -171,6 +176,7 @@ "( audio.rate=<sample rate, default:"SPA_STRINGIFY(DEFAULT_RATE)"> ) " \ "( audio.channels=<number of channels, default:"SPA_STRINGIFY(DEFAULT_CHANNELS)"> ) " \ "( audio.position=<channel map, default:"DEFAULT_POSITION"> ) " \ + "( audio.layout=<channel layout, default:"DEFAULT_LAYOUT"> ) " \ "( stream.props= { key=value ... } ) " static const struct spa_dict_item module_info = { @@ -180,6 +186,23 @@ { PW_KEY_MODULE_VERSION, PACKAGE_VERSION }, }; +struct igmp_recovery { + struct pw_timer timer; + int socket_fd; + struct sockaddr_storage mcast_addr; + socklen_t mcast_len; + uint32_t if_index; + bool is_ipv6; + /* This is the interval the recovery timer runs at. The timer + * checks at each interval if recovery is required. This value + * is defined by the igmp.check.interval.sec property. */ + uint32_t check_interval; + /* This is the deadline for packets to arrive. If the deadline + * is exceeded, an IGMP recovery is attempted. This value is + * defined by the igmp.deadline.sec property. */ + uint32_t deadline; +}; + struct impl { struct pw_impl_module *module; struct spa_hook module_listener; @@ -201,6 +224,15 @@ bool always_process; uint32_t cleanup_interval; + /* IGMP recovery (triggers when no RTP packets are + * received after the recovery deadline is reached) */ + struct igmp_recovery igmp_recovery; + + /* Monotonic timestamp of the last time a packet was + * received. This is accessed with atomic accessors + * to avoid race conditions. */ + uint64_t last_packet_time; + struct pw_timer standby_timer; /* This timer is used when the first stream_start() call fails because * of an ENODEV error (see the stream_start() code for details) */ @@ -227,13 +259,6 @@ bool waiting; }; -static inline uint64_t get_time_ns(void) -{ - struct timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - return SPA_TIMESPEC_TO_NSEC(&ts); -} - static int do_start(struct spa_loop *loop, bool async, uint32_t seq, const void *data, size_t size, void *user_data) { @@ -261,6 +286,9 @@ struct impl *impl = data; ssize_t len; int suppressed; + uint64_t current_time; + + current_time = rtp_stream_get_nsec(impl->stream); if (mask & SPA_IO_IN) { if ((len = recv(fd, impl->buffer, impl->buffer_size, 0)) < 0) @@ -270,10 +298,17 @@ goto short_packet; if (SPA_LIKELY(impl->stream)) { - if (rtp_stream_receive_packet(impl->stream, impl->buffer, len) < 0) + if (rtp_stream_receive_packet(impl->stream, impl->buffer, len, + current_time) < 0) goto receive_error; } + /* Update last packet timestamp for IGMP recovery. + * The recovery timer will check this to see if recovery + * is necessary. Do this _before_ invoking do_start() + * in case the stream is waking up from standby. */ + SPA_ATOMIC_STORE(impl->last_packet_time, current_time); + if (SPA_ATOMIC_LOAD(impl->state) != STATE_RECEIVING) { if (!SPA_ATOMIC_CAS(impl->state, STATE_PROBE, STATE_RECEIVING)) { if (SPA_ATOMIC_CAS(impl->state, STATE_IDLE, STATE_RECEIVING)) @@ -284,17 +319,148 @@ return; receive_error: - if ((suppressed = spa_ratelimit_test(&impl->rate_limit, get_time_ns())) >= 0) + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, current_time)) >= 0) pw_log_warn("(%d suppressed) recv() error: %m", suppressed); return; short_packet: - if ((suppressed = spa_ratelimit_test(&impl->rate_limit, get_time_ns())) >= 0) + if ((suppressed = spa_ratelimit_test(&impl->rate_limit, current_time)) >= 0) pw_log_warn("(%d suppressed) short packet of len %zd received", suppressed, len); return; } -static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname) +static int rejoin_igmp_group(struct spa_loop *loop, bool async, uint32_t seq, + const void *data, size_t size, void *user_data) +{ + /* IMPORTANT: This must be run from within the data loop. */ + + int res; + struct impl *impl = user_data; + uint64_t current_time; + + /* Force IGMP membership refresh by leaving the group first, then rejoin */ + if (impl->igmp_recovery.is_ipv6) { + struct ipv6_mreq mr6; + memset(&mr6, 0, sizeof(mr6)); + mr6.ipv6mr_multiaddr = ((struct sockaddr_in6*)&impl->igmp_recovery.mcast_addr)->sin6_addr; + mr6.ipv6mr_interface = impl->igmp_recovery.if_index; + + /* Leave the group first */ + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, + &mr6, sizeof(mr6)); + if (SPA_LIKELY(res == 0)) { + pw_log_info("left IPv6 multicast group"); + } else { + if (errno == EADDRNOTAVAIL) { + pw_log_info("attempted to leave IPv6 multicast group, but " + "membership was already silently dropped"); + } else { + pw_log_warn("failed to leave IPv6 multicast group: %m"); + } + } + + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, + &mr6, sizeof(mr6)); + if (res < 0) { + pw_log_warn("failed to re-join IPv6 multicast group: %m"); + } else { + pw_log_info("re-joined IPv6 multicast group successfully"); + } + } else { + struct ip_mreqn mr4; + memset(&mr4, 0, sizeof(mr4)); + mr4.imr_multiaddr = ((struct sockaddr_in*)&impl->igmp_recovery.mcast_addr)->sin_addr; + mr4.imr_ifindex = impl->igmp_recovery.if_index; + + /* Leave the group first */ + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, + &mr4, sizeof(mr4)); + if (SPA_LIKELY(res == 0)) { + pw_log_info("left IPv4 multicast group"); + } else { + if (errno == EADDRNOTAVAIL) { + pw_log_info("attempted to leave IPv4 multicast group, but " + "membership was already silently dropped"); + } else { + pw_log_warn("failed to leave IPv4 multicast group: %m"); + } + } + + res = setsockopt(impl->igmp_recovery.socket_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, + &mr4, sizeof(mr4)); + if (res < 0) { + pw_log_warn("failed to re-join IPv4 multicast group: %m"); + } else { + pw_log_info("re-joined IPv4 multicast group successfully"); + } + } + + current_time = rtp_stream_get_nsec(impl->stream); + SPA_ATOMIC_STORE(impl->last_packet_time, current_time); + + return res; +} + +static void on_igmp_recovery_timer_event(void *data) +{ + int res; + struct impl *impl = data; + char addr128; + uint64_t current_time, elapsed_seconds, last_packet_time; + + /* Only attempt recovery if we have a valid socket and multicast address */ + if (SPA_UNLIKELY(impl->igmp_recovery.socket_fd < 0)) { + pw_log_trace("no socket, skipping IGMP recovery"); + goto finish; + } + + /* This check if performed even if standby = false or + * receiving != STATE_RECEIVING , because the very reason + * for these states may be that the receiver socket was + * silently kicked out of the IGMP group (which causes data + * to no longer arrive, thus leading to these states). */ + + current_time = rtp_stream_get_nsec(impl->stream); + last_packet_time = SPA_ATOMIC_LOAD(impl->last_packet_time); + elapsed_seconds = (current_time - last_packet_time) / SPA_NSEC_PER_SEC; + + /* Only trigger recovery if enough time has elapsed since last packet */ + if (elapsed_seconds < impl->igmp_recovery.deadline) { + pw_log_trace("IGMP recovery check: %" PRIu64 " seconds elapsed, " + "need %" PRIu32 " seconds", elapsed_seconds, + impl->igmp_recovery.deadline); + goto finish; + } + + pw_net_get_ip(&impl->igmp_recovery.mcast_addr, addr, sizeof(addr), NULL, NULL); + pw_log_info("starting IGMP recovery for %s", addr); + + /* Run the actual recovery in the data loop, since recovery involves + * rejoining the socket to the IGMP group. By running this in the + * data loop, race conditions due to stray packets causing an on_rtp_io() + * invocation at the same time when the IGMP group rejoining takes place + * is avoided, since on_rtp_io() too runs in the data loop. + * This is a blocking call to make sure the rejoin attempt was fully + * done by the time this callback ends. (rejoin_igmp_group() does not + * do work that takes a long time to finish. )*/ + res = pw_loop_locked(impl->data_loop, rejoin_igmp_group, 1, NULL, 0, impl); + + if (SPA_LIKELY(res == 0)) { + pw_log_info("IGMP recovery for %s finished", addr); + } else { + pw_log_error("error while finishing IGMP recovery for %s: %s", + addr, spa_strerror(res)); + } + +finish: + pw_timer_queue_add(impl->timer_queue, &impl->igmp_recovery.timer, + &impl->igmp_recovery.timer.timeout, + impl->igmp_recovery.check_interval * SPA_NSEC_PER_SEC, + on_igmp_recovery_timer_event, impl); +} + +static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname, + struct igmp_recovery *igmp_recovery) { int af, fd, val, res; struct ifreq req; @@ -374,6 +540,16 @@ goto error; } + /* Store multicast info for recovery */ + igmp_recovery->socket_fd = fd; + igmp_recovery->mcast_addr = ba; + igmp_recovery->mcast_len = salen; + igmp_recovery->if_index = req.ifr_ifindex; + igmp_recovery->is_ipv6 = (af == AF_INET6); + pw_log_debug("stored %s multicast info: socket_fd=%d, " + "if_index=%d", igmp_recovery->is_ipv6 ? + "IPv6" : "IPv4", fd, req.ifr_ifindex); + if (bind(fd, (struct sockaddr*)&ba, salen) < 0) { res = -errno; pw_log_error("bind() failed: %m"); @@ -422,7 +598,8 @@ pw_log_info("starting RTP listener"); if ((fd = make_socket((const struct sockaddr *)&impl->src_addr, - impl->src_len, impl->ifname)) < 0) { + impl->src_len, impl->ifname, + &(impl->igmp_recovery))) < 0) { /* If make_socket() tries to create a socket and join to a multicast * group while the network interfaces are not ready yet to do so * (usually because a network manager component is still setting up @@ -433,7 +610,7 @@ * stream_start() call after some time. The stream_start_retry_timer exists * precisely for that purpose. This means that ENODEV is not treated as * an error, but instead, it triggers the creation of that timer. */ - if (errno == ENODEV) { + if (fd == -ENODEV) { pw_log_warn("failed to create socket because network device is not ready " "and present yet; will try again"); @@ -449,12 +626,12 @@ res = 0; goto finish; } else { - pw_log_error("failed to create socket: %m"); + pw_log_error("failed to create socket: %s", spa_strerror(fd)); /* If ENODEV was returned earlier, and the stream_start_retry_timer * was consequently created, but then a non-ENODEV error occurred, * the timer must be stopped and removed. */ pw_timer_queue_cancel(&impl->stream_start_retry_timer); - res = -errno; + res = fd; goto finish; } } @@ -472,6 +649,13 @@ goto finish; } + if ((res = pw_timer_queue_add(impl->timer_queue, &impl->igmp_recovery.timer, + NULL, impl->igmp_recovery.check_interval * SPA_NSEC_PER_SEC, + on_igmp_recovery_timer_event, impl)) < 0) { + pw_log_error("can't add timer: %s", spa_strerror(res)); + goto finish; + } + finish: if (res != 0) { pw_log_error("failed to start RTP stream: %s", spa_strerror(res)); @@ -495,6 +679,7 @@ pw_log_info("stopping RTP listener"); pw_timer_queue_cancel(&impl->stream_start_retry_timer); + pw_timer_queue_cancel(&impl->igmp_recovery.timer); pw_loop_destroy_source(impl->data_loop, impl->source); impl->source = NULL; @@ -633,6 +818,7 @@ pw_timer_queue_cancel(&impl->standby_timer); pw_timer_queue_cancel(&impl->stream_start_retry_timer); + pw_timer_queue_cancel(&impl->igmp_recovery.timer); if (impl->data_loop) pw_context_release_loop(impl->context, impl->data_loop); @@ -739,6 +925,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION); @@ -797,9 +984,20 @@ * till we make it (or get timed out) */ pw_properties_set(stream_props, "rtp.receiving", "true"); - impl->cleanup_interval = pw_properties_get_uint32(props, + impl->cleanup_interval = pw_properties_get_uint32(stream_props, "cleanup.sec", DEFAULT_CLEANUP_SEC); + impl->igmp_recovery.check_interval = SPA_MAX(pw_properties_get_uint32(stream_props, + "igmp.check.interval.sec", + DEFAULT_IGMP_CHECK_INTERVAL_SEC), 1u); + pw_log_info("using IGMP check interval of %" PRIu32 " second(s)", + impl->igmp_recovery.check_interval); + + impl->igmp_recovery.deadline = SPA_MAX(pw_properties_get_uint32(stream_props, + "igmp.deadline.sec", DEFAULT_IGMP_DEADLINE_SEC), 5u); + pw_log_info("using IGMP deadline of %" PRIu32 " second(s)", + impl->igmp_recovery.deadline); + impl->core = pw_context_get_object(impl->context, PW_TYPE_INTERFACE_Core); if (impl->core == NULL) { str = pw_properties_get(props, PW_KEY_REMOTE_NAME);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp/audio.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp/audio.c
Changed
@@ -233,7 +233,8 @@ pw_stream_queue_buffer(impl->stream, buf); } -static int rtp_audio_receive(struct impl *impl, uint8_t *buffer, ssize_t len) +static int rtp_audio_receive(struct impl *impl, uint8_t *buffer, ssize_t len, + uint64_t current_time) { struct rtp_header *hdr; ssize_t hlen, plen; @@ -273,7 +274,7 @@ timestamp = ntohl(hdr->timestamp) - impl->ts_offset; impl->receiving = true; - impl->last_recv_timestamp = pw_stream_get_nsec(impl->stream); + impl->last_recv_timestamp = current_time; plen = len - hlen; samples = plen / stride;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp/midi.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp/midi.c
Changed
@@ -318,7 +318,8 @@ return 0; } -static int rtp_midi_receive(struct impl *impl, uint8_t *buffer, ssize_t len) +static int rtp_midi_receive(struct impl *impl, uint8_t *buffer, ssize_t len, + uint64_t current_time) { struct rtp_header *hdr; ssize_t hlen;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp/opus.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp/opus.c
Changed
@@ -99,7 +99,8 @@ pw_stream_queue_buffer(impl->stream, buf); } -static int rtp_opus_receive(struct impl *impl, uint8_t *buffer, ssize_t len) +static int rtp_opus_receive(struct impl *impl, uint8_t *buffer, ssize_t len, + uint64_t current_time) { struct rtp_header *hdr; ssize_t hlen, plen; @@ -334,9 +335,12 @@ static int rtp_opus_init(struct impl *impl, enum spa_direction direction) { int err; - unsigned char mappingSPA_AUDIO_MAX_CHANNELS; + unsigned char mapping255; uint32_t i; + if (impl->info.info.opus.channels > 255) + return -EINVAL; + if (impl->psamples >= 2880) impl->psamples = 2880; else if (impl->psamples >= 1920)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp/stream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp/stream.c
Changed
@@ -151,7 +151,8 @@ * access below for the reason why. */ uint8_t timer_running; - int (*receive_rtp)(struct impl *impl, uint8_t *buffer, ssize_t len); + int (*receive_rtp)(struct impl *impl, uint8_t *buffer, ssize_t len, + uint64_t current_time); /* Used for resetting the ring buffer before the stream starts, to prevent * reading from uninitialized memory. This can otherwise happen in direct * timestamp mode when the read index is set to an uninitialized location. @@ -569,9 +570,9 @@ return NULL; } -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -580,6 +581,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -675,7 +677,10 @@ switch (impl->info.media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - parse_audio_info(props, &impl->info.info.raw); + if ((res = parse_audio_info(props, &impl->info.info.raw)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + goto out; + } impl->stream_info = impl->info; impl->format_info = find_audio_format_info(&impl->info); if (impl->format_info == NULL) { @@ -704,7 +709,10 @@ case SPA_MEDIA_SUBTYPE_opus: impl->stream_info.media_type = SPA_MEDIA_TYPE_audio; impl->stream_info.media_subtype = SPA_MEDIA_SUBTYPE_raw; - parse_audio_info(props, &impl->stream_info.info.raw); + if ((res = parse_audio_info(props, &impl->stream_info.info.raw)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + goto out; + } impl->stream_info.info.raw.format = SPA_AUDIO_FORMAT_F32; impl->info.info.opus.rate = impl->stream_info.info.raw.rate; impl->info.info.opus.channels = impl->stream_info.info.raw.channels; @@ -1030,10 +1038,17 @@ return pw_stream_update_properties(impl->stream, dict); } -int rtp_stream_receive_packet(struct rtp_stream *s, uint8_t *buffer, size_t len) +int rtp_stream_receive_packet(struct rtp_stream *s, uint8_t *buffer, size_t len, + uint64_t current_time) +{ + struct impl *impl = (struct impl*)s; + return impl->receive_rtp(impl, buffer, len, current_time); +} + +uint64_t rtp_stream_get_nsec(struct rtp_stream *s) { struct impl *impl = (struct impl*)s; - return impl->receive_rtp(impl, buffer, len); + return pw_stream_get_nsec(impl->stream); } uint64_t rtp_stream_get_time(struct rtp_stream *s, uint32_t *rate)
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-rtp/stream.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-rtp/stream.h
Changed
@@ -15,6 +15,7 @@ #define DEFAULT_RATE 48000 #define DEFAULT_CHANNELS 2 #define DEFAULT_POSITION " FL FR " +#define DEFAULT_LAYOUT "Stereo" #define ERROR_MSEC 2.0f #define DEFAULT_SESS_LATENCY 100.0f @@ -62,7 +63,10 @@ int rtp_stream_update_properties(struct rtp_stream *s, const struct spa_dict *dict); -int rtp_stream_receive_packet(struct rtp_stream *s, uint8_t *buffer, size_t len); +int rtp_stream_receive_packet(struct rtp_stream *s, uint8_t *buffer, size_t len, + uint64_t current_time); + +uint64_t rtp_stream_get_nsec(struct rtp_stream *s); uint64_t rtp_stream_get_time(struct rtp_stream *s, uint32_t *rate);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-snapcast-discover.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-snapcast-discover.c
Changed
@@ -503,9 +503,11 @@ return -ENOENT; } -static void parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + int res; + + if ((res = spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -514,12 +516,15 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, - SPA_KEY_AUDIO_POSITION, NULL); + SPA_KEY_AUDIO_LAYOUT, + SPA_KEY_AUDIO_POSITION, NULL)) < 0) + return res; pw_properties_set(props, PW_KEY_AUDIO_FORMAT, spa_type_audio_format_to_short_name(info->format)); pw_properties_setf(props, PW_KEY_AUDIO_RATE, "%d", info->rate); pw_properties_setf(props, PW_KEY_AUDIO_CHANNELS, "%d", info->channels); + return res; } static int create_stream(struct impl *impl, struct pw_properties *props, @@ -545,7 +550,10 @@ if ((str = pw_properties_get(props, "capture.props")) == NULL) pw_properties_set(props, "capture.props", "{ media.class = Audio/Sink }"); - parse_audio_info(props, &t->audio_info); + if ((res = parse_audio_info(props, &t->audio_info)) < 0) { + pw_log_error("Can't parse format: %s", spa_strerror(res)); + goto done; + } if ((f = open_memstream(&args, &size)) == NULL) { res = -errno;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-vban-recv.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-vban-recv.c
Changed
@@ -75,6 +75,7 @@ * Options with well-known behavior: * * - \ref PW_KEY_REMOTE_NAME + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_MEDIA_NAME * - \ref PW_KEY_MEDIA_CLASS @@ -694,6 +695,7 @@ pw_properties_update_string(stream_props, str, strlen(str)); copy_props(impl, props, PW_KEY_NODE_LOOP_NAME); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-vban-send.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-vban-send.c
Changed
@@ -68,6 +68,7 @@ * - \ref PW_KEY_AUDIO_FORMAT * - \ref PW_KEY_AUDIO_RATE * - \ref PW_KEY_AUDIO_CHANNELS + * - \ref SPA_KEY_AUDIO_LAYOUT * - \ref SPA_KEY_AUDIO_POSITION * - \ref PW_KEY_NODE_NAME * - \ref PW_KEY_NODE_DESCRIPTION @@ -417,6 +418,7 @@ copy_props(impl, props, PW_KEY_AUDIO_FORMAT); copy_props(impl, props, PW_KEY_AUDIO_RATE); copy_props(impl, props, PW_KEY_AUDIO_CHANNELS); + copy_props(impl, props, SPA_KEY_AUDIO_LAYOUT); copy_props(impl, props, SPA_KEY_AUDIO_POSITION); copy_props(impl, props, PW_KEY_NODE_NAME); copy_props(impl, props, PW_KEY_NODE_DESCRIPTION);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-vban/stream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-vban/stream.c
Changed
@@ -185,9 +185,9 @@ return NULL; } -static void parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) +static int parse_audio_info(const struct pw_properties *props, struct spa_audio_info_raw *info) { - spa_audio_info_raw_init_dict_keys(info, + return spa_audio_info_raw_init_dict_keys(info, &SPA_DICT_ITEMS( SPA_DICT_ITEM(SPA_KEY_AUDIO_FORMAT, DEFAULT_FORMAT), SPA_DICT_ITEM(SPA_KEY_AUDIO_RATE, SPA_STRINGIFY(DEFAULT_RATE)), @@ -196,6 +196,7 @@ SPA_KEY_AUDIO_FORMAT, SPA_KEY_AUDIO_RATE, SPA_KEY_AUDIO_CHANNELS, + SPA_KEY_AUDIO_LAYOUT, SPA_KEY_AUDIO_POSITION, NULL); } @@ -274,9 +275,14 @@ switch (impl->info.media_subtype) { case SPA_MEDIA_SUBTYPE_raw: - parse_audio_info(props, &impl->info.info.raw); - if (SPA_FLAG_IS_SET(impl->info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED)) + if ((res = parse_audio_info(props, &impl->info.info.raw)) < 0) { + pw_log_error("can't parse format: %s", spa_strerror(res)); + goto out; + } + if (SPA_FLAG_IS_SET(impl->info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED)) { default_layout(impl->info.info.raw.channels, impl->info.info.raw.position); + SPA_FLAG_CLEAR(impl->info.info.raw.flags, SPA_AUDIO_FLAG_UNPOSITIONED); + } impl->stream_info = impl->info; impl->format_info = find_audio_format_info(&impl->info); if (impl->format_info == NULL) {
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/modules/module-zeroconf-discover.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/modules/module-zeroconf-discover.c
Changed
@@ -188,17 +188,17 @@ else if (spa_streq(key, "channel_map")) { struct channel_map channel_map; uint32_t i, posCHANNELS_MAX; - char *p, *s; + char *p, *s, buf8; spa_zero(channel_map); channel_map_parse(value, &channel_map); - channel_map_to_positions(&channel_map, pos); + channel_map_to_positions(&channel_map, pos, CHANNELS_MAX); p = s = alloca(4 + channel_map.channels * 8); p += spa_scnprintf(p, 2, ""); for (i = 0; i < channel_map.channels; i++) p += spa_scnprintf(p, 8, "%s%s", i == 0 ? "" : ",", - channel_id2name(posi)); + channel_id2name(posi, buf, sizeof(buf))); p += spa_scnprintf(p, 2, ""); pw_properties_set(props, SPA_KEY_AUDIO_POSITION, s); }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/data-loop.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/data-loop.c
Changed
@@ -110,6 +110,7 @@ } this->loop = loop; this->rt_prio = -1; + this->reset_on_fork = true; if (props != NULL) { if ((str = spa_dict_lookup(props, PW_KEY_LOOP_CANCEL)) != NULL) @@ -122,6 +123,8 @@ name = str; if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_AFFINITY)) != NULL) this->affinity = strdup(str); + if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_RESET_ON_FORK)) != NULL) + this->reset_on_fork = spa_atob(str); } if (class == NULL) class = this->rt_prio != 0 ? "data.rt" : "data"; @@ -236,7 +239,7 @@ if (!loop->running) { struct spa_thread_utils *utils; struct spa_thread *thr; - struct spa_dict_item items2; + struct spa_dict_item items3; uint32_t n_items = 0; loop->running = true; @@ -248,6 +251,8 @@ if (loop->affinity) itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_THREAD_AFFINITY, loop->affinity); + itemsn_items++ = SPA_DICT_ITEM_INIT(SPA_KEY_THREAD_RESET_ON_FORK, + loop->reset_on_fork ? "true" : "false"); thr = spa_thread_utils_create(utils, &SPA_DICT_INIT(items, n_items), do_loop, loop); loop->thread = (pthread_t)thr;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/impl-port.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/impl-port.c
Changed
@@ -1874,11 +1874,10 @@ tag = other->tagother->direction; if (tag) { void *state = NULL; - while (spa_tag_parse(tag, &info, &state) == 1) { + while (spa_tag_parse(tag, &info, &state) == 1) spa_tag_build_add_info(&b.b, info.info); - count++; - } } + count++; } } else { spa_list_for_each(l, &port->links, input_link) { @@ -1886,11 +1885,10 @@ tag = other->tagother->direction; if (tag) { void *state = NULL; - while (spa_tag_parse(tag, &info, &state) == 1) { + while (spa_tag_parse(tag, &info, &state) == 1) spa_tag_build_add_info(&b.b, info.info); - count++; - } } + count++; } } param = count == 0 ? NULL : spa_tag_build_end(&b.b, &f);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/private.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/private.h
Changed
@@ -431,6 +431,7 @@ char *class; char **classes; int rt_prio; + bool reset_on_fork; struct spa_hook_list listener_list; struct spa_thread_utils *thread_utils;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/properties.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/properties.c
Changed
@@ -252,7 +252,8 @@ continue; } /* item changed or added, apply changes later */ - if ((errno = -add_item(&changes, key, false, val, true) < 0)) { + if ((res = add_item(&changes, key, false, val, true)) < 0) { + errno = -res; it0.state = SPA_JSON_ERROR_FLAG; break; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/settings.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/settings.c
Changed
@@ -245,24 +245,21 @@ static void expose_settings(struct pw_context *context, struct pw_impl_metadata *metadata) { struct settings *s = &context->settings; - uint32_t i, o; - char ratesMAX_RATES*16 = ""; + uint32_t i; + char ratesMAX_RATES*16; + struct spa_strbuf b; pw_impl_metadata_set_propertyf(metadata, PW_ID_CORE, "log.level", "", "%d", s->log_level); pw_impl_metadata_set_propertyf(metadata, PW_ID_CORE, "clock.rate", "", "%d", s->clock_rate); - for (i = 0, o = 0; i < s->n_clock_rates; i++) { - int r = snprintf(rates+o, sizeof(rates)-o, "%s%d", i == 0 ? "" : ", ", + + spa_strbuf_init(&b, rates, sizeof(rates)); + for (i = 0; i < s->n_clock_rates; i++) + spa_strbuf_append(&b, "%s%d", i == 0 ? "" : ", ", s->clock_ratesi); - if (r < 0 || o + r >= (int)sizeof(rates)) { - snprintf(rates, sizeof(rates), "%d", s->clock_rate); - break; - } - o += r; - } if (s->n_clock_rates == 0) - snprintf(rates, sizeof(rates), "%d", s->clock_rate); + spa_strbuf_append(&b, "%d", s->clock_rate); pw_impl_metadata_set_propertyf(metadata, PW_ID_CORE, "clock.allowed-rates", "", " %s ", rates);
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/stream.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/stream.c
Changed
@@ -1270,6 +1270,9 @@ return 0; c = calloc(1, sizeof(*c) + SPA_POD_SIZE(param)); + if (c == NULL) + return -errno; + c->info = SPA_PTROFF(c, sizeof(*c), struct spa_pod); memcpy(c->info, param, SPA_POD_SIZE(param)); c->control.n_values = 0; @@ -1286,7 +1289,7 @@ } pod = spa_pod_get_values(type, &n_vals, &choice); - if (n_vals == 0) { + if (n_vals < 1) { free(c); return -EINVAL; } @@ -1318,19 +1321,12 @@ switch (choice) { case SPA_CHOICE_None: - if (n_vals < 1) { - free(c); - return -EINVAL; - } c->control.n_values = 1; c->control.max_values = 1; c->control.values0 = c->control.def = c->control.min = c->control.max = vals0; break; case SPA_CHOICE_Range: - if (n_vals < 3) { - free(c); - return -EINVAL; - } + case SPA_CHOICE_Step: c->control.n_values = 1; c->control.max_values = 1; c->control.values0 = vals0;
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/thread.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/thread.c
Changed
@@ -92,8 +92,10 @@ pthread_t pt; pthread_attr_t *attr = NULL, attributes; const char *str; - int err; + int err, old_policy, new_policy; int (*create_func)(pthread_t *, const pthread_attr_t *attr, void *(*start)(void*), void *) = NULL; + struct sched_param sp; + bool reset_on_fork = true; attr = pw_thread_fill_attr(props, &attributes); @@ -118,7 +120,16 @@ if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_AFFINITY)) != NULL && (err = thread_setaffinity(pt, str)) != 0) pw_log_warn("pthread_setaffinity error: %s", strerror(-err)); + if ((str = spa_dict_lookup(props, SPA_KEY_THREAD_RESET_ON_FORK)) != NULL) + reset_on_fork = spa_atob(str); } + + pthread_getschedparam(pt, &old_policy, &sp); + new_policy = old_policy; + SPA_FLAG_UPDATE(new_policy, SCHED_RESET_ON_FORK, reset_on_fork); + if (old_policy != new_policy) + pthread_setschedparam(pt, new_policy, &sp); + return (struct spa_thread*)pt; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/pipewire/utils.h -> _service:download_files:pipewire-1.5.83.tar.bz2/src/pipewire/utils.h
Changed
@@ -12,6 +12,7 @@ # include <sys/mount.h> #endif #include <errno.h> +#include <sys/types.h> #include <spa/utils/cleanup.h> #include <spa/utils/defs.h>
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/tools/pw-cat.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/tools/pw-cat.c
Changed
@@ -70,6 +70,8 @@ #define DEFAULT_VOLUME 1.0 #define DEFAULT_QUALITY 4 +#define MAX_CHANNELS SPA_AUDIO_MAX_CHANNELS + enum mode { mode_none, mode_playback, @@ -91,7 +93,7 @@ struct channelmap { uint32_t n_channels; - uint32_t channelsSPA_AUDIO_MAX_CHANNELS; + uint32_t channelsMAX_CHANNELS; }; struct data { @@ -702,7 +704,8 @@ } } - spa_audio_parse_position(channel_map, strlen(channel_map), map->channels, &map->n_channels); + spa_audio_parse_position_n(channel_map, strlen(channel_map), + map->channels, SPA_N_ELEMENTS(map->channels), &map->n_channels); return 0; } @@ -744,10 +747,11 @@ static void channelmap_print(struct channelmap *map) { uint32_t i; - + char pos8; for (i = 0; i < map->n_channels; i++) { - const char *name = spa_type_audio_channel_to_short_name(map->channelsi); - fprintf(stderr, "%s%s", name, i + 1 < map->n_channels ? "," : ""); + fprintf(stderr, "%s%s", i ? "," : "", + spa_type_audio_channel_make_short_name(map->channelsi, + pos, sizeof(pos), "UNK")); } } @@ -2344,9 +2348,23 @@ .rate = data.rate, .channels = data.channels); - if (data.channelmap.n_channels) - memcpy(info.position, data.channelmap.channels, data.channels * sizeof(int)); - + if (data.channels > MAX_CHANNELS) { + fprintf(stderr, "error: too many channels %d > %d\n", + data.channels, MAX_CHANNELS); + goto error_bad_file; + } + if (data.channelmap.n_channels) { + if (data.channels > MAX_CHANNELS) { + fprintf(stderr, "error: too many channels in channelmap %d > %d\n", + data.channelmap.n_channels, MAX_CHANNELS); + goto error_bad_file; + } + uint32_t i; + for (i = 0; i < data.channelmap.n_channels; i++) + info.positioni = data.channelmap.channelsi; + for (; i < data.channels; i++) + info.positioni = SPA_AUDIO_CHANNEL_AUX0 + i; + } paramsn_params++ = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info); break; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/src/tools/pw-link.c -> _service:download_files:pipewire-1.5.83.tar.bz2/src/tools/pw-link.c
Changed
@@ -871,6 +871,7 @@ " -o, --output List output ports\n" " -i, --input List input ports\n" " -l, --links List links\n" + " -t, --latency List port latencies\n" " -m, --monitor Monitor links and ports\n" " -I, --id List IDs\n" " -v, --verbose Verbose port properties\n"
View file
_service:download_files:pipewire-1.5.81.tar.bz2/test/meson.build -> _service:download_files:pipewire-1.5.83.tar.bz2/test/meson.build
Changed
@@ -112,6 +112,7 @@ executable('test-spa', 'test-spa-buffer.c', 'test-spa-control.c', + 'test-spa-format.c', 'test-spa-json.c', 'test-spa-utils.c', 'test-spa-log.c',
View file
_service:download_files:pipewire-1.5.83.tar.bz2/test/test-spa-format.c
Added
@@ -0,0 +1,129 @@ +/* Simple Plugin API */ +/* SPDX-FileCopyrightText: Copyright © 2025 Pauli Virtanen */ +/* SPDX-License-Identifier: MIT */ + +#include <spa/param/audio/format-utils.h> +#include <spa/param/audio/format.h> + +#include "pwtest.h" + +PWTEST(audio_format_sizes) +{ + union { + uint8_t buf1024; + struct spa_audio_info align; + } data; + struct spa_audio_info info; + size_t i; + + memset(&info, 0xf3, sizeof(info)); + info.media_type = SPA_MEDIA_TYPE_audio; + info.media_subtype = SPA_MEDIA_SUBTYPE_raw; + info.info.raw.channels = 5; + info.info.raw.format = SPA_AUDIO_FORMAT_F32P; + info.info.raw.rate = 12345; + info.info.raw.flags = 0; + info.info.raw.position0 = 1; + info.info.raw.position1 = 2; + info.info.raw.position2 = 3; + info.info.raw.position3 = 4; + info.info.raw.position4 = 5; + + for (i = 0; i < sizeof(data.buf); ++i) { + struct spa_pod *pod; + uint8_t buf4096; + struct spa_pod_builder b; + + spa_pod_builder_init(&b, buf, sizeof(buf)); + memcpy(data.buf, &info, sizeof(info)); + + pod = spa_format_audio_ext_build(&b, 123, (void *)data.buf, i); + if (i < offsetof(struct spa_audio_info, info.raw) + + offsetof(struct spa_audio_info_raw, position)) + pwtest_bool_true(!pod); + else + pwtest_bool_true(pod); + } + + for (i = 0; i < sizeof(data.buf); ++i) { + struct spa_pod *pod; + uint8_t buf4096; + struct spa_pod_builder b; + int ret; + + spa_pod_builder_init(&b, buf, sizeof(buf)); + pod = spa_format_audio_ext_build(&b, 123, &info, sizeof(info)); + pwtest_bool_true(pod); + + memset(data.buf, 0xf3, sizeof(data.buf)); + + ret = spa_format_audio_ext_parse(pod, (void *)data.buf, i); + if (i < offsetof(struct spa_audio_info, info.raw) + + offsetof(struct spa_audio_info_raw, position) + + info.info.raw.channels*sizeof(uint32_t)) { + for (size_t j = i; j < sizeof(data.buf); ++j) + pwtest_int_eq(data.bufj, 0xf3); + pwtest_int_lt(ret, 0); + } else { + pwtest_int_ge(ret, 0); + pwtest_bool_true(memcmp(data.buf, &info, SPA_MIN(i, sizeof(info))) == 0); + } + } + + memset(&info, 0xf3, sizeof(info)); + info.media_type = SPA_MEDIA_TYPE_audio; + info.media_subtype = SPA_MEDIA_SUBTYPE_aac; + info.info.aac.rate = 12345; + info.info.aac.channels = 6; + info.info.aac.bitrate = 54321; + info.info.aac.stream_format = SPA_AUDIO_AAC_STREAM_FORMAT_MP4LATM; + + for (i = 0; i < sizeof(data.buf); ++i) { + struct spa_pod *pod; + uint8_t buf4096; + struct spa_pod_builder b; + + spa_pod_builder_init(&b, buf, sizeof(buf)); + memcpy(data.buf, &info, sizeof(info)); + + pod = spa_format_audio_ext_build(&b, 123, (void *)data.buf, i); + if (i < offsetof(struct spa_audio_info, info.raw) + + sizeof(struct spa_audio_info_aac)) + pwtest_bool_true(!pod); + else + pwtest_bool_true(pod); + } + + for (i = 0; i < sizeof(data.buf); ++i) { + struct spa_pod *pod; + uint8_t buf4096; + struct spa_pod_builder b; + int ret; + + spa_pod_builder_init(&b, buf, sizeof(buf)); + pod = spa_format_audio_ext_build(&b, 123, &info, sizeof(info)); + pwtest_bool_true(pod); + + memset(data.buf, 0xf3, sizeof(data.buf)); + + ret = spa_format_audio_ext_parse(pod, (void *)data.buf, i); + if (i < offsetof(struct spa_audio_info, info.raw) + + sizeof(struct spa_audio_info_aac)) { + for (size_t j = i; j < sizeof(data.buf); ++j) + pwtest_int_eq(data.bufj, 0xf3); + pwtest_int_lt(ret, 0); + } else { + pwtest_int_ge(ret, 0); + pwtest_bool_true(memcmp(data.buf, &info, SPA_MIN(i, sizeof(info))) == 0); + } + } + + return PWTEST_PASS; +} + +PWTEST_SUITE(spa_format) +{ + pwtest_add(audio_format_sizes, PWTEST_NOARG); + + return PWTEST_PASS; +}
View file
_service:download_files:pipewire-1.5.81.tar.bz2/test/test-spa-json.c -> _service:download_files:pipewire-1.5.83.tar.bz2/test/test-spa-json.c
Changed
@@ -609,7 +609,7 @@ spa_json_init(&it0, str, strlen(str)); if (spa_json_enter_array(&it0, &it1) <= 0) - spa_json_init(&it1, str, strlen(str)); + spa_json_init_relax(&it1, '', str, strlen(str)); for (i = 0; valsi; i++) { pwtest_int_gt(spa_json_get_string(&it1, val, sizeof(val)), 0); pwtest_str_eq(val, valsi); @@ -624,6 +624,7 @@ test_array("FL FR", (const char *){ "FL", "FR", NULL }); test_array("FL FR", (const char *){ "FL", "FR", NULL }); test_array(" FL FR ", (const char *){ "FL", "FR", NULL }); + test_array("FL FR FC", (const char *){ "FL", "FR", "FC", NULL }); return PWTEST_PASS; }
View file
_service:download_files:pipewire-1.5.81.tar.bz2/test/test-spa-pod.c -> _service:download_files:pipewire-1.5.83.tar.bz2/test/test-spa-pod.c
Changed
@@ -1612,7 +1612,7 @@ spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); spa_pod_builder_add(&b, SPA_PROP_INFO_id, SPA_POD_Id(32567359), - SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, 0), + SPA_PROP_INFO_type, SPA_POD_Int(0), SPA_PROP_INFO_description, SPA_POD_String("DV Timings"), 0); @@ -1669,7 +1669,7 @@ spa_pod_builder_push_object(&b, &f0, SPA_TYPE_OBJECT_PropInfo, SPA_PARAM_PropInfo); spa_pod_builder_add(&b, SPA_PROP_INFO_id, SPA_POD_Id(32567359), - SPA_PROP_INFO_type, SPA_POD_CHOICE_ENUM_Int(1, 0), + SPA_PROP_INFO_type, SPA_POD_Int(0), SPA_PROP_INFO_description, SPA_POD_String("DV Timings"), 0);
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
.