From f32977831a0d0a76131680635b497c6ccc0bb9d8 Mon Sep 17 00:00:00 2001
From: Rafael Fontenelle
Date: Sat, 18 Jul 2020 15:12:15 +0000
Subject: [PATCH 001/872] Update Brazilian Portuguese translation
---
po/pt_BR.po | 542 +++++++++++++++++++++++++++++-----------------------
1 file changed, 308 insertions(+), 234 deletions(-)
diff --git a/po/pt_BR.po b/po/pt_BR.po
index 82b36edae..6008f9d28 100644
--- a/po/pt_BR.po
+++ b/po/pt_BR.po
@@ -9,8 +9,8 @@ msgid ""
msgstr ""
"Project-Id-Version: pulseaudio\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues\n"
-"POT-Creation-Date: 2020-04-20 03:32+0000\n"
-"PO-Revision-Date: 2020-04-20 11:43-0300\n"
+"POT-Creation-Date: 2020-06-17 15:28+0000\n"
+"PO-Revision-Date: 2020-07-18 12:08-0300\n"
"Last-Translator: Rafael Fontenelle \n"
"Language-Team: Brazilian Portuguese \n"
"Language: pt_BR\n"
@@ -520,173 +520,172 @@ msgstr "Sistema de som PulseAudio"
#: src/daemon/pulseaudio.desktop.in:5
msgid "Start the PulseAudio Sound System"
-msgstr "Iniciar o sistema de som PulseAudio"
+msgstr "Inicie o sistema de som PulseAudio"
-#: src/modules/alsa/alsa-mixer.c:2544
+#: src/modules/alsa/alsa-mixer.c:2621
msgid "Input"
msgstr "Entrada"
-#: src/modules/alsa/alsa-mixer.c:2545
+#: src/modules/alsa/alsa-mixer.c:2622
msgid "Docking Station Input"
msgstr "Entrada da base de encaixe"
-#: src/modules/alsa/alsa-mixer.c:2546
+#: src/modules/alsa/alsa-mixer.c:2623
msgid "Docking Station Microphone"
msgstr "Microfone de estação de base de encaixe"
-#: src/modules/alsa/alsa-mixer.c:2547
+#: src/modules/alsa/alsa-mixer.c:2624
msgid "Docking Station Line In"
msgstr "Entrada de linha de estação de base de encaixe"
-#: src/modules/alsa/alsa-mixer.c:2548 src/modules/alsa/alsa-mixer.c:2639
+#: src/modules/alsa/alsa-mixer.c:2625 src/modules/alsa/alsa-mixer.c:2716
msgid "Line In"
msgstr "Entrada de linha"
-#: src/modules/alsa/alsa-mixer.c:2549 src/modules/alsa/alsa-mixer.c:2633
-#: src/modules/bluetooth/module-bluez5-device.c:1788
+#: src/modules/alsa/alsa-mixer.c:2626 src/modules/alsa/alsa-mixer.c:2710
+#: src/modules/bluetooth/module-bluez5-device.c:1792
msgid "Microphone"
msgstr "Microfone"
-#: src/modules/alsa/alsa-mixer.c:2550 src/modules/alsa/alsa-mixer.c:2634
+#: src/modules/alsa/alsa-mixer.c:2627 src/modules/alsa/alsa-mixer.c:2711
msgid "Front Microphone"
msgstr "Microfone frontal"
-#: src/modules/alsa/alsa-mixer.c:2551 src/modules/alsa/alsa-mixer.c:2635
+#: src/modules/alsa/alsa-mixer.c:2628 src/modules/alsa/alsa-mixer.c:2712
msgid "Rear Microphone"
msgstr "Microfone traseiro"
-#: src/modules/alsa/alsa-mixer.c:2552
+#: src/modules/alsa/alsa-mixer.c:2629
msgid "External Microphone"
msgstr "Microfone externo"
-#: src/modules/alsa/alsa-mixer.c:2553 src/modules/alsa/alsa-mixer.c:2637
+#: src/modules/alsa/alsa-mixer.c:2630 src/modules/alsa/alsa-mixer.c:2714
msgid "Internal Microphone"
msgstr "Microfone interno"
-#: src/modules/alsa/alsa-mixer.c:2554 src/modules/alsa/alsa-mixer.c:2640
+#: src/modules/alsa/alsa-mixer.c:2631 src/modules/alsa/alsa-mixer.c:2717
+#: src/utils/pactl.c:258
msgid "Radio"
msgstr "Rádio"
-#: src/modules/alsa/alsa-mixer.c:2555 src/modules/alsa/alsa-mixer.c:2641
+#: src/modules/alsa/alsa-mixer.c:2632 src/modules/alsa/alsa-mixer.c:2718
+#: src/utils/pactl.c:259
msgid "Video"
msgstr "Vídeo"
# https://pt.wikipedia.org/wiki/Controle_autom%C3%A1tico_de_ganho
-#: src/modules/alsa/alsa-mixer.c:2556
+#: src/modules/alsa/alsa-mixer.c:2633
msgid "Automatic Gain Control"
msgstr "Controle automático de ganho"
# https://pt.wikipedia.org/wiki/Controle_autom%C3%A1tico_de_ganho
-#: src/modules/alsa/alsa-mixer.c:2557
+#: src/modules/alsa/alsa-mixer.c:2634
msgid "No Automatic Gain Control"
msgstr "Sem controle automático de ganho"
# Este contexto de Boost é "reforço" no áudio, e não "impulso".
-#: src/modules/alsa/alsa-mixer.c:2558
+#: src/modules/alsa/alsa-mixer.c:2635
msgid "Boost"
msgstr "Reforço"
# Este contexto de Boost é "reforço" no áudio, e não "impulso".
-#: src/modules/alsa/alsa-mixer.c:2559
+#: src/modules/alsa/alsa-mixer.c:2636
msgid "No Boost"
msgstr "Sem reforço"
-#: src/modules/alsa/alsa-mixer.c:2560
+#: src/modules/alsa/alsa-mixer.c:2637
msgid "Amplifier"
msgstr "Amplificador"
-#: src/modules/alsa/alsa-mixer.c:2561
+#: src/modules/alsa/alsa-mixer.c:2638
msgid "No Amplifier"
msgstr "Sem amplificador"
# Este contexto de Boost é "reforço" no áudio, e não "impulso".
-#: src/modules/alsa/alsa-mixer.c:2562
+#: src/modules/alsa/alsa-mixer.c:2639
msgid "Bass Boost"
msgstr "Reforço de graves"
# Este contexto de Boost é "reforço" no áudio, e não "impulso".
-#: src/modules/alsa/alsa-mixer.c:2563
+#: src/modules/alsa/alsa-mixer.c:2640
msgid "No Bass Boost"
msgstr "Sem reforço de graves"
-#: src/modules/alsa/alsa-mixer.c:2564
-#: src/modules/bluetooth/module-bluez5-device.c:1795
+#: src/modules/alsa/alsa-mixer.c:2641
+#: src/modules/bluetooth/module-bluez5-device.c:1800 src/utils/pactl.c:248
msgid "Speaker"
msgstr "Auto-falante"
-#: src/modules/alsa/alsa-mixer.c:2565 src/modules/alsa/alsa-mixer.c:2643
+#: src/modules/alsa/alsa-mixer.c:2642 src/modules/alsa/alsa-mixer.c:2720
+#: src/utils/pactl.c:249
msgid "Headphones"
msgstr "Fones de ouvido"
-#: src/modules/alsa/alsa-mixer.c:2632
+#: src/modules/alsa/alsa-mixer.c:2709
msgid "Analog Input"
msgstr "Entrada analógica"
-#: src/modules/alsa/alsa-mixer.c:2636
+#: src/modules/alsa/alsa-mixer.c:2713
msgid "Dock Microphone"
msgstr "Microfone de base de encaixe"
-#: src/modules/alsa/alsa-mixer.c:2638
+#: src/modules/alsa/alsa-mixer.c:2715
msgid "Headset Microphone"
msgstr "Microfone de headset"
-#: src/modules/alsa/alsa-mixer.c:2642
+#: src/modules/alsa/alsa-mixer.c:2719
msgid "Analog Output"
msgstr "Saída analógica"
-#: src/modules/alsa/alsa-mixer.c:2644
+#: src/modules/alsa/alsa-mixer.c:2721
msgid "Headphones Mono Output"
msgstr "Saída analógica fones de ouvido"
-#: src/modules/alsa/alsa-mixer.c:2645
-msgid "LFE on Separate Mono Output"
-msgstr "Saída monofônica separada em LFE"
-
-#: src/modules/alsa/alsa-mixer.c:2646
+#: src/modules/alsa/alsa-mixer.c:2722
msgid "Line Out"
msgstr "Saída de linha"
-#: src/modules/alsa/alsa-mixer.c:2647
+#: src/modules/alsa/alsa-mixer.c:2723
msgid "Analog Mono Output"
msgstr "Saída analógica monofônica"
-#: src/modules/alsa/alsa-mixer.c:2648
+#: src/modules/alsa/alsa-mixer.c:2724
msgid "Speakers"
msgstr "Alto-falantes"
-#: src/modules/alsa/alsa-mixer.c:2649
+#: src/modules/alsa/alsa-mixer.c:2725
msgid "HDMI / DisplayPort"
msgstr "HDMI / DisplayPort"
-#: src/modules/alsa/alsa-mixer.c:2650
+#: src/modules/alsa/alsa-mixer.c:2726
msgid "Digital Output (S/PDIF)"
msgstr "Saída digital (S/PDIF)"
-#: src/modules/alsa/alsa-mixer.c:2651
+#: src/modules/alsa/alsa-mixer.c:2727
msgid "Digital Input (S/PDIF)"
msgstr "Entrada digital (S/PDIF)"
-#: src/modules/alsa/alsa-mixer.c:2652
+#: src/modules/alsa/alsa-mixer.c:2728
msgid "Digital Passthrough (S/PDIF)"
msgstr "Conversor digital (S/PDIF)"
-#: src/modules/alsa/alsa-mixer.c:2653
+#: src/modules/alsa/alsa-mixer.c:2729
msgid "Multichannel Input"
msgstr "Entrada multicanal"
-#: src/modules/alsa/alsa-mixer.c:2654
+#: src/modules/alsa/alsa-mixer.c:2730
msgid "Multichannel Output"
msgstr "Saída multicanal"
-#: src/modules/alsa/alsa-mixer.c:2655
+#: src/modules/alsa/alsa-mixer.c:2731
msgid "Game Output"
msgstr "Saída de jogo"
-#: src/modules/alsa/alsa-mixer.c:2656
+#: src/modules/alsa/alsa-mixer.c:2732
msgid "Chat Output"
msgstr "Saída de bate-papo"
-#: src/modules/alsa/alsa-mixer.c:4225
+#: src/modules/alsa/alsa-mixer.c:4355
msgid "Analog Mono"
msgstr "Monofônico analógico"
@@ -695,127 +694,127 @@ msgstr "Monofônico analógico"
#. * 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.
-#: src/modules/alsa/alsa-mixer.c:4226 src/modules/alsa/alsa-mixer.c:4234
-#: src/modules/alsa/alsa-mixer.c:4235
+#: src/modules/alsa/alsa-mixer.c:4356 src/modules/alsa/alsa-mixer.c:4364
+#: src/modules/alsa/alsa-mixer.c:4365
msgid "Analog Stereo"
msgstr "Estéreo analógico"
-#: src/modules/alsa/alsa-mixer.c:4227 src/pulse/channelmap.c:103
+#: src/modules/alsa/alsa-mixer.c:4357 src/pulse/channelmap.c:103
#: src/pulse/channelmap.c:771
msgid "Mono"
msgstr "Mono"
-#: src/modules/alsa/alsa-mixer.c:4228 src/pulse/channelmap.c:775
+#: src/modules/alsa/alsa-mixer.c:4358 src/pulse/channelmap.c:775
msgid "Stereo"
msgstr "Estéreo"
-#: src/modules/alsa/alsa-mixer.c:4236 src/modules/alsa/alsa-mixer.c:4237
+#: src/modules/alsa/alsa-mixer.c:4366 src/modules/alsa/alsa-mixer.c:4367
msgid "Multichannel"
msgstr "Multicanal"
-#: src/modules/alsa/alsa-mixer.c:4238
+#: src/modules/alsa/alsa-mixer.c:4368
msgid "Analog Surround 2.1"
msgstr "Surround analógico 2.1"
-#: src/modules/alsa/alsa-mixer.c:4239
+#: src/modules/alsa/alsa-mixer.c:4369
msgid "Analog Surround 3.0"
msgstr "Surround analógico 3.0"
-#: src/modules/alsa/alsa-mixer.c:4240
+#: src/modules/alsa/alsa-mixer.c:4370
msgid "Analog Surround 3.1"
msgstr "Surround analógico 3.1"
-#: src/modules/alsa/alsa-mixer.c:4241
+#: src/modules/alsa/alsa-mixer.c:4371
msgid "Analog Surround 4.0"
msgstr "Surround analógico 4.0"
-#: src/modules/alsa/alsa-mixer.c:4242
+#: src/modules/alsa/alsa-mixer.c:4372
msgid "Analog Surround 4.1"
msgstr "Surround analógico 4.1"
-#: src/modules/alsa/alsa-mixer.c:4243
+#: src/modules/alsa/alsa-mixer.c:4373
msgid "Analog Surround 5.0"
msgstr "Surround analógico 5.0"
-#: src/modules/alsa/alsa-mixer.c:4244
+#: src/modules/alsa/alsa-mixer.c:4374
msgid "Analog Surround 5.1"
msgstr "Surround analógico 5.1"
-#: src/modules/alsa/alsa-mixer.c:4245
+#: src/modules/alsa/alsa-mixer.c:4375
msgid "Analog Surround 6.0"
msgstr "Surround analógico 6.0"
-#: src/modules/alsa/alsa-mixer.c:4246
+#: src/modules/alsa/alsa-mixer.c:4376
msgid "Analog Surround 6.1"
msgstr "Surround analógico 6.1"
-#: src/modules/alsa/alsa-mixer.c:4247
+#: src/modules/alsa/alsa-mixer.c:4377
msgid "Analog Surround 7.0"
msgstr "Surround analógico 7.0"
-#: src/modules/alsa/alsa-mixer.c:4248
+#: src/modules/alsa/alsa-mixer.c:4378
msgid "Analog Surround 7.1"
msgstr "Surround analógico 7.1"
-#: src/modules/alsa/alsa-mixer.c:4249
+#: src/modules/alsa/alsa-mixer.c:4379
msgid "Digital Stereo (IEC958)"
msgstr "Estéreo digital (IEC958)"
-#: src/modules/alsa/alsa-mixer.c:4250
+#: src/modules/alsa/alsa-mixer.c:4380
msgid "Digital Passthrough (IEC958)"
msgstr "Conversor digital (IEC958)"
-#: src/modules/alsa/alsa-mixer.c:4251
+#: src/modules/alsa/alsa-mixer.c:4381
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr "Surround digital 4.0 (IEC958/AC3)"
-#: src/modules/alsa/alsa-mixer.c:4252
+#: src/modules/alsa/alsa-mixer.c:4382
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr "Surround digital 5.1 (IEC958/AC3)"
-#: src/modules/alsa/alsa-mixer.c:4253
+#: src/modules/alsa/alsa-mixer.c:4383
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr "Surround digital 5.1 (IEC958/DTS)"
-#: src/modules/alsa/alsa-mixer.c:4254
+#: src/modules/alsa/alsa-mixer.c:4384
msgid "Digital Stereo (HDMI)"
msgstr "Estéreo digital (HDMI)"
-#: src/modules/alsa/alsa-mixer.c:4255
+#: src/modules/alsa/alsa-mixer.c:4385
msgid "Digital Surround 5.1 (HDMI)"
msgstr "Surround digital 5.1 (HDMI)"
-#: src/modules/alsa/alsa-mixer.c:4388
+#: src/modules/alsa/alsa-mixer.c:4518
msgid "Analog Mono Duplex"
msgstr "Duplex monofônico analógico"
-#: src/modules/alsa/alsa-mixer.c:4389
+#: src/modules/alsa/alsa-mixer.c:4519
msgid "Analog Stereo Duplex"
msgstr "Duplex estéreo analógico"
-#: src/modules/alsa/alsa-mixer.c:4390
+#: src/modules/alsa/alsa-mixer.c:4520
msgid "Digital Stereo Duplex (IEC958)"
msgstr "Duplex estéreo digital (IEC958)"
-#: src/modules/alsa/alsa-mixer.c:4391
+#: src/modules/alsa/alsa-mixer.c:4521
msgid "Multichannel Duplex"
msgstr "Duplex multicanal"
-#: src/modules/alsa/alsa-mixer.c:4392
+#: src/modules/alsa/alsa-mixer.c:4522
msgid "Stereo Duplex"
msgstr "Duplex estéreo"
-#: src/modules/alsa/alsa-mixer.c:4393 src/modules/alsa/module-alsa-card.c:188
-#: src/modules/bluetooth/module-bluez5-device.c:2043
+#: src/modules/alsa/alsa-mixer.c:4523 src/modules/alsa/module-alsa-card.c:188
+#: src/modules/bluetooth/module-bluez5-device.c:2053
msgid "Off"
msgstr "Desligado"
-#: src/modules/alsa/alsa-mixer.c:4492
+#: src/modules/alsa/alsa-mixer.c:4622
#, c-format
msgid "%s Output"
msgstr "Saída %s"
-#: src/modules/alsa/alsa-mixer.c:4500
+#: src/modules/alsa/alsa-mixer.c:4630
#, c-format
msgid "%s Input"
msgstr "Entrada %s"
@@ -896,62 +895,60 @@ msgstr[1] ""
"snd_pcm_mmap_begin() retornou um valor que é excepcionalmente grande: %lu bytes (%lu ms).\n"
"É mais provável que isso seja um erro no driver “%s” do ALSA. Por favor, relate esse problema aos desenvolvedores do ALSA."
-#: src/modules/bluetooth/module-bluez5-device.c:1772
-#: src/modules/bluetooth/module-bluez5-device.c:1794
-#: src/modules/bluetooth/module-bluez5-device.c:1800
-#: src/modules/bluetooth/module-bluez5-device.c:1826
+#: src/modules/bluetooth/module-bluez5-device.c:1773
+#: src/modules/bluetooth/module-bluez5-device.c:1799
+#: src/modules/bluetooth/module-bluez5-device.c:1806
msgid "Bluetooth Input"
msgstr "Entrada Bluetooth"
-#: src/modules/bluetooth/module-bluez5-device.c:1773
-#: src/modules/bluetooth/module-bluez5-device.c:1789
-#: src/modules/bluetooth/module-bluez5-device.c:1827
+#: src/modules/bluetooth/module-bluez5-device.c:1774
+#: src/modules/bluetooth/module-bluez5-device.c:1793
msgid "Bluetooth Output"
msgstr "Saída Bluetooth"
# Fone de ouvido não se encaixa como tradução aqui, pois há ou pode haver microfone junto.
-#: src/modules/bluetooth/module-bluez5-device.c:1778
+#: src/modules/bluetooth/module-bluez5-device.c:1780 src/utils/pactl.c:252
msgid "Headset"
msgstr "Headset"
# Desconheço tradução comum para esta palavra.
-#: src/modules/bluetooth/module-bluez5-device.c:1783
+#: src/modules/bluetooth/module-bluez5-device.c:1786 src/utils/pactl.c:263
msgid "Handsfree"
msgstr "Handsfree"
-#: src/modules/bluetooth/module-bluez5-device.c:1801
+#: src/modules/bluetooth/module-bluez5-device.c:1807
msgid "Headphone"
msgstr "Fones de ouvido"
-#: src/modules/bluetooth/module-bluez5-device.c:1806
+#: src/modules/bluetooth/module-bluez5-device.c:1813 src/utils/pactl.c:262
msgid "Portable"
msgstr "Portátil"
-#: src/modules/bluetooth/module-bluez5-device.c:1811
+#: src/modules/bluetooth/module-bluez5-device.c:1819 src/utils/pactl.c:264
msgid "Car"
msgstr "Carro"
-#: src/modules/bluetooth/module-bluez5-device.c:1816
+#: src/modules/bluetooth/module-bluez5-device.c:1825 src/utils/pactl.c:265
msgid "HiFi"
msgstr "HiFi"
-#: src/modules/bluetooth/module-bluez5-device.c:1821
+#: src/modules/bluetooth/module-bluez5-device.c:1831 src/utils/pactl.c:266
msgid "Phone"
msgstr "Telefone"
-#: src/modules/bluetooth/module-bluez5-device.c:1868
+#: src/modules/bluetooth/module-bluez5-device.c:1878
msgid "High Fidelity Playback (A2DP Sink)"
msgstr "Reprodução de alta fidelidade (Destino A2DP)"
-#: src/modules/bluetooth/module-bluez5-device.c:1880
+#: src/modules/bluetooth/module-bluez5-device.c:1890
msgid "High Fidelity Capture (A2DP Source)"
msgstr "Captura de alta fidelidade (Fonte A2DP)"
-#: src/modules/bluetooth/module-bluez5-device.c:1892
+#: src/modules/bluetooth/module-bluez5-device.c:1902
msgid "Headset Head Unit (HSP/HFP)"
msgstr "Unidade de headset (HSP/HFP)"
-#: src/modules/bluetooth/module-bluez5-device.c:1905
+#: src/modules/bluetooth/module-bluez5-device.c:1915
msgid "Headset Audio Gateway (HSP/HFP)"
msgstr "Gateway de Áudio do Headset (HSP/HFP)"
@@ -1011,7 +1008,7 @@ msgstr "Destino nulo temporizado"
msgid "Null Output"
msgstr "Saída nula"
-#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1058
+#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1094
#, c-format
msgid "Failed to set format: invalid format string %s"
msgstr "Falha ao definir formato: string %s de formato inválida"
@@ -1058,7 +1055,7 @@ msgstr "sink_name= sink_properties= ma
msgid "Unknown device model"
msgstr "Modelo desconhecido de dispositivo"
-#: src/modules/raop/raop-sink.c:653
+#: src/modules/raop/raop-sink.c:655
msgid "RAOP standard profile"
msgstr "Perfil padrão RAOP"
@@ -1647,7 +1644,7 @@ msgstr "Falha ao definir o fluxo de monitoração: %s"
msgid "pa_stream_connect_record() failed: %s"
msgstr "pa_stream_connect_record() falhou: %s"
-#: src/utils/pacat.c:514 src/utils/pactl.c:1454
+#: src/utils/pacat.c:514 src/utils/pactl.c:1490
#, c-format
msgid "Connection failure: %s"
msgstr "Falha na conexão: %s"
@@ -1705,9 +1702,9 @@ msgid ""
" --stream-name=NAME How to call this stream on the server\n"
" --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n"
" --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n"
-" --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n"
-" float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n"
-" s24-32le, s24-32be (defaults to s16ne)\n"
+" --format=SAMPLEFORMAT The sample format, see\n"
+" https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SupportedAudioFormats/\n"
+" for possible values (defaults to s16ne)\n"
" --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n"
" (defaults to 2)\n"
" --channel-map=CHANNELMAP Channel map to use instead of the default\n"
@@ -1748,19 +1745,19 @@ msgstr ""
" --volume=VOLUME Especifica a faixa (linear) inicial\n"
" de volume no intervalo 0...65536\n"
" --rate=TAXA_DE_AMOSTRAGEM Taxa de amostragem, Hz (padrão 44100)\n"
-" --format=FORMATO_DE_AMOSTRAGEM Tipo de amostragem, um de s16le,\n"
-" s16be, u8, float32le, float32be,\n"
-" ulaw, alaw, s32le, s32be, s24le, s24be\n"
-" s24-32le, s24-32be (padrão s16ne)\n"
+" --format=FORMATO_DE_AMOSTRAGEM Tipo de amostragem, veja\n"
+" https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SupportedAudioFormats/\n"
+" para valores possíveis (padrão: s16ne)\n"
" --channels=CANAIS O número de canais, 1 para mono,\n"
-" 2 para estéreo (o padrão é 2)\n"
+" 2 para estéreo (padrão: 2)\n"
" --channel-map=MAPA_DE_CANAIS Mapeamento de canais a ser usado no\n"
" lugar do padrão\n"
" --fix-format Obtém o formato da amostragem do\n"
" destino/fonte onde o fluxo está\n"
" sendo conectado.\n"
-" --fix-rate Obtém a taxa de amostragem do destino/fonte\n"
-" onde o fluxo está sendo conectado.\n"
+" --fix-rate Obtém a taxa de amostragem do\n"
+" destino/fonte onde o fluxo está\n"
+" sendo conectado.\n"
" --fix-channels Obtém o número de canais e o mapa de\n"
" canais do destino onde o fluxo está\n"
" sendo conectado.\n"
@@ -1810,7 +1807,7 @@ msgstr ""
"Compilado com libpulse %s\n"
"Vinculado com libpulse %s\n"
-#: src/utils/pacat.c:852 src/utils/pactl.c:1656
+#: src/utils/pacat.c:852 src/utils/pactl.c:1692
#, c-format
msgid "Invalid client name '%s'"
msgstr "Nome do cliente “%s” inválido"
@@ -1879,7 +1876,7 @@ msgstr "Falha ao abrir o arquivo de áudio."
msgid "Warning: specified sample specification will be overwritten with specification from file."
msgstr "Aviso: a especificação de amostragem especificada será sobrescrita pela especificação do arquivo."
-#: src/utils/pacat.c:1079 src/utils/pactl.c:1720
+#: src/utils/pacat.c:1079 src/utils/pactl.c:1756
msgid "Failed to determine sample specification from file."
msgstr "Falha ao determinar a especificação de amostragem a partir do arquivo."
@@ -1912,7 +1909,7 @@ msgstr "playback"
msgid "Failed to set media name."
msgstr "Falha ao definir o nome da mídia."
-#: src/utils/pacat.c:1160 src/utils/pactl.c:2070
+#: src/utils/pacat.c:1160 src/utils/pactl.c:2106
msgid "pa_mainloop_new() failed."
msgstr "pa_mainloop_new() falhou."
@@ -1920,11 +1917,11 @@ msgstr "pa_mainloop_new() falhou."
msgid "io_new() failed."
msgstr "io_new() falhou."
-#: src/utils/pacat.c:1190 src/utils/pactl.c:2082
+#: src/utils/pacat.c:1190 src/utils/pactl.c:2118
msgid "pa_context_new() failed."
msgstr "pa_context_new() falhou."
-#: src/utils/pacat.c:1198 src/utils/pactl.c:2088
+#: src/utils/pacat.c:1198 src/utils/pactl.c:2124
#, c-format
msgid "pa_context_connect() failed: %s"
msgstr "pa_context_new() falhou: %s"
@@ -1933,20 +1930,20 @@ msgstr "pa_context_new() falhou: %s"
msgid "pa_context_rttime_new() failed."
msgstr "pa_context_rttime_new() falhou."
-#: src/utils/pacat.c:1211 src/utils/pactl.c:2093
+#: src/utils/pacat.c:1211 src/utils/pactl.c:2129
msgid "pa_mainloop_run() failed."
msgstr "pa_mainloop_run() falhou."
-#: src/utils/pacmd.c:51 src/utils/pactl.c:1578
+#: src/utils/pacmd.c:51 src/utils/pactl.c:1614
msgid "NAME [ARGS ...]"
msgstr "NOME [ARGS ...]"
-#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1579
+#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1615
msgid "NAME|#N"
msgstr "NOME|#N"
-#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1577
-#: src/utils/pactl.c:1583
+#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1613
+#: src/utils/pactl.c:1619
msgid "NAME"
msgstr "NOME"
@@ -1958,7 +1955,7 @@ msgstr "NOME|#N VOLUME"
msgid "#N VOLUME"
msgstr "#N VOLUME"
-#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1581
+#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1617
msgid "NAME|#N 1|0"
msgstr "NOME|#N 1|0"
@@ -1994,7 +1991,7 @@ msgstr "NOME_DE_CAMINHO"
msgid "FILENAME SINK|#N"
msgstr "NOME_DE_ARQUIVO DESTINO|#N"
-#: src/utils/pacmd.c:69 src/utils/pactl.c:1580
+#: src/utils/pacmd.c:69 src/utils/pactl.c:1616
msgid "#N SINK|SOURCE"
msgstr "#N DESTINO|FONTE"
@@ -2002,15 +1999,15 @@ msgstr "#N DESTINO|FONTE"
msgid "1|0"
msgstr "1|0"
-#: src/utils/pacmd.c:72 src/utils/pactl.c:1582
+#: src/utils/pacmd.c:72 src/utils/pactl.c:1618
msgid "CARD PROFILE"
msgstr "PLACA PERFIL"
-#: src/utils/pacmd.c:73 src/utils/pactl.c:1584
+#: src/utils/pacmd.c:73 src/utils/pactl.c:1620
msgid "NAME|#N PORT"
msgstr "NOME|#N PORTA"
-#: src/utils/pacmd.c:74 src/utils/pactl.c:1590
+#: src/utils/pacmd.c:74 src/utils/pactl.c:1626
msgid "CARD-NAME|CARD-#N PORT OFFSET"
msgstr "NOME-PLACA|PLACA-#N PORTA POSIÇÃO"
@@ -2156,12 +2153,72 @@ msgstr ""
"Fonte padrão: %s\n"
"Cookie: %04x:%04x\n"
-#: src/utils/pactl.c:261 src/utils/pactl.c:908 src/utils/pactl.c:986
+#: src/utils/pactl.c:237
+msgid ", available"
+msgstr ", disponível"
+
+#: src/utils/pactl.c:238
+msgid ", not available"
+msgstr ", não disponível"
+
+#: src/utils/pactl.c:246 src/utils/pactl.c:270
+msgid "Unknown"
+msgstr "Desconhecido"
+
+#: src/utils/pactl.c:247
+msgid "Aux"
+msgstr "Aux"
+
+#: src/utils/pactl.c:250
+msgid "Line"
+msgstr "Linha"
+
+#: src/utils/pactl.c:251
+msgid "Mic"
+msgstr "Mic"
+
+#: src/utils/pactl.c:253
+msgid "Handset"
+msgstr "Monofone"
+
+#: src/utils/pactl.c:254
+msgid "Earpiece"
+msgstr "Fone de ouvido"
+
+#: src/utils/pactl.c:255
+msgid "SPDIF"
+msgstr "SPDIF"
+
+#: src/utils/pactl.c:256
+msgid "HDMI"
+msgstr "HDMI"
+
+#: src/utils/pactl.c:257
+msgid "TV"
+msgstr "TV"
+
+#: src/utils/pactl.c:260
+msgid "USB"
+msgstr "USB"
+
+#: src/utils/pactl.c:261
+msgid "Bluetooth"
+msgstr "Bluetooth"
+
+#: src/utils/pactl.c:267
+msgid "Network"
+msgstr "Rede"
+
+#: src/utils/pactl.c:268
+msgid "Analog"
+msgstr "Analógico"
+
+#: src/utils/pactl.c:292 src/utils/pactl.c:944 src/utils/pactl.c:1022
#, c-format
msgid "Failed to get sink information: %s"
msgstr "Falha ao obter informações do destino: %s"
-#: src/utils/pactl.c:287
+#: src/utils/pactl.c:318
#, c-format
msgid ""
"Sink #%u\n"
@@ -2200,27 +2257,36 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:331 src/utils/pactl.c:437 src/utils/pactl.c:598
+#: src/utils/pactl.c:362 src/utils/pactl.c:470 src/utils/pactl.c:633
#, c-format
msgid "\tPorts:\n"
msgstr "\tPortas:\n"
-#: src/utils/pactl.c:338 src/utils/pactl.c:444
+#: src/utils/pactl.c:364 src/utils/pactl.c:472
+#, c-format
+msgid "\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"
+msgstr "\t\t%s: %s (tipo: %s, prioridade: %u%s%s%s)\n"
+
+#: src/utils/pactl.c:366 src/utils/pactl.c:474 src/utils/pactl.c:638
+msgid ", available group: "
+msgstr ", grupo disponível: "
+
+#: src/utils/pactl.c:371 src/utils/pactl.c:479
#, c-format
msgid "\tActive Port: %s\n"
msgstr "\tPorta ativa: %s\n"
-#: src/utils/pactl.c:344 src/utils/pactl.c:450
+#: src/utils/pactl.c:377 src/utils/pactl.c:485
#, c-format
msgid "\tFormats:\n"
msgstr "\tFormatos:\n"
-#: src/utils/pactl.c:368 src/utils/pactl.c:928 src/utils/pactl.c:1001
+#: src/utils/pactl.c:401 src/utils/pactl.c:964 src/utils/pactl.c:1037
#, c-format
msgid "Failed to get source information: %s"
msgstr "Falha ao obter informações da fonte: %s"
-#: src/utils/pactl.c:394
+#: src/utils/pactl.c:427
#, c-format
msgid ""
"Source #%u\n"
@@ -2259,20 +2325,20 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:422 src/utils/pactl.c:492 src/utils/pactl.c:535
-#: src/utils/pactl.c:577 src/utils/pactl.c:675 src/utils/pactl.c:676
-#: src/utils/pactl.c:687 src/utils/pactl.c:745 src/utils/pactl.c:746
-#: src/utils/pactl.c:757 src/utils/pactl.c:808 src/utils/pactl.c:809
-#: src/utils/pactl.c:815
+#: src/utils/pactl.c:455 src/utils/pactl.c:527 src/utils/pactl.c:570
+#: src/utils/pactl.c:612 src/utils/pactl.c:711 src/utils/pactl.c:712
+#: src/utils/pactl.c:723 src/utils/pactl.c:781 src/utils/pactl.c:782
+#: src/utils/pactl.c:793 src/utils/pactl.c:844 src/utils/pactl.c:845
+#: src/utils/pactl.c:851
msgid "n/a"
msgstr "n/d"
-#: src/utils/pactl.c:461 src/utils/pactl.c:865
+#: src/utils/pactl.c:496 src/utils/pactl.c:901
#, c-format
msgid "Failed to get module information: %s"
msgstr "Falha ao obter informações do módulo: %s"
-#: src/utils/pactl.c:484
+#: src/utils/pactl.c:519
#, c-format
msgid ""
"Module #%u\n"
@@ -2289,12 +2355,12 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:503
+#: src/utils/pactl.c:538
#, c-format
msgid "Failed to get client information: %s"
msgstr "Falha ao obter informações do cliente: %s"
-#: src/utils/pactl.c:529
+#: src/utils/pactl.c:564
#, c-format
msgid ""
"Client #%u\n"
@@ -2309,12 +2375,12 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:546
+#: src/utils/pactl.c:581
#, c-format
msgid "Failed to get card information: %s"
msgstr "Falha ao obter informações da placa: %s"
-#: src/utils/pactl.c:569
+#: src/utils/pactl.c:604
#, c-format
msgid ""
"Card #%u\n"
@@ -2331,22 +2397,27 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:585
+#: src/utils/pactl.c:620
#, c-format
msgid "\tProfiles:\n"
msgstr "\tPerfis:\n"
-#: src/utils/pactl.c:587
+#: src/utils/pactl.c:622
#, c-format
msgid "\t\t%s: %s (sinks: %u, sources: %u, priority: %u, available: %s)\n"
msgstr "\t\t%s: %s (destino: %u, fontes: %u, prioridade: %u, disponível: %s)\n"
-#: src/utils/pactl.c:592
+#: src/utils/pactl.c:627
#, c-format
msgid "\tActive Profile: %s\n"
msgstr "\tPerfil ativo: %s\n"
-#: src/utils/pactl.c:606
+#: src/utils/pactl.c:636
+#, c-format
+msgid "\t\t%s: %s (type: %s, priority: %u, latency offset: % usec%s%s%s)\n"
+msgstr "\t\t%s: %s (tipo: %s, prioridade: %u, mudança da latência: % usec%s%s%s)\n"
+
+#: src/utils/pactl.c:642
#, c-format
msgid ""
"\t\t\tProperties:\n"
@@ -2355,17 +2426,17 @@ msgstr ""
"\t\t\tPropriedades:\n"
"\t\t\t\t%s\n"
-#: src/utils/pactl.c:611
+#: src/utils/pactl.c:647
#, c-format
msgid "\t\t\tPart of profile(s): %s"
msgstr "\t\t\tParte de perfil/perfis: %s"
-#: src/utils/pactl.c:628 src/utils/pactl.c:948 src/utils/pactl.c:1016
+#: src/utils/pactl.c:664 src/utils/pactl.c:984 src/utils/pactl.c:1052
#, c-format
msgid "Failed to get sink input information: %s"
msgstr "Falha ao obter informações da entrada do destino: %s"
-#: src/utils/pactl.c:657
+#: src/utils/pactl.c:693
#, c-format
msgid ""
"Sink Input #%u\n"
@@ -2404,12 +2475,12 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:698 src/utils/pactl.c:968 src/utils/pactl.c:1031
+#: src/utils/pactl.c:734 src/utils/pactl.c:1004 src/utils/pactl.c:1067
#, c-format
msgid "Failed to get source output information: %s"
msgstr "Falha ao obter informações da saída da fonte: %s"
-#: src/utils/pactl.c:727
+#: src/utils/pactl.c:763
#, c-format
msgid ""
"Source Output #%u\n"
@@ -2448,12 +2519,12 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:768
+#: src/utils/pactl.c:804
#, c-format
msgid "Failed to get sample information: %s"
msgstr "Falha ao obter informações sobre a amostragem: %s"
-#: src/utils/pactl.c:795
+#: src/utils/pactl.c:831
#, c-format
msgid ""
"Sample #%u\n"
@@ -2482,152 +2553,152 @@ msgstr ""
"\tPropriedades:\n"
"\t\t%s\n"
-#: src/utils/pactl.c:823 src/utils/pactl.c:833
+#: src/utils/pactl.c:859 src/utils/pactl.c:869
#, c-format
msgid "Failure: %s"
msgstr "Falha: %s"
-#: src/utils/pactl.c:872
+#: src/utils/pactl.c:908
#, c-format
msgid "Failed to unload module: Module %s not loaded"
msgstr "Falha ao descarregar o módulo: módulo %s não carregado"
-#: src/utils/pactl.c:890
+#: src/utils/pactl.c:926
#, c-format
msgid "Failed to set volume: You tried to set volumes for %d channel, whereas channel(s) supported = %d\n"
msgid_plural "Failed to set volume: You tried to set volumes for %d channels, whereas channel(s) supported = %d\n"
msgstr[0] "Falha ao definir volume: Você tentou definir volumes para %d canal, havendo suporte ao(s) canal(is) = %d\n"
msgstr[1] "Falha ao definir volume: Você tentou definir volumes para %d canais, havendo suporte ao(s) canal(is) = %d\n"
-#: src/utils/pactl.c:1101
+#: src/utils/pactl.c:1137
#, c-format
msgid "Failed to upload sample: %s"
msgstr "Falha ao enviar a amostragem: %s"
-#: src/utils/pactl.c:1118
+#: src/utils/pactl.c:1154
msgid "Premature end of file"
msgstr "Fim prematuro do arquivo"
-#: src/utils/pactl.c:1138
+#: src/utils/pactl.c:1174
msgid "new"
msgstr "novo"
-#: src/utils/pactl.c:1141
+#: src/utils/pactl.c:1177
msgid "change"
msgstr "alterar"
-#: src/utils/pactl.c:1144
+#: src/utils/pactl.c:1180
msgid "remove"
msgstr "remover"
-#: src/utils/pactl.c:1147 src/utils/pactl.c:1182
+#: src/utils/pactl.c:1183 src/utils/pactl.c:1218
msgid "unknown"
msgstr "desconhecido"
-#: src/utils/pactl.c:1155
+#: src/utils/pactl.c:1191
msgid "sink"
msgstr "destino"
-#: src/utils/pactl.c:1158
+#: src/utils/pactl.c:1194
msgid "source"
msgstr "fonte"
-#: src/utils/pactl.c:1161
+#: src/utils/pactl.c:1197
msgid "sink-input"
msgstr "entrada-destino"
-#: src/utils/pactl.c:1164
+#: src/utils/pactl.c:1200
msgid "source-output"
msgstr "saída-fonte"
-#: src/utils/pactl.c:1167
+#: src/utils/pactl.c:1203
msgid "module"
msgstr "módulo"
-#: src/utils/pactl.c:1170
+#: src/utils/pactl.c:1206
msgid "client"
msgstr "cliente"
-#: src/utils/pactl.c:1173
+#: src/utils/pactl.c:1209
msgid "sample-cache"
msgstr "cache-amostragem"
-#: src/utils/pactl.c:1176
+#: src/utils/pactl.c:1212
msgid "server"
msgstr "servidor"
-#: src/utils/pactl.c:1179
+#: src/utils/pactl.c:1215
msgid "card"
msgstr "placa"
-#: src/utils/pactl.c:1188
+#: src/utils/pactl.c:1224
#, c-format
msgid "Event '%s' on %s #%u\n"
msgstr "Evento “%s” em %s #%u\n"
-#: src/utils/pactl.c:1460
+#: src/utils/pactl.c:1496
msgid "Got SIGINT, exiting."
msgstr "SIGINT recebido, saindo."
-#: src/utils/pactl.c:1493
+#: src/utils/pactl.c:1529
msgid "Invalid volume specification"
msgstr "Especificação de volume inválida"
-#: src/utils/pactl.c:1516
+#: src/utils/pactl.c:1552
msgid "Volume outside permissible range.\n"
msgstr "Volume fora da faixa admissível.\n"
-#: src/utils/pactl.c:1529
+#: src/utils/pactl.c:1565
msgid "Invalid number of volume specifications.\n"
msgstr "Número de especificações de volume inválido.\n"
-#: src/utils/pactl.c:1541
+#: src/utils/pactl.c:1577
msgid "Inconsistent volume specification.\n"
msgstr "Especificação de volume inconsistente.\n"
-#: src/utils/pactl.c:1571 src/utils/pactl.c:1572 src/utils/pactl.c:1573
-#: src/utils/pactl.c:1574 src/utils/pactl.c:1575 src/utils/pactl.c:1576
-#: src/utils/pactl.c:1577 src/utils/pactl.c:1578 src/utils/pactl.c:1579
-#: src/utils/pactl.c:1580 src/utils/pactl.c:1581 src/utils/pactl.c:1582
-#: src/utils/pactl.c:1583 src/utils/pactl.c:1584 src/utils/pactl.c:1585
-#: src/utils/pactl.c:1586 src/utils/pactl.c:1587 src/utils/pactl.c:1588
-#: src/utils/pactl.c:1589 src/utils/pactl.c:1590 src/utils/pactl.c:1591
+#: src/utils/pactl.c:1607 src/utils/pactl.c:1608 src/utils/pactl.c:1609
+#: src/utils/pactl.c:1610 src/utils/pactl.c:1611 src/utils/pactl.c:1612
+#: src/utils/pactl.c:1613 src/utils/pactl.c:1614 src/utils/pactl.c:1615
+#: src/utils/pactl.c:1616 src/utils/pactl.c:1617 src/utils/pactl.c:1618
+#: src/utils/pactl.c:1619 src/utils/pactl.c:1620 src/utils/pactl.c:1621
+#: src/utils/pactl.c:1622 src/utils/pactl.c:1623 src/utils/pactl.c:1624
+#: src/utils/pactl.c:1625 src/utils/pactl.c:1626 src/utils/pactl.c:1627
msgid "[options]"
msgstr "[opções]"
-#: src/utils/pactl.c:1573
+#: src/utils/pactl.c:1609
msgid "[TYPE]"
msgstr "[TIPO]"
-#: src/utils/pactl.c:1575
+#: src/utils/pactl.c:1611
msgid "FILENAME [NAME]"
msgstr "NOME_DE_ARQUIVO [NOME]"
-#: src/utils/pactl.c:1576
+#: src/utils/pactl.c:1612
msgid "NAME [SINK]"
msgstr "NOME [DESTINO]"
-#: src/utils/pactl.c:1585
+#: src/utils/pactl.c:1621
msgid "NAME|#N VOLUME [VOLUME ...]"
msgstr "NOME|#N VOLUME [VOLUME ...]"
-#: src/utils/pactl.c:1586
+#: src/utils/pactl.c:1622
msgid "#N VOLUME [VOLUME ...]"
msgstr "#N VOLUME [VOLUME ...]"
-#: src/utils/pactl.c:1587
+#: src/utils/pactl.c:1623
msgid "NAME|#N 1|0|toggle"
msgstr "NOME|#N 1|0|toggle"
-#: src/utils/pactl.c:1588
+#: src/utils/pactl.c:1624
msgid "#N 1|0|toggle"
msgstr "#N 1|0|toggle"
-#: src/utils/pactl.c:1589
+#: src/utils/pactl.c:1625
msgid "#N FORMATS"
msgstr "#N FORMATOS"
-#: src/utils/pactl.c:1592
+#: src/utils/pactl.c:1628
#, c-format
msgid ""
"\n"
@@ -2638,7 +2709,7 @@ msgstr ""
"Os nomes especiais @DEFAULT_SINK@, @DEFAULT_SOURCE@ e @DEFAULT_MONITOR@\n"
"podem ser usados para especificar o destino, a fonte e a monitoração padrão.\n"
-#: src/utils/pactl.c:1595
+#: src/utils/pactl.c:1631
#, c-format
msgid ""
"\n"
@@ -2655,7 +2726,7 @@ msgstr ""
" -s, --server=SERVIDOR Nome do servidor a ser conectado\n"
" -n, --client-name=NOME Como chamar este cliente no servidor\n"
-#: src/utils/pactl.c:1636
+#: src/utils/pactl.c:1672
#, c-format
msgid ""
"pactl %s\n"
@@ -2666,145 +2737,145 @@ msgstr ""
"Compilado com libpulse %s\n"
"Vinculado com libpulse %s\n"
-#: src/utils/pactl.c:1692
+#: src/utils/pactl.c:1728
#, c-format
msgid "Specify nothing, or one of: %s"
msgstr "Especifique nada ou uma de: %s"
-#: src/utils/pactl.c:1702
+#: src/utils/pactl.c:1738
msgid "Please specify a sample file to load"
msgstr "Por favor, especifique um arquivo de amostragem a ser carregado"
-#: src/utils/pactl.c:1715
+#: src/utils/pactl.c:1751
msgid "Failed to open sound file."
msgstr "Falha ao abrir o arquivo de som."
-#: src/utils/pactl.c:1727
+#: src/utils/pactl.c:1763
msgid "Warning: Failed to determine sample specification from file."
msgstr "Aviso: Falha ao determinar a especificação da amostragem a partir do arquivo."
-#: src/utils/pactl.c:1737
+#: src/utils/pactl.c:1773
msgid "You have to specify a sample name to play"
msgstr "Você deve especificar um nome para amostra a ser reproduzida"
-#: src/utils/pactl.c:1749
+#: src/utils/pactl.c:1785
msgid "You have to specify a sample name to remove"
msgstr "Você deve especificar um nome para a amostra a ser removida"
-#: src/utils/pactl.c:1758
+#: src/utils/pactl.c:1794
msgid "You have to specify a sink input index and a sink"
msgstr "Você deve especificar a entrada do destino e um destino"
-#: src/utils/pactl.c:1768
+#: src/utils/pactl.c:1804
msgid "You have to specify a source output index and a source"
msgstr "Você deve especificar um índice de saída da fonte e uma fonte"
-#: src/utils/pactl.c:1783
+#: src/utils/pactl.c:1819
msgid "You have to specify a module name and arguments."
msgstr "Você deve especificar um nome para o módulo e seus argumentos."
-#: src/utils/pactl.c:1803
+#: src/utils/pactl.c:1839
msgid "You have to specify a module index or name"
msgstr "Você deve especificar um nome ou índice do módulo"
-#: src/utils/pactl.c:1816
+#: src/utils/pactl.c:1852
msgid "You may not specify more than one sink. You have to specify a boolean value."
msgstr "Você não pode especificar mais de um destino. Você deve especificar um valor booleano."
-#: src/utils/pactl.c:1821 src/utils/pactl.c:1841
+#: src/utils/pactl.c:1857 src/utils/pactl.c:1877
msgid "Invalid suspend specification."
msgstr "Especificação de suspensão inválida."
-#: src/utils/pactl.c:1836
+#: src/utils/pactl.c:1872
msgid "You may not specify more than one source. You have to specify a boolean value."
msgstr "Você não pode especificar mais de uma fonte. Você deve especificar um valor booleano."
-#: src/utils/pactl.c:1853
+#: src/utils/pactl.c:1889
msgid "You have to specify a card name/index and a profile name"
msgstr "Você deve especificar um nome/índice para a placa e um nome de perfil"
-#: src/utils/pactl.c:1864
+#: src/utils/pactl.c:1900
msgid "You have to specify a sink name/index and a port name"
msgstr "Você deve especificar um nome/índice do destino e o nome da porta"
-#: src/utils/pactl.c:1875
+#: src/utils/pactl.c:1911
msgid "You have to specify a sink name"
msgstr "Você deve especificar um nome de destino"
-#: src/utils/pactl.c:1885
+#: src/utils/pactl.c:1921
msgid "You have to specify a source name/index and a port name"
msgstr "Você deve especificar um nome/índice da fonte e o nome da porta"
-#: src/utils/pactl.c:1896
+#: src/utils/pactl.c:1932
msgid "You have to specify a source name"
msgstr "Você deve especificar um nome de fonte"
-#: src/utils/pactl.c:1906
+#: src/utils/pactl.c:1942
msgid "You have to specify a sink name/index and a volume"
msgstr "Você deve especificar um nome/índice do destino e um volume"
-#: src/utils/pactl.c:1919
+#: src/utils/pactl.c:1955
msgid "You have to specify a source name/index and a volume"
msgstr "Você deve especificar um nome/índice da fonte e um volume"
-#: src/utils/pactl.c:1932
+#: src/utils/pactl.c:1968
msgid "You have to specify a sink input index and a volume"
msgstr "Você deve especificar um índice de entrada para o destino e um volume"
-#: src/utils/pactl.c:1937
+#: src/utils/pactl.c:1973
msgid "Invalid sink input index"
msgstr "Índice de entrada de destino inválido"
-#: src/utils/pactl.c:1948
+#: src/utils/pactl.c:1984
msgid "You have to specify a source output index and a volume"
msgstr "Você deve especificar um índice de saída da fonte e um volume"
-#: src/utils/pactl.c:1953
+#: src/utils/pactl.c:1989
msgid "Invalid source output index"
msgstr "Índice de saída de fonte inválido"
-#: src/utils/pactl.c:1964
+#: src/utils/pactl.c:2000
msgid "You have to specify a sink name/index and a mute action (0, 1, or 'toggle')"
msgstr "Você deve especificar um nome/índice do destino e uma ação de mudo (0, 1 ou “toogle”)"
-#: src/utils/pactl.c:1969 src/utils/pactl.c:1984 src/utils/pactl.c:2004
-#: src/utils/pactl.c:2022
+#: src/utils/pactl.c:2005 src/utils/pactl.c:2020 src/utils/pactl.c:2040
+#: src/utils/pactl.c:2058
msgid "Invalid mute specification"
msgstr "Especificação de mudo inválida"
-#: src/utils/pactl.c:1979
+#: src/utils/pactl.c:2015
msgid "You have to specify a source name/index and a mute action (0, 1, or 'toggle')"
msgstr "Você deve especificar um nome/índice da fonte e uma ação de mudo (0, 1 ou “toogle”)"
-#: src/utils/pactl.c:1994
+#: src/utils/pactl.c:2030
msgid "You have to specify a sink input index and a mute action (0, 1, or 'toggle')"
msgstr "Você deve especificar um índice de entrada do destino e uma ação de mudo (0, 1 ou “toogle”)"
-#: src/utils/pactl.c:1999
+#: src/utils/pactl.c:2035
msgid "Invalid sink input index specification"
msgstr "Especificação do índice de entrada de destino inválida"
-#: src/utils/pactl.c:2012
+#: src/utils/pactl.c:2048
msgid "You have to specify a source output index and a mute action (0, 1, or 'toggle')"
msgstr "Você deve especificar um índice de saída de fonte e uma ação de mudo (0, 1 ou “toogle”)"
-#: src/utils/pactl.c:2017
+#: src/utils/pactl.c:2053
msgid "Invalid source output index specification"
msgstr "Especificação do índice de saída de fonte inválida"
-#: src/utils/pactl.c:2034
+#: src/utils/pactl.c:2070
msgid "You have to specify a sink index and a semicolon-separated list of supported formats"
msgstr "Você deve especificar um índice do destino e uma lista separada por ponto-e-vírgulas de formatos aceitos"
-#: src/utils/pactl.c:2046
+#: src/utils/pactl.c:2082
msgid "You have to specify a card name/index, a port name and a latency offset"
msgstr "Você deve especificar nome/índice de uma placa, um nome de porta e uma mudança de latência"
-#: src/utils/pactl.c:2053
+#: src/utils/pactl.c:2089
msgid "Could not parse latency offset"
msgstr "Não foi possível analisar a mudança da latência"
-#: src/utils/pactl.c:2065
+#: src/utils/pactl.c:2101
msgid "No valid command specified."
msgstr "Nenhum comando válido especificado."
@@ -2963,6 +3034,9 @@ msgstr "Falha ao carregar os dados do cookie\n"
msgid "Not yet implemented.\n"
msgstr "Não implementado ainda.\n"
+#~ msgid "LFE on Separate Mono Output"
+#~ msgstr "Saída monofônica separada em LFE"
+
#~ msgid "Failed to initialize daemon."
#~ msgstr "Falha em iniciar o daemon."
@@ -3474,4 +3548,4 @@ msgstr "Não implementado ainda.\n"
#~ msgstr "', ou eleve o RLIMIT_NICE/RLIMIT_RTPRIO dos limites do recurso para este usuário."
#~ msgid "socketpair(): %s"
-#~ msgstr "socketpair(): %s"
+#~ msgstr "socketpair(): %s"
\ No newline at end of file
From b5a6365f1862512fc7cf447f68983358e474e8f7 Mon Sep 17 00:00:00 2001
From: zhaochengyi
Date: Sat, 18 Jul 2020 16:47:40 +0800
Subject: [PATCH 002/872] pulsecore: Add exception judgment to fix the crash
when playing music
When playing music for a period of time, the Shared Memory is
frequently accessed, and occasionally read/write errors occur,
which causes the program to crash
[Current thread is 1 (Thread 0xffff86823010 (LWP 2841))]
(gdb) bt
0 0x0000ffff8702a714 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:50
1 0x0000ffff870188e8 in __GI_abort () at abort.c:79
2 0x0000ffff873b5728 in do_read (p=p@entry=0x3673a170, re=re@entry=0x3673a338) at pulsecore/pstream.c:856
3 0x0000ffff873b7fd8 in do_pstream_read_write (p=0x3673a170) at pulsecore/pstream.c:248
4 0x0000ffff873b8368 in srb_callback (srb=, userdata=0x3673a170) at pulsecore/pstream.c:287
5 0x0000ffff873b8bec in srbchannel_rwloop (sr=0x36766ae0) at pulsecore/srbchannel.c:190
6 0x0000ffff87339c70 in dispatch_pollfds (m=0x36670db0) at pulse/mainloop.c:655
7 0x0000ffff87339c70 in pa_mainloop_dispatch (m=m@entry=0x36670db0) at pulse/mainloop.c:898
8 0x0000ffff8733a01c in pa_mainloop_iterate (m=0x36670db0, block=, retval=0xffffd9683030) at pulse/mainloop.c:929
9 0x0000ffff8733a0d8 in pa_mainloop_run (m=m@entry=0x36670db0, retval=retval@entry=0xffffd9683030) at pulse/mainloop.c:945
10 0x0000000000406894 in main (argc=, argv=) at daemon/main.c:1144
Signed-off-by: zhaochengyi
---
src/pulsecore/pstream.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index 3b94a3adf..eb7050828 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -244,8 +244,16 @@ static void do_pstream_read_write(pa_pstream *p) {
p->mainloop->defer_enable(p->defer_event, 0);
if (!p->dead && p->srb) {
- do_write(p);
- while (!p->dead && do_read(p, &p->readsrb) == 0);
+ int r = 0;
+
+ if(do_write(p) < 0)
+ goto fail;
+
+ while (!p->dead && r == 0) {
+ r = do_read(p, &p->readsrb);
+ if (r < 0)
+ goto fail;
+ }
}
if (!p->dead && pa_iochannel_is_readable(p->io)) {
From 5c0ad422a818520337108acd700b1b4744588260 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Mon, 13 Jul 2020 12:42:14 +0300
Subject: [PATCH 003/872] remap_neon: use register r12 instead of r7
When the Thumb instructions set is used and frame pointers are enabled
(-fno-omit-frame-pointer), r7 can't be used, because it's used for the
frame pointer. Trying to use r7 caused the compilation to fail.
Thanks to Andre McCurdy for suggesting[1] this fix, all I had to do was to
test that it works. The code builds now, and cpu-remap-test also
succeeds.
[1] https://lists.openembedded.org/g/openembedded-core/message/136786
---
src/pulsecore/remap_neon.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/src/pulsecore/remap_neon.c b/src/pulsecore/remap_neon.c
index ca3b95b48..6f71345f8 100644
--- a/src/pulsecore/remap_neon.c
+++ b/src/pulsecore/remap_neon.c
@@ -52,11 +52,15 @@ static void remap_mono_to_stereo_float32ne_generic_arm(pa_remap_t *m, float *dst
__asm__ __volatile__ (
"ldm %[src]!, {r4,r6} \n\t"
"mov r5, r4 \n\t"
- "mov r7, r6 \n\t"
- "stm %[dst]!, {r4-r7} \n\t"
+
+ /* We use r12 instead of r7 here, because r7 is reserved for the
+ * frame pointer when using Thumb. */
+ "mov r12, r6 \n\t"
+
+ "stm %[dst]!, {r4-r6,r12} \n\t"
: [dst] "+r" (dst), [src] "+r" (src) /* output operands */
: /* input operands */
- : "memory", "r4", "r5", "r6", "r7" /* clobber list */
+ : "memory", "r4", "r5", "r6", "r12" /* clobber list */
);
}
From 9dd7f48b4911cbf35ee1f4ddb4a04a930c7ef4f9 Mon Sep 17 00:00:00 2001
From: Eero Nurkkala
Date: Tue, 21 Jul 2020 11:13:01 +0300
Subject: [PATCH 004/872] tests: hashmap-test.c: fix memory leak
When compiled with ASAN: -O1 -fsanitize=address -fno-omit-frame-pointer,
the following issue is seen:
==14272==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 1072 byte(s) in 1 object(s) allocated from:
#0 0x7f0180966d28 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded28)
#1 0x7f018039f043 in pa_xmalloc0 pulse/xmalloc.c:74
#2 0x7f01803c5cc8 in pa_hashmap_new_full pulsecore/hashmap.c:61
#3 0x7f01803c5df9 in pa_hashmap_new pulsecore/hashmap.c:76
#4 0x556ee75ff7f4 in remove_all_test tests/hashmap-test.c:96
#5 0x556ee7602965 in srunner_run (/home/eenurkka/pulse/pulseaudio/src/.libs/hashmap-test+0x6965)
SUMMARY: AddressSanitizer: 1072 byte(s) leaked in 1 allocation(s).
Fix it by freeing the resource properly.
Signed-off-by: Eero Nurkkala
---
src/tests/hashmap-test.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/src/tests/hashmap-test.c b/src/tests/hashmap-test.c
index 39d3e8502..f460bd434 100644
--- a/src/tests/hashmap-test.c
+++ b/src/tests/hashmap-test.c
@@ -108,6 +108,8 @@ START_TEST(remove_all_test)
if ((size = pa_hashmap_size(map)) != 0) {
ck_abort_msg("Hashmap has wrong size; got %u, want 0", size);
}
+
+ pa_hashmap_free(map);
}
END_TEST
From 1f1fb8eb6b3e9ce9a6d7b382f48ddb2349d98be6 Mon Sep 17 00:00:00 2001
From: Eero Nurkkala
Date: Tue, 21 Jul 2020 11:22:39 +0300
Subject: [PATCH 005/872] tests: cpu-remap-test.c: fix memory leaks
When compiled with ASAN: -O1 -fsanitize=address -fno-omit-frame-pointer,
the following issues are seen:
==17217==ERROR: LeakSanitizer: detected memory leaks
Direct leak of 32 byte(s) in 1 object(s) allocated from:
#0 0x7fceba414b40 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb40)
#1 0x7fceb9b3eac9 in pa_xmalloc pulse/xmalloc.c:63
#2 0x7fceb9b3ed22 in pa_xmemdup pulse/xmalloc.c:94
#3 0x7fceb9e1eed5 in _pa_xnewdup_internal pulse/xmalloc.h:86
#4 0x7fceb9e1eed5 in init_remap_c pulsecore/remap.c:580
#5 0x7fceb9e1efe5 in pa_init_remap_func pulsecore/remap.c:608
#6 0x5574e72422b7 in remap_init2_test_channels tests/cpu-remap-test.c:303
#7 0x5574e7242420 in rearrange_special_test tests/cpu-remap-test.c:345
#8 0x5574e7245ce5 in srunner_run (/home/eenurkka/pulse/pulseaudio/src/.libs/cpu-remap-test+0x9ce5)
...
SUMMARY: AddressSanitizer: 192 byte(s) leaked in 6 allocation(s).
Fix those issues by freeing the allocated resources properly.
Signed-off-by: Eero Nurkkala
---
src/tests/cpu-remap-test.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/tests/cpu-remap-test.c b/src/tests/cpu-remap-test.c
index 7e2b7a498..28c3b34b2 100644
--- a/src/tests/cpu-remap-test.c
+++ b/src/tests/cpu-remap-test.c
@@ -26,6 +26,7 @@
#include
#include
#include
+#include
#include "runtime-test-util.h"
@@ -290,7 +291,7 @@ static void remap_init2_test_channels(
bool rearrange) {
pa_cpu_info cpu_info = { PA_CPU_UNDEFINED, {}, false };
- pa_remap_t remap_orig, remap_func;
+ pa_remap_t remap_orig, remap_func = {0};
cpu_info.force_generic_code = true;
pa_remap_func_init(&cpu_info);
@@ -303,6 +304,8 @@ static void remap_init2_test_channels(
pa_init_remap_func(&remap_func);
remap_test_channels(&remap_func, &remap_orig);
+
+ pa_xfree(remap_func.state);
}
START_TEST (remap_special_test) {
From 414644dff1abd32294db3be1fde001f56ec9e65a Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Wed, 22 Jul 2020 13:28:47 +0300
Subject: [PATCH 006/872] device-port: send sink and source change events when
availability changes
The lack of change events caused GUIs to not update the port status.
Related bug report:
https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/941
---
src/pulsecore/device-port.c | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 07761365e..416bb1a8a 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -107,8 +107,20 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
* be created before port objects, and then p->card could be non-NULL for
* the whole lifecycle of pa_device_port. */
if (p->card && p->card->linked) {
+ pa_sink *sink;
+ pa_source *source;
+
pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_CARD|PA_SUBSCRIPTION_EVENT_CHANGE, p->card->index);
+
+ sink = pa_device_port_get_sink(p);
+ source = pa_device_port_get_source(p);
+ if (sink)
+ pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_CHANGE, sink->index);
+ if (source)
+ pa_subscription_post(p->core, PA_SUBSCRIPTION_EVENT_SOURCE|PA_SUBSCRIPTION_EVENT_CHANGE, source->index);
+
pa_hook_fire(&p->core->hooks[PA_CORE_HOOK_PORT_AVAILABLE_CHANGED], p);
+
/* A sink or source whose active port is unavailable can't be the
* default sink/source, so port availability changes may affect the
* default sink/source choice. */
@@ -118,9 +130,6 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
pa_core_update_default_source(p->core);
if (p->direction == PA_DIRECTION_OUTPUT) {
- pa_sink *sink;
-
- sink = pa_device_port_get_sink(p);
if (sink && p == sink->active_port) {
if (sink->active_port->available == PA_AVAILABLE_NO) {
if (p->core->rescue_streams)
@@ -129,9 +138,6 @@ void pa_device_port_set_available(pa_device_port *p, pa_available_t status) {
pa_core_move_streams_to_newly_available_preferred_sink(p->core, sink);
}
} else {
- pa_source *source;
-
- source = pa_device_port_get_source(p);
if (source && p == source->active_port) {
if (source->active_port->available == PA_AVAILABLE_NO) {
if (p->core->rescue_streams)
From 680d7bb976f1ea5ecbec40413bef2f4b863c6ded Mon Sep 17 00:00:00 2001
From: Tomasz Kontusz
Date: Sun, 19 Jul 2020 15:06:55 +0200
Subject: [PATCH 007/872] alsa-mixer: Fix well-known descriptions for
steelseries game/chat outputs
---
src/modules/alsa/alsa-mixer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 0ab9b8180..5805ffd4d 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2728,8 +2728,8 @@ static int path_verify(pa_alsa_path *p) {
{ "iec958-passthrough-output", N_("Digital Passthrough (S/PDIF)"), PA_DEVICE_PORT_TYPE_SPDIF },
{ "multichannel-input", N_("Multichannel Input"), PA_DEVICE_PORT_TYPE_LINE },
{ "multichannel-output", N_("Multichannel Output"), PA_DEVICE_PORT_TYPE_LINE },
- { "steelseries-arctis-5-output-game", N_("Game Output"), PA_DEVICE_PORT_TYPE_HEADSET },
- { "steelseries-arctis-5-output-chat", N_("Chat Output"), PA_DEVICE_PORT_TYPE_HEADSET },
+ { "steelseries-arctis-output-game-common", N_("Game Output"), PA_DEVICE_PORT_TYPE_HEADSET },
+ { "steelseries-arctis-output-chat-common", N_("Chat Output"), PA_DEVICE_PORT_TYPE_HEADSET },
};
pa_alsa_element *e;
From 9696e1079123b47eb2fbfd55a078ca73e8f9c608 Mon Sep 17 00:00:00 2001
From: Tomasz Kontusz
Date: Mon, 20 Jul 2020 17:55:18 +0200
Subject: [PATCH 008/872] alsa-mixer: Remove unused iec958-passthrough*
descriptions
They were unused since 20f1fa17bebe086cb9cff09a5157dc7ca009ba61.
---
src/modules/alsa/alsa-mixer.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 5805ffd4d..ae2a93f2f 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2725,7 +2725,6 @@ static int path_verify(pa_alsa_path *p) {
{ "hdmi-output", N_("HDMI / DisplayPort"), PA_DEVICE_PORT_TYPE_HDMI },
{ "iec958-stereo-output", N_("Digital Output (S/PDIF)"), PA_DEVICE_PORT_TYPE_SPDIF },
{ "iec958-stereo-input", N_("Digital Input (S/PDIF)"), PA_DEVICE_PORT_TYPE_SPDIF },
- { "iec958-passthrough-output", N_("Digital Passthrough (S/PDIF)"), PA_DEVICE_PORT_TYPE_SPDIF },
{ "multichannel-input", N_("Multichannel Input"), PA_DEVICE_PORT_TYPE_LINE },
{ "multichannel-output", N_("Multichannel Output"), PA_DEVICE_PORT_TYPE_LINE },
{ "steelseries-arctis-output-game-common", N_("Game Output"), PA_DEVICE_PORT_TYPE_HEADSET },
@@ -4377,7 +4376,6 @@ static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
{ "analog-surround-70", N_("Analog Surround 7.0") },
{ "analog-surround-71", N_("Analog Surround 7.1") },
{ "iec958-stereo", N_("Digital Stereo (IEC958)") },
- { "iec958-passthrough", N_("Digital Passthrough (IEC958)") },
{ "iec958-ac3-surround-40", N_("Digital Surround 4.0 (IEC958/AC3)") },
{ "iec958-ac3-surround-51", N_("Digital Surround 5.1 (IEC958/AC3)") },
{ "iec958-dts-surround-51", N_("Digital Surround 5.1 (IEC958/DTS)") },
From 8482b62b0aae3dbca8aac767d411ac4dd9c93342 Mon Sep 17 00:00:00 2001
From: Tomasz Kontusz
Date: Wed, 22 Jul 2020 07:45:22 +0200
Subject: [PATCH 009/872] alsa-mixer: add description-key to Mappings and
Profiles
---
src/modules/alsa/alsa-mixer.c | 33 +++++++++++++++++++++++++++++++--
src/modules/alsa/alsa-mixer.h | 2 ++
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index ae2a93f2f..318a3eca6 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -3714,6 +3714,7 @@ static void mapping_free(pa_alsa_mapping *m) {
pa_xfree(m->name);
pa_xfree(m->description);
+ pa_xfree(m->description_key);
pa_proplist_free(m->proplist);
@@ -3740,6 +3741,7 @@ static void profile_free(pa_alsa_profile *p) {
pa_xfree(p->name);
pa_xfree(p->description);
+ pa_xfree(p->description_key);
pa_xfree(p->input_name);
pa_xfree(p->output_name);
@@ -4014,6 +4016,30 @@ static int mapping_parse_description(pa_config_parser_state *state) {
return 0;
}
+static int mapping_parse_description_key(pa_config_parser_state *state) {
+ pa_alsa_profile_set *ps;
+ pa_alsa_profile *p;
+ pa_alsa_mapping *m;
+
+ pa_assert(state);
+
+ ps = state->userdata;
+
+ if ((m = pa_alsa_mapping_get(ps, state->section))) {
+ pa_xfree(m->description_key);
+ m->description_key = pa_xstrdup(state->rvalue);
+ } else if ((p = profile_get(ps, state->section))) {
+ pa_xfree(p->description_key);
+ p->description_key = pa_xstrdup(state->rvalue);
+ } else {
+ pa_log("[%s:%u] Section name %s invalid.", state->filename, state->lineno, state->section);
+ return -1;
+ }
+
+ return 0;
+}
+
+
static int mapping_parse_priority(pa_config_parser_state *state) {
pa_alsa_profile_set *ps;
pa_alsa_profile *p;
@@ -4382,6 +4408,7 @@ static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
{ "hdmi-stereo", N_("Digital Stereo (HDMI)") },
{ "hdmi-surround-51", N_("Digital Surround 5.1 (HDMI)") },
};
+ const char *description_key = m->description_key ? m->description_key : m->name;
pa_assert(m);
@@ -4402,7 +4429,7 @@ static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
}
if (!m->description)
- m->description = pa_xstrdup(lookup_description(m->name,
+ m->description = pa_xstrdup(lookup_description(description_key,
well_known_descriptions,
PA_ELEMENTSOF(well_known_descriptions)));
@@ -4520,6 +4547,7 @@ static int profile_verify(pa_alsa_profile *p) {
{ "output:unknown-stereo+input:unknown-stereo", N_("Stereo Duplex") },
{ "off", N_("Off") }
};
+ const char *description_key = p->description_key ? p->description_key : p->name;
pa_assert(p);
@@ -4601,7 +4629,7 @@ static int profile_verify(pa_alsa_profile *p) {
}
if (!p->description)
- p->description = pa_xstrdup(lookup_description(p->name,
+ p->description = pa_xstrdup(lookup_description(description_key,
well_known_descriptions,
PA_ELEMENTSOF(well_known_descriptions)));
@@ -4725,6 +4753,7 @@ pa_alsa_profile_set* pa_alsa_profile_set_new(const char *fname, const pa_channel
/* Shared by [Mapping ...] and [Profile ...] */
{ "description", mapping_parse_description, NULL, NULL },
+ { "description-key", mapping_parse_description_key,NULL, NULL },
{ "priority", mapping_parse_priority, NULL, NULL },
{ "fallback", mapping_parse_fallback, NULL, NULL },
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 88fc4d3eb..a7d0ddce9 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -281,6 +281,7 @@ struct pa_alsa_mapping {
char *name;
char *description;
+ char *description_key;
unsigned priority;
pa_alsa_direction_t direction;
/* These are copied over to the resultant sink/source */
@@ -322,6 +323,7 @@ struct pa_alsa_profile {
char *name;
char *description;
+ char *description_key;
unsigned priority;
char *input_name;
From 47d811224dc70ab2f04b3714cbc36ae3f3650b0a Mon Sep 17 00:00:00 2001
From: Tomasz Kontusz
Date: Sun, 12 Jul 2020 14:53:14 +0200
Subject: [PATCH 010/872] alsa-mixer: add support for Astro A50 gaming headset
---
src/modules/alsa/90-pulseaudio.rules | 2 ++
src/modules/alsa/alsa-mixer.c | 2 ++
.../steelseries-arctis-common-usb-audio.conf | 4 +--
.../profile-sets/usb-gaming-headset.conf | 33 ++++++++++++++-----
4 files changed, 30 insertions(+), 11 deletions(-)
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
index fa43cb802..eff3ea66d 100644
--- a/src/modules/alsa/90-pulseaudio.rules
+++ b/src/modules/alsa/90-pulseaudio.rules
@@ -119,6 +119,8 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1294", ENV{PULSE_PROFILE_SET}="usb-g
ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1730", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# Lucidsound LS31
ATTRS{idVendor}=="2f12", ATTRS{idProduct}=="0109", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
+# ID 9886:002c is for the Astro A50 Gen4
+ATTRS{idVendor}=="9886", ATTRS{idProduct}=="002c", ENV{PULSE_PROFILE_SET}="usb-gaming-headset.conf"
# ID 1038:1250 is for the Arctis 5
# ID 1037:12aa is for the Arctis 5 2019
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 318a3eca6..11551a7bf 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -4407,6 +4407,8 @@ static int mapping_verify(pa_alsa_mapping *m, const pa_channel_map *bonus) {
{ "iec958-dts-surround-51", N_("Digital Surround 5.1 (IEC958/DTS)") },
{ "hdmi-stereo", N_("Digital Stereo (HDMI)") },
{ "hdmi-surround-51", N_("Digital Surround 5.1 (HDMI)") },
+ { "gaming-headset-chat", N_("Chat") },
+ { "gaming-headset-game", N_("Game") },
};
const char *description_key = m->description_key ? m->description_key : m->name;
diff --git a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
index 5f11ed1e2..0c589175f 100644
--- a/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
+++ b/src/modules/alsa/mixer/profile-sets/steelseries-arctis-common-usb-audio.conf
@@ -2,7 +2,7 @@
auto-profiles = yes
[Mapping analog-chat]
-description = Chat
+description-key = gaming-headset-chat
device-strings = hw:%f,0,0
channel-map = left,right
paths-input = analog-input-mic
@@ -10,7 +10,7 @@ paths-output = steelseries-arctis-output-chat-common
intended-roles = phone
[Mapping analog-game]
-description = Game
+description-key = gaming-headset-game
device-strings = hw:%f,1,0
channel-map = left,right
paths-output = steelseries-arctis-output-game-common
diff --git a/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
index f48b44f03..adda54d5a 100644
--- a/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
+++ b/src/modules/alsa/mixer/profile-sets/usb-gaming-headset.conf
@@ -14,36 +14,51 @@
# along with PulseAudio; if not, see .
; USB gaming headset.
-; These headsets usually have two output devices. The first one is mono,
-; meant for voice audio, and the second one is stereo, meant for everything
-; else. The purpose of this unusual design is to provide separate volume
+; These headsets usually have two output devices. The first one is meant
+; for voice audio, and the second one is meant for everything else.
+; The purpose of this unusual design is to provide separate volume
; controls for voice and other audio, which can be useful in gaming.
;
; Works with:
; Steelseries Arctis 7
; Steelseries Arctis Pro Wireless.
; Lucidsound LS31
+; Astro A50
;
; See default.conf for an explanation on the directives used here.
[General]
auto-profiles = yes
-[Mapping analog-mono]
+[Mapping mono-chat]
+description-key = gaming-headset-chat
device-strings = hw:%f,0,0
channel-map = mono
paths-output = usb-gaming-headset-output-mono
paths-input = usb-gaming-headset-input
intended-roles = phone
-[Mapping analog-stereo]
+[Mapping stereo-chat]
+description-key = gaming-headset-chat
+device-strings = hw:%f,0,0
+channel-map = left,right
+paths-output = usb-gaming-headset-output-stereo
+paths-input = usb-gaming-headset-input
+intended-roles = phone
+
+[Mapping stereo-game]
+description-key = gaming-headset-game
device-strings = hw:%f,1,0
channel-map = left,right
paths-output = usb-gaming-headset-output-stereo
direction = output
-[Profile output:analog-mono+output:analog-stereo+input:analog-mono]
-output-mappings = analog-mono analog-stereo
-input-mappings = analog-mono
+[Profile output:mono-chat+output:stereo-game+input:mono-chat]
+output-mappings = mono-chat stereo-game
+input-mappings = mono-chat
+priority = 5100
+
+[Profile output:stereo-game+output:stereo-chat+input:mono-chat]
+output-mappings = stereo-game stereo-chat
+input-mappings = mono-chat
priority = 5100
-skip-probe = yes
From 4d1e5686194d5c6671e3023b5e55a4043d6e1824 Mon Sep 17 00:00:00 2001
From: Wim Taymans
Date: Mon, 3 Aug 2020 09:58:39 +0200
Subject: [PATCH 011/872] alsa-util: fix check for digit
Fix the check for a digit by checking if the value is between the
*character* '0' (not *value* 0) and '9'.
---
src/modules/alsa/alsa-util.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index d86f43c10..02e6ff1c3 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1752,7 +1752,7 @@ snd_mixer_t *pa_alsa_open_mixer_by_name(pa_hashmap *mixers, const char *dev, boo
if (!pm && pa_strneq(dev, "hw:", 3)) {
const char *s = dev + 3;
int card_index;
- while (*s && *s >= 0 && *s <= '9') s++;
+ while (*s && *s >= '0' && *s <= '9') s++;
if (*s == '\0' && pa_atoi(dev + 3, &card_index) >= 0) {
PA_HASHMAP_FOREACH_KV(dev2, pm, mixers, state) {
if (pm->card_index == card_index) {
From 99db8038de96f4ce043f88bfb3a5b000a6c4ee22 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 4 Aug 2020 14:42:59 +0300
Subject: [PATCH 012/872] build-sys: Build atomic-test only if
pthread_setaffinity_np() is available
The function seems to be essential to the test, so the test has to be
disabled entirely if pthread_setaffinity_np() is not available.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/850
---
configure.ac | 4 +++-
src/Makefile.am | 8 ++++++--
2 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index a30772ac6..a708d6d5b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -561,10 +561,12 @@ AC_FUNC_GETGROUPS
AC_CHECK_FUNCS_ONCE([chmod chown fstat fchown fchmod clock_gettime getaddrinfo getgrgid_r getgrnam_r \
getpwnam_r getpwuid_r gettimeofday getuid mlock nanosleep \
pipe posix_fadvise posix_madvise posix_memalign setpgid setsid shm_open \
- sigaction sleep symlink sysconf uname pthread_setaffinity_np pthread_getname_np pthread_setname_np])
+ sigaction sleep symlink sysconf uname pthread_getname_np pthread_setname_np])
AC_CHECK_FUNCS([mkfifo], [HAVE_MKFIFO=1], [HAVE_MKFIFO=0])
AC_SUBST(HAVE_MKFIFO)
AM_CONDITIONAL(HAVE_MKFIFO, test "x$HAVE_MKFIFO" = "x1")
+AC_CHECK_FUNCS([pthread_setaffinity_np], [HAVE_PTHREAD_SETAFFINITY_NP=1], [HAVE_PTHREAD_SETAFFINITY_NP=0])
+AM_CONDITIONAL(HAVE_PTHREAD_SETAFFINITY_NP, test "x$HAVE_PTHREAD_SETAFFINITY_NP" = "x1")
# X/OPEN
AC_CHECK_FUNCS_ONCE([readlink])
diff --git a/src/Makefile.am b/src/Makefile.am
index 5b0186b9e..1ee899789 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -296,8 +296,7 @@ TESTS_norun = \
sig2str-test \
stripnul \
echo-cancel-test \
- lo-latency-test \
- atomic-test
+ lo-latency-test
# These tests need a running pulseaudio daemon
TESTS_daemon = \
@@ -316,6 +315,11 @@ TESTS_default += \
usergroup-test
endif
+if HAVE_PTHREAD_SETAFFINITY_NP
+TESTS_norun += \
+ atomic-test
+endif
+
if HAVE_SYS_EVENTFD_H
TESTS_default += \
srbchannel-test
From 7742c9aa50f5435873dda0118c5ce90398633082 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 4 Aug 2020 14:44:38 +0300
Subject: [PATCH 013/872] meson: Build atomic-test
The test was missing from the build system.
---
src/tests/meson.build | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/tests/meson.build b/src/tests/meson.build
index 4f2ca9395..f0500467f 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -160,6 +160,13 @@ if cc.has_header_symbol('signal.h', 'SIGXCPU')
]
endif
+if cc.has_function('pthread_setaffinity_np', dependencies : thread_dep)
+ norun_tests += [
+ [ 'atomic-test', 'atomic-test.c',
+ [ check_dep, libpulsecommon_dep ] ]
+ ]
+endif
+
if alsa_dep.found()
norun_tests += [
[ 'alsa-time-test', 'alsa-time-test.c', [ alsa_dep ] ]
From 9636c2940b3c76714922932d1d30ce226eb8f037 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 4 Aug 2020 11:38:41 +0300
Subject: [PATCH 014/872] udev: fix too long card name with HyperX Cloud Orbit
S
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/820
---
src/modules/alsa/90-pulseaudio.rules | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
index eff3ea66d..1614a1685 100644
--- a/src/modules/alsa/90-pulseaudio.rules
+++ b/src/modules/alsa/90-pulseaudio.rules
@@ -131,6 +131,16 @@ ATTRS{idVendor}=="1038", ATTRS{idProduct}=="1252", ENV{PULSE_PROFILE_SET}="steel
ATTRS{idVendor}=="147a", ATTRS{idProduct}=="e055", ENV{PULSE_PROFILE_SET}="cmedia-high-speed-true-hdaudio.conf"
+# HyperX Cloud Orbit S has three modes. Each mode has a separate product ID.
+# ID_SERIAL for this device is the device name + mode repeated three times.
+# ID_SERIAL is used for the ID_ID property, and the ID_ID property is used in
+# the card name in PulseAudio. The resulting card name is too long for the name
+# length limit, so we set a more sensible ID_ID here (the same as the default
+# ID_ID, but without repetition in the serial part).
+ATTRS{idVendor}=="0951", ATTRS{idProduct}=="16ff", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_2Ch-$env{ID_USB_INTERFACE_NUM}"
+ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1702", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_Hi-Res_2Ch-$env{ID_USB_INTERFACE_NUM}"
+ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_3D_8Ch-$env{ID_USB_INTERFACE_NUM}"
+
GOTO="pulseaudio_end"
LABEL="pulseaudio_firewire_quirk"
From e153fb870618b1dcf65f6fce1667ea76acc5a28b Mon Sep 17 00:00:00 2001
From: Kai-Heng Feng
Date: Tue, 4 Aug 2020 00:20:02 +0800
Subject: [PATCH 015/872] alsa-mixer: Recognize USB audio jack mixer
UAC v2 and v3 support insertion control (jack detection), and the
created jack mixers have "- Input" suffix and "- Output" suffix for
input jack and output jack, respectively.
Add these jacks so we don't always need to rely on UCM or PulseAudio
profile-set.
---
src/modules/alsa/mixer/paths/analog-input-linein.conf | 3 +++
src/modules/alsa/mixer/paths/analog-input-mic.conf | 3 +++
src/modules/alsa/mixer/paths/analog-output-headphones.conf | 3 +++
src/modules/alsa/mixer/paths/analog-output-speaker.conf | 3 +++
4 files changed, 12 insertions(+)
diff --git a/src/modules/alsa/mixer/paths/analog-input-linein.conf b/src/modules/alsa/mixer/paths/analog-input-linein.conf
index 8163ffb2c..cf2079074 100644
--- a/src/modules/alsa/mixer/paths/analog-input-linein.conf
+++ b/src/modules/alsa/mixer/paths/analog-input-linein.conf
@@ -28,6 +28,9 @@ required-any = any
state.plugged = unknown
state.unplugged = unknown
+[Jack Line - Input]
+required-any = any
+
[Element Capture]
switch = mute
volume = merge
diff --git a/src/modules/alsa/mixer/paths/analog-input-mic.conf b/src/modules/alsa/mixer/paths/analog-input-mic.conf
index 123439b6c..53c03c820 100644
--- a/src/modules/alsa/mixer/paths/analog-input-mic.conf
+++ b/src/modules/alsa/mixer/paths/analog-input-mic.conf
@@ -29,6 +29,9 @@ required-any = any
state.plugged = unknown
state.unplugged = unknown
+[Jack Mic - Input]
+required-any = any
+
[Element Capture]
switch = mute
volume = merge
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index d2147c50f..d4ad7777d 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -52,6 +52,9 @@ state.unplugged = unknown
[Jack Headphone Mic]
required-any = any
+[Jack Headphone - Output]
+required-any = any
+
[Element Hardware Master]
switch = mute
volume = merge
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 6f9968e1f..27a3983d5 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -69,6 +69,9 @@ required-any = any
state.plugged = unknown
state.unplugged = unknown
+[Jack Speaker - Output]
+required-any = any
+
[Element Hardware Master]
switch = mute
volume = merge
From 628f068788094053c2a760f6a2211297b19d4f48 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 6 Aug 2020 14:34:56 +0300
Subject: [PATCH 016/872] gitignore: Ignore hashmap-test
---
src/.gitignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/.gitignore b/src/.gitignore
index aa7b5715f..3197482f0 100644
--- a/src/.gitignore
+++ b/src/.gitignore
@@ -49,6 +49,7 @@ flist-test
format-test
get-binary-name-test
gtk-test
+hashmap-test
hook-list-test
interpol-test
ipacl-test
From af5ae60b333d743cff941620c51e3cb2a9aee64a Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)"
Date: Sun, 9 Aug 2020 03:28:52 +0200
Subject: [PATCH 017/872] meson: Add missing thread_dep to atomic-test
Otherwise it won't link.
/usr/bin/ld: /tmp/atomic-test.uzrv5D.ltrans0.ltrans.o:
undefined reference to symbol 'pthread_setaffinity_np@@GLIBC_2.3.4'
---
src/tests/meson.build | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/tests/meson.build b/src/tests/meson.build
index f0500467f..5caf3abe6 100644
--- a/src/tests/meson.build
+++ b/src/tests/meson.build
@@ -163,7 +163,7 @@ endif
if cc.has_function('pthread_setaffinity_np', dependencies : thread_dep)
norun_tests += [
[ 'atomic-test', 'atomic-test.c',
- [ check_dep, libpulsecommon_dep ] ]
+ [ check_dep, libpulsecommon_dep, thread_dep ] ]
]
endif
From b657cff40078564e97d05663166a091832d588a6 Mon Sep 17 00:00:00 2001
From: "Jan Alexander Steffens (heftig)"
Date: Sun, 2 Aug 2020 17:43:03 +0200
Subject: [PATCH 018/872] build: Make alsadatadir configurable
Pipewire has started shipping copies of PulseAudio's ALSA card profiles.
It would be useful if both projects could share the same profiles and
this patch is a step toward that.
---
configure.ac | 8 ++++++++
meson.build | 7 ++++++-
meson_options.txt | 3 +++
src/Makefile.am | 4 ++--
4 files changed, 19 insertions(+), 3 deletions(-)
diff --git a/configure.ac b/configure.ac
index a708d6d5b..b96bf2808 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1511,6 +1511,13 @@ AC_ARG_WITH(
AC_SUBST(modlibexecdir)
AX_DEFINE_DIR(PA_DLSEARCHPATH, modlibexecdir, [Modules dir])
+AC_ARG_WITH(
+ [alsa-data-dir],
+ AS_HELP_STRING([--with-alsa-data-dir],[Directory for ALSA card profiles (defaults to ${datadir}/pulseaudio/alsa-mixer)]),
+ [alsadatadir=$withval], [alsadatadir="${datadir}/pulseaudio/alsa-mixer"])
+
+AC_SUBST(alsadatadir)
+
AC_ARG_WITH(
[udev-rules-dir],
AS_HELP_STRING([--with-udev-rules-dir],[Directory where to install udev rules to (defaults to /lib/udev/rules.d)]),
@@ -1656,6 +1663,7 @@ echo "
sysconfdir: ${sysconfdir}
localstatedir: ${localstatedir}
modlibexecdir: ${modlibexecdir}
+ alsadatadir: ${alsadatadir}
System Runtime Path: ${PA_SYSTEM_RUNTIME_PATH}
System State Path: ${PA_SYSTEM_STATE_PATH}
System Config Path: ${PA_SYSTEM_CONFIG_PATH}
diff --git a/meson.build b/meson.build
index b055a92c8..a40846479 100644
--- a/meson.build
+++ b/meson.build
@@ -66,7 +66,11 @@ localedir = join_paths(prefix, get_option('localedir'))
localstatedir = join_paths(prefix, get_option('localstatedir'))
sysconfdir = join_paths(prefix, get_option('sysconfdir'))
privlibdir = join_paths(libdir, 'pulseaudio')
-alsadatadir = join_paths(datadir, 'pulseaudio', 'alsa-mixer')
+
+alsadatadir = get_option('alsadatadir')
+if alsadatadir == ''
+ alsadatadir = join_paths(datadir, 'pulseaudio', 'alsa-mixer')
+endif
pkgconfigdir = join_paths(libdir, 'pkgconfig')
pulselibexecdir = join_paths(libexecdir, 'pulse')
@@ -788,6 +792,7 @@ summary = [
'sysconfdir: @0@'.format(sysconfdir),
'localstatedir: @0@'.format(localstatedir),
'modlibexecdir: @0@'.format(modlibexecdir),
+ 'alsadatadir: @0@'.format(alsadatadir),
'System Runtime Path: @0@'.format(cdata.get_unquoted('PA_SYSTEM_RUNTIME_PATH')),
'System State Path: @0@'.format(cdata.get_unquoted('PA_SYSTEM_STATE_PATH')),
'System Config Path: @0@'.format(cdata.get_unquoted('PA_SYSTEM_CONFIG_PATH')),
diff --git a/meson_options.txt b/meson_options.txt
index c11b67ea8..8f8a383ec 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -51,6 +51,9 @@ option('pulsedsp-location',
option('modlibexecdir',
type : 'string',
description : 'Specify location where modules will be installed')
+option('alsadatadir',
+ type : 'string',
+ description : 'Directory for ALSA card profiles (defaults to ${datadir}/pulseaudio/alsa-mixer)')
option('systemduserunitdir',
type : 'string',
description : 'Directory for systemd user service files')
diff --git a/src/Makefile.am b/src/Makefile.am
index 1ee899789..f9f26f520 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -28,8 +28,8 @@ if HAVE_X11
xdgautostartdir=$(sysconfdir)/xdg/autostart
endif
if HAVE_ALSA
-alsaprofilesetsdir=$(datadir)/pulseaudio/alsa-mixer/profile-sets
-alsapathsdir=$(datadir)/pulseaudio/alsa-mixer/paths
+alsaprofilesetsdir=$(alsadatadir)/profile-sets
+alsapathsdir=$(alsadatadir)/paths
endif
if HAVE_DBUS
dbuspolicydir=$(sysconfdir)/dbus-1/system.d
From 1ae8097b8b69c1ce6053c60e46f750e93f67c439 Mon Sep 17 00:00:00 2001
From: Rosen Penev
Date: Wed, 5 Aug 2020 18:38:19 -0700
Subject: [PATCH 019/872] modules: fix wrong formats under 32-bit
Signed-off-by: Rosen Penev
---
src/modules/module-loopback.c | 6 +++---
src/modules/raop/raop-client.c | 2 +-
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index ed559e4c7..871f01166 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -401,7 +401,7 @@ static void adjust_rates(struct userdata *u) {
/* Drop or insert samples if fast_adjust_threshold_msec was specified and the latency difference is too large. */
if (u->fast_adjust_threshold > 0 && abs(latency_difference) > u->fast_adjust_threshold) {
- pa_log_debug ("Latency difference larger than %lu msec, skipping or inserting samples.", u->fast_adjust_threshold / PA_USEC_PER_MSEC);
+ pa_log_debug ("Latency difference larger than %" PRIu64 " msec, skipping or inserting samples.", u->fast_adjust_threshold / PA_USEC_PER_MSEC);
pa_asyncmsgq_send(u->sink_input->sink->asyncmsgq, PA_MSGOBJECT(u->sink_input), SINK_INPUT_MESSAGE_FAST_ADJUST, NULL, current_source_sink_latency, NULL);
@@ -539,13 +539,13 @@ static void memblockq_adjust(struct userdata *u, int64_t latency_offset_usec, bo
if (current_memblockq_length > requested_memblockq_length) {
/* Drop audio from queue */
buffer_correction = current_memblockq_length - requested_memblockq_length;
- pa_log_info("Dropping %lu usec of audio from queue", pa_bytes_to_usec(buffer_correction, &u->sink_input->sample_spec));
+ pa_log_info("Dropping %" PRIu64 " usec of audio from queue", pa_bytes_to_usec(buffer_correction, &u->sink_input->sample_spec));
pa_memblockq_drop(u->memblockq, buffer_correction);
} else if (current_memblockq_length < requested_memblockq_length && allow_push) {
/* Add silence to queue */
buffer_correction = requested_memblockq_length - current_memblockq_length;
- pa_log_info("Adding %lu usec of silence to queue", pa_bytes_to_usec(buffer_correction, &u->sink_input->sample_spec));
+ pa_log_info("Adding %" PRIu64 " usec of silence to queue", pa_bytes_to_usec(buffer_correction, &u->sink_input->sample_spec));
pa_memblockq_seek(u->memblockq, (int64_t)buffer_correction, PA_SEEK_RELATIVE, true);
}
}
diff --git a/src/modules/raop/raop-client.c b/src/modules/raop/raop-client.c
index 85dea55e5..885b3f157 100644
--- a/src/modules/raop/raop-client.c
+++ b/src/modules/raop/raop-client.c
@@ -669,7 +669,7 @@ static size_t handle_udp_timing_packet(pa_raop_client *c, const uint8_t packet[]
payload = packet[1] ^ 0x80;
switch (payload) {
case PAYLOAD_TIMING_REQUEST:
- pa_log_debug("Sending timing packet at %lu", rci);
+ pa_log_debug("Sending timing packet at %" PRIu64 , rci);
written = send_udp_timing_packet(c, data, rci);
break;
case PAYLOAD_TIMING_REPLY:
From ceaa69d71f757bb99b4b8a6f6af7beeafb4a9e71 Mon Sep 17 00:00:00 2001
From: Rosen Penev
Date: Wed, 5 Aug 2020 18:32:03 -0700
Subject: [PATCH 020/872] raop-crypto: add missing header
Fixes compilation without deprecated OpenSSL APIs.
Signed-off-by: Rosen Penev
---
src/modules/raop/raop-crypto.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/modules/raop/raop-crypto.c b/src/modules/raop/raop-crypto.c
index 83a862cdb..710e93c82 100644
--- a/src/modules/raop/raop-crypto.c
+++ b/src/modules/raop/raop-crypto.c
@@ -30,6 +30,7 @@
#include
#include
#include
+#include
#include
From dd70c3c5890ce27b9ba4bd041dea4a01c3e1fc0f Mon Sep 17 00:00:00 2001
From: Kai-Heng Feng
Date: Thu, 6 Aug 2020 17:17:27 +0800
Subject: [PATCH 021/872] module-alsa-card: Set a minimum profile priority if
it's not set
If the profile is generated from UCM, the priority won't be set so it
stays as 0.
Assume a card has two available profiles, when the selected one becomes
unavailable, module-switch-on-port-available's find_best_profile()
should pick the next available one. However, since the priority is 0,
the "off" profile was chosen instead of the available one.
So let's set the priority to 1 to make profile that is available has
higher priority than "off" profile.
---
src/modules/alsa/module-alsa-card.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index c5852b43d..d312fb5d9 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -144,7 +144,7 @@ static void add_profiles(struct userdata *u, pa_hashmap *h, pa_hashmap *ports) {
uint32_t idx;
cp = pa_card_profile_new(ap->name, ap->description, sizeof(struct profile_data));
- cp->priority = ap->priority;
+ cp->priority = ap->priority ? ap->priority : 1;
cp->input_name = pa_xstrdup(ap->input_name);
cp->output_name = pa_xstrdup(ap->output_name);
From 1781031c8b9cf986fd343e9e18c8415a059df168 Mon Sep 17 00:00:00 2001
From: Sanchayan Maity
Date: Tue, 28 Jul 2020 14:11:05 +0530
Subject: [PATCH 022/872] modules: rtp-gstreamer: Fix RTP sound lag
In the current scenario of reading samples from the appsink, it is
observed that we do not actually read all the data available in the
appsink to read. This results in a choppy sound or heard as gaps in
the playback.
The underlying reason for this happening is as follows. Let's say
the appsink new sample callback is called 2-3 times, but, with the
underlying fdsem post machinery when pa_rtp_recv eventually gets
called, there would be those 2-3 samples to read. However, we were
only reading one sample in the current implementation.
Fix this by reading all samples from the appsink in a loop, coalescing
them and then writing to the memchunk.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/889
Signed-off-by: Sanchayan Maity
---
src/modules/rtp/rtp-gstreamer.c | 86 ++++++++++++++++++++++++---------
1 file changed, 62 insertions(+), 24 deletions(-)
diff --git a/src/modules/rtp/rtp-gstreamer.c b/src/modules/rtp/rtp-gstreamer.c
index 3ee77cb7f..0db330958 100644
--- a/src/modules/rtp/rtp-gstreamer.c
+++ b/src/modules/rtp/rtp-gstreamer.c
@@ -32,6 +32,7 @@
#include
#include
#include
+#include
#include
#define MAKE_ELEMENT_NAMED(v, e, n) \
@@ -438,36 +439,73 @@ fail:
/* Called from I/O thread context */
int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_t *rtp_tstamp, struct timeval *tstamp) {
GstSample *sample = NULL;
+ GstBufferList *buf_list;
+ GstAdapter *adapter;
GstBuffer *buf;
GstMapInfo info;
- void *data;
+ uint8_t *data;
+ uint64_t data_len = 0;
if (!process_bus_messages(c))
goto fail;
- sample = gst_app_sink_pull_sample(GST_APP_SINK(c->appsink));
- if (!sample) {
- pa_log_warn("Could not get any more data");
- goto fail;
+ adapter = gst_adapter_new();
+ pa_assert(adapter);
+
+ while (true) {
+ sample = gst_app_sink_try_pull_sample(GST_APP_SINK(c->appsink), 0);
+ if (!sample)
+ break;
+
+ buf = gst_sample_get_buffer(sample);
+
+ if (GST_BUFFER_IS_DISCONT(buf))
+ pa_log_info("Discontinuity detected, possibly lost some packets");
+
+ if (!gst_buffer_map(buf, &info, GST_MAP_READ)) {
+ pa_log_info("Failed to map buffer");
+ gst_sample_unref(sample);
+ goto fail;
+ }
+
+ data_len += info.size;
+ /* We need the buffer to be valid longer than the sample, which will
+ * be valid only for the duration of this loop.
+ *
+ * To do this, increase the ref count. Ownership is transferred to the
+ * adapter in gst_adapter_push.
+ */
+ gst_buffer_ref(buf);
+ gst_adapter_push(adapter, buf);
+ gst_buffer_unmap(buf, &info);
+
+ gst_sample_unref(sample);
}
- buf = gst_sample_get_buffer(sample);
+ buf_list = gst_adapter_take_buffer_list(adapter, data_len);
+ pa_assert(buf_list);
- if (GST_BUFFER_IS_DISCONT(buf))
- pa_log_info("Discontinuity detected, possibly lost some packets");
+ pa_assert(pa_mempool_block_size_max(pool) >= data_len);
- if (!gst_buffer_map(buf, &info, GST_MAP_READ))
- goto fail;
-
- pa_assert(pa_mempool_block_size_max(pool) >= info.size);
-
- chunk->memblock = pa_memblock_new(pool, info.size);
+ chunk->memblock = pa_memblock_new(pool, data_len);
chunk->index = 0;
- chunk->length = info.size;
+ chunk->length = data_len;
+
+ data = (uint8_t *) pa_memblock_acquire_chunk(chunk);
+
+ for (int i = 0; i < gst_buffer_list_length(buf_list); i++) {
+ buf = gst_buffer_list_get(buf_list, i);
+
+ if (!gst_buffer_map(buf, &info, GST_MAP_READ)) {
+ gst_buffer_list_unref(buf_list);
+ goto fail;
+ }
+
+ memcpy(data, info.data, info.size);
+ data += info.size;
+ gst_buffer_unmap(buf, &info);
+ }
- data = pa_memblock_acquire_chunk(chunk);
- /* TODO: we could probably just provide an allocator and avoid a memcpy */
- memcpy(data, info.data, info.size);
pa_memblock_release(chunk->memblock);
/* When buffer-mode = none, the buffer PTS is the RTP timestamp, converted
@@ -475,17 +513,17 @@ int pa_rtp_recv(pa_rtp_context *c, pa_memchunk *chunk, pa_mempool *pool, uint32_
* wraparound-corrected, and the DTS is the pipeline clock timestamp from
* when the buffer was acquired at the source (this is actually the running
* time which is why we need to add base time). */
- *rtp_tstamp = gst_util_uint64_scale_int(GST_BUFFER_PTS(buf), c->ss.rate, GST_SECOND) & 0xFFFFFFFFU;
- pa_timeval_rtstore(tstamp, (GST_BUFFER_DTS(buf) + gst_element_get_base_time(c->pipeline)) / GST_USECOND, false);
+ *rtp_tstamp = gst_util_uint64_scale_int(GST_BUFFER_PTS(gst_buffer_list_get(buf_list, 0)), c->ss.rate, GST_SECOND) & 0xFFFFFFFFU;
+ pa_timeval_rtstore(tstamp, (GST_BUFFER_DTS(gst_buffer_list_get(buf_list, 0)) + gst_element_get_base_time(c->pipeline)) / GST_USECOND, false);
- gst_buffer_unmap(buf, &info);
- gst_sample_unref(sample);
+ gst_buffer_list_unref(buf_list);
+ gst_object_unref(adapter);
return 0;
fail:
- if (sample)
- gst_sample_unref(sample);
+ if (adapter)
+ gst_object_unref(adapter);
if (chunk->memblock)
pa_memblock_unref(chunk->memblock);
From 6fce5b2eac085dc6f7ca105c0750b691e405d7e0 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Mon, 10 Aug 2020 19:38:07 +0300
Subject: [PATCH 023/872] build-sys: Configure doxygen.conf.in a bit
differently
This change prepares for adding a doxygen target to the Meson build
system. The DOXYGEN_OUTPUT_DIRECTORY substitution variable is needed so
that the output will go to the build directory. I also replaced @srcdir@
with @top_srcdir@. I think it looks cleaner, since the ".." parent
directory traversal is avoided. It also happened to make writing the
Meson rules easier.
---
configure.ac | 7 +++++
doxygen/doxygen.conf.in | 64 ++++++++++++++++++++---------------------
2 files changed, 39 insertions(+), 32 deletions(-)
diff --git a/configure.ac b/configure.ac
index b96bf2808..8b2d6318f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1552,6 +1552,13 @@ fi
AM_CONDITIONAL([FORCE_PREOPEN], [test "x$FORCE_PREOPEN" = "xyes"])
+# Substitute the variable with an empty string. This makes the output go to the
+# directory where doxygen is run (which is the doxygen directory under the
+# build directory). Substituting a variable with a constant value wouldn't
+# otherwise make sense, but the substitution variable needs to exist, because
+# we substitute a different value when using Meson.
+AC_SUBST([DOXYGEN_OUTPUT_DIRECTORY], [])
+
AC_CONFIG_FILES([
Makefile
src/Makefile
diff --git a/doxygen/doxygen.conf.in b/doxygen/doxygen.conf.in
index c195e7b28..a97c16543 100644
--- a/doxygen/doxygen.conf.in
+++ b/doxygen/doxygen.conf.in
@@ -52,7 +52,7 @@ PROJECT_LOGO =
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
-OUTPUT_DIRECTORY =
+OUTPUT_DIRECTORY = @DOXYGEN_OUTPUT_DIRECTORY@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@@ -668,37 +668,37 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
-INPUT = @srcdir@/../src/pulse/channelmap.h \
- @srcdir@/../src/pulse/context.h \
- @srcdir@/../src/pulse/def.h \
- @srcdir@/../src/pulse/direction.h \
- @srcdir@/../src/pulse/error.h \
- @srcdir@/../src/pulse/ext-stream-restore.h \
- @srcdir@/../src/pulse/ext-device-manager.h \
- @srcdir@/../src/pulse/ext-device-restore.h \
- @srcdir@/../src/pulse/format.h \
- @srcdir@/../src/pulse/gccmacro.h \
- @srcdir@/../src/pulse/glib-mainloop.h \
- @srcdir@/../src/pulse/introspect.h \
- @srcdir@/../src/pulse/mainloop-api.h \
- @srcdir@/../src/pulse/mainloop-signal.h \
- @srcdir@/../src/pulse/mainloop.h \
- @srcdir@/../src/pulse/operation.h \
- @srcdir@/../src/pulse/proplist.h \
- @srcdir@/../src/pulse/pulseaudio.h \
- @srcdir@/../src/pulse/rtclock.h \
- @srcdir@/../src/pulse/sample.h \
- @srcdir@/../src/pulse/scache.h \
- @srcdir@/../src/pulse/simple.h \
- @srcdir@/../src/pulse/stream.h \
- @srcdir@/../src/pulse/subscribe.h \
- @srcdir@/../src/pulse/thread-mainloop.h \
- @srcdir@/../src/pulse/timeval.h \
- @srcdir@/../src/pulse/utf8.h \
- @srcdir@/../src/pulse/util.h \
- @srcdir@/../src/pulse/version.h \
- @srcdir@/../src/pulse/volume.h \
- @srcdir@/../src/pulse/xmalloc.h
+INPUT = @top_srcdir@/src/pulse/channelmap.h \
+ @top_srcdir@/src/pulse/context.h \
+ @top_srcdir@/src/pulse/def.h \
+ @top_srcdir@/src/pulse/direction.h \
+ @top_srcdir@/src/pulse/error.h \
+ @top_srcdir@/src/pulse/ext-stream-restore.h \
+ @top_srcdir@/src/pulse/ext-device-manager.h \
+ @top_srcdir@/src/pulse/ext-device-restore.h \
+ @top_srcdir@/src/pulse/format.h \
+ @top_srcdir@/src/pulse/gccmacro.h \
+ @top_srcdir@/src/pulse/glib-mainloop.h \
+ @top_srcdir@/src/pulse/introspect.h \
+ @top_srcdir@/src/pulse/mainloop-api.h \
+ @top_srcdir@/src/pulse/mainloop-signal.h \
+ @top_srcdir@/src/pulse/mainloop.h \
+ @top_srcdir@/src/pulse/operation.h \
+ @top_srcdir@/src/pulse/proplist.h \
+ @top_srcdir@/src/pulse/pulseaudio.h \
+ @top_srcdir@/src/pulse/rtclock.h \
+ @top_srcdir@/src/pulse/sample.h \
+ @top_srcdir@/src/pulse/scache.h \
+ @top_srcdir@/src/pulse/simple.h \
+ @top_srcdir@/src/pulse/stream.h \
+ @top_srcdir@/src/pulse/subscribe.h \
+ @top_srcdir@/src/pulse/thread-mainloop.h \
+ @top_srcdir@/src/pulse/timeval.h \
+ @top_srcdir@/src/pulse/utf8.h \
+ @top_srcdir@/src/pulse/util.h \
+ @top_srcdir@/src/pulse/version.h \
+ @top_srcdir@/src/pulse/volume.h \
+ @top_srcdir@/src/pulse/xmalloc.h
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
From 2c790e193730f17b70734a26a417f46189fbc6c0 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Mon, 10 Aug 2020 19:47:45 +0300
Subject: [PATCH 024/872] meson: Add doxygen target
The documentation can be generated with "ninja -C build doxygen". The
output will go to "doxygen/html" under the build directory.
---
doxygen/meson.build | 10 ++++++++++
meson.build | 2 ++
2 files changed, 12 insertions(+)
create mode 100644 doxygen/meson.build
diff --git a/doxygen/meson.build b/doxygen/meson.build
new file mode 100644
index 000000000..afc0e4989
--- /dev/null
+++ b/doxygen/meson.build
@@ -0,0 +1,10 @@
+cdata.set('DOXYGEN_OUTPUT_DIRECTORY', meson.current_build_dir())
+
+doxygen_conf = configure_file(
+ input : 'doxygen.conf.in',
+ output : 'doxygen.conf',
+ configuration : cdata,
+)
+
+run_target('doxygen',
+ command : ['doxygen', doxygen_conf])
diff --git a/meson.build b/meson.build
index a40846479..88d02bd49 100644
--- a/meson.build
+++ b/meson.build
@@ -151,6 +151,7 @@ cdata.set_quoted('DESKTOPFILEDIR', join_paths(datadir, 'applications'))
cdata.set_quoted('PULSE_LOCALEDIR', localedir)
cdata.set_quoted('GETTEXT_PACKAGE', 'pulseaudio')
cdata.set('ENABLE_NLS', 1)
+cdata.set('top_srcdir', meson.source_root())
# Platform specifics
# First some defaults to keep config file generation happy
@@ -699,6 +700,7 @@ check_dep = dependency('check', version : '>= 0.9.10', required : get_option('te
# Subdirs
+subdir('doxygen')
subdir('po')
if get_option('man')
subdir('man')
From 0ce3008605e5f644fac4bb5edbb1443110201ec1 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Wed, 17 Jun 2020 08:14:18 +0300
Subject: [PATCH 025/872] Improve the port available_group and type
documentation
---
PROTOCOL | 6 +-
.../mixer/paths/analog-output.conf.common | 2 +
src/pulse/def.h | 4 +-
src/pulse/introspect.h | 76 +++++++++++++++++--
4 files changed, 80 insertions(+), 8 deletions(-)
diff --git a/PROTOCOL b/PROTOCOL
index 6d3a3c7c0..0b18edf03 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -429,7 +429,11 @@ Added two values to the pa_encoding_t enum:
## v34, implemented by >= 14.0
-Added available_group and type fields to the device port info.
+New fields in the port introspection data (duplicated for all port types:
+sink, source and card ports):
+
+ string available_group
+ uint32 type
#### If you just changed the protocol, read this
## module-tunnel depends on the sink/source/sink-input/source-input protocol
diff --git a/src/modules/alsa/mixer/paths/analog-output.conf.common b/src/modules/alsa/mixer/paths/analog-output.conf.common
index 7bf346346..31d4b447b 100644
--- a/src/modules/alsa/mixer/paths/analog-output.conf.common
+++ b/src/modules/alsa/mixer/paths/analog-output.conf.common
@@ -53,6 +53,8 @@
; [General]
+; type = ... # The device type. It's highly recommended to set a type for every path.
+; # See parse_type() in alsa-mixer.c for supported values.
; priority = ... # Priority for this path
; description-key = ... # The path description is looked up from a table in path_verify() in
; # src/modules/alsa/alsa-mixer.c. By default the path name (i.e. the file name
diff --git a/src/pulse/def.h b/src/pulse/def.h
index 2e5a5ec37..4097bd89c 100644
--- a/src/pulse/def.h
+++ b/src/pulse/def.h
@@ -1070,7 +1070,9 @@ typedef enum pa_port_available {
/** \endcond */
#endif
-/** Port type. \since 14.0 */
+/** Port type. New types can be added in the future, so applications should
+ * gracefully handle situations where a type identifier doesn't match any item
+ * in this enumeration. \since 14.0 */
typedef enum pa_device_port_type {
PA_DEVICE_PORT_TYPE_UNKNOWN = 0,
PA_DEVICE_PORT_TYPE_AUX = 1,
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 89685b501..657510747 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -229,8 +229,31 @@ typedef struct pa_sink_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
- const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
- uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
+ const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ * each other. This is meant especially for handling cases where one 3.5 mm connector
+ * is used for headphones, headsets and microphones, and the hardware can only tell
+ * that something was plugged in but not what exactly. In this situation the ports for
+ * all those devices share their availability status, and PulseAudio can't tell which
+ * one is actually plugged in, and some application may ask the user what was plugged
+ * in. Such applications should get a list of all card ports and compare their
+ * `available_group` fields. Ports that have the same group are those that need
+ * input from the user to determine which device was plugged in. The application should
+ * then activate the user-chosen port.
+ *
+ * May be NULL, in which case the port is not part of any availability group (which is
+ * the same as having a group with only one member).
+ *
+ * The group identifier must be treated as an opaque identifier. The string may look
+ * like an ALSA control name, but applications must not assume any such relationship.
+ * The group naming scheme can change without a warning.
+ *
+ * Since one group can include both input and output ports, the grouping should be done
+ * using pa_card_port_info instead of pa_sink_port_info, but this field is duplicated
+ * also in pa_sink_port_info (and pa_source_port_info) in case someone finds that
+ * convenient.
+ *
+ * \since 14.0 */
+ uint32_t type; /**< Port type, see #pa_device_port_type. \since 14.0 */
} pa_sink_port_info;
/** Stores information about sinks. Please note that this structure
@@ -311,8 +334,31 @@ typedef struct pa_source_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
- const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
- uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
+ const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ * each other. This is meant especially for handling cases where one 3.5 mm connector
+ * is used for headphones, headsets and microphones, and the hardware can only tell
+ * that something was plugged in but not what exactly. In this situation the ports for
+ * all those devices share their availability status, and PulseAudio can't tell which
+ * one is actually plugged in, and some application may ask the user what was plugged
+ * in. Such applications should get a list of all card ports and compare their
+ * `available_group` fields. Ports that have the same group are those that need
+ * input from the user to determine which device was plugged in. The application should
+ * then activate the user-chosen port.
+ *
+ * May be NULL, in which case the port is not part of any availability group (which is
+ * the same as having a group with only one member).
+ *
+ * The group identifier must be treated as an opaque identifier. The string may look
+ * like an ALSA control name, but applications must not assume any such relationship.
+ * The group naming scheme can change without a warning.
+ *
+ * Since one group can include both input and output ports, the grouping should be done
+ * using pa_card_port_info instead of pa_source_port_info, but this field is duplicated
+ * also in pa_source_port_info (and pa_sink_port_info) in case someone finds that
+ * convenient.
+ *
+ * \since 14.0 */
+ uint32_t type; /**< Port type, see #pa_device_port_type. \since 14.0 */
} pa_source_port_info;
/** Stores information about sources. Please note that this structure
@@ -513,8 +559,26 @@ typedef struct pa_card_port_info {
pa_proplist *proplist; /**< Property list */
int64_t latency_offset; /**< Latency offset of the port that gets added to the sink/source latency when the port is active. \since 3.0 */
pa_card_profile_info2** profiles2; /**< Array of pointers to available profiles, or NULL. Array is terminated by an entry set to NULL. \since 5.0 */
- const char *available_group; /**< A string indentifier which determine the group of devices handling the available state simultaneously. \since 14.0 */
- uint32_t type; /**< Port device type (PA_PORT_DEVICE_TYPE). \since 14.0 */
+ const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ * each other. This is meant especially for handling cases where one 3.5 mm connector
+ * is used for headphones, headsets and microphones, and the hardware can only tell
+ * that something was plugged in but not what exactly. In this situation the ports for
+ * all those devices share their availability status, and PulseAudio can't tell which
+ * one is actually plugged in, and some application may ask the user what was plugged
+ * in. Such applications should get a list of all card ports and compare their
+ * `available_group` fields. Ports that have the same group are those that need
+ * input from the user to determine which device was plugged in. The application should
+ * then activate the user-chosen port.
+ *
+ * May be NULL, in which case the port is not part of any availability group (which is
+ * the same as having a group with only one member).
+ *
+ * The group identifier must be treated as an opaque identifier. The string may look
+ * like an ALSA control name, but applications must not assume any such relationship.
+ * The group naming scheme can change without a warning.
+ *
+ * \since 14.0 */
+ uint32_t type; /**< Port type, see #pa_device_port_type. \since 14.0 */
} pa_card_port_info;
/** Stores information about cards. Please note that this structure
From 1b44b44c75dab41a58a8c4803e65e7ffcb58077a Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 21 Jul 2020 10:26:43 +0300
Subject: [PATCH 026/872] alsa-mixer: Fix mapping_group_available() logic
There were three bugs:
1) j->state_plugged was set to PA_AVAILABLE_UNKNOWN too early. It must
be set only after we have found that the jack is shared by two ports.
The result of setting it too early was that no jack ever could have
the PA_AVAILABLE_YES status.
2) The inner jack loop iterated through p->jacks instead of p2->jacks,
so the code didn't compare jacks between two ports at all. As a result
all ports were put in the same availability group.
3) The inner jack loop checked j->state_plugged instead of
j2->state_plugged. The result was that the speaker port, which uses the
Headphone jack to toggle between unknown and unavailable, was put in the
same group with the headphone port.
---
src/modules/alsa/alsa-mixer.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 11551a7bf..758bef22e 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -4291,14 +4291,14 @@ static void mapping_group_available(pa_hashmap *paths)
if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
continue;
has_control = true;
- j->state_plugged = PA_AVAILABLE_UNKNOWN;
PA_HASHMAP_FOREACH(p2, paths, state2) {
if (p2 == p)
break;
- PA_LLIST_FOREACH(j2, p->jacks) {
- if (!j2->has_control || j->state_plugged == PA_AVAILABLE_NO)
+ PA_LLIST_FOREACH(j2, p2->jacks) {
+ if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
continue;
if (pa_streq(j->name, j2->name)) {
+ j->state_plugged = PA_AVAILABLE_UNKNOWN;
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
found = p2->available_group;
break;
From af42b3eb6f6ff9d19715b1e008343a25a1008051 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Wed, 17 Jun 2020 08:40:16 +0300
Subject: [PATCH 027/872] Rename "available group" to "availability group"
"Availability group" is more clear about what the field is about.
Credits to Arun Raghavan for coming up with the better name.
---
PROTOCOL | 2 +-
src/modules/alsa/alsa-mixer.c | 12 ++++++------
src/modules/alsa/alsa-mixer.h | 2 +-
src/modules/alsa/alsa-ucm.c | 2 +-
src/modules/module-tunnel.c | 2 +-
src/pulse/introspect.c | 12 ++++++------
src/pulse/introspect.h | 12 ++++++------
src/pulsecore/device-port.c | 14 +++++++-------
src/pulsecore/device-port.h | 6 +++---
src/pulsecore/protocol-native.c | 6 +++---
src/utils/pactl.c | 10 +++++-----
11 files changed, 40 insertions(+), 40 deletions(-)
diff --git a/PROTOCOL b/PROTOCOL
index 0b18edf03..4307898c2 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -432,7 +432,7 @@ Added two values to the pa_encoding_t enum:
New fields in the port introspection data (duplicated for all port types:
sink, source and card ports):
- string available_group
+ string availability_group
uint32 type
#### If you just changed the protocol, read this
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 758bef22e..b22fba7ee 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -758,7 +758,7 @@ void pa_alsa_path_free(pa_alsa_path *p) {
}
pa_proplist_free(p->proplist);
- pa_xfree(p->available_group);
+ pa_xfree(p->availability_group);
pa_xfree(p->name);
pa_xfree(p->description);
pa_xfree(p->description_key);
@@ -4276,7 +4276,7 @@ fail:
}
/* the logic is simple: if we see the jack in multiple paths */
-/* assign all those jacks to one available_group */
+/* assign all those jacks to one availability_group */
static void mapping_group_available(pa_hashmap *paths)
{
void *state, *state2;
@@ -4300,7 +4300,7 @@ static void mapping_group_available(pa_hashmap *paths)
if (pa_streq(j->name, j2->name)) {
j->state_plugged = PA_AVAILABLE_UNKNOWN;
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
- found = p2->available_group;
+ found = p2->availability_group;
break;
}
}
@@ -4311,9 +4311,9 @@ static void mapping_group_available(pa_hashmap *paths)
if (!has_control)
continue;
if (!found) {
- p->available_group = pa_sprintf_malloc("Legacy %d", num);
+ p->availability_group = pa_sprintf_malloc("Legacy %d", num);
} else {
- p->available_group = pa_xstrdup(found);
+ p->availability_group = pa_xstrdup(found);
}
if (!found)
num++;
@@ -5173,7 +5173,7 @@ static pa_device_port* device_port_alsa_init(pa_hashmap *ports, /* card ports */
pa_device_port_new_data_set_description(&port_data, description);
pa_device_port_new_data_set_direction(&port_data, path->direction == PA_ALSA_DIRECTION_OUTPUT ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
pa_device_port_new_data_set_type(&port_data, path->device_port_type);
- pa_device_port_new_data_set_available_group(&port_data, path->available_group);
+ pa_device_port_new_data_set_availability_group(&port_data, path->availability_group);
p = pa_device_port_new(core, &port_data, sizeof(pa_alsa_port_data));
pa_device_port_new_data_done(&port_data);
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index a7d0ddce9..905e3128b 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -211,7 +211,7 @@ struct pa_alsa_path {
char *name;
char *description_key;
char *description;
- char *available_group;
+ char *availability_group;
pa_device_port_type_t device_port_type;
unsigned priority;
bool autodetect_eld_device;
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index c32d3c121..b63ae364f 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -1065,7 +1065,7 @@ static void ucm_add_port_combination(
pa_device_port_new_data_set_type(&port_data, type);
pa_device_port_new_data_set_direction(&port_data, is_sink ? PA_DIRECTION_OUTPUT : PA_DIRECTION_INPUT);
if (jack)
- pa_device_port_new_data_set_available_group(&port_data, jack->name);
+ pa_device_port_new_data_set_availability_group(&port_data, jack->name);
port = pa_device_port_new(core, &port_data, sizeof(pa_alsa_ucm_port_data));
pa_device_port_new_data_done(&port_data);
diff --git a/src/modules/module-tunnel.c b/src/modules/module-tunnel.c
index bb4ae489e..4c384eec5 100644
--- a/src/modules/module-tunnel.c
+++ b/src/modules/module-tunnel.c
@@ -1040,7 +1040,7 @@ static int read_ports(struct userdata *u, pa_tagstruct *t) {
return -PA_ERR_PROTOCOL;
}
if (u->version >= 34 &&
- (pa_tagstruct_gets(t, &s) < 0 || /* available_group */
+ (pa_tagstruct_gets(t, &s) < 0 || /* availability group */
pa_tagstruct_getu32(t, &priority) < 0)) { /* device port type */
pa_log("Parse failure");
return -PA_ERR_PROTOCOL;
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index b19c3fd25..3027f38ed 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -219,10 +219,10 @@ static void context_get_sink_info_callback(pa_pdispatch *pd, uint32_t command, u
goto fail;
i.ports[j]->available = av;
}
- i.ports[j]->available_group = NULL;
+ i.ports[j]->availability_group = NULL;
i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
if (o->context->version >= 34) {
- if (pa_tagstruct_gets(t, &i.ports[j]->available_group) < 0 ||
+ if (pa_tagstruct_gets(t, &i.ports[j]->availability_group) < 0 ||
pa_tagstruct_getu32(t, &i.ports[j]->type) < 0)
goto fail;
}
@@ -499,10 +499,10 @@ static void context_get_source_info_callback(pa_pdispatch *pd, uint32_t command,
goto fail;
i.ports[j]->available = av;
}
- i.ports[j]->available_group = NULL;
+ i.ports[j]->availability_group = NULL;
i.ports[j]->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
if (o->context->version >= 34) {
- if (pa_tagstruct_gets(t, &i.ports[j]->available_group) < 0 ||
+ if (pa_tagstruct_gets(t, &i.ports[j]->availability_group) < 0 ||
pa_tagstruct_getu32(t, &i.ports[j]->type))
goto fail;
}
@@ -879,11 +879,11 @@ static int fill_card_port_info(pa_context *context, pa_tagstruct* t, pa_card_inf
port->type = PA_DEVICE_PORT_TYPE_UNKNOWN;
if (context->version >= 34) {
- if (pa_tagstruct_gets(t, &port->available_group) < 0 ||
+ if (pa_tagstruct_gets(t, &port->availability_group) < 0 ||
pa_tagstruct_getu32(t, &port->type) < 0)
return -PA_ERR_PROTOCOL;
} else
- port->available_group = NULL;
+ port->availability_group = NULL;
}
return 0;
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index 657510747..8fff1ac77 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -229,14 +229,14 @@ typedef struct pa_sink_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
- const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ const char *availability_group; /**< An indentifier for the group of ports that share their availability status with
* each other. This is meant especially for handling cases where one 3.5 mm connector
* is used for headphones, headsets and microphones, and the hardware can only tell
* that something was plugged in but not what exactly. In this situation the ports for
* all those devices share their availability status, and PulseAudio can't tell which
* one is actually plugged in, and some application may ask the user what was plugged
* in. Such applications should get a list of all card ports and compare their
- * `available_group` fields. Ports that have the same group are those that need
+ * `availability_group` fields. Ports that have the same group are those that need
* input from the user to determine which device was plugged in. The application should
* then activate the user-chosen port.
*
@@ -334,14 +334,14 @@ typedef struct pa_source_port_info {
const char *description; /**< Description of this port */
uint32_t priority; /**< The higher this value is, the more useful this port is as a default. */
int available; /**< A flags (see #pa_port_available), indicating availability status of this port. \since 2.0 */
- const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ const char *availability_group; /**< An indentifier for the group of ports that share their availability status with
* each other. This is meant especially for handling cases where one 3.5 mm connector
* is used for headphones, headsets and microphones, and the hardware can only tell
* that something was plugged in but not what exactly. In this situation the ports for
* all those devices share their availability status, and PulseAudio can't tell which
* one is actually plugged in, and some application may ask the user what was plugged
* in. Such applications should get a list of all card ports and compare their
- * `available_group` fields. Ports that have the same group are those that need
+ * `availability_group` fields. Ports that have the same group are those that need
* input from the user to determine which device was plugged in. The application should
* then activate the user-chosen port.
*
@@ -559,14 +559,14 @@ typedef struct pa_card_port_info {
pa_proplist *proplist; /**< Property list */
int64_t latency_offset; /**< Latency offset of the port that gets added to the sink/source latency when the port is active. \since 3.0 */
pa_card_profile_info2** profiles2; /**< Array of pointers to available profiles, or NULL. Array is terminated by an entry set to NULL. \since 5.0 */
- const char *available_group; /**< An indentifier for the group of ports that share their availability status with
+ const char *availability_group; /**< An indentifier for the group of ports that share their availability status with
* each other. This is meant especially for handling cases where one 3.5 mm connector
* is used for headphones, headsets and microphones, and the hardware can only tell
* that something was plugged in but not what exactly. In this situation the ports for
* all those devices share their availability status, and PulseAudio can't tell which
* one is actually plugged in, and some application may ask the user what was plugged
* in. Such applications should get a list of all card ports and compare their
- * `available_group` fields. Ports that have the same group are those that need
+ * `availability_group` fields. Ports that have the same group are those that need
* input from the user to determine which device was plugged in. The application should
* then activate the user-chosen port.
*
diff --git a/src/pulsecore/device-port.c b/src/pulsecore/device-port.c
index 416bb1a8a..8263c9e9b 100644
--- a/src/pulsecore/device-port.c
+++ b/src/pulsecore/device-port.c
@@ -54,11 +54,11 @@ void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_ava
data->available = available;
}
-void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group) {
+void pa_device_port_new_data_set_availability_group(pa_device_port_new_data *data, const char *group) {
pa_assert(data);
- pa_xfree(data->available_group);
- data->available_group = pa_xstrdup(group);
+ pa_xfree(data->availability_group);
+ data->availability_group = pa_xstrdup(group);
}
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction) {
@@ -78,7 +78,7 @@ void pa_device_port_new_data_done(pa_device_port_new_data *data) {
pa_xfree(data->name);
pa_xfree(data->description);
- pa_xfree(data->available_group);
+ pa_xfree(data->availability_group);
}
void pa_device_port_set_preferred_profile(pa_device_port *p, const char *new_pp) {
@@ -164,7 +164,7 @@ static void device_port_free(pa_object *o) {
if (p->profiles)
pa_hashmap_free(p->profiles);
- pa_xfree(p->available_group);
+ pa_xfree(p->availability_group);
pa_xfree(p->preferred_profile);
pa_xfree(p->name);
pa_xfree(p->description);
@@ -190,8 +190,8 @@ pa_device_port *pa_device_port_new(pa_core *c, pa_device_port_new_data *data, si
p->card = NULL;
p->priority = 0;
p->available = data->available;
- p->available_group = data->available_group;
- data->available_group = NULL;
+ p->availability_group = data->availability_group;
+ data->availability_group = NULL;
p->profiles = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
p->direction = data->direction;
p->type = data->type;
diff --git a/src/pulsecore/device-port.h b/src/pulsecore/device-port.h
index d75eb3c36..7178ff2ae 100644
--- a/src/pulsecore/device-port.h
+++ b/src/pulsecore/device-port.h
@@ -47,7 +47,7 @@ struct pa_device_port {
unsigned priority;
pa_available_t available; /* PA_AVAILABLE_UNKNOWN, PA_AVAILABLE_NO or PA_AVAILABLE_YES */
- char *available_group; /* a string indentifier which determine the group of devices handling the available state simulteneously */
+ char *availability_group; /* a string indentifier which determine the group of devices handling the available state simulteneously */
pa_proplist *proplist;
pa_hashmap *profiles; /* Does not own the profiles */
@@ -69,7 +69,7 @@ typedef struct pa_device_port_new_data {
char *name;
char *description;
pa_available_t available;
- char *available_group;
+ char *availability_group;
pa_direction_t direction;
pa_device_port_type_t type;
} pa_device_port_new_data;
@@ -78,7 +78,7 @@ pa_device_port_new_data *pa_device_port_new_data_init(pa_device_port_new_data *d
void pa_device_port_new_data_set_name(pa_device_port_new_data *data, const char *name);
void pa_device_port_new_data_set_description(pa_device_port_new_data *data, const char *description);
void pa_device_port_new_data_set_available(pa_device_port_new_data *data, pa_available_t available);
-void pa_device_port_new_data_set_available_group(pa_device_port_new_data *data, const char *group);
+void pa_device_port_new_data_set_availability_group(pa_device_port_new_data *data, const char *group);
void pa_device_port_new_data_set_direction(pa_device_port_new_data *data, pa_direction_t direction);
void pa_device_port_new_data_set_type(pa_device_port_new_data *data, pa_device_port_type_t type);
void pa_device_port_new_data_done(pa_device_port_new_data *data);
diff --git a/src/pulsecore/protocol-native.c b/src/pulsecore/protocol-native.c
index 25bd5ddf8..e8559b239 100644
--- a/src/pulsecore/protocol-native.c
+++ b/src/pulsecore/protocol-native.c
@@ -3208,7 +3208,7 @@ static void sink_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_sin
if (c->version >= 24) {
pa_tagstruct_putu32(t, p->available);
if (c->version >= 34) {
- pa_tagstruct_puts(t, p->available_group);
+ pa_tagstruct_puts(t, p->availability_group);
pa_tagstruct_putu32(t, p->type);
}
}
@@ -3283,7 +3283,7 @@ static void source_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_s
if (c->version >= 24) {
pa_tagstruct_putu32(t, p->available);
if (c->version >= 34) {
- pa_tagstruct_puts(t, p->available_group);
+ pa_tagstruct_puts(t, p->availability_group);
pa_tagstruct_putu32(t, p->type);
}
}
@@ -3371,7 +3371,7 @@ static void card_fill_tagstruct(pa_native_connection *c, pa_tagstruct *t, pa_car
if (c->version >= 27) {
pa_tagstruct_puts64(t, port->latency_offset);
if (c->version >= 34) {
- pa_tagstruct_puts(t, port->available_group);
+ pa_tagstruct_puts(t, port->availability_group);
pa_tagstruct_putu32(t, port->type);
}
}
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 0b82921b7..1f9ce4633 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -363,8 +363,8 @@ static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_
for (p = i->ports; *p; p++)
printf(_("\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"),
(*p)->name, (*p)->description, get_device_port_type((*p)->type),
- (*p)->priority, (*p)->available_group ? _(", available group: ") : "",
- (*p)->available_group ?: "", get_available_str_ynonly((*p)->available));
+ (*p)->priority, (*p)->availability_group ? _(", availability group: ") : "",
+ (*p)->availability_group ?: "", get_available_str_ynonly((*p)->available));
}
if (i->active_port)
@@ -471,8 +471,8 @@ static void get_source_info_callback(pa_context *c, const pa_source_info *i, int
for (p = i->ports; *p; p++)
printf(_("\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"),
(*p)->name, (*p)->description, get_device_port_type((*p)->type),
- (*p)->priority, (*p)->available_group ? _(", available group: ") : "",
- (*p)->available_group ?: "", get_available_str_ynonly((*p)->available));
+ (*p)->priority, (*p)->availability_group ? _(", availability group: ") : "",
+ (*p)->availability_group ?: "", get_available_str_ynonly((*p)->available));
}
if (i->active_port)
@@ -635,7 +635,7 @@ static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_
pa_card_profile_info **pr = (*p)->profiles;
printf(_("\t\t%s: %s (type: %s, priority: %u, latency offset: %" PRId64 " usec%s%s%s)\n"), (*p)->name,
(*p)->description, get_device_port_type((*p)->type), (*p)->priority, (*p)->latency_offset,
- (*p)->available_group ? _(", available group: ") : "", (*p)->available_group ?: "",
+ (*p)->availability_group ? _(", availability group: ") : "", (*p)->availability_group ?: "",
get_available_str_ynonly((*p)->available));
if (!pa_proplist_isempty((*p)->proplist)) {
From a863b5795a6a67bd1dc6398fe4f240934641ea8e Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Mon, 10 Aug 2020 20:56:43 +0300
Subject: [PATCH 028/872] alsa-mixer: Fix indentation
---
src/modules/alsa/alsa-mixer.c | 48 +++++++++++++++++------------------
1 file changed, 24 insertions(+), 24 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index b22fba7ee..b1f6c490a 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -4288,34 +4288,34 @@ static void mapping_group_available(pa_hashmap *paths)
const char *found = NULL;
bool has_control = false;
PA_LLIST_FOREACH(j, p->jacks) {
- if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
- continue;
- has_control = true;
- PA_HASHMAP_FOREACH(p2, paths, state2) {
- if (p2 == p)
+ if (!j->has_control || j->state_plugged == PA_AVAILABLE_NO)
+ continue;
+ has_control = true;
+ PA_HASHMAP_FOREACH(p2, paths, state2) {
+ if (p2 == p)
break;
PA_LLIST_FOREACH(j2, p2->jacks) {
if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
- continue;
- if (pa_streq(j->name, j2->name)) {
+ continue;
+ if (pa_streq(j->name, j2->name)) {
j->state_plugged = PA_AVAILABLE_UNKNOWN;
- j2->state_plugged = PA_AVAILABLE_UNKNOWN;
- found = p2->availability_group;
- break;
- }
- }
- }
- if (found)
- break;
- }
- if (!has_control)
- continue;
- if (!found) {
- p->availability_group = pa_sprintf_malloc("Legacy %d", num);
- } else {
- p->availability_group = pa_xstrdup(found);
- }
- if (!found)
+ j2->state_plugged = PA_AVAILABLE_UNKNOWN;
+ found = p2->availability_group;
+ break;
+ }
+ }
+ }
+ if (found)
+ break;
+ }
+ if (!has_control)
+ continue;
+ if (!found) {
+ p->availability_group = pa_sprintf_malloc("Legacy %d", num);
+ } else {
+ p->availability_group = pa_xstrdup(found);
+ }
+ if (!found)
num++;
}
}
From c7343ef68320022f601419bda9924da3e49397f1 Mon Sep 17 00:00:00 2001
From: Geert Warrink
Date: Fri, 10 Jul 2020 19:00:45 +0000
Subject: [PATCH 029/872] Translated using Weblate (Dutch)
Currently translated at 85.8% (426 of 496 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/nl/
---
po/nl.po | 103 +++++++++++++++++++++++++++++--------------------------
1 file changed, 55 insertions(+), 48 deletions(-)
diff --git a/po/nl.po b/po/nl.po
index e5be84d78..4470aefda 100644
--- a/po/nl.po
+++ b/po/nl.po
@@ -9,13 +9,16 @@ msgstr ""
"Project-Id-Version: pulseaudio.master-tx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-01-30 10:10+0000\n"
-"PO-Revision-Date: 2012-01-30 09:54+0000\n"
-"Last-Translator: Reinout van Schouwen \n"
-"Language-Team: Dutch \n"
+"PO-Revision-Date: 2020-07-11 20:27+0000\n"
+"Last-Translator: Geert Warrink \n"
+"Language-Team: Dutch \n"
"Language: nl\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
-"Content-Transfer-Encoding: \n"
+"Content-Transfer-Encoding: \n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.1.1\n"
#: ../src/modules/alsa/alsa-util.c:1136 ../src/modules/alsa/alsa-util.c:1204
#, c-format
@@ -44,17 +47,17 @@ msgstr ""
"probleem alstublieft aan de ALSA-ontwikkelaars."
#: ../src/modules/alsa/alsa-util.c:1220
-#, fuzzy, c-format
+#, c-format
msgid ""
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
"%lu.\n"
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
"to the ALSA developers."
msgstr ""
-"snd_pcm_avail() gaf een waarde terug die uitzonderlijk groot is: %lu bytes "
-"(%lu ms).\n"
-"Waarschijnlijk is dit een fout in het ALSA-stuurprogramma ‘%s’. Meld dit "
-"probleem alstublieft aan de ALSA-ontwikkelaars."
+"snd_pcm_avail_delay() gaf vreemde waardes terug: vertraging %lu is minder "
+"dan %lu.\n"
+"Waarschijnlijk is dit een fout in het ALSA-stuurprogramma '%s'. Meld dit "
+"probleem aan de ALSA-ontwikkelaars."
#: ../src/modules/alsa/alsa-util.c:1263
#, c-format
@@ -83,7 +86,6 @@ msgid "Virtual LADSPA sink"
msgstr "Virtuele LADSPA afvoer"
#: ../src/modules/module-ladspa-sink.c:52
-#, fuzzy
msgid ""
"sink_name= sink_properties= "
"master= format= rate= "
@@ -95,9 +97,11 @@ msgid ""
msgstr ""
"sink_name= sink_properties= master= format= "
-"rate= channels= channel_map= "
-"plugin= label= "
-"control="
+"rate= channels= "
+"channel_map= plugin= label= control= "
+"input_ladspaport_map= "
+"output_ladspaport_map= "
#: ../src/modules/module-null-sink.c:49
msgid "Clocked NULL sink"
@@ -203,6 +207,8 @@ msgid ""
"System mode refused for non-root user. Only starting the D-Bus server lookup "
"service."
msgstr ""
+"Systeemmodus geweigerd voor niet-rootgebruiker. Alleen starten van de D-Bus-"
+"server zoekservice."
#: ../src/daemon/main.c:611
msgid "Daemon not running"
@@ -238,12 +244,16 @@ msgstr "--start wordt niet ondersteund voor systeeminstanties"
#, c-format
msgid "User-configured server at %s, refusing to start/autospawn."
msgstr ""
+"Door gebruiker geconfigureerde server op %s, die weigert te starten/"
+"autospawn."
#: ../src/daemon/main.c:713
#, c-format
msgid ""
"User-configured server at %s, which appears to be local. Probing deeper."
msgstr ""
+"Door gebruiker geconfigureerde server op %s, die lokaal lijkt te zijn. "
+"Dieper onderzoeken."
#: ../src/daemon/main.c:718
msgid "Running in system mode, but --disallow-exit not set!"
@@ -267,9 +277,9 @@ msgid "Failed to acquire stdio."
msgstr "Verkrijgen van stdio mislukte."
#: ../src/daemon/main.c:763 ../src/daemon/main.c:828
-#, fuzzy, c-format
+#, c-format
msgid "pipe() failed: %s"
-msgstr "pipe mislukte: %s"
+msgstr "pipe() mislukte: %s"
#: ../src/daemon/main.c:768 ../src/daemon/main.c:833
#, c-format
@@ -290,9 +300,9 @@ msgid "Daemon startup successful."
msgstr "Voorziening met succes opgestart."
#: ../src/daemon/main.c:816
-#, fuzzy, c-format
+#, c-format
msgid "setsid() failed: %s"
-msgstr "read() mislukte: %s"
+msgstr "setsid() mislukte: %s"
#: ../src/daemon/main.c:901
#, c-format
@@ -338,9 +348,9 @@ msgid "Running in valgrind mode: %s"
msgstr "Draaiend in valgrind-modus: %s"
#: ../src/daemon/main.c:921
-#, fuzzy, c-format
+#, c-format
msgid "Running in VM: %s"
-msgstr "Draaiend op host: %s"
+msgstr "Draaiend in VM: %s"
#: ../src/daemon/main.c:924
msgid "Optimized build: yes"
@@ -455,7 +465,7 @@ msgid "Daemon terminated."
msgstr "Voorziening is afgesloten."
#: ../src/daemon/cmdline.c:113
-#, fuzzy, c-format
+#, c-format
msgid ""
"%s [options]\n"
"\n"
@@ -547,7 +557,8 @@ msgstr ""
" --fail[=BOOL] Verlaat als opstarten mislukt\n"
" --high-priority[=BOOL] Probeer een hoog nice nivo in te "
"stellen\n"
-" (only beschikbaar voor, als SUID of\n"
+" (alleen beschikbaar voor, als SUID "
+"of\n"
" met verhoogde RLIMIT_NICE)\n"
" --realtime[=BOOL] Probeer realtime scheduling aan te "
"zetten \n"
@@ -563,26 +574,24 @@ msgstr ""
" --exit-idle-time=SECS Sluit de daemon af deze niets doet "
"en deze tijd\n"
" verstreken is\n"
-" --module-idle-time=SECS Verwijder automatisch geladen "
-"modules als deze niets\n"
-" doen en deze tijd verstreken is\n"
-" --scache-idle-time=SECS Verwijder automatisch geladen "
-"samples als deze niets\n"
+" --scache-idle-time=SECS Verwijder automatisch geladen samples "
+"als deze niets\n"
" doen en deze tijd verstreken is\n"
" --log-level[=LEVEL] Verhoog of instellen van "
"breedsprakigheids nivo\n"
-" -v Verhoog breedsprakigheids nivo\n"
-" --log-target={auto,syslog,stderr} Specificeer het log doel\n"
+" -v Verhoog breedsprakigheids-niveau\n"
+" --log-target={auto,syslog,stderr,file:PAD}\n"
+" Specificeer het log doel\n"
" --log-meta[=BOOL] Voeg code locatie toe aan log "
"boodschappen\n"
" --log-time[=BOOL] Voeg tijdstempels toe aan log "
"boodschappen\n"
" --log-backtrace=FRAMES Voeg een backtrace toe aan log "
"boodscvhappen\n"
-" -p, --dl-search-path=PATH Stel het zoek pad voor dynamisch "
+" -p, --dl-search-path=PAD Stel het zoek pad voor dynamisch "
"gedeelde\n"
" objecten in (plugins)\n"
-" --resample-method=METHOD Gebruik de opgegeven resampling "
+" --resample-method=METHODE Gebruik de opgegeven resampling "
"methode\n"
" (Zie --dump-resample-methods voor\n"
" mogelijke waardes)\n"
@@ -590,14 +599,14 @@ msgstr ""
" --no-cpu-limit[=BOOL] Installeer geen CPU load begrenzer "
"op\n"
" platforms die dat ondersteunen.\n"
-" --disable-shm[=BOOL] Zet gedeeld heugen ondersteuning "
-"uit.\n"
+" --disable-shm[=BOOL] Zet gedeeld heugen ondersteuning uit."
+"\n"
"\n"
"OPSTART SCRIPT:\n"
" -L, --load=\"MODULE ARGUMENTS\" Laad de opgegeven plugin module "
"met\n"
" de opgegeven argumenten\n"
-" -F, --file=FILENAME Draai het opgegeven script\n"
+" -F, --file=BESTANSNAAM Draai het opgegeven script\n"
" -C Open een opdrachtregel op de "
"draaiende TTY\n"
" na het opstarten\n"
@@ -642,11 +651,12 @@ msgid "--use-pid-file expects boolean argument"
msgstr "--use-pid-file verwacht een boolean argument"
#: ../src/daemon/cmdline.c:318
-#, fuzzy
msgid ""
"Invalid log target: use either 'syslog', 'stderr' or 'auto' or a valid file "
"name 'file:'."
-msgstr "Ongeldig log doel: gebruik een van 'syslog', 'stderr', 'auto'."
+msgstr ""
+"Ongeldig log doel: gebruik een van 'syslog', 'stderr' of 'auto' of een "
+"geldige bestandsnaam 'file:'."
#: ../src/daemon/cmdline.c:325
msgid "--log-time expects boolean argument"
@@ -774,9 +784,9 @@ msgid "[%s:%u] Invalid nice level '%s'."
msgstr "[%s:%u] Ongeldig nice niveau ‘%s’."
#: ../src/daemon/daemon-conf.c:528
-#, fuzzy, c-format
+#, c-format
msgid "[%s:%u] Invalid server type '%s'."
-msgstr "[%s:%u] Ongeldige samlperate ‘%s’."
+msgstr "[%s:%u] Ongeldige servertype '%s'."
#: ../src/daemon/daemon-conf.c:641
#, c-format
@@ -809,14 +819,12 @@ msgid "Start the PulseAudio Sound System"
msgstr "Start het PulseAudio geluidssysteem"
#: ../src/daemon/pulseaudio-kde.desktop.in.h:1
-#, fuzzy
msgid "PulseAudio Sound System KDE Routing Policy"
-msgstr "PulseAudio geluidssysteem"
+msgstr "PulseAudio geluidssysteem KDE-routeringsbeleid"
#: ../src/daemon/pulseaudio-kde.desktop.in.h:2
-#, fuzzy
msgid "Start the PulseAudio Sound System with KDE Routing Policy"
-msgstr "Start het PulseAudio geluidssysteem"
+msgstr "Start het PulseAudio geluidssysteem met KDE-routeringsbeleid"
#: ../src/pulse/channelmap.c:105 ../src/pulse/channelmap.c:757
msgid "Mono"
@@ -848,7 +856,7 @@ msgstr "Achter rechts"
#: ../src/pulse/channelmap.c:115
msgid "Subwoofer"
-msgstr ""
+msgstr "Subwoofer"
#: ../src/pulse/channelmap.c:117
msgid "Front Left-of-center"
@@ -1187,13 +1195,12 @@ msgid "%u B"
msgstr "%u B"
#: ../src/pulse/client-conf-x11.c:54 ../src/utils/pax11publish.c:100
-#, fuzzy
msgid "xcb_connect() failed"
-msgstr "pa_context_connect() mislukte: %s"
+msgstr "xcb_connect() mislukte"
#: ../src/pulse/client-conf-x11.c:59 ../src/utils/pax11publish.c:105
msgid "xcb_connection_has_error() returned true"
-msgstr ""
+msgstr "xcb_connection_has_error() gaf true terug"
#: ../src/pulse/client-conf-x11.c:97
msgid "Failed to parse cookie data"
@@ -1331,15 +1338,15 @@ msgstr "Stroom buffer attributen veranderden.%s"
#: ../src/utils/pacat.c:416
msgid "Cork request stack is empty: corking stream"
-msgstr ""
+msgstr "Cork verzoekstack is leeg: corking stream"
#: ../src/utils/pacat.c:422
msgid "Cork request stack is empty: uncorking stream"
-msgstr ""
+msgstr "Cork verzoekstack is leeg: uncorking stream"
#: ../src/utils/pacat.c:426
msgid "Warning: Received more uncork requests than cork requests!"
-msgstr ""
+msgstr "Waarschuwing: meer ontkurkverzoeken ontvangen dan kurkverzoeken!"
#: ../src/utils/pacat.c:451
#, c-format
From 10964e0f088778c9cfc71635ca1cad948b7da598 Mon Sep 17 00:00:00 2001
From: Milo Ivir
Date: Tue, 14 Jul 2020 18:17:36 +0000
Subject: [PATCH 030/872] Translated using Weblate (Croatian)
Currently translated at 100.0% (531 of 531 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/hr/
---
po/hr.po | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/po/hr.po b/po/hr.po
index 746d74013..b88daf40b 100644
--- a/po/hr.po
+++ b/po/hr.po
@@ -8,17 +8,18 @@ msgstr ""
"Project-Id-Version: pulseaudio\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2019-11-10 14:12+0100\n"
-"PO-Revision-Date: 2019-11-10 14:21+0100\n"
-"Last-Translator: gogo \n"
-"Language-Team: Croatian \n"
+"PO-Revision-Date: 2020-07-15 19:29+0000\n"
+"Last-Translator: Milo Ivir \n"
+"Language-Team: Croatian \n"
"Language: hr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
+"%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
+"X-Generator: Weblate 4.1.1\n"
"X-Launchpad-Export-Date: 2017-04-20 21:04+0000\n"
-"X-Generator: Poedit 2.2.1\n"
-"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n"
-"%10<=4 && (n%100<12 || n%100>14) ? 1 : 2);\n"
#: ../src/daemon/cmdline.c:113
#, c-format
@@ -186,9 +187,8 @@ msgid ""
"--log-level expects log level argument (either numeric in range 0..4 or one "
"of debug, info, notice, warn, error)."
msgstr ""
-"--log-level očekuje argument na razini zapisa (ili brojeve u rasponu 0..4 "
-"ili jedan od zapisa uklanjanja grešaka,informacija,bilješka,upozorenje,"
-"greška)"
+"--log-level očekuje argument na razini zapisa (numerički u rasponu od 0 do 4 "
+"ili jedan od sljedećih: debug, info, notice, warn, error)."
#: ../src/daemon/cmdline.c:277
msgid "--high-priority expects boolean argument"
@@ -449,8 +449,8 @@ msgid ""
"System mode refused for non-root user. Only starting the D-Bus server lookup "
"service."
msgstr ""
-"Način rada sustava je nedostupan za nekorijenske korinike. Samo pokreni D-"
-"Bus poslužitelja usluge pretraživanja."
+"Način rada sustava nedostupan je za neadministratorske korisnike. Pokreće se "
+"samo usluga pretraživanja D-Bus poslužitelja."
#: ../src/daemon/main.c:633
#, c-format
@@ -462,8 +462,8 @@ msgid ""
"This program is not intended to be run as root (unless --system is "
"specified)."
msgstr ""
-"Ovaj program nije namijenjen za korijensko pokretanje (osim -- ako je "
-"određeno sustavom)"
+"Ovaj program nije namijenjen za pokretanje kao administrator (osim ako je "
+"određen --system)."
#: ../src/daemon/main.c:665
msgid "Root privileges required."
@@ -706,7 +706,7 @@ msgstr "Zvučnici"
#: ../src/modules/alsa/alsa-mixer.c:2541
msgid "HDMI / DisplayPort"
-msgstr "HDMI / DisplayPort"
+msgstr "HDMI / Ekranski priključak"
#: ../src/modules/alsa/alsa-mixer.c:2542
msgid "Digital Output (S/PDIF)"
@@ -2205,7 +2205,7 @@ msgstr "NAZIV SLIVNIKA|#N"
#: ../src/utils/pacmd.c:64 ../src/utils/pacmd.c:65
msgid "NAME FILENAME"
-msgstr "NAZIV NAZIV DATOTEKE"
+msgstr "NAZIV NAZIV-DATOTEKE"
#: ../src/utils/pacmd.c:66
msgid "PATHNAME"
@@ -2385,7 +2385,7 @@ msgstr ""
"Zadane specifikacije uzorka: %s\n"
"Zadano mapiranje kanala: %s\n"
"Zadani slivnik: %s\n"
-"Zadani izvor: %s\n"
+"Zadani izvor: %s\n"
"Kolačić: %04x:%04x\n"
#: ../src/utils/pactl.c:261 ../src/utils/pactl.c:908 ../src/utils/pactl.c:986
From 09e03b7bc67836d8e184884150203340213cedb1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bal=C3=A1zs=20Mesk=C3=B3?=
Date: Mon, 20 Jul 2020 14:15:48 +0000
Subject: [PATCH 031/872] Translated using Weblate (Hungarian)
Currently translated at 100.0% (526 of 526 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/hu/
---
po/hu.po | 29 ++++++++++++++++-------------
1 file changed, 16 insertions(+), 13 deletions(-)
diff --git a/po/hu.po b/po/hu.po
index d6796229f..52fa4966f 100644
--- a/po/hu.po
+++ b/po/hu.po
@@ -8,20 +8,22 @@
msgid ""
msgstr ""
"Project-Id-Version: PulseAudio master\n"
-"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new\n"
+"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/"
+"issues/new\n"
"POT-Creation-Date: 2016-08-23 02:28+0000\n"
-"PO-Revision-Date: 2016-08-23 12:10+0200\n"
-"Last-Translator: Balázs Úr \n"
-"Language-Team: Hungarian \n"
+"PO-Revision-Date: 2020-07-21 15:29+0000\n"
+"Last-Translator: Balázs Meskó \n"
+"Language-Team: Hungarian \n"
"Language: hu\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.1.1\n"
"X-Poedit-Language: Hungarian\n"
"X-Poedit-Country: HUNGARY\n"
"X-Poedit-SourceCharset: utf-8\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Lokalize 1.2\n"
#: ../src/daemon/cmdline.c:113
#, c-format
@@ -567,7 +569,7 @@ msgstr "A „pa_pid_file_create()” függvényhívás meghiúsult."
#: ../src/daemon/main.c:1022
msgid "pa_core_new() failed."
-msgstr "A „pa_core_new()” függvényhívás meghiúsult: %s"
+msgstr "A pa_core_new() sikertelen."
#: ../src/daemon/main.c:1090
msgid "Failed to initialize daemon."
@@ -1091,7 +1093,7 @@ msgstr ""
"sink_master= format= "
"rate= channels= "
"channel_map= autoloaded= use_volume_sharing="
+"automatikusan betöltődik> use_volume_sharing= "
#: ../src/modules/module-filter-apply.c:47
msgid "autoclean="
@@ -1115,10 +1117,10 @@ msgstr ""
"master= format= rate= channels= channel_map= "
"plugin= label= "
-"control= "
+"control= "
"input_ladspaport_map= output_ladspaport_map="
+"elválasztott listája> "
#: ../src/modules/module-null-sink.c:47
msgid "Clocked NULL sink"
@@ -1554,7 +1556,7 @@ msgstr "Belső hiba"
#: ../src/pulse/error.c:49
msgid "Connection terminated"
-msgstr "A kapcsolat megszakadt."
+msgstr "A kapcsolat megszakadt"
#: ../src/pulse/error.c:50
msgid "Entity killed"
@@ -1566,7 +1568,7 @@ msgstr "Érvénytelen kiszolgáló"
#: ../src/pulse/error.c:52
msgid "Module initialization failed"
-msgstr "A modul előkészítése meghiúsult."
+msgstr "A modul előkészítése sikertelen"
#: ../src/pulse/error.c:53
msgid "Bad state"
@@ -1744,7 +1746,7 @@ msgstr ""
#: ../src/utils/pacat.c:409
msgid "not "
-msgstr "nem"
+msgstr "nem "
#: ../src/utils/pacat.c:416
#, c-format
@@ -2852,6 +2854,7 @@ msgstr ""
"\n"
" -h, --help Ezen súgó megjelenítése\n"
" --version Verziószám megjelenítése\n"
+"\n"
" -s, --server=KISZOLGÁLÓ Csatlakozás ehhez a kiszolgálóhoz\n"
" -n, --client-name=NÉV A kliens neve a kiszolgálón\n"
From 1d066f2264be984f7a1a5b9fb40ba616dd15ba17 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 13 Aug 2020 22:01:18 +0300
Subject: [PATCH 032/872] i18n: Update pulseaudio.pot
---
po/pulseaudio.pot | 88 +++++++++++++++++++++++------------------------
1 file changed, 44 insertions(+), 44 deletions(-)
diff --git a/po/pulseaudio.pot b/po/pulseaudio.pot
index 113a0a0c8..a082fa2a7 100644
--- a/po/pulseaudio.pot
+++ b/po/pulseaudio.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: pulseaudio\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new\n"
-"POT-Creation-Date: 2020-07-10 13:43+0300\n"
+"POT-Creation-Date: 2020-08-13 22:00+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -598,26 +598,22 @@ msgid "Digital Input (S/PDIF)"
msgstr ""
#: src/modules/alsa/alsa-mixer.c:2728
-msgid "Digital Passthrough (S/PDIF)"
-msgstr ""
-
-#: src/modules/alsa/alsa-mixer.c:2729
msgid "Multichannel Input"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:2730
+#: src/modules/alsa/alsa-mixer.c:2729
msgid "Multichannel Output"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:2731
+#: src/modules/alsa/alsa-mixer.c:2730
msgid "Game Output"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:2732
+#: src/modules/alsa/alsa-mixer.c:2731
msgid "Chat Output"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4355
+#: src/modules/alsa/alsa-mixer.c:4380
msgid "Analog Mono"
msgstr ""
@@ -626,127 +622,131 @@ msgstr ""
#. * 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.
-#: src/modules/alsa/alsa-mixer.c:4356 src/modules/alsa/alsa-mixer.c:4364
-#: src/modules/alsa/alsa-mixer.c:4365
+#: src/modules/alsa/alsa-mixer.c:4381 src/modules/alsa/alsa-mixer.c:4389
+#: src/modules/alsa/alsa-mixer.c:4390
msgid "Analog Stereo"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4357 src/pulse/channelmap.c:103
+#: src/modules/alsa/alsa-mixer.c:4382 src/pulse/channelmap.c:103
#: src/pulse/channelmap.c:771
msgid "Mono"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4358 src/pulse/channelmap.c:775
+#: src/modules/alsa/alsa-mixer.c:4383 src/pulse/channelmap.c:775
msgid "Stereo"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4366 src/modules/alsa/alsa-mixer.c:4367
+#: src/modules/alsa/alsa-mixer.c:4391 src/modules/alsa/alsa-mixer.c:4392
msgid "Multichannel"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4368
+#: src/modules/alsa/alsa-mixer.c:4393
msgid "Analog Surround 2.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4369
+#: src/modules/alsa/alsa-mixer.c:4394
msgid "Analog Surround 3.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4370
+#: src/modules/alsa/alsa-mixer.c:4395
msgid "Analog Surround 3.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4371
+#: src/modules/alsa/alsa-mixer.c:4396
msgid "Analog Surround 4.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4372
+#: src/modules/alsa/alsa-mixer.c:4397
msgid "Analog Surround 4.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4373
+#: src/modules/alsa/alsa-mixer.c:4398
msgid "Analog Surround 5.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4374
+#: src/modules/alsa/alsa-mixer.c:4399
msgid "Analog Surround 5.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4375
+#: src/modules/alsa/alsa-mixer.c:4400
msgid "Analog Surround 6.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4376
+#: src/modules/alsa/alsa-mixer.c:4401
msgid "Analog Surround 6.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4377
+#: src/modules/alsa/alsa-mixer.c:4402
msgid "Analog Surround 7.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4378
+#: src/modules/alsa/alsa-mixer.c:4403
msgid "Analog Surround 7.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4379
+#: src/modules/alsa/alsa-mixer.c:4404
msgid "Digital Stereo (IEC958)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4380
-msgid "Digital Passthrough (IEC958)"
-msgstr ""
-
-#: src/modules/alsa/alsa-mixer.c:4381
+#: src/modules/alsa/alsa-mixer.c:4405
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4382
+#: src/modules/alsa/alsa-mixer.c:4406
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4383
+#: src/modules/alsa/alsa-mixer.c:4407
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4384
+#: src/modules/alsa/alsa-mixer.c:4408
msgid "Digital Stereo (HDMI)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4385
+#: src/modules/alsa/alsa-mixer.c:4409
msgid "Digital Surround 5.1 (HDMI)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4518
+#: src/modules/alsa/alsa-mixer.c:4410
+msgid "Chat"
+msgstr ""
+
+#: src/modules/alsa/alsa-mixer.c:4411
+msgid "Game"
+msgstr ""
+
+#: src/modules/alsa/alsa-mixer.c:4545
msgid "Analog Mono Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4519
+#: src/modules/alsa/alsa-mixer.c:4546
msgid "Analog Stereo Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4520
+#: src/modules/alsa/alsa-mixer.c:4547
msgid "Digital Stereo Duplex (IEC958)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4521
+#: src/modules/alsa/alsa-mixer.c:4548
msgid "Multichannel Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4522
+#: src/modules/alsa/alsa-mixer.c:4549
msgid "Stereo Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4523 src/modules/alsa/module-alsa-card.c:188
+#: src/modules/alsa/alsa-mixer.c:4550 src/modules/alsa/module-alsa-card.c:188
#: src/modules/bluetooth/module-bluez5-device.c:2053
msgid "Off"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4622
+#: src/modules/alsa/alsa-mixer.c:4650
#, c-format
msgid "%s Output"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4630
+#: src/modules/alsa/alsa-mixer.c:4658
#, c-format
msgid "%s Input"
msgstr ""
@@ -2132,7 +2132,7 @@ msgid "\t\t%s: %s (type: %s, priority: %u%s%s%s)\n"
msgstr ""
#: src/utils/pactl.c:366 src/utils/pactl.c:474 src/utils/pactl.c:638
-msgid ", available group: "
+msgid ", availability group: "
msgstr ""
#: src/utils/pactl.c:371 src/utils/pactl.c:479
From 1887a0f88bb0e785342ede23d80b06fdf68b8995 Mon Sep 17 00:00:00 2001
From: Felix Yan
Date: Fri, 14 Aug 2020 14:13:32 +0000
Subject: [PATCH 033/872] shell-completion: zsh: Correct a typo
---
shell-completion/zsh/_pulseaudio | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/shell-completion/zsh/_pulseaudio b/shell-completion/zsh/_pulseaudio
index 0e9e89bd3..da72010c6 100644
--- a/shell-completion/zsh/_pulseaudio
+++ b/shell-completion/zsh/_pulseaudio
@@ -668,7 +668,7 @@ _pacat_completion() {
'--process-time-msec=[request the specified process time in msec]:msec' \
'--property=[set the specified property]:property' \
'--raw[record/play raw PCM data]' \
- '--passthrough[passtrough data]' \
+ '--passthrough[passthrough data]' \
'--file-format=[record/play formatted PCM data]:format:_pacat_file_formats' \
'--list-file-formats[list available formats]' \
'::files:_files' \
From 90a6c5ef0707ff024f1dab68ff0ffa2e9fd9b8b5 Mon Sep 17 00:00:00 2001
From: itsthem
Date: Fri, 28 Aug 2020 13:15:50 +0000
Subject: [PATCH 034/872] pulsecore: Replace gendered pronouns with gender
neutral ones
---
src/pulsecore/client.h | 2 +-
src/pulsecore/mcalign.h | 2 +-
src/pulsecore/memblock.h | 2 +-
src/pulsecore/sink.c | 4 ++--
src/pulsecore/source.c | 4 ++--
5 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/src/pulsecore/client.h b/src/pulsecore/client.h
index eb8173d32..c6952e3c9 100644
--- a/src/pulsecore/client.h
+++ b/src/pulsecore/client.h
@@ -29,7 +29,7 @@
/* Every connection to the server should have a pa_client
* attached. That way the user may generate a listing of all connected
- * clients easily and kill them if he wants.*/
+ * clients easily and kill them if they want.*/
struct pa_client {
uint32_t index;
diff --git a/src/pulsecore/mcalign.h b/src/pulsecore/mcalign.h
index e29d82e7e..353e66ad6 100644
--- a/src/pulsecore/mcalign.h
+++ b/src/pulsecore/mcalign.h
@@ -28,7 +28,7 @@
/* Method of operation: the user creates a new mcalign object by
* calling pa_mcalign_new() with the appropriate aligning
- * granularity. After that he may call pa_mcalign_push() for an input
+ * granularity. After that they may call pa_mcalign_push() for an input
* memchunk. After exactly one memchunk the user has to call
* pa_mcalign_pop() until it returns -1. If pa_mcalign_pop() returns
* 0, the memchunk *c is valid and aligned to the granularity. Some
diff --git a/src/pulsecore/memblock.h b/src/pulsecore/memblock.h
index 57ae4b294..4273c098e 100644
--- a/src/pulsecore/memblock.h
+++ b/src/pulsecore/memblock.h
@@ -99,7 +99,7 @@ void pa_memblock_unref(pa_memblock*b);
pa_memblock* pa_memblock_ref(pa_memblock*b);
/* This special unref function has to be called by the owner of the
-memory of a static memory block when he wants to release all
+memory of a static memory block when they want to release all
references to the memory. This causes the memory to be copied and
converted into a pool of malloc'ed memory block. Please note that this
function is not multiple caller safe, i.e. needs to be locked
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 9bb5ae506..56a3ce433 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -704,8 +704,8 @@ void pa_sink_put(pa_sink* s) {
pa_cvolume_remap(&s->real_volume, &root_sink->channel_map, &s->channel_map);
} else
/* We assume that if the sink implementor changed the default
- * volume he did so in real_volume, because that is the usual
- * place where he is supposed to place his changes. */
+ * volume they did so in real_volume, because that is the usual
+ * place where they are supposed to place their changes. */
s->reference_volume = s->real_volume;
s->thread_info.soft_volume = s->soft_volume;
diff --git a/src/pulsecore/source.c b/src/pulsecore/source.c
index 039c7bd5f..705c93906 100644
--- a/src/pulsecore/source.c
+++ b/src/pulsecore/source.c
@@ -654,8 +654,8 @@ void pa_source_put(pa_source *s) {
pa_cvolume_remap(&s->real_volume, &root_source->channel_map, &s->channel_map);
} else
/* We assume that if the sink implementor changed the default
- * volume he did so in real_volume, because that is the usual
- * place where he is supposed to place his changes. */
+ * volume they did so in real_volume, because that is the usual
+ * place where they are supposed to place their changes. */
s->reference_volume = s->real_volume;
s->thread_info.soft_volume = s->soft_volume;
From e36132b7dcc4283b1f8b89a14f145966e7264463 Mon Sep 17 00:00:00 2001
From: Tom Yan
Date: Sun, 16 Aug 2020 20:16:01 +0000
Subject: [PATCH 035/872] main, core: check idle after loading conf
pa_core_check_idle() uses pa_core.exit_idle_time, which is set after the
pa_core_new() call, so pa_core_check_idle() needs to be called later.
This patch preserves the fact that core state is set to PA_CORE_RUNNING
after checking idle (now in main). It doesn't seem to matter anyway and
main(pa_core_new(state:PA_CORE_STARTUP)->...->state:PA_CORE_RUNNING)
seems right as well.
---
src/daemon/main.c | 4 ++++
src/pulsecore/core.c | 4 ----
2 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/daemon/main.c b/src/daemon/main.c
index f1810c5f1..59f931219 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -1067,6 +1067,10 @@ int main(int argc, char *argv[]) {
c->server_type = conf->local_server_type;
#endif
+ pa_core_check_idle(c);
+
+ c->state = PA_CORE_RUNNING;
+
pa_cpu_init(&c->cpu_info);
pa_assert_se(pa_signal_init(pa_mainloop_get_api(mainloop)) == 0);
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index 335f8029e..c28c5312b 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -159,10 +159,6 @@ pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t
pa_check_signal_is_blocked(SIGPIPE);
#endif
- pa_core_check_idle(c);
-
- c->state = PA_CORE_RUNNING;
-
return c;
}
From f003d6ca62186e2b5394a7f9a2e29c1b3fbf56c7 Mon Sep 17 00:00:00 2001
From: Tom Yan
Date: Sun, 16 Aug 2020 22:16:23 +0000
Subject: [PATCH 036/872] man: mention that exit-idle-time is complied if the
user is lingering
---
man/pulse-daemon.conf.5.xml.in | 3 ++-
man/pulseaudio.1.xml.in | 5 +++--
2 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/man/pulse-daemon.conf.5.xml.in b/man/pulse-daemon.conf.5.xml.in
index d76e0b31d..52223fb8c 100644
--- a/man/pulse-daemon.conf.5.xml.in
+++ b/man/pulse-daemon.conf.5.xml.in
@@ -326,7 +326,8 @@ License along with PulseAudio; if not, see .
session, then any positive value will be reset to 0 so that PulseAudio
will terminate immediately on logout. A positive value therefore has
effect only in environments where there's no support for login session
- tracking. A negative value can still be used to disable any automatic
+ tracking (or if the user is logged in without a session spawned, a.k.a.
+ lingering). A negative value can still be used to disable any automatic
exit.
When PulseAudio runs in the system mode, automatic exit is always
diff --git a/man/pulseaudio.1.xml.in b/man/pulseaudio.1.xml.in
index 4b9f085d3..996bee082 100644
--- a/man/pulseaudio.1.xml.in
+++ b/man/pulseaudio.1.xml.in
@@ -212,8 +212,9 @@ License along with PulseAudio; if not, see .
session, then any positive value will be reset to 0 so that PulseAudio
will terminate immediately on logout. A positive value therefore has
effect only in environments where there's no support for login session
- tracking. A negative value can still be used to disable any automatic
- exit.
+ tracking (or if the user is logged in without a session spawned,
+ a.k.a. lingering). A negative value can still be used to disable any
+ automatic exit.
When PulseAudio runs in the system mode, automatic exit is always
disabled, so this option does nothing.
From 460d0c0b79939e4e43f30824bcd6358feb1727f5 Mon Sep 17 00:00:00 2001
From: Arun Raghavan
Date: Tue, 11 Aug 2020 00:46:56 -0400
Subject: [PATCH 037/872] alsa-mixer: Add an explicit profile-set for Audigy
devices
These lost analog-mono support when we made that a fallback profile, as
the stereo-fallback would be picked up as the only input profile, and
that does not work in duplex mode.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/750
---
src/Makefile.am | 1 +
src/modules/alsa/90-pulseaudio.rules | 11 +++
.../alsa/mixer/profile-sets/audigy.conf | 94 +++++++++++++++++++
3 files changed, 106 insertions(+)
create mode 100644 src/modules/alsa/mixer/profile-sets/audigy.conf
diff --git a/src/Makefile.am b/src/Makefile.am
index f9f26f520..bd764037b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1353,6 +1353,7 @@ dist_alsaprofilesets_DATA = \
modules/alsa/mixer/profile-sets/default.conf \
modules/alsa/mixer/profile-sets/force-speaker.conf \
modules/alsa/mixer/profile-sets/force-speaker-and-int-mic.conf \
+ modules/alsa/mixer/profile-sets/audigy.conf \
modules/alsa/mixer/profile-sets/maudio-fasttrack-pro.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio4dj.conf \
modules/alsa/mixer/profile-sets/native-instruments-audio8dj.conf \
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
index 1614a1685..2f82e8e9a 100644
--- a/src/modules/alsa/90-pulseaudio.rules
+++ b/src/modules/alsa/90-pulseaudio.rules
@@ -19,6 +19,7 @@ SUBSYSTEM!="sound", GOTO="pulseaudio_end"
ACTION!="change", GOTO="pulseaudio_end"
KERNEL!="card*", GOTO="pulseaudio_end"
SUBSYSTEMS=="usb", GOTO="pulseaudio_check_usb"
+SUBSYSTEMS=="pci", GOTO="pulseaudio_check_pci"
SUBSYSTEMS=="firewire", GOTO="pulseaudio_firewire_quirk"
SUBSYSTEMS=="platform", DRIVERS=="thinkpad_acpi", ENV{PULSE_IGNORE}="1"
@@ -143,6 +144,16 @@ ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_
GOTO="pulseaudio_end"
+LABEL="pulseaudio_check_pci"
+
+# Creative SoundBlaster Audigy-based cards
+# EMU10k2/CA0100/CA0102/CA10200
+ATTRS{vendor}=="0x1102", ATTRS{device}=="0x0004", ENV{PULSE_PROFILE_SET}="audigy.conf"
+# CA0108/CA10300
+ATTRS{vendor}=="0x1102", ATTRS{device}=="0x0008", ENV{PULSE_PROFILE_SET}="audigy.conf"
+
+GOTO="pulseaudio_end"
+
LABEL="pulseaudio_firewire_quirk"
# Focusrite Saffire Pro 10/26 i/o has a quirk to disappear from IEEE 1394 bus when losing connections.
diff --git a/src/modules/alsa/mixer/profile-sets/audigy.conf b/src/modules/alsa/mixer/profile-sets/audigy.conf
new file mode 100644
index 000000000..043596e30
--- /dev/null
+++ b/src/modules/alsa/mixer/profile-sets/audigy.conf
@@ -0,0 +1,94 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+; Creative Sound Blaster Audigy product line
+;
+; These are just copies of the mappings we find in default.conf, with the
+; small change of making analog-stereo and analog-mono non-fallback mappings.
+; This is needed because these cards only support duplex profiles with mono
+; inputs, and in the default configuration, with stereo being a fallback
+; mapping, the mono mapping is never tried.
+;
+; See default.conf for an explanation on the directives used here.
+
+[General]
+auto-profiles = yes
+
+# Based on stereo-fallback
+[Mapping analog-stereo]
+device-strings = hw:%f
+channel-map = front-left,front-right
+paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
+paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
+priority = 1
+
+# Based on mono-fallback
+[Mapping analog-mono]
+device-strings = hw:%f
+channel-map = mono
+paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2 analog-output-mono
+paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headset-mic
+priority = 1
+
+# The rest of these are identical to what's in default.conf
+[Mapping analog-surround-21]
+device-strings = surround21:%f
+channel-map = front-left,front-right,lfe
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 13
+direction = output
+
+[Mapping analog-surround-40]
+device-strings = surround40:%f
+channel-map = front-left,front-right,rear-left,rear-right
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 12
+direction = output
+
+[Mapping analog-surround-41]
+device-strings = surround41:%f
+channel-map = front-left,front-right,rear-left,rear-right,lfe
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 13
+direction = output
+
+[Mapping analog-surround-50]
+device-strings = surround50:%f
+channel-map = front-left,front-right,rear-left,rear-right,front-center
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 12
+direction = output
+
+[Mapping analog-surround-51]
+device-strings = surround51:%f
+channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 13
+direction = output
+
+[Mapping analog-surround-71]
+device-strings = surround71:%f
+channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
+description = Analog Surround 7.1
+paths-output = analog-output analog-output-lineout analog-output-speaker
+priority = 12
+direction = output
+
+[Mapping iec958-stereo]
+device-strings = iec958:%f
+channel-map = left,right
+paths-input = iec958-stereo-input
+paths-output = iec958-stereo-output
+priority = 5
From d0ccc50c1e57fbd7990b6a48b3520eab80586dff Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?G=C3=B6ran=20Uddeborg?=
Date: Thu, 13 Aug 2020 19:24:58 +0000
Subject: [PATCH 038/872] Translated using Weblate (Swedish)
Currently translated at 100.0% (534 of 534 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/sv/
---
po/sv.po | 75 ++++++++++++++++++++++++++++----------------------------
1 file changed, 38 insertions(+), 37 deletions(-)
diff --git a/po/sv.po b/po/sv.po
index ac9e7a625..9260259df 100644
--- a/po/sv.po
+++ b/po/sv.po
@@ -20,15 +20,16 @@ msgstr ""
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/"
"issues\n"
"POT-Creation-Date: 2018-12-11 15:29+0000\n"
-"PO-Revision-Date: 2019-01-08 23:44+0100\n"
-"Last-Translator: Josef Andersson \n"
-"Language-Team: Svenska \n"
+"PO-Revision-Date: 2020-08-14 19:29+0000\n"
+"Last-Translator: Göran Uddeborg \n"
+"Language-Team: Swedish \n"
"Language: sv\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.1.1\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.1.1\n"
#: src/daemon/cmdline.c:113
#, c-format
@@ -1289,131 +1290,131 @@ msgstr "Höger sida"
#: src/pulse/channelmap.c:121
msgid "Auxiliary 0"
-msgstr "Auxiliary 0"
+msgstr "Extra 0"
#: src/pulse/channelmap.c:122
msgid "Auxiliary 1"
-msgstr "Auxiliary 1"
+msgstr "Extra 1"
#: src/pulse/channelmap.c:123
msgid "Auxiliary 2"
-msgstr "Auxiliary 2"
+msgstr "Extra 2"
#: src/pulse/channelmap.c:124
msgid "Auxiliary 3"
-msgstr "Auxiliary 3"
+msgstr "Extra 3"
#: src/pulse/channelmap.c:125
msgid "Auxiliary 4"
-msgstr "Auxiliary 4"
+msgstr "Extra 4"
#: src/pulse/channelmap.c:126
msgid "Auxiliary 5"
-msgstr "Auxiliary 5"
+msgstr "Extra 5"
#: src/pulse/channelmap.c:127
msgid "Auxiliary 6"
-msgstr "Auxiliary 6"
+msgstr "Extra 6"
#: src/pulse/channelmap.c:128
msgid "Auxiliary 7"
-msgstr "Auxiliary 7"
+msgstr "Extra 7"
#: src/pulse/channelmap.c:129
msgid "Auxiliary 8"
-msgstr "Auxiliary 8"
+msgstr "Extra 8"
#: src/pulse/channelmap.c:130
msgid "Auxiliary 9"
-msgstr "Auxiliary 9"
+msgstr "Extra 9"
#: src/pulse/channelmap.c:131
msgid "Auxiliary 10"
-msgstr "Auxiliary 10"
+msgstr "Extra 10"
#: src/pulse/channelmap.c:132
msgid "Auxiliary 11"
-msgstr "Auxiliary 11"
+msgstr "Extra 11"
#: src/pulse/channelmap.c:133
msgid "Auxiliary 12"
-msgstr "Auxiliary 12"
+msgstr "Extra 12"
#: src/pulse/channelmap.c:134
msgid "Auxiliary 13"
-msgstr "Auxiliary 13"
+msgstr "Extra 13"
#: src/pulse/channelmap.c:135
msgid "Auxiliary 14"
-msgstr "Auxiliary 14"
+msgstr "Extra 14"
#: src/pulse/channelmap.c:136
msgid "Auxiliary 15"
-msgstr "Auxiliary 15"
+msgstr "Extra 15"
#: src/pulse/channelmap.c:137
msgid "Auxiliary 16"
-msgstr "Auxiliary 16"
+msgstr "Extra 16"
#: src/pulse/channelmap.c:138
msgid "Auxiliary 17"
-msgstr "Auxiliary 17"
+msgstr "Extra 17"
#: src/pulse/channelmap.c:139
msgid "Auxiliary 18"
-msgstr "Auxiliary 18"
+msgstr "Extra 18"
#: src/pulse/channelmap.c:140
msgid "Auxiliary 19"
-msgstr "Auxiliary 19"
+msgstr "Extra 19"
#: src/pulse/channelmap.c:141
msgid "Auxiliary 20"
-msgstr "Auxiliary 20"
+msgstr "Extra 20"
#: src/pulse/channelmap.c:142
msgid "Auxiliary 21"
-msgstr "Auxiliary 21"
+msgstr "Extra 21"
#: src/pulse/channelmap.c:143
msgid "Auxiliary 22"
-msgstr "Auxiliary 22"
+msgstr "Extra 22"
#: src/pulse/channelmap.c:144
msgid "Auxiliary 23"
-msgstr "Auxiliary 23"
+msgstr "Extra 23"
#: src/pulse/channelmap.c:145
msgid "Auxiliary 24"
-msgstr "Auxiliary 24"
+msgstr "Extra 24"
#: src/pulse/channelmap.c:146
msgid "Auxiliary 25"
-msgstr "Auxiliary 25"
+msgstr "Extra 25"
#: src/pulse/channelmap.c:147
msgid "Auxiliary 26"
-msgstr "Auxiliary 26"
+msgstr "Extra 26"
#: src/pulse/channelmap.c:148
msgid "Auxiliary 27"
-msgstr "Auxiliary 27"
+msgstr "Extra 27"
#: src/pulse/channelmap.c:149
msgid "Auxiliary 28"
-msgstr "Auxiliary 28"
+msgstr "Extra 28"
#: src/pulse/channelmap.c:150
msgid "Auxiliary 29"
-msgstr "Auxiliary 29"
+msgstr "Extra 29"
#: src/pulse/channelmap.c:151
msgid "Auxiliary 30"
-msgstr "Auxiliary 30"
+msgstr "Extra 30"
#: src/pulse/channelmap.c:152
msgid "Auxiliary 31"
-msgstr "Auxiliary 31"
+msgstr "Extra 31"
#: src/pulse/channelmap.c:154
msgid "Top Center"
From c2b05eb704c81cba9b88b2eadbd3a4ea103e1ae9 Mon Sep 17 00:00:00 2001
From: Milo Casagrande
Date: Mon, 7 Sep 2020 08:56:16 +0000
Subject: [PATCH 039/872] Translated using Weblate (Italian)
Currently translated at 100.0% (533 of 533 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/it/
---
po/it.po | 23 ++++++++++++-----------
1 file changed, 12 insertions(+), 11 deletions(-)
diff --git a/po/it.po b/po/it.po
index 33cece3ea..0d66a7c36 100644
--- a/po/it.po
+++ b/po/it.po
@@ -12,15 +12,16 @@ msgstr ""
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/"
"issues\n"
"POT-Creation-Date: 2019-09-17 03:33+0000\n"
-"PO-Revision-Date: 2019-09-19 09:56+0200\n"
+"PO-Revision-Date: 2020-09-08 09:29+0000\n"
"Last-Translator: Milo Casagrande \n"
-"Language-Team: Italian \n"
+"Language-Team: Italian \n"
"Language: it\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
-"Plural-Forms: nplurals=2; plural=(n != 1);\n"
-"X-Generator: Poedit 2.2.3\n"
+"Plural-Forms: nplurals=2; plural=n != 1;\n"
+"X-Generator: Weblate 4.2.2\n"
# mamma mia che impressione
#: src/daemon/cmdline.c:113
@@ -1986,13 +1987,13 @@ msgstr ""
" connesso\n"
" --fix-channels Recupera il numero di canali e la "
"mappa\n"
-" dei canali dal sink a cui lo "
-"stream \n"
+" dei canali dal sink a cui lo stream "
+"\n"
" sta per essere connesso\n"
" --no-remix Non esegue l'upmix o il downmix \n"
" dei canali\n"
-" --no-remap Mappa i canali per indice invece "
-"che \n"
+" --no-remap Mappa i canali per indice invece che "
+"\n"
" per nome\n"
" --latency=BYTE Richiede la latenza specificata in "
"byte\n"
@@ -2006,9 +2007,9 @@ msgstr ""
" richiesta specificato in msec\n"
" --property=PROPRIETÀ=VAL Imposta la proprietà al valore "
"specificato\n"
-" --raw Registra/riproduce dati PCM grezzi\n"
+" --raw Registra/Riproduce dati PCM grezzi\n"
" --passthrough Dati pass-through\n"
-" --file-format=FFORMAT Registra/riproduce dati PCM "
+" --file-format=FFORMAT Registra/Riproduce dati PCM "
"formattati\n"
" --list-file-formats Elenca i formati disponibili\n"
" --monitor-stream=INDICE Registra dall'input sink con INDICE\n"
@@ -2894,7 +2895,7 @@ msgstr "Volume"
#: src/utils/pactl.c:1587
msgid "NAME|#N 1|0|toggle"
-msgstr "NAME|#N 1|0|toggle"
+msgstr "NOME|#N 1|0|toggle"
#: src/utils/pactl.c:1588
msgid "#N 1|0|toggle"
From c1a7d516b10114327ac4739b9af9307b1ab056c9 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Fri, 11 Sep 2020 11:13:02 +0300
Subject: [PATCH 040/872] man: client.conf: Explain that autospawn=no doesn't
disable systemd autostarting
---
man/pulse-client.conf.5.xml.in | 13 +++++++++++--
1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/man/pulse-client.conf.5.xml.in b/man/pulse-client.conf.5.xml.in
index b88898cb0..5c0eff31b 100644
--- a/man/pulse-client.conf.5.xml.in
+++ b/man/pulse-client.conf.5.xml.in
@@ -77,8 +77,17 @@ License along with PulseAudio; if not, see .
+
+
+
+
diff --git a/shell-completion/bash/pulseaudio b/shell-completion/bash/pulseaudio
index 1ca0e40b8..6c2635f65 100644
--- a/shell-completion/bash/pulseaudio
+++ b/shell-completion/bash/pulseaudio
@@ -113,7 +113,7 @@ _pactl() {
local comps
local flags='-h --help --version -s --server= --client-name='
local list_types='short sinks sources sink-inputs source-outputs cards
- modules samples clients'
+ modules samples clients message-handlers'
local commands=(stat info list exit upload-sample play-sample remove-sample
load-module unload-module move-sink-input move-source-output
suspend-sink suspend-source set-card-profile set-default-sink
diff --git a/shell-completion/zsh/_pulseaudio b/shell-completion/zsh/_pulseaudio
index 7668386fc..2a1f18eaa 100644
--- a/shell-completion/zsh/_pulseaudio
+++ b/shell-completion/zsh/_pulseaudio
@@ -285,6 +285,7 @@ _pactl_completion() {
'clients: list connected clients'
'samples: list samples'
'cards: list available cards'
+ 'message-handlers: list available message-handlers'
)
if ((CURRENT == 2)); then
diff --git a/src/Makefile.am b/src/Makefile.am
index d298d85d3..19f100f11 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -929,6 +929,7 @@ libpulse_la_SOURCES = \
pulse/timeval.c pulse/timeval.h \
pulse/utf8.c pulse/utf8.h \
pulse/util.c pulse/util.h \
+ pulse/message-params.c pulse/message-params.h \
pulse/volume.c pulse/volume.h \
pulse/xmalloc.c pulse/xmalloc.h
diff --git a/src/map-file b/src/map-file
index ea3f70268..0acbf05b5 100644
--- a/src/map-file
+++ b/src/map-file
@@ -229,6 +229,8 @@ pa_mainloop_quit;
pa_mainloop_run;
pa_mainloop_set_poll_func;
pa_mainloop_wakeup;
+pa_message_params_read_raw;
+pa_message_params_read_string;
pa_msleep;
pa_thread_make_realtime;
pa_operation_cancel;
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 7fefb9ce0..0671fa163 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -2236,8 +2236,15 @@ static void context_string_callback(pa_pdispatch *pd, uint32_t command, uint32_t
response = "";
if (o->callback) {
- pa_context_string_cb_t cb = (pa_context_string_cb_t) o->callback;
- cb(o->context, success, response, o->userdata);
+ char *response_copy;
+ pa_context_string_cb_t cb;
+
+ response_copy = pa_xstrdup(response);
+
+ cb = (pa_context_string_cb_t) o->callback;
+ cb(o->context, success, response_copy, o->userdata);
+
+ pa_xfree(response_copy);
}
finish:
diff --git a/src/pulse/introspect.h b/src/pulse/introspect.h
index d8cdc3c8c..2c3c4acf4 100644
--- a/src/pulse/introspect.h
+++ b/src/pulse/introspect.h
@@ -498,7 +498,7 @@ pa_operation* pa_context_unload_module(pa_context *c, uint32_t idx, pa_context_s
/** @{ \name Messages */
/** Callback prototype for pa_context_send_message_to_object() \since 15.0 */
-typedef void (*pa_context_string_cb_t)(pa_context *c, int success, const char *response, void *userdata);
+typedef void (*pa_context_string_cb_t)(pa_context *c, int success, char *response, void *userdata);
/** Send a message to an object that registered a message handler. For more information
* see https://cgit.freedesktop.org/pulseaudio/pulseaudio/tree/doc/messaging_api.txt. \since 15.0 */
diff --git a/src/pulse/meson.build b/src/pulse/meson.build
index aaebff53e..abc1e7921 100644
--- a/src/pulse/meson.build
+++ b/src/pulse/meson.build
@@ -19,6 +19,7 @@ libpulse_sources = [
'mainloop-api.c',
'mainloop-signal.c',
'mainloop.c',
+ 'message-params.c',
'operation.c',
'proplist.c',
'rtclock.c',
@@ -50,6 +51,7 @@ libpulse_headers = [
'mainloop-api.h',
'mainloop-signal.h',
'mainloop.h',
+ 'message-params.h',
'operation.h',
'proplist.h',
'pulseaudio.h',
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
new file mode 100644
index 000000000..0afda4f38
--- /dev/null
+++ b/src/pulse/message-params.c
@@ -0,0 +1,118 @@
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+
+#include "message-params.h"
+
+/* Split the specified string into elements. An element is defined as
+ * a sub-string between curly braces. The function is needed to parse
+ * the parameters of messages. Each time it is called it returns the
+ * position of the current element in result and the state pointer is
+ * advanced to the next list element.
+ *
+ * The variable state points to, should be initialized to NULL before
+ * the first call. The function returns 1 on success, 0 if end of string
+ * is encountered and -1 on parse error.
+ *
+ * result is set to NULL on end of string or parse error. */
+static int split_list(char *c, char **result, void **state) {
+ char *current = *state ? *state : c;
+ uint32_t open_braces;
+
+ pa_assert(result);
+
+ *result = NULL;
+
+ /* Empty or no string */
+ if (!current || *current == 0)
+ return 0;
+
+ /* Find opening brace */
+ while (*current != 0) {
+
+ if (*current == '{')
+ break;
+
+ /* unexpected closing brace, parse error */
+ if (*current == '}')
+ return -1;
+
+ current++;
+ }
+
+ /* No opening brace found, end of string */
+ if (*current == 0)
+ return 0;
+
+ *result = current + 1;
+ open_braces = 1;
+
+ while (open_braces != 0 && *current != 0) {
+ current++;
+ if (*current == '{')
+ open_braces++;
+ if (*current == '}')
+ open_braces--;
+ }
+
+ /* Parse error, closing brace missing */
+ if (open_braces != 0) {
+ *result = NULL;
+ return -1;
+ }
+
+ /* Replace } with 0 */
+ *current = 0;
+
+ *state = current + 1;
+
+ return 1;
+}
+
+/* Read a string from the parameter list. The state pointer is
+ * advanced to the next element of the list. Returns a pointer
+ * to a sub-string within c. The result must not be freed. */
+int pa_message_params_read_string(char *c, const char **result, void **state) {
+ char *start_pos;
+ int r;
+
+ pa_assert(result);
+
+ if ((r = split_list(c, &start_pos, state)) == 1)
+ *result = start_pos;
+
+ return r;
+}
+
+/* Another wrapper for split_list() to distinguish between reading
+ * pure string data and raw data which may contain further lists. */
+int pa_message_params_read_raw(char *c, char **result, void **state) {
+ return split_list(c, result, state);
+}
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
new file mode 100644
index 000000000..5c9bc1a6e
--- /dev/null
+++ b/src/pulse/message-params.h
@@ -0,0 +1,42 @@
+#ifndef foomessagehelperhfoo
+#define foomessagehelperhfoo
+
+/***
+ This file is part of PulseAudio.
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, see .
+***/
+
+#include
+#include
+#include
+
+#include
+#include
+
+/** \file
+ * Utility functions for reading and writing message parameters */
+
+PA_C_DECL_BEGIN
+
+/** Read raw data from a parameter list. Used to split a message parameter
+ * string into list elements \since 15.0 */
+int pa_message_params_read_raw(char *c, char **result, void **state);
+
+/** Read a string from a parameter list. \since 15.0 */
+int pa_message_params_read_string(char *c, const char **result, void **state);
+
+PA_C_DECL_END
+
+#endif
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index cb824ed17..da8b3b3da 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -86,7 +86,7 @@ static char *message_handler_list(pa_core *c) {
return pa_strbuf_to_string_free(buf);
}
-static int core_message_handler(const char *object_path, const char *message, const char *message_parameters, char **response, void *userdata) {
+static int core_message_handler(const char *object_path, const char *message, char *message_parameters, char **response, void *userdata) {
pa_core *c;
pa_assert(c = (pa_core *) userdata);
diff --git a/src/pulsecore/message-handler.c b/src/pulsecore/message-handler.c
index 18c62fc2d..427186dbd 100644
--- a/src/pulsecore/message-handler.c
+++ b/src/pulsecore/message-handler.c
@@ -90,6 +90,8 @@ void pa_message_handler_unregister(pa_core *c, const char *object_path) {
/* Send a message to an object identified by object_path */
int pa_message_handler_send_message(pa_core *c, const char *object_path, const char *message, const char *message_parameters, char **response) {
struct pa_message_handler *handler;
+ int ret;
+ char *parameter_copy;
pa_assert(c);
pa_assert(object_path);
@@ -101,9 +103,14 @@ int pa_message_handler_send_message(pa_core *c, const char *object_path, const c
if (!(handler = pa_hashmap_get(c->message_handlers, object_path)))
return -PA_ERR_NOENTITY;
+ parameter_copy = pa_xstrdup(message_parameters);
+
/* The handler is expected to return an error code and may also
return an error string in response */
- return handler->callback(handler->object_path, message, message_parameters, response, handler->userdata);
+ ret = handler->callback(handler->object_path, message, parameter_copy, response, handler->userdata);
+
+ pa_xfree(parameter_copy);
+ return ret;
}
/* Set handler description */
diff --git a/src/pulsecore/message-handler.h b/src/pulsecore/message-handler.h
index be94510f0..38b24e1b2 100644
--- a/src/pulsecore/message-handler.h
+++ b/src/pulsecore/message-handler.h
@@ -26,7 +26,7 @@
typedef int (*pa_message_handler_cb_t)(
const char *object_path,
const char *message,
- const char *message_parameters,
+ char *message_parameters,
char **response,
void *userdata);
diff --git a/src/utils/pactl.c b/src/utils/pactl.c
index 26b85dfc3..bc1c5265a 100644
--- a/src/utils/pactl.c
+++ b/src/utils/pactl.c
@@ -35,6 +35,7 @@
#include
#include
+#include
#include
#include
@@ -882,7 +883,7 @@ static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
complete_action();
}
-static void send_message_callback(pa_context *c, int success, const char *response, void *userdata) {
+static void send_message_callback(pa_context *c, int success, char *response, void *userdata) {
if (!success) {
pa_log(_("Send message failed: %s"), pa_strerror(pa_context_errno(c)));
@@ -895,6 +896,62 @@ static void send_message_callback(pa_context *c, int success, const char *respon
complete_action();
}
+static void list_handlers_callback(pa_context *c, int success, char *response, void *userdata) {
+ void *state = NULL;
+ char *handler_list;
+ char *handler_struct;
+ int err;
+
+ if (!success) {
+ pa_log(_("list-handlers message failed: %s"), pa_strerror(pa_context_errno(c)));
+ quit(1);
+ return;
+ }
+
+ if (pa_message_params_read_raw(response, &handler_list, &state) <= 0) {
+ pa_log(_("list-handlers message response could not be parsed correctly"));
+ quit(1);
+ return;
+ }
+
+ state = NULL;
+ while ((err = pa_message_params_read_raw(handler_list, &handler_struct, &state)) > 0) {
+ void *state2 = NULL;
+ const char *path;
+ const char *description;
+
+ if (pa_message_params_read_string(handler_struct, &path, &state2) <= 0) {
+ err = -1;
+ break;
+ }
+ if (pa_message_params_read_string(handler_struct, &description, &state2) <= 0) {
+ err = -1;
+ break;
+ }
+
+ if (short_list_format)
+ printf("%s\n", path);
+ else {
+ if (nl)
+ printf("\n");
+ nl = true;
+
+ printf("Message Handler %s\n"
+ "\tDescription: %s\n",
+ path,
+ description);
+ }
+ }
+
+ if (err < 0) {
+ pa_log(_("list-handlers message response could not be parsed correctly"));
+ quit(1);
+ return;
+ }
+
+ complete_action();
+}
+
static void volume_relative_adjust(pa_cvolume *cv) {
pa_assert(volume_flags & VOL_RELATIVE);
@@ -1308,6 +1365,8 @@ static void context_state_callback(pa_context *c, void *userdata) {
o = pa_context_get_sample_info_list(c, get_sample_info_callback, NULL);
else if (pa_streq(list_type, "cards"))
o = pa_context_get_card_info_list(c, get_card_info_callback, NULL);
+ else if (pa_streq(list_type, "message-handlers"))
+ o = pa_context_send_message_to_object(c, "/core", "list-handlers", NULL, list_handlers_callback, NULL);
else
pa_assert_not_reached();
} else {
@@ -1744,12 +1803,13 @@ int main(int argc, char *argv[]) {
if (pa_streq(argv[i], "modules") || pa_streq(argv[i], "clients") ||
pa_streq(argv[i], "sinks") || pa_streq(argv[i], "sink-inputs") ||
pa_streq(argv[i], "sources") || pa_streq(argv[i], "source-outputs") ||
- pa_streq(argv[i], "samples") || pa_streq(argv[i], "cards")) {
+ pa_streq(argv[i], "samples") || pa_streq(argv[i], "cards") ||
+ pa_streq(argv[i], "message-handlers")) {
list_type = pa_xstrdup(argv[i]);
} else if (pa_streq(argv[i], "short")) {
short_list_format = true;
} else {
- pa_log(_("Specify nothing, or one of: %s"), "modules, sinks, sources, sink-inputs, source-outputs, clients, samples, cards");
+ pa_log(_("Specify nothing, or one of: %s"), "modules, sinks, sources, sink-inputs, source-outputs, clients, samples, cards, message-handlers");
goto quit;
}
}
From 590fd1ca698031b77ddcf6fc44d3729211760dac Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Tue, 14 Jan 2020 13:24:16 +0100
Subject: [PATCH 110/872] message-params: Allow parameter strings to contain
escaped curly braces
The patch adds the possibility to escape curly braces within parameter strings
and introduces several new functions that can be used for writing parameters.
For writing, the structure pa_message_params, which is a wrapper for pa_strbuf
has been created. Following new write functions are available:
pa_message_params_new() - creates a new pa_message_params structure
pa_message_params_free() - frees a pa_message_params structure
pa_message_param_to_string_free() - converts a pa_message_param to string and
frees the structure
pa_message_params_begin_list() - starts a list
pa_message_params_end_list() - ends a list
pa_message_params_write_string() - writes a string to a pa_message_params structure
pa_message_params_write_raw() - writes a raw string to a pa_message_params structure
For string parameters that contain curly braces or backslashes, those characters
will be escaped when using pa_message_params_write_string(), while write_raw() will
put the string into the buffer without any changes.
For reading, pa_message_params_read_string() reverts the changes that
pa_message_params_write_string() might have introduced.
The patch also adds more restrictions on the object path name. Now only
alphanumeric characters and one of "_", ".", "-" and "/" are allowed.
The path name may not end with a / or contain a double slash. If the user
specifies a trailing / when sending a message, it will be silently removed.
Part-of:
---
doc/messaging_api.txt | 7 +-
src/Makefile.am | 3 +-
src/map-file | 7 ++
src/meson.build | 2 +
src/pulse/message-params.c | 158 +++++++++++++++++++++++++++++---
src/pulse/message-params.h | 39 +++++++-
src/pulsecore/core.c | 22 +++--
src/pulsecore/message-handler.c | 58 ++++++++----
8 files changed, 249 insertions(+), 47 deletions(-)
diff --git a/doc/messaging_api.txt b/doc/messaging_api.txt
index 431a5df27..e0a921da4 100644
--- a/doc/messaging_api.txt
+++ b/doc/messaging_api.txt
@@ -14,10 +14,15 @@ look like that:
{{Integer} {{1st float} {2nd float} ...}}{...}
Any characters that are not enclosed in curly braces are ignored (all characters
between { and {, between } and } and between } and {). The same syntax is used
-to specify message parameters. The following reference lists available messages,
+to specify message parameters. The reference further down lists available messages,
their parameters and return values. If a return value is enclosed in {}, this
means that multiple elements of the same type may be returned.
+For string parameters that contain curly braces or backslashes, those characters
+must be escaped by adding a "\" before them.
+
+Reference:
+
Object path: /core
Message: list-handlers
Parameters: None
diff --git a/src/Makefile.am b/src/Makefile.am
index 19f100f11..df912a8b3 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -711,6 +711,7 @@ libpulsecommon_@PA_MAJORMINOR@_la_SOURCES = \
pulse/timeval.c pulse/timeval.h \
pulse/rtclock.c pulse/rtclock.h \
pulse/volume.c pulse/volume.h \
+ pulse/message-params.c pulse/message-params.h \
pulsecore/atomic.h \
pulsecore/authkey.c pulsecore/authkey.h \
pulsecore/conf-parser.c pulsecore/conf-parser.h \
@@ -917,6 +918,7 @@ libpulse_la_SOURCES = \
pulse/mainloop-api.c pulse/mainloop-api.h \
pulse/mainloop-signal.c pulse/mainloop-signal.h \
pulse/mainloop.c pulse/mainloop.h \
+ pulse/message-params.c pulse/message-params.h \
pulse/operation.c pulse/operation.h \
pulse/proplist.c pulse/proplist.h \
pulse/pulseaudio.h \
@@ -929,7 +931,6 @@ libpulse_la_SOURCES = \
pulse/timeval.c pulse/timeval.h \
pulse/utf8.c pulse/utf8.h \
pulse/util.c pulse/util.h \
- pulse/message-params.c pulse/message-params.h \
pulse/volume.c pulse/volume.h \
pulse/xmalloc.c pulse/xmalloc.h
diff --git a/src/map-file b/src/map-file
index 0acbf05b5..4d196c11d 100644
--- a/src/map-file
+++ b/src/map-file
@@ -229,8 +229,15 @@ pa_mainloop_quit;
pa_mainloop_run;
pa_mainloop_set_poll_func;
pa_mainloop_wakeup;
+pa_message_params_begin_list;
+pa_message_params_end_list;
+pa_message_params_free;
+pa_message_params_new;
pa_message_params_read_raw;
pa_message_params_read_string;
+pa_message_params_to_string_free;
+pa_message_params_write_raw;
+pa_message_params_write_string;
pa_msleep;
pa_thread_make_realtime;
pa_operation_cancel;
diff --git a/src/meson.build b/src/meson.build
index 8d74a3164..b84112eee 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -5,6 +5,7 @@ libpulsecommon_sources = [
'pulse/format.c',
'pulse/json.c',
'pulse/mainloop-api.c',
+ 'pulse/message-params.c',
'pulse/xmalloc.c',
'pulse/proplist.c',
'pulse/utf8.c',
@@ -78,6 +79,7 @@ libpulsecommon_headers = [
'pulse/format.h',
'pulse/json.h',
'pulse/mainloop-api.h',
+ 'pulse/message-params.h',
'pulse/xmalloc.h',
'pulse/proplist.h',
'pulse/utf8.h',
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index 0afda4f38..236800bca 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -28,23 +28,33 @@
#include
#include
+#include
+#include
#include "message-params.h"
+/* Message parameter structure, a wrapper for pa_strbuf */
+struct pa_message_params {
+ pa_strbuf *buffer;
+};
+
/* Split the specified string into elements. An element is defined as
* a sub-string between curly braces. The function is needed to parse
* the parameters of messages. Each time it is called it returns the
* position of the current element in result and the state pointer is
- * advanced to the next list element.
+ * advanced to the next list element. On return, the parameter
+ * *is_unpacked indicates if the string is plain text or contains a
+ * sub-list. is_unpacked may be NULL.
*
* The variable state points to, should be initialized to NULL before
* the first call. The function returns 1 on success, 0 if end of string
* is encountered and -1 on parse error.
*
* result is set to NULL on end of string or parse error. */
-static int split_list(char *c, char **result, void **state) {
+static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
char *current = *state ? *state : c;
uint32_t open_braces;
+ bool found_backslash = false;
pa_assert(result);
@@ -57,29 +67,52 @@ static int split_list(char *c, char **result, void **state) {
/* Find opening brace */
while (*current != 0) {
- if (*current == '{')
+ /* Skip escaped curly braces. */
+ if (*current == '\\' && !found_backslash) {
+ found_backslash = true;
+ current++;
+ continue;
+ }
+
+ if (*current == '{' && !found_backslash)
break;
/* unexpected closing brace, parse error */
- if (*current == '}')
+ if (*current == '}' && !found_backslash)
return -1;
+ found_backslash = false;
current++;
}
/* No opening brace found, end of string */
if (*current == 0)
- return 0;
+ return 0;
+ if (is_unpacked)
+ *is_unpacked = true;
*result = current + 1;
+ found_backslash = false;
open_braces = 1;
while (open_braces != 0 && *current != 0) {
current++;
- if (*current == '{')
+
+ /* Skip escaped curly braces. */
+ if (*current == '\\' && !found_backslash) {
+ found_backslash = true;
+ continue;
+ }
+
+ if (*current == '{' && !found_backslash) {
open_braces++;
- if (*current == '}')
+ if (is_unpacked)
+ *is_unpacked = false;
+ }
+ if (*current == '}' && !found_backslash)
open_braces--;
+
+ found_backslash = false;
}
/* Parse error, closing brace missing */
@@ -96,23 +129,122 @@ static int split_list(char *c, char **result, void **state) {
return 1;
}
+/* Read functions */
+
/* Read a string from the parameter list. The state pointer is
* advanced to the next element of the list. Returns a pointer
- * to a sub-string within c. The result must not be freed. */
+ * to a sub-string within c. Escape characters will be removed
+ * from the string. The result must not be freed. */
int pa_message_params_read_string(char *c, const char **result, void **state) {
char *start_pos;
+ char *value = NULL;
int r;
+ bool is_unpacked = true;
pa_assert(result);
- if ((r = split_list(c, &start_pos, state)) == 1)
- *result = start_pos;
+ if ((r = split_list(c, &start_pos, &is_unpacked, state)) == 1)
+ value = start_pos;
+
+ /* Check if we got a plain string not containing further lists */
+ if (!is_unpacked) {
+ /* Parse error */
+ r = -1;
+ value = NULL;
+ }
+
+ if (value)
+ *result = pa_unescape(value);
return r;
}
-/* Another wrapper for split_list() to distinguish between reading
- * pure string data and raw data which may contain further lists. */
+/* A wrapper for split_list() to distinguish between reading pure
+ * string data and raw data which may contain further lists. */
int pa_message_params_read_raw(char *c, char **result, void **state) {
- return split_list(c, result, state);
+ return split_list(c, result, NULL, state);
+}
+
+/* Write functions. The functions are wrapper functions around pa_strbuf,
+ * so that the client does not need to use pa_strbuf directly. */
+
+/* Creates a new pa_message_param structure */
+pa_message_params *pa_message_params_new(void) {
+ pa_message_params *params;
+
+ params = pa_xnew(pa_message_params, 1);
+ params->buffer = pa_strbuf_new();
+
+ return params;
+}
+
+/* Frees a pa_message_params structure */
+void pa_message_params_free(pa_message_params *params) {
+ pa_assert(params);
+
+ pa_strbuf_free(params->buffer);
+ pa_xfree(params);
+}
+
+/* Converts a pa_message_param structure to string and frees the structure.
+ * The returned string needs to be freed with pa_xree(). */
+char *pa_message_params_to_string_free(pa_message_params *params) {
+ char *result;
+
+ pa_assert(params);
+
+ result = pa_strbuf_to_string_free(params->buffer);
+
+ pa_xfree(params);
+ return result;
+}
+
+/* Writes an opening curly brace */
+void pa_message_params_begin_list(pa_message_params *params) {
+
+ pa_assert(params);
+
+ pa_strbuf_putc(params->buffer, '{');
+}
+
+/* Writes a closing curly brace */
+void pa_message_params_end_list(pa_message_params *params) {
+
+ pa_assert(params);
+
+ pa_strbuf_putc(params->buffer, '}');
+}
+
+/* Writes a string to a message_params structure, adding curly braces
+ * around the string and escaping curly braces within the string. */
+void pa_message_params_write_string(pa_message_params *params, const char *value) {
+ char *output;
+
+ pa_assert(params);
+
+ /* Null value is written as empty element */
+ if (!value)
+ value = "";
+
+ output = pa_escape(value, "{}");
+ pa_strbuf_printf(params->buffer, "{%s}", output);
+
+ pa_xfree(output);
+}
+
+/* Writes a raw string to a message_params structure, adding curly braces
+ * around the string if add_braces is true. This function can be used to
+ * write parts of a string or whole parameter lists that have been prepared
+ * elsewhere (for example an array). */
+void pa_message_params_write_raw(pa_message_params *params, const char *value, bool add_braces) {
+ pa_assert(params);
+
+ /* Null value is written as empty element */
+ if (!value)
+ value = "";
+
+ if (add_braces)
+ pa_strbuf_printf(params->buffer, "{%s}", value);
+ else
+ pa_strbuf_puts(params->buffer, value);
}
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index 5c9bc1a6e..f30164ff9 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -30,13 +30,48 @@
PA_C_DECL_BEGIN
+/** Structure which holds a parameter list. Wrapper for pa_strbuf \since 15.0 */
+typedef struct pa_message_params pa_message_params;
+
+/** @{ \name Read functions */
+
/** Read raw data from a parameter list. Used to split a message parameter
- * string into list elements \since 15.0 */
+ * string into list elements. The string returned in *result must not be freed. \since 15.0 */
int pa_message_params_read_raw(char *c, char **result, void **state);
-/** Read a string from a parameter list. \since 15.0 */
+/** Read a string from a parameter list. Escaped curly braces and backslashes
+ * will be unescaped. \since 15.0 */
int pa_message_params_read_string(char *c, const char **result, void **state);
+/** @} */
+
+/** @{ \name Write functions */
+
+/** Create a new pa_message_params structure \since 15.0 */
+pa_message_params *pa_message_params_new(void);
+
+/** Free a pa_message_params structure. \since 15.0 */
+void pa_message_params_free(pa_message_params *params);
+
+/** Convert pa_message_params to string, free pa_message_params structure. \since 15.0 */
+char *pa_message_params_to_string_free(pa_message_params *params);
+
+/** Start a list by writing an opening brace. \since 15.0 */
+void pa_message_params_begin_list(pa_message_params *params);
+
+/** End a list by writing a closing brace. \since 15.0 */
+void pa_message_params_end_list(pa_message_params *params);
+
+/** Append string to parameter list. Curly braces and backslashes will be escaped. \since 15.0 */
+void pa_message_params_write_string(pa_message_params *params, const char *value);
+
+/** Append raw string to parameter list. Used to write incomplete strings
+ * or complete parameter lists (for example arrays). Adds curly braces around
+ * the string if add_braces is true. \since 15.0 */
+void pa_message_params_write_raw(pa_message_params *params, const char *value, bool add_braces);
+
+/** @} */
+
PA_C_DECL_END
#endif
diff --git a/src/pulsecore/core.c b/src/pulsecore/core.c
index da8b3b3da..8b830199f 100644
--- a/src/pulsecore/core.c
+++ b/src/pulsecore/core.c
@@ -29,6 +29,7 @@
#include
#include
#include
+#include
#include
#include
@@ -65,25 +66,26 @@ static void core_free(pa_object *o);
/* Returns a list of handlers. */
static char *message_handler_list(pa_core *c) {
- pa_strbuf *buf;
+ pa_message_params *param;
void *state = NULL;
struct pa_message_handler *handler;
- buf = pa_strbuf_new();
+ param = pa_message_params_new();
- pa_strbuf_putc(buf, '{');
+ pa_message_params_begin_list(param);
PA_HASHMAP_FOREACH(handler, c->message_handlers, state) {
- pa_strbuf_putc(buf, '{');
+ pa_message_params_begin_list(param);
- pa_strbuf_printf(buf, "{%s} {", handler->object_path);
- if (handler->description)
- pa_strbuf_puts(buf, handler->description);
+ /* object_path cannot contain characters that need escaping, therefore
+ * pa_message_params_write_raw() can safely be used here. */
+ pa_message_params_write_raw(param, handler->object_path, true);
+ pa_message_params_write_string(param, handler->description);
- pa_strbuf_puts(buf, "}}");
+ pa_message_params_end_list(param);
}
- pa_strbuf_putc(buf, '}');
+ pa_message_params_end_list(param);
- return pa_strbuf_to_string_free(buf);
+ return pa_message_params_to_string_free(param);
}
static int core_message_handler(const char *object_path, const char *message, char *message_parameters, char **response, void *userdata) {
diff --git a/src/pulsecore/message-handler.c b/src/pulsecore/message-handler.c
index 427186dbd..40644554a 100644
--- a/src/pulsecore/message-handler.c
+++ b/src/pulsecore/message-handler.c
@@ -31,17 +31,36 @@
#include "message-handler.h"
-/* Check if a string does not contain control characters. Currently these are
- * only "{" and "}". */
-static bool string_is_valid(const char *test_string) {
+/* Check if a path string starts with a / and only contains valid characters.
+ * Also reject double slashes. */
+static bool object_path_is_valid(const char *test_string) {
uint32_t i;
+ if (!test_string)
+ return false;
+
+ /* Make sure the string starts with a / */
+ if (test_string[0] != '/')
+ return false;
+
for (i = 0; test_string[i]; i++) {
- if (test_string[i] == '{' ||
- test_string[i] == '}')
- return false;
+
+ if ((test_string[i] >= 'a' && test_string[i] <= 'z') ||
+ (test_string[i] >= 'A' && test_string[i] <= 'Z') ||
+ (test_string[i] >= '0' && test_string[i] <= '9') ||
+ test_string[i] == '.' ||
+ test_string[i] == '_' ||
+ test_string[i] == '-' ||
+ (test_string[i] == '/' && test_string[i + 1] != '/'))
+ continue;
+
+ return false;
}
+ /* Make sure the string does not end with a / */
+ if (test_string[i - 1] == '/')
+ return false;
+
return true;
}
@@ -56,13 +75,8 @@ void pa_message_handler_register(pa_core *c, const char *object_path, const char
pa_assert(cb);
pa_assert(userdata);
- /* Ensure that the object path is not empty and starts with "/". */
- pa_assert(object_path[0] == '/');
-
- /* Ensure that object path and description are valid strings */
- pa_assert(string_is_valid(object_path));
- if (description)
- pa_assert(string_is_valid(description));
+ /* Ensure that object path is valid */
+ pa_assert(object_path_is_valid(object_path));
handler = pa_xnew0(struct pa_message_handler, 1);
handler->userdata = userdata;
@@ -91,7 +105,7 @@ void pa_message_handler_unregister(pa_core *c, const char *object_path) {
int pa_message_handler_send_message(pa_core *c, const char *object_path, const char *message, const char *message_parameters, char **response) {
struct pa_message_handler *handler;
int ret;
- char *parameter_copy;
+ char *parameter_copy, *path_copy;
pa_assert(c);
pa_assert(object_path);
@@ -100,8 +114,16 @@ int pa_message_handler_send_message(pa_core *c, const char *object_path, const c
*response = NULL;
- if (!(handler = pa_hashmap_get(c->message_handlers, object_path)))
+ path_copy = pa_xstrdup(object_path);
+
+ /* Remove trailing / from path name if present */
+ if (path_copy[strlen(path_copy) - 1] == '/')
+ path_copy[strlen(path_copy) - 1] = 0;
+
+ if (!(handler = pa_hashmap_get(c->message_handlers, path_copy))) {
+ pa_xfree(path_copy);
return -PA_ERR_NOENTITY;
+ }
parameter_copy = pa_xstrdup(message_parameters);
@@ -110,6 +132,7 @@ int pa_message_handler_send_message(pa_core *c, const char *object_path, const c
ret = handler->callback(handler->object_path, message, parameter_copy, response, handler->userdata);
pa_xfree(parameter_copy);
+ pa_xfree(path_copy);
return ret;
}
@@ -123,11 +146,6 @@ int pa_message_handler_set_description(pa_core *c, const char *object_path, cons
if (!(handler = pa_hashmap_get(c->message_handlers, object_path)))
return -PA_ERR_NOENTITY;
- if (description) {
- if (!string_is_valid(description))
- return -PA_ERR_INVALID;
- }
-
pa_xfree(handler->description);
handler->description = pa_xstrdup(description);
From ca6638860805366148ab8bbd6d731a1df8ce8bbb Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Tue, 14 Jan 2020 14:04:11 +0100
Subject: [PATCH 111/872] core-util: Add pa_atoi64() and pa_atou64() functions
Part-of:
---
src/pulsecore/core-util.c | 87 +++++++++++++++++++++++++++++++++++++++
src/pulsecore/core-util.h | 2 +
2 files changed, 89 insertions(+)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 601b1d1df..d421a7572 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2243,6 +2243,50 @@ int pa_atou(const char *s, uint32_t *ret_u) {
return 0;
}
+/* Convert the string s to an unsigned 64 bit integer in *ret_u */
+int pa_atou64(const char *s, uint64_t *ret_u) {
+ char *x = NULL;
+ unsigned long long l;
+
+ pa_assert(s);
+ pa_assert(ret_u);
+
+ /* strtoull() ignores leading spaces. We don't. */
+ if (isspace((unsigned char)*s)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* strtoull() accepts strings that start with a minus sign. In that case the
+ * original negative number gets negated, and strtoull() returns the negated
+ * result. We don't want that kind of behaviour. strtoull() also allows a
+ * leading plus sign, which is also a thing that we don't want. */
+ if (*s == '-' || *s == '+') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ errno = 0;
+ l = strtoull(s, &x, 0);
+
+ /* If x doesn't point to the end of s, there was some trailing garbage in
+ * the string. If x points to s, no conversion was done (empty string). */
+ if (!x || *x || x == s || errno) {
+ if (!errno)
+ errno = EINVAL;
+ return -1;
+ }
+
+ if ((uint64_t) l != l) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ *ret_u = (uint64_t) l;
+
+ return 0;
+}
+
/* Convert the string s to a signed long integer in *ret_l. */
int pa_atol(const char *s, long *ret_l) {
char *x = NULL;
@@ -2281,6 +2325,49 @@ int pa_atol(const char *s, long *ret_l) {
return 0;
}
+/* Convert the string s to a signed 64 bit integer in *ret_l. */
+int pa_atoi64(const char *s, int64_t *ret_l) {
+ char *x = NULL;
+ long long l;
+
+ pa_assert(s);
+ pa_assert(ret_l);
+
+ /* strtoll() ignores leading spaces. We don't. */
+ if (isspace((unsigned char)*s)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ /* strtoll() accepts leading plus signs, but that's ugly, so we don't allow
+ * that. */
+ if (*s == '+') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ errno = 0;
+ l = strtoll(s, &x, 0);
+
+ /* If x doesn't point to the end of s, there was some trailing garbage in
+ * the string. If x points to s, no conversion was done (at least an empty
+ * string can trigger this). */
+ if (!x || *x || x == s || errno) {
+ if (!errno)
+ errno = EINVAL;
+ return -1;
+ }
+
+ *ret_l = l;
+
+ if ((int64_t) l != l) {
+ errno = ERANGE;
+ return -1;
+ }
+
+ return 0;
+}
+
#ifdef HAVE_STRTOD_L
static locale_t c_locale = NULL;
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 9440af917..3117df882 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -151,6 +151,8 @@ int pa_atoi(const char *s, int32_t *ret_i);
int pa_atou(const char *s, uint32_t *ret_u);
int pa_atol(const char *s, long *ret_l);
int pa_atod(const char *s, double *ret_d);
+int pa_atoi64(const char *s, int64_t *ret_l);
+int pa_atou64(const char *s, uint64_t *ret_u);
size_t pa_snprintf(char *str, size_t size, const char *format, ...);
size_t pa_vsnprintf(char *str, size_t size, const char *format, va_list ap);
From 8140932afdccbe29e7b03456f965b28a0abf24bb Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Tue, 14 Jan 2020 16:41:59 +0100
Subject: [PATCH 112/872] message-params: Add read/write functions for various
simple data types
The following functions have been added:
pa_message_params_write_double() - writes a double to a pa_message_params structure
pa_message_params_write_int64() - writes an integer to a pa_message_params structure
pa_message_params_write_uint64() - writes an unsigned to a pa_message_params structure
pa_message_params_write_bool() - writes a boolean to a pa_message_params structure
pa_message_params_read_double() - read a double from a parameter list
pa_message_params_read_int64() - read an integer from a parameter list
pa_message_params_read_uint64() - read an unsigned from a parameter list
pa_message_params_read_bool() - read a boolean from a parameter list
The patch also improves the doxygen documentation im message-params.h
Part-of:
---
src/map-file | 8 ++
src/pulse/message-params.c | 192 +++++++++++++++++++++++++++++++++++--
src/pulse/message-params.h | 62 +++++++++++-
3 files changed, 250 insertions(+), 12 deletions(-)
diff --git a/src/map-file b/src/map-file
index 4d196c11d..172fd441d 100644
--- a/src/map-file
+++ b/src/map-file
@@ -233,11 +233,19 @@ pa_message_params_begin_list;
pa_message_params_end_list;
pa_message_params_free;
pa_message_params_new;
+pa_message_params_read_bool;
+pa_message_params_read_double;
+pa_message_params_read_int64;
pa_message_params_read_raw;
pa_message_params_read_string;
+pa_message_params_read_uint64;
pa_message_params_to_string_free;
+pa_message_params_write_bool;
+pa_message_params_write_double;
+pa_message_params_write_int64;
pa_message_params_write_raw;
pa_message_params_write_string;
+pa_message_params_write_uint64;
pa_msleep;
pa_thread_make_realtime;
pa_operation_cancel;
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index 236800bca..8885f95e8 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
@@ -62,7 +63,7 @@ static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
/* Empty or no string */
if (!current || *current == 0)
- return 0;
+ return PA_MESSAGE_PARAMS_LIST_END;
/* Find opening brace */
while (*current != 0) {
@@ -79,7 +80,7 @@ static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
/* unexpected closing brace, parse error */
if (*current == '}' && !found_backslash)
- return -1;
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
found_backslash = false;
current++;
@@ -87,7 +88,7 @@ static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
/* No opening brace found, end of string */
if (*current == 0)
- return 0;
+ return PA_MESSAGE_PARAMS_LIST_END;
if (is_unpacked)
*is_unpacked = true;
@@ -118,7 +119,7 @@ static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
/* Parse error, closing brace missing */
if (open_braces != 0) {
*result = NULL;
- return -1;
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
}
/* Replace } with 0 */
@@ -126,7 +127,7 @@ static int split_list(char *c, char **result, bool *is_unpacked, void **state) {
*state = current + 1;
- return 1;
+ return PA_MESSAGE_PARAMS_OK;
}
/* Read functions */
@@ -143,13 +144,13 @@ int pa_message_params_read_string(char *c, const char **result, void **state) {
pa_assert(result);
- if ((r = split_list(c, &start_pos, &is_unpacked, state)) == 1)
+ if ((r = split_list(c, &start_pos, &is_unpacked, state)) == PA_MESSAGE_PARAMS_OK)
value = start_pos;
/* Check if we got a plain string not containing further lists */
if (!is_unpacked) {
/* Parse error */
- r = -1;
+ r = PA_MESSAGE_PARAMS_PARSE_ERROR;
value = NULL;
}
@@ -165,6 +166,129 @@ int pa_message_params_read_raw(char *c, char **result, void **state) {
return split_list(c, result, NULL, state);
}
+/* Read a double from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_params_read_double(char *c, double *result, void **state) {
+ char *start_pos, *end_pos, *s;
+ int err;
+ struct lconv *locale;
+ double value;
+ bool is_unpacked = true;
+
+ pa_assert(result);
+
+ if ((err = split_list(c, &start_pos, &is_unpacked, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
+ /* Empty element */
+ if (!*start_pos)
+ return PA_MESSAGE_PARAMS_IS_NULL;
+
+ /* Check if we got a plain string not containing further lists */
+ if (!is_unpacked)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ /* Convert to double */
+ locale = localeconv();
+
+ /* Replace decimal point with the correct character for the
+ * current locale. This assumes that no thousand separator
+ * is used. */
+ for (s = start_pos; *s; s++) {
+ if (*s == '.' || *s == ',')
+ *s = *locale->decimal_point;
+ }
+
+ /* Convert to double */
+ errno = 0;
+ value = strtod(start_pos, &end_pos);
+
+ /* Conversion error or string contains invalid characters. If the
+ * whole string was used for conversion, end_pos should point to
+ * the end of the string. */
+ if (errno != 0 || *end_pos != 0 || end_pos == start_pos)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ *result = value;
+ return PA_MESSAGE_PARAMS_OK;
+}
+
+/* Read an integer from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_params_read_int64(char *c, int64_t *result, void **state) {
+ char *start_pos;
+ int err;
+ int64_t value;
+ bool is_unpacked = true;
+
+ pa_assert(result);
+
+ if ((err = split_list(c, &start_pos, &is_unpacked, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
+ /* Empty element */
+ if (!*start_pos)
+ return PA_MESSAGE_PARAMS_IS_NULL;
+
+ /* Check if we got a plain string not containing further lists */
+ if (!is_unpacked)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ /* Convert to int64 */
+ if (pa_atoi64(start_pos, &value) < 0)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ *result = value;
+ return PA_MESSAGE_PARAMS_OK;
+}
+
+/* Read an unsigned integer from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_params_read_uint64(char *c, uint64_t *result, void **state) {
+ char *start_pos;
+ int err;
+ uint64_t value;
+ bool is_unpacked = true;
+
+ pa_assert(result);
+
+ if ((err = split_list(c, &start_pos, &is_unpacked, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
+ /* Empty element */
+ if (!*start_pos)
+ return PA_MESSAGE_PARAMS_IS_NULL;
+
+ /* Check if we got a plain string not containing further lists */
+ if (!is_unpacked)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ /* Convert to int64 */
+ if (pa_atou64(start_pos, &value) < 0)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ *result = value;
+ return PA_MESSAGE_PARAMS_OK;
+}
+
+/* Read a boolean from the parameter list. The state pointer is
+ * advanced to the next element of the list. */
+int pa_message_params_read_bool(char *c, bool *result, void **state) {
+ int err;
+ uint64_t value;
+
+ pa_assert(result);
+
+ if ((err = pa_message_params_read_uint64(c, &value, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
+ *result = false;
+ if (value)
+ *result = true;
+
+ return PA_MESSAGE_PARAMS_OK;
+}
+
/* Write functions. The functions are wrapper functions around pa_strbuf,
* so that the client does not need to use pa_strbuf directly. */
@@ -239,7 +363,8 @@ void pa_message_params_write_string(pa_message_params *params, const char *value
void pa_message_params_write_raw(pa_message_params *params, const char *value, bool add_braces) {
pa_assert(params);
- /* Null value is written as empty element */
+ /* Null value is written as empty element if add_braces is true.
+ * Otherwise nothing is written. */
if (!value)
value = "";
@@ -248,3 +373,54 @@ void pa_message_params_write_raw(pa_message_params *params, const char *value, b
else
pa_strbuf_puts(params->buffer, value);
}
+
+/* Writes a double to a message_params structure, adding curly braces.
+ * precision gives the number of significant digits, not digits after
+ * the decimal point. */
+void pa_message_params_write_double(pa_message_params *params, double value, int precision) {
+ char *buf, *s;
+
+ pa_assert(params);
+
+ /* We do not care about locale because we do not know which locale is
+ * used on the server side. If the decimal separator is a comma, we
+ * replace it with a dot to achieve consistent output on all locales. */
+ buf = pa_sprintf_malloc("{%.*g}", precision, value);
+ for (s = buf; *s; s++) {
+ if (*s == ',') {
+ *s = '.';
+ break;
+ }
+ }
+
+ pa_strbuf_puts(params->buffer, buf);
+
+ pa_xfree(buf);
+}
+
+/* Writes an integer to a message_param structure, adding curly braces. */
+void pa_message_params_write_int64(pa_message_params *params, int64_t value) {
+
+ pa_assert(params);
+
+ pa_strbuf_printf(params->buffer, "{%lli}", (long long)value);
+}
+
+/* Writes an unsigned integer to a message_params structure, adding curly braces. */
+void pa_message_params_write_uint64(pa_message_params *params, uint64_t value) {
+
+ pa_assert(params);
+
+ pa_strbuf_printf(params->buffer, "{%llu}", (unsigned long long)value);
+}
+
+/* Writes a boolean to a message_params structure, adding curly braces. */
+void pa_message_params_write_bool(pa_message_params *params, bool value) {
+
+ pa_assert(params);
+
+ if (value)
+ pa_strbuf_puts(params->buffer, "{1}");
+ else
+ pa_strbuf_puts(params->buffer, "{0}");
+}
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index f30164ff9..a2e0f9e8d 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -26,28 +26,68 @@
#include
/** \file
- * Utility functions for reading and writing message parameters */
+ * Utility functions for reading and writing message parameters.
+ * All read functions return a value from pa_message_params_error_code
+ * and the read value in result (or *result for string functions).
+ * The string read functions read_string() and read_raw() return a pointer
+ * to a sub-string within the parameter list in *result, therefore the
+ * string in *result must not be freed and is only valid within the
+ * message handler callback function. If the string is needed outside
+ * the callback, it must be copied using pa_xstrdup().
+ * When a read function is called, the state pointer is advanced to the
+ * next list element. The variable state points to should be initialized
+ * to NULL before the first call.\n
+ * Write functions operate on a pa_message_params structure which is a
+ * wrapper for pa_strbuf. A parameter list or sub-list is started by a
+ * call to begin_list() and ended by a call to end_list().
+ * A pa_message_params structure must be converted to a string using
+ * pa_message_params_to_string_free() before it can be passed to a
+ * message handler. */
PA_C_DECL_BEGIN
/** Structure which holds a parameter list. Wrapper for pa_strbuf \since 15.0 */
typedef struct pa_message_params pa_message_params;
+/** Read function return values \since 15.0 */
+enum pa_message_params_error_code {
+ /** No value (empty element) found for numeric or boolean value */
+ PA_MESSAGE_PARAMS_IS_NULL = -2,
+ /** Error encountered while parsing a value */
+ PA_MESSAGE_PARAMS_PARSE_ERROR = -1,
+ /** End of parameter list reached */
+ PA_MESSAGE_PARAMS_LIST_END = 0,
+ /** Parsing successful */
+ PA_MESSAGE_PARAMS_OK = 1,
+};
+
/** @{ \name Read functions */
-/** Read raw data from a parameter list. Used to split a message parameter
+/** Read a boolean from parameter list in c. \since 15.0 */
+int pa_message_params_read_bool(char *c, bool *result, void **state);
+
+/** Read a double from parameter list in c. \since 15.0 */
+int pa_message_params_read_double(char *c, double *result, void **state);
+
+/** Read an integer from parameter list in c. \since 15.0 */
+int pa_message_params_read_int64(char *c, int64_t *result, void **state);
+
+/** Read raw data from parameter list in c. Used to split a message parameter
* string into list elements. The string returned in *result must not be freed. \since 15.0 */
int pa_message_params_read_raw(char *c, char **result, void **state);
-/** Read a string from a parameter list. Escaped curly braces and backslashes
+/** Read a string from a parameter list in c. Escaped curly braces and backslashes
* will be unescaped. \since 15.0 */
int pa_message_params_read_string(char *c, const char **result, void **state);
+/** Read an unsigned integer from parameter list in c. \since 15.0 */
+int pa_message_params_read_uint64(char *c, uint64_t *result, void **state);
+
/** @} */
/** @{ \name Write functions */
-/** Create a new pa_message_params structure \since 15.0 */
+/** Create a new pa_message_params structure. \since 15.0 */
pa_message_params *pa_message_params_new(void);
/** Free a pa_message_params structure. \since 15.0 */
@@ -62,6 +102,17 @@ void pa_message_params_begin_list(pa_message_params *params);
/** End a list by writing a closing brace. \since 15.0 */
void pa_message_params_end_list(pa_message_params *params);
+/** Append a boolean to parameter list. \since 15.0 */
+void pa_message_params_write_bool(pa_message_params *params, bool value);
+
+/** Append a double to parameter list. Precision gives the number of
+ * significant digits. The decimal separator will always be written as
+ * dot, regardless which locale is used. \since 15.0 */
+void pa_message_params_write_double(pa_message_params *params, double value, int precision);
+
+/** Append an integer to parameter list. \since 15.0 */
+void pa_message_params_write_int64(pa_message_params *params, int64_t value);
+
/** Append string to parameter list. Curly braces and backslashes will be escaped. \since 15.0 */
void pa_message_params_write_string(pa_message_params *params, const char *value);
@@ -70,6 +121,9 @@ void pa_message_params_write_string(pa_message_params *params, const char *value
* the string if add_braces is true. \since 15.0 */
void pa_message_params_write_raw(pa_message_params *params, const char *value, bool add_braces);
+/** Append an unsigned integer to parameter list. \since 15.0 */
+void pa_message_params_write_uint64(pa_message_params *params, uint64_t value);
+
/** @} */
PA_C_DECL_END
From ff64defc137f61f1376653f523b5aa17f139ae2c Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Tue, 14 Jan 2020 20:50:24 +0100
Subject: [PATCH 113/872] message-params: Add read functions for arrays
The following new functions have been added:
pa_message_params_read_double_array() - read an array of double from list
pa_message_params_read_int64_array() - read an array of int64 from list
pa_message_params_read_uint64_array() - read an array of uint64 from list
pa_message_params_read_string_array() - read an array of strings from list
Part-of:
---
src/map-file | 4 +
src/pulse/message-params.c | 173 ++++++++++++++++++++++++++++++++++++-
src/pulse/message-params.h | 29 ++++++-
3 files changed, 204 insertions(+), 2 deletions(-)
diff --git a/src/map-file b/src/map-file
index 172fd441d..7b1ed5206 100644
--- a/src/map-file
+++ b/src/map-file
@@ -235,10 +235,14 @@ pa_message_params_free;
pa_message_params_new;
pa_message_params_read_bool;
pa_message_params_read_double;
+pa_message_params_read_double_array;
pa_message_params_read_int64;
+pa_message_params_read_int64_array;
pa_message_params_read_raw;
pa_message_params_read_string;
+pa_message_params_read_string_array;
pa_message_params_read_uint64;
+pa_message_params_read_uint64_array;
pa_message_params_to_string_free;
pa_message_params_write_bool;
pa_message_params_write_double;
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index 8885f95e8..7d2dd8020 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -39,6 +39,61 @@ struct pa_message_params {
pa_strbuf *buffer;
};
+/* Helper functions */
+
+/* Count number of top level elements in parameter list */
+static int count_elements(const char *c) {
+ const char *s;
+ uint32_t element_count;
+ bool found_element, found_backslash;
+ int open_braces;
+
+ if (!c || *c == 0)
+ return PA_MESSAGE_PARAMS_LIST_END;
+
+ element_count = 0;
+ open_braces = 0;
+ found_element = false;
+ found_backslash = false;
+ s = c;
+
+ /* Count elements in list */
+ while (*s != 0) {
+
+ /* Skip escaped curly braces. */
+ if (*s == '\\' && !found_backslash) {
+ found_backslash = true;
+ s++;
+ continue;
+ }
+
+ if (*s == '{' && !found_backslash) {
+ found_element = true;
+ open_braces++;
+ }
+ if (*s == '}' && !found_backslash)
+ open_braces--;
+
+ /* unexpected closing brace, parse error */
+ if (open_braces < 0)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ if (open_braces == 0 && found_element) {
+ element_count++;
+ found_element = false;
+ }
+
+ found_backslash = false;
+ s++;
+ }
+
+ /* missing closing brace, parse error */
+ if (open_braces > 0)
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+
+ return element_count;
+}
+
/* Split the specified string into elements. An element is defined as
* a sub-string between curly braces. The function is needed to parse
* the parameters of messages. Each time it is called it returns the
@@ -188,7 +243,7 @@ int pa_message_params_read_double(char *c, double *result, void **state) {
if (!is_unpacked)
return PA_MESSAGE_PARAMS_PARSE_ERROR;
- /* Convert to double */
+ /* Get decimal separator for current locale */
locale = localeconv();
/* Replace decimal point with the correct character for the
@@ -289,6 +344,122 @@ int pa_message_params_read_bool(char *c, bool *result, void **state) {
return PA_MESSAGE_PARAMS_OK;
}
+/* Converts a parameter list to a string array. Escaping is removed from
+ * the strings. Returns an array of pointers to sub-strings within c in
+ * *results. The returned array must be freed, but not the strings
+ * within the array. The function returns the number of strings in the
+ * array. */
+int pa_message_params_read_string_array(char *c, const char ***results) {
+ void *state = NULL;
+ uint32_t element_count, i;
+ int err;
+ const char **values;
+
+ pa_assert(results);
+
+ /* Count elements, return if no element was found or parse error. */
+ if ((element_count = count_elements(c)) <= 0)
+ return element_count;
+
+ /* Allocate array */
+ values = pa_xmalloc0(element_count * sizeof(char *));
+
+ for (i = 0; (err = pa_message_params_read_string(c, &(values[i]), &state)) > 0; i++)
+ ;
+
+ if (err < 0) {
+ pa_xfree(values);
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ }
+
+ *results = values;
+ return element_count;
+}
+
+/* Converts a parameter list to a double array. */
+int pa_message_params_read_double_array(char *c, double **results) {
+ double *values;
+ void *state = NULL;
+ uint32_t element_count, i;
+ int err;
+
+ pa_assert(results);
+
+ /* Count elements, return if no element was found or parse error. */
+ if ((element_count = count_elements(c)) <= 0)
+ return element_count;
+
+ /* Allocate array */
+ values = pa_xmalloc0(element_count * sizeof(double));
+
+ for (i = 0; (err = pa_message_params_read_double(c, &(values[i]), &state)) > 0; i++)
+ ;
+
+ if (err < 0) {
+ pa_xfree(values);
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ }
+
+ *results = values;
+ return element_count;
+}
+
+/* Converts a parameter list to an int64 array. */
+int pa_message_params_read_int64_array(char *c, int64_t **results) {
+ int64_t *values;
+ void *state = NULL;
+ uint32_t element_count, i;
+ int err;
+
+ pa_assert(results);
+
+ /* Count elements, return if no element was found or parse error. */
+ if ((element_count = count_elements(c)) <= 0)
+ return element_count;
+
+ /* Allocate array */
+ values = pa_xmalloc0(element_count * sizeof(int64_t));
+
+ for (i = 0; (err = pa_message_params_read_int64(c, &(values[i]), &state)) > 0; i++)
+ ;
+
+ if (err < 0) {
+ pa_xfree(values);
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ }
+
+ *results = values;
+ return element_count;
+}
+
+/* Converts a parameter list to an uint64 array. */
+int pa_message_params_read_uint64_array(char *c, uint64_t **results) {
+ uint64_t *values;
+ void *state = NULL;
+ uint32_t element_count, i;
+ int err;
+
+ pa_assert(results);
+
+ /* Count elements, return if no element was found or parse error. */
+ if ((element_count = count_elements(c)) <= 0)
+ return element_count;
+
+ /* Allocate array */
+ values = pa_xmalloc0(element_count * sizeof(uint64_t));
+
+ for (i = 0; (err = pa_message_params_read_uint64(c, &(values[i]), &state)) > 0; i++)
+ ;
+
+ if (err < 0) {
+ pa_xfree(values);
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ }
+
+ *results = values;
+ return element_count;
+}
+
/* Write functions. The functions are wrapper functions around pa_strbuf,
* so that the client does not need to use pa_strbuf directly. */
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index a2e0f9e8d..3d90eac3c 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -36,7 +36,12 @@
* the callback, it must be copied using pa_xstrdup().
* When a read function is called, the state pointer is advanced to the
* next list element. The variable state points to should be initialized
- * to NULL before the first call.\n
+ * to NULL before the first call.
+ * All read functions except read_raw() preserve a default value passed
+ * in result if the call fails. For the array functions, results must be
+ * initialized prior to the call either to NULL or to an array with default
+ * values. If the function succeeds, the default array will be freed and
+ * the number of elements in the result array is returned.\n\n
* Write functions operate on a pa_message_params structure which is a
* wrapper for pa_strbuf. A parameter list or sub-list is started by a
* call to begin_list() and ended by a call to end_list().
@@ -69,9 +74,19 @@ int pa_message_params_read_bool(char *c, bool *result, void **state);
/** Read a double from parameter list in c. \since 15.0 */
int pa_message_params_read_double(char *c, double *result, void **state);
+/** Converts a parameter list to a double array. Empty elements in the parameter
+ * list are treated as error. Before the call, results must be initialized, either
+ * to NULL or to an array with default values. \since 15.0 */
+int pa_message_params_read_double_array(char *c, double **results);
+
/** Read an integer from parameter list in c. \since 15.0 */
int pa_message_params_read_int64(char *c, int64_t *result, void **state);
+/** Converts a parameter list to an int64 array. Empty elements in the parameter
+ * list are treated as error. Before the call, results must be initialized, either
+ * to NULL or to an array with default values. \since 15.0 */
+int pa_message_params_read_int64_array(char *c, int64_t **results);
+
/** Read raw data from parameter list in c. Used to split a message parameter
* string into list elements. The string returned in *result must not be freed. \since 15.0 */
int pa_message_params_read_raw(char *c, char **result, void **state);
@@ -80,9 +95,21 @@ int pa_message_params_read_raw(char *c, char **result, void **state);
* will be unescaped. \since 15.0 */
int pa_message_params_read_string(char *c, const char **result, void **state);
+/** Convert a parameter list to a string array. Escaping is removed from
+ * the strings. Returns an array of pointers to sub-strings within c in
+ * *results. The returned array must be freed, but not the strings
+ * within the array. Before the call, results must be initialized, either
+ * to NULL or to an array with default values. \since 15.0 */
+int pa_message_params_read_string_array(char *c, const char ***results);
+
/** Read an unsigned integer from parameter list in c. \since 15.0 */
int pa_message_params_read_uint64(char *c, uint64_t *result, void **state);
+/** Converts a parameter list to an uint64 array. Empty elements in the parameter
+ * list are treated as error. Before the call, results must be initialized, either
+ * to NULL or to an array with default values. \since 15.0 */
+int pa_message_params_read_uint64_array(char *c, uint64_t **results);
+
/** @} */
/** @{ \name Write functions */
From 6722b2d8c422493829c4c57ca5ec1919c7c74231 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 9 Jun 2020 07:56:17 +0300
Subject: [PATCH 114/872] core-util: Make range checks easier to read
It wasn't immediately obvious to me what these checks are supposed to
do. Explicitly checking against the min/max values should make the code
easier to understand.
Part-of:
---
src/pulsecore/core-util.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index d421a7572..a6473c14a 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2189,7 +2189,7 @@ int pa_atoi(const char *s, int32_t *ret_i) {
if (pa_atol(s, &l) < 0)
return -1;
- if ((int32_t) l != l) {
+ if (l < INT32_MIN || l > INT32_MAX) {
errno = ERANGE;
return -1;
}
@@ -2233,7 +2233,7 @@ int pa_atou(const char *s, uint32_t *ret_u) {
return -1;
}
- if ((uint32_t) l != l) {
+ if (l > UINT32_MAX) {
errno = ERANGE;
return -1;
}
@@ -2277,7 +2277,7 @@ int pa_atou64(const char *s, uint64_t *ret_u) {
return -1;
}
- if ((uint64_t) l != l) {
+ if (l > UINT64_MAX) {
errno = ERANGE;
return -1;
}
@@ -2360,7 +2360,7 @@ int pa_atoi64(const char *s, int64_t *ret_l) {
*ret_l = l;
- if ((int64_t) l != l) {
+ if (l < INT64_MIN || l > INT64_MAX) {
errno = ERANGE;
return -1;
}
From 5d022a07a635568f7964e24b326cebaf8d64b7da Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 11 Jul 2020 13:58:36 +0300
Subject: [PATCH 115/872] introspect: Add version check to
pa_context_send_message_to_object()
If an application calls the function when the server doesn't support the
feature, the result should be just an error from the function. Without
the check the whole connection gets terminated due to protocol error.
Part-of:
---
src/pulse/introspect.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/pulse/introspect.c b/src/pulse/introspect.c
index 0671fa163..daae4cac4 100644
--- a/src/pulse/introspect.c
+++ b/src/pulse/introspect.c
@@ -2262,6 +2262,7 @@ pa_operation* pa_context_send_message_to_object(pa_context *c, const char *objec
PA_CHECK_VALIDITY_RETURN_NULL(c, !pa_detect_fork(), PA_ERR_FORKED);
PA_CHECK_VALIDITY_RETURN_NULL(c, c->state == PA_CONTEXT_READY, PA_ERR_BADSTATE);
+ PA_CHECK_VALIDITY_RETURN_NULL(c, c->version >= 35, PA_ERR_NOTSUPPORTED);
o = pa_operation_new(c, NULL, (pa_operation_cb_t) cb, userdata);
From d50145a9160ffcba49c1af0eec571d18f318b30e Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Wed, 22 Jul 2020 16:06:23 +0300
Subject: [PATCH 116/872] core-util: Reduce repetition in number parsing
functions
Part-of:
---
src/pulsecore/core-util.c | 80 +++++++++++++++------------------------
1 file changed, 31 insertions(+), 49 deletions(-)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index a6473c14a..5b6062f61 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2199,6 +2199,32 @@ int pa_atoi(const char *s, int32_t *ret_i) {
return 0;
}
+enum numtype {
+ NUMTYPE_UINT,
+ NUMTYPE_INT,
+ NUMTYPE_DOUBLE,
+};
+
+/* A helper function for pa_atou() and friends. This does some common checks,
+ * because our number parsing is more strict than the strtoX functions. */
+static int prepare_number_string(const char *s, enum numtype type) {
+ /* The strtoX functions ignore leading spaces, we don't. */
+ if (isspace((unsigned char) s[0]))
+ return -1;
+
+ /* The strtoX functions accept a plus sign, we don't. */
+ if (s[0] == '+')
+ return -1;
+
+ /* The strtoul and strtoull functions allow a minus sign even though they
+ * parse an unsigned number. In case of a minus sign the original negative
+ * number gets negated. We don't want that kind of behviour. */
+ if (type == NUMTYPE_UINT && s[0] == '-')
+ return -1;
+
+ return 0;
+}
+
/* Convert the string s to an unsigned integer in *ret_u */
int pa_atou(const char *s, uint32_t *ret_u) {
char *x = NULL;
@@ -2207,17 +2233,7 @@ int pa_atou(const char *s, uint32_t *ret_u) {
pa_assert(s);
pa_assert(ret_u);
- /* strtoul() ignores leading spaces. We don't. */
- if (isspace((unsigned char)*s)) {
- errno = EINVAL;
- return -1;
- }
-
- /* strtoul() accepts strings that start with a minus sign. In that case the
- * original negative number gets negated, and strtoul() returns the negated
- * result. We don't want that kind of behaviour. strtoul() also allows a
- * leading plus sign, which is also a thing that we don't want. */
- if (*s == '-' || *s == '+') {
+ if (prepare_number_string(s, NUMTYPE_UINT) < 0) {
errno = EINVAL;
return -1;
}
@@ -2251,17 +2267,7 @@ int pa_atou64(const char *s, uint64_t *ret_u) {
pa_assert(s);
pa_assert(ret_u);
- /* strtoull() ignores leading spaces. We don't. */
- if (isspace((unsigned char)*s)) {
- errno = EINVAL;
- return -1;
- }
-
- /* strtoull() accepts strings that start with a minus sign. In that case the
- * original negative number gets negated, and strtoull() returns the negated
- * result. We don't want that kind of behaviour. strtoull() also allows a
- * leading plus sign, which is also a thing that we don't want. */
- if (*s == '-' || *s == '+') {
+ if (prepare_number_string(s, NUMTYPE_UINT) < 0) {
errno = EINVAL;
return -1;
}
@@ -2295,15 +2301,7 @@ int pa_atol(const char *s, long *ret_l) {
pa_assert(s);
pa_assert(ret_l);
- /* strtol() ignores leading spaces. We don't. */
- if (isspace((unsigned char)*s)) {
- errno = EINVAL;
- return -1;
- }
-
- /* strtol() accepts leading plus signs, but that's ugly, so we don't allow
- * that. */
- if (*s == '+') {
+ if (prepare_number_string(s, NUMTYPE_INT) < 0) {
errno = EINVAL;
return -1;
}
@@ -2333,15 +2331,7 @@ int pa_atoi64(const char *s, int64_t *ret_l) {
pa_assert(s);
pa_assert(ret_l);
- /* strtoll() ignores leading spaces. We don't. */
- if (isspace((unsigned char)*s)) {
- errno = EINVAL;
- return -1;
- }
-
- /* strtoll() accepts leading plus signs, but that's ugly, so we don't allow
- * that. */
- if (*s == '+') {
+ if (prepare_number_string(s, NUMTYPE_INT) < 0) {
errno = EINVAL;
return -1;
}
@@ -2383,15 +2373,7 @@ int pa_atod(const char *s, double *ret_d) {
pa_assert(s);
pa_assert(ret_d);
- /* strtod() ignores leading spaces. We don't. */
- if (isspace((unsigned char)*s)) {
- errno = EINVAL;
- return -1;
- }
-
- /* strtod() accepts leading plus signs, but that's ugly, so we don't allow
- * that. */
- if (*s == '+') {
+ if (prepare_number_string(s, NUMTYPE_DOUBLE) < 0) {
errno = EINVAL;
return -1;
}
From 6bc00720f3213c80d4c7b8d7cd8ebcee8b43dcae Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 18 Jul 2020 10:13:26 +0300
Subject: [PATCH 117/872] core-util: Never parse integers as octal
I believe nobody needs to pass octal numbers to PulseAudio, and if we
encounter integer strings starting with zeros, the intention is to use
them in base 10. Hexadecimal numbers are more common, and they can't be
interpreted in base 10 anyway, so they are still supported.
Part-of:
---
src/pulsecore/core-util.c | 82 +++++++++++++++++++++++++++++++++++----
1 file changed, 74 insertions(+), 8 deletions(-)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 5b6062f61..25498c5a0 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -2206,9 +2206,29 @@ enum numtype {
};
/* A helper function for pa_atou() and friends. This does some common checks,
- * because our number parsing is more strict than the strtoX functions. */
-static int prepare_number_string(const char *s, enum numtype type) {
- /* The strtoX functions ignore leading spaces, we don't. */
+ * because our number parsing is more strict than the strtoX functions.
+ *
+ * Leading zeros are stripped from integers so that they don't get parsed as
+ * octal (but "0x" is preserved for hexadecimal numbers). For NUMTYPE_INT the
+ * zero stripping may involve allocating a new string, in which case it's
+ * stored in tmp. Otherwise tmp is set to NULL. The caller needs to free tmp
+ * after they're done with ret. When parsing other types than NUMTYPE_INT the
+ * caller can pass NULL as tmp.
+ *
+ * The final string to parse is returned in ret. ret will point either inside
+ * s or to tmp. */
+static int prepare_number_string(const char *s, enum numtype type, char **tmp, const char **ret) {
+ const char *original = s;
+ bool negative = false;
+
+ pa_assert(s);
+ pa_assert(type != NUMTYPE_INT || tmp);
+ pa_assert(ret);
+
+ if (tmp)
+ *tmp = NULL;
+
+ /* The strtoX functions accept leading spaces, we don't. */
if (isspace((unsigned char) s[0]))
return -1;
@@ -2222,6 +2242,44 @@ static int prepare_number_string(const char *s, enum numtype type) {
if (type == NUMTYPE_UINT && s[0] == '-')
return -1;
+ /* The strtoX functions interpret the number as octal if it starts with
+ * a zero. We prefer to use base 10, so we strip all leading zeros (if the
+ * string starts with "0x", strtoul() interprets it as hexadecimal, which
+ * is fine, because it's unambiguous unlike octal).
+ *
+ * While stripping the leading zeros, we have to remember to also handle
+ * the case where the number is negative, which makes the zero skipping
+ * code somewhat complex. */
+
+ /* Doubles don't need zero stripping, we can finish now. */
+ if (type == NUMTYPE_DOUBLE)
+ goto finish;
+
+ if (s[0] == '-') {
+ negative = true;
+ s++; /* Skip the minus sign. */
+ }
+
+ /* Don't skip zeros if the string starts with "0x". */
+ if (s[0] == '0' && s[1] != 'x') {
+ while (s[0] == '0' && s[1])
+ s++; /* Skip zeros. */
+ }
+
+ if (negative) {
+ s--; /* Go back one step, we need the minus sign back. */
+
+ /* If s != original, then we have skipped some zeros and we need to replace
+ * the last skipped zero with a minus sign. */
+ if (s != original) {
+ *tmp = pa_xstrdup(s);
+ *tmp[0] = '-';
+ s = *tmp;
+ }
+ }
+
+finish:
+ *ret = s;
return 0;
}
@@ -2233,7 +2291,7 @@ int pa_atou(const char *s, uint32_t *ret_u) {
pa_assert(s);
pa_assert(ret_u);
- if (prepare_number_string(s, NUMTYPE_UINT) < 0) {
+ if (prepare_number_string(s, NUMTYPE_UINT, NULL, &s) < 0) {
errno = EINVAL;
return -1;
}
@@ -2267,7 +2325,7 @@ int pa_atou64(const char *s, uint64_t *ret_u) {
pa_assert(s);
pa_assert(ret_u);
- if (prepare_number_string(s, NUMTYPE_UINT) < 0) {
+ if (prepare_number_string(s, NUMTYPE_UINT, NULL, &s) < 0) {
errno = EINVAL;
return -1;
}
@@ -2295,13 +2353,14 @@ int pa_atou64(const char *s, uint64_t *ret_u) {
/* Convert the string s to a signed long integer in *ret_l. */
int pa_atol(const char *s, long *ret_l) {
+ char *tmp;
char *x = NULL;
long l;
pa_assert(s);
pa_assert(ret_l);
- if (prepare_number_string(s, NUMTYPE_INT) < 0) {
+ if (prepare_number_string(s, NUMTYPE_INT, &tmp, &s) < 0) {
errno = EINVAL;
return -1;
}
@@ -2315,9 +2374,12 @@ int pa_atol(const char *s, long *ret_l) {
if (!x || *x || x == s || errno) {
if (!errno)
errno = EINVAL;
+ pa_xfree(tmp);
return -1;
}
+ pa_xfree(tmp);
+
*ret_l = l;
return 0;
@@ -2325,13 +2387,14 @@ int pa_atol(const char *s, long *ret_l) {
/* Convert the string s to a signed 64 bit integer in *ret_l. */
int pa_atoi64(const char *s, int64_t *ret_l) {
+ char *tmp;
char *x = NULL;
long long l;
pa_assert(s);
pa_assert(ret_l);
- if (prepare_number_string(s, NUMTYPE_INT) < 0) {
+ if (prepare_number_string(s, NUMTYPE_INT, &tmp, &s) < 0) {
errno = EINVAL;
return -1;
}
@@ -2345,9 +2408,12 @@ int pa_atoi64(const char *s, int64_t *ret_l) {
if (!x || *x || x == s || errno) {
if (!errno)
errno = EINVAL;
+ pa_xfree(tmp);
return -1;
}
+ pa_xfree(tmp);
+
*ret_l = l;
if (l < INT64_MIN || l > INT64_MAX) {
@@ -2373,7 +2439,7 @@ int pa_atod(const char *s, double *ret_d) {
pa_assert(s);
pa_assert(ret_d);
- if (prepare_number_string(s, NUMTYPE_DOUBLE) < 0) {
+ if (prepare_number_string(s, NUMTYPE_DOUBLE, NULL, &s) < 0) {
errno = EINVAL;
return -1;
}
From b76964e480812466c9f528a7fb7a589debefa2e1 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 23 Jul 2020 09:39:25 +0300
Subject: [PATCH 118/872] core-util-test: Test parsing integer strings with
leading zeros
Part-of:
---
src/tests/core-util-test.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
index 8d1db0c07..1a9603ac2 100644
--- a/src/tests/core-util-test.c
+++ b/src/tests/core-util-test.c
@@ -100,6 +100,10 @@ START_TEST (modargs_test_atoi) {
ck_assert_int_eq(value, 100000);
ck_assert_int_eq(pa_atoi("-100000", &value), 0);
ck_assert_int_eq(value, -100000);
+ ck_assert_int_eq(pa_atoi("010", &value), 0);
+ ck_assert_int_eq(value, 10);
+ ck_assert_int_eq(pa_atoi("-010", &value), 0);
+ ck_assert_int_eq(value, -10);
// hexadecimal
ck_assert_int_eq(pa_atoi("0x100000", &value), 0);
@@ -120,6 +124,8 @@ START_TEST (modargs_test_atou) {
// decimal
ck_assert_int_eq(pa_atou("100000", &value), 0);
ck_assert_int_eq(value, 100000);
+ ck_assert_int_eq(pa_atou("010", &value), 0);
+ ck_assert_int_eq(value, 10);
// hexadecimal
ck_assert_int_eq(pa_atou("0x100000", &value), 0);
@@ -142,6 +148,10 @@ START_TEST (modargs_test_atol) {
ck_assert_int_eq(value, 100000l);
ck_assert_int_eq(pa_atol("-100000", &value), 0);
ck_assert_int_eq(value, -100000l);
+ ck_assert_int_eq(pa_atol("010", &value), 0);
+ ck_assert_int_eq(value, 10);
+ ck_assert_int_eq(pa_atol("-010", &value), 0);
+ ck_assert_int_eq(value, -10);
// hexadecimal
ck_assert_int_eq(pa_atol("0x100000", &value), 0);
From ef5a2f15541cfe5e325be9136c84a7945ac54404 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 23 Jul 2020 09:49:12 +0300
Subject: [PATCH 119/872] core-util-test: Drop "modargs" from test function
names
These tests aren't directly related to modargs. I suppose these were
first written for the modargs.h API and renaming was forgotten.
Part-of:
---
src/tests/core-util-test.c | 52 +++++++++++++++++++-------------------
1 file changed, 26 insertions(+), 26 deletions(-)
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
index 1a9603ac2..e48cb3807 100644
--- a/src/tests/core-util-test.c
+++ b/src/tests/core-util-test.c
@@ -26,7 +26,7 @@
#include
#include
-START_TEST (modargs_test_parse_boolean) {
+START_TEST (test_parse_boolean) {
ck_assert_int_eq(pa_parse_boolean("true"), true);
ck_assert_int_eq(pa_parse_boolean("yes"), true);
ck_assert_int_eq(pa_parse_boolean("1"), true);
@@ -40,7 +40,7 @@ START_TEST (modargs_test_parse_boolean) {
}
END_TEST
-START_TEST (modargs_test_parse_volume) {
+START_TEST (test_parse_volume) {
pa_volume_t value;
// dB volumes
@@ -92,7 +92,7 @@ START_TEST (modargs_test_parse_volume) {
}
END_TEST
-START_TEST (modargs_test_atoi) {
+START_TEST (test_atoi) {
int32_t value;
// decimal
@@ -118,7 +118,7 @@ START_TEST (modargs_test_atoi) {
}
END_TEST
-START_TEST (modargs_test_atou) {
+START_TEST (test_atou) {
uint32_t value;
// decimal
@@ -140,7 +140,7 @@ START_TEST (modargs_test_atou) {
}
END_TEST
-START_TEST (modargs_test_atol) {
+START_TEST (test_atol) {
long value;
// decimal
@@ -166,7 +166,7 @@ START_TEST (modargs_test_atol) {
}
END_TEST
-START_TEST (modargs_test_atod) {
+START_TEST (test_atod) {
double value;
double epsilon = 0.001;
@@ -187,7 +187,7 @@ START_TEST (modargs_test_atod) {
}
END_TEST
-START_TEST (modargs_test_replace) {
+START_TEST (test_replace) {
char* value;
value = pa_replace("abcde", "bcd", "XYZ");
@@ -208,22 +208,22 @@ START_TEST (modargs_test_replace) {
}
END_TEST
-START_TEST (modargs_test_replace_fail_1) {
+START_TEST (test_replace_fail_1) {
pa_replace(NULL, "b", "bab");
}
END_TEST
-START_TEST (modargs_test_replace_fail_2) {
+START_TEST (test_replace_fail_2) {
pa_replace("abe", NULL, "bab");
}
END_TEST
-START_TEST (modargs_test_replace_fail_3) {
+START_TEST (test_replace_fail_3) {
pa_replace("abcde", "b", NULL);
}
END_TEST
-START_TEST (modargs_test_escape) {
+START_TEST (test_escape) {
char* value;
value = pa_escape("abcde", "bcd");
@@ -240,12 +240,12 @@ START_TEST (modargs_test_escape) {
}
END_TEST
-START_TEST (modargs_test_replace_fail_4) {
+START_TEST (test_replace_fail_4) {
pa_replace("abe", "", "bab");
}
END_TEST
-START_TEST (modargs_test_unescape) {
+START_TEST (test_unescape) {
char* value;
value = pa_unescape(pa_xstrdup("a\\b\\c\\de"));
@@ -271,19 +271,19 @@ int main(int argc, char *argv[]) {
tc = tcase_create("core-util");
suite_add_tcase(s, tc);
- tcase_add_test(tc, modargs_test_parse_boolean);
- tcase_add_test(tc, modargs_test_parse_volume);
- tcase_add_test(tc, modargs_test_atoi);
- tcase_add_test(tc, modargs_test_atou);
- tcase_add_test(tc, modargs_test_atol);
- tcase_add_test(tc, modargs_test_atod);
- tcase_add_test(tc, modargs_test_replace);
- tcase_add_test_raise_signal(tc, modargs_test_replace_fail_1, SIGABRT);
- tcase_add_test_raise_signal(tc, modargs_test_replace_fail_2, SIGABRT);
- tcase_add_test_raise_signal(tc, modargs_test_replace_fail_3, SIGABRT);
- tcase_add_test_raise_signal(tc, modargs_test_replace_fail_4, SIGABRT);
- tcase_add_test(tc, modargs_test_escape);
- tcase_add_test(tc, modargs_test_unescape);
+ tcase_add_test(tc, test_parse_boolean);
+ tcase_add_test(tc, test_parse_volume);
+ tcase_add_test(tc, test_atoi);
+ tcase_add_test(tc, test_atou);
+ tcase_add_test(tc, test_atol);
+ tcase_add_test(tc, test_atod);
+ tcase_add_test(tc, test_replace);
+ tcase_add_test_raise_signal(tc, test_replace_fail_1, SIGABRT);
+ tcase_add_test_raise_signal(tc, test_replace_fail_2, SIGABRT);
+ tcase_add_test_raise_signal(tc, test_replace_fail_3, SIGABRT);
+ tcase_add_test_raise_signal(tc, test_replace_fail_4, SIGABRT);
+ tcase_add_test(tc, test_escape);
+ tcase_add_test(tc, test_unescape);
sr = srunner_create(s);
srunner_run_all(sr, CK_NORMAL);
From fe162e0bbda7efcee489db10bd76c8853297d96e Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 23 Jul 2020 10:01:49 +0300
Subject: [PATCH 120/872] core-util-test: Test pa_atou64() and pa_atoi64()
Part-of:
---
src/tests/core-util-test.c | 56 ++++++++++++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/src/tests/core-util-test.c b/src/tests/core-util-test.c
index e48cb3807..49aa4abcc 100644
--- a/src/tests/core-util-test.c
+++ b/src/tests/core-util-test.c
@@ -115,6 +115,7 @@ START_TEST (test_atoi) {
ck_assert_int_lt(pa_atoi("3.14", &value), 0);
ck_assert_int_lt(pa_atoi("7*8", &value), 0);
ck_assert_int_lt(pa_atoi("false", &value), 0);
+ ck_assert_int_lt(pa_atoi("10000000000", &value), 0);
}
END_TEST
@@ -137,6 +138,31 @@ START_TEST (test_atou) {
ck_assert_int_lt(pa_atou("3.14", &value), 0);
ck_assert_int_lt(pa_atou("7*8", &value), 0);
ck_assert_int_lt(pa_atou("false", &value), 0);
+ ck_assert_int_lt(pa_atou("10000000000", &value), 0);
+}
+END_TEST
+
+START_TEST (test_atou64) {
+ uint64_t value;
+
+ // decimal
+ ck_assert_int_eq(pa_atou64("100000", &value), 0);
+ ck_assert_int_eq(value, 100000);
+ ck_assert_int_eq(pa_atou64("010", &value), 0);
+ ck_assert_int_eq(value, 10);
+ ck_assert_int_eq(pa_atou64("10000000000", &value), 0);
+ ck_assert_int_eq(value, 10000000000);
+
+ // hexadecimal
+ ck_assert_int_eq(pa_atou64("0x100000", &value), 0);
+ ck_assert_int_eq(value, 0x100000);
+
+ // invalid values
+ ck_assert_int_lt(pa_atou64("-100000", &value), 0);
+ ck_assert_int_lt(pa_atou64("-0x100000", &value), 0);
+ ck_assert_int_lt(pa_atou64("3.14", &value), 0);
+ ck_assert_int_lt(pa_atou64("7*8", &value), 0);
+ ck_assert_int_lt(pa_atou64("false", &value), 0);
}
END_TEST
@@ -166,6 +192,34 @@ START_TEST (test_atol) {
}
END_TEST
+START_TEST (test_atoi64) {
+ int64_t value;
+
+ // decimal
+ ck_assert_int_eq(pa_atoi64("100000", &value), 0);
+ ck_assert_int_eq(value, 100000);
+ ck_assert_int_eq(pa_atoi64("-100000", &value), 0);
+ ck_assert_int_eq(value, -100000);
+ ck_assert_int_eq(pa_atoi64("010", &value), 0);
+ ck_assert_int_eq(value, 10);
+ ck_assert_int_eq(pa_atoi64("-010", &value), 0);
+ ck_assert_int_eq(value, -10);
+ ck_assert_int_eq(pa_atoi64("10000000000", &value), 0);
+ ck_assert_int_eq(value, 10000000000);
+
+ // hexadecimal
+ ck_assert_int_eq(pa_atoi64("0x100000", &value), 0);
+ ck_assert_int_eq(value, 0x100000);
+ ck_assert_int_eq(pa_atoi64("-0x100000", &value), 0);
+ ck_assert_int_eq(value, -0x100000);
+
+ // invalid values
+ ck_assert_int_lt(pa_atoi64("3.14", &value), 0);
+ ck_assert_int_lt(pa_atoi64("7*8", &value), 0);
+ ck_assert_int_lt(pa_atoi64("false", &value), 0);
+}
+END_TEST
+
START_TEST (test_atod) {
double value;
double epsilon = 0.001;
@@ -275,7 +329,9 @@ int main(int argc, char *argv[]) {
tcase_add_test(tc, test_parse_volume);
tcase_add_test(tc, test_atoi);
tcase_add_test(tc, test_atou);
+ tcase_add_test(tc, test_atou64);
tcase_add_test(tc, test_atol);
+ tcase_add_test(tc, test_atoi64);
tcase_add_test(tc, test_atod);
tcase_add_test(tc, test_replace);
tcase_add_test_raise_signal(tc, test_replace_fail_1, SIGABRT);
From 818a87deb280aadb6cb127df99012548e9198485 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Mon, 30 Nov 2020 22:39:23 +0300
Subject: [PATCH 121/872] message-params: add read length param reference to
array read methods
Part-of:
---
src/pulse/message-params.c | 70 ++++++++++++++++++++++++++------------
src/pulse/message-params.h | 27 +++++++--------
2 files changed, 62 insertions(+), 35 deletions(-)
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index 7d2dd8020..d5cafab3b 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -344,22 +344,24 @@ int pa_message_params_read_bool(char *c, bool *result, void **state) {
return PA_MESSAGE_PARAMS_OK;
}
-/* Converts a parameter list to a string array. Escaping is removed from
- * the strings. Returns an array of pointers to sub-strings within c in
- * *results. The returned array must be freed, but not the strings
- * within the array. The function returns the number of strings in the
- * array. */
-int pa_message_params_read_string_array(char *c, const char ***results) {
+/* Converts a parameter list to a string array. */
+int pa_message_params_read_string_array(char *c, const char ***results, int *length) {
void *state = NULL;
uint32_t element_count, i;
int err;
const char **values;
pa_assert(results);
+ pa_assert(length);
/* Count elements, return if no element was found or parse error. */
- if ((element_count = count_elements(c)) <= 0)
- return element_count;
+ element_count = count_elements(c);
+ if (element_count < 0) {
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ } else if (element_count == 0) {
+ *length = 0;
+ return PA_MESSAGE_PARAMS_OK;
+ }
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(char *));
@@ -373,21 +375,29 @@ int pa_message_params_read_string_array(char *c, const char ***results) {
}
*results = values;
- return element_count;
+ *length = element_count;
+
+ return PA_MESSAGE_PARAMS_OK;
}
/* Converts a parameter list to a double array. */
-int pa_message_params_read_double_array(char *c, double **results) {
+int pa_message_params_read_double_array(char *c, double **results, int *length) {
double *values;
void *state = NULL;
uint32_t element_count, i;
int err;
pa_assert(results);
+ pa_assert(length);
/* Count elements, return if no element was found or parse error. */
- if ((element_count = count_elements(c)) <= 0)
- return element_count;
+ element_count = count_elements(c);
+ if (element_count < 0) {
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ } else if (element_count == 0) {
+ *length = 0;
+ return PA_MESSAGE_PARAMS_OK;
+ }
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(double));
@@ -401,21 +411,29 @@ int pa_message_params_read_double_array(char *c, double **results) {
}
*results = values;
- return element_count;
+ *length = element_count;
+
+ return PA_MESSAGE_PARAMS_OK;
}
/* Converts a parameter list to an int64 array. */
-int pa_message_params_read_int64_array(char *c, int64_t **results) {
+int pa_message_params_read_int64_array(char *c, int64_t **results, int *length) {
int64_t *values;
void *state = NULL;
uint32_t element_count, i;
int err;
pa_assert(results);
+ pa_assert(length);
/* Count elements, return if no element was found or parse error. */
- if ((element_count = count_elements(c)) <= 0)
- return element_count;
+ element_count = count_elements(c);
+ if (element_count < 0) {
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ } else if (element_count == 0) {
+ *length = 0;
+ return PA_MESSAGE_PARAMS_OK;
+ }
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(int64_t));
@@ -429,21 +447,29 @@ int pa_message_params_read_int64_array(char *c, int64_t **results) {
}
*results = values;
- return element_count;
+ *length = element_count;
+
+ return PA_MESSAGE_PARAMS_OK;
}
/* Converts a parameter list to an uint64 array. */
-int pa_message_params_read_uint64_array(char *c, uint64_t **results) {
+int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length) {
uint64_t *values;
void *state = NULL;
uint32_t element_count, i;
int err;
pa_assert(results);
+ pa_assert(length);
/* Count elements, return if no element was found or parse error. */
- if ((element_count = count_elements(c)) <= 0)
- return element_count;
+ element_count = count_elements(c);
+ if (element_count < 0) {
+ return PA_MESSAGE_PARAMS_PARSE_ERROR;
+ } else if (element_count == 0) {
+ *length = 0;
+ return PA_MESSAGE_PARAMS_OK;
+ }
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(uint64_t));
@@ -457,7 +483,9 @@ int pa_message_params_read_uint64_array(char *c, uint64_t **results) {
}
*results = values;
- return element_count;
+ *length = element_count;
+
+ return PA_MESSAGE_PARAMS_OK;
}
/* Write functions. The functions are wrapper functions around pa_strbuf,
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index 3d90eac3c..18addee96 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -75,17 +75,17 @@ int pa_message_params_read_bool(char *c, bool *result, void **state);
int pa_message_params_read_double(char *c, double *result, void **state);
/** Converts a parameter list to a double array. Empty elements in the parameter
- * list are treated as error. Before the call, results must be initialized, either
- * to NULL or to an array with default values. \since 15.0 */
-int pa_message_params_read_double_array(char *c, double **results);
+ * list are treated as error. Returns allocated array in *results and array size in *length.
+ * The returned array must be freed with pa_xfree(). \since 15.0 */
+int pa_message_params_read_double_array(char *c, double **results, int *length);
/** Read an integer from parameter list in c. \since 15.0 */
int pa_message_params_read_int64(char *c, int64_t *result, void **state);
/** Converts a parameter list to an int64 array. Empty elements in the parameter
- * list are treated as error. Before the call, results must be initialized, either
- * to NULL or to an array with default values. \since 15.0 */
-int pa_message_params_read_int64_array(char *c, int64_t **results);
+ * list are treated as error. Returns allocated array in *results and array size in *length.
+ * The returned array must be freed with pa_xfree(). \since 15.0 */
+int pa_message_params_read_int64_array(char *c, int64_t **results, int *length);
/** Read raw data from parameter list in c. Used to split a message parameter
* string into list elements. The string returned in *result must not be freed. \since 15.0 */
@@ -96,19 +96,18 @@ int pa_message_params_read_raw(char *c, char **result, void **state);
int pa_message_params_read_string(char *c, const char **result, void **state);
/** Convert a parameter list to a string array. Escaping is removed from
- * the strings. Returns an array of pointers to sub-strings within c in
- * *results. The returned array must be freed, but not the strings
- * within the array. Before the call, results must be initialized, either
- * to NULL or to an array with default values. \since 15.0 */
-int pa_message_params_read_string_array(char *c, const char ***results);
+ * the strings. Returns allocated array of pointers to sub-strings within c in
+ * *results and stores array size in *length. The returned array must be
+ * freed with pa_xfree(), but not the strings within the array. \since 15.0 */
+int pa_message_params_read_string_array(char *c, const char ***results, int *length);
/** Read an unsigned integer from parameter list in c. \since 15.0 */
int pa_message_params_read_uint64(char *c, uint64_t *result, void **state);
/** Converts a parameter list to an uint64 array. Empty elements in the parameter
- * list are treated as error. Before the call, results must be initialized, either
- * to NULL or to an array with default values. \since 15.0 */
-int pa_message_params_read_uint64_array(char *c, uint64_t **results);
+ * list are treated as error. Returns allocated array in *results and array size in *length.
+ * The returned array must be freed with pa_xfree(). \since 15.0 */
+int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length);
/** @} */
From c1ac76014e89e995f107a0f569a8cf7fe661b307 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Mon, 30 Nov 2020 22:25:16 +0300
Subject: [PATCH 122/872] message-params: consume array enclosing {} by array
read methods
Part-of:
---
src/pulse/message-params.c | 36 ++++++++++++++++++++++++++++--------
1 file changed, 28 insertions(+), 8 deletions(-)
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index d5cafab3b..ae2ed8b68 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -350,12 +350,16 @@ int pa_message_params_read_string_array(char *c, const char ***results, int *len
uint32_t element_count, i;
int err;
const char **values;
+ char *start_pos;
pa_assert(results);
pa_assert(length);
+ if ((err = split_list(c, &start_pos, NULL, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
/* Count elements, return if no element was found or parse error. */
- element_count = count_elements(c);
+ element_count = count_elements(start_pos);
if (element_count < 0) {
return PA_MESSAGE_PARAMS_PARSE_ERROR;
} else if (element_count == 0) {
@@ -366,7 +370,8 @@ int pa_message_params_read_string_array(char *c, const char ***results, int *len
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(char *));
- for (i = 0; (err = pa_message_params_read_string(c, &(values[i]), &state)) > 0; i++)
+ state = NULL;
+ for (i = 0; (err = pa_message_params_read_string(start_pos, &(values[i]), &state)) > 0; i++)
;
if (err < 0) {
@@ -386,12 +391,16 @@ int pa_message_params_read_double_array(char *c, double **results, int *length)
void *state = NULL;
uint32_t element_count, i;
int err;
+ char *start_pos;
pa_assert(results);
pa_assert(length);
+ if ((err = split_list(c, &start_pos, NULL, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
/* Count elements, return if no element was found or parse error. */
- element_count = count_elements(c);
+ element_count = count_elements(start_pos);
if (element_count < 0) {
return PA_MESSAGE_PARAMS_PARSE_ERROR;
} else if (element_count == 0) {
@@ -402,7 +411,8 @@ int pa_message_params_read_double_array(char *c, double **results, int *length)
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(double));
- for (i = 0; (err = pa_message_params_read_double(c, &(values[i]), &state)) > 0; i++)
+ state = NULL;
+ for (i = 0; (err = pa_message_params_read_double(start_pos, &(values[i]), &state)) > 0; i++)
;
if (err < 0) {
@@ -422,12 +432,16 @@ int pa_message_params_read_int64_array(char *c, int64_t **results, int *length)
void *state = NULL;
uint32_t element_count, i;
int err;
+ char *start_pos;
pa_assert(results);
pa_assert(length);
+ if ((err = split_list(c, &start_pos, NULL, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
/* Count elements, return if no element was found or parse error. */
- element_count = count_elements(c);
+ element_count = count_elements(start_pos);
if (element_count < 0) {
return PA_MESSAGE_PARAMS_PARSE_ERROR;
} else if (element_count == 0) {
@@ -438,7 +452,8 @@ int pa_message_params_read_int64_array(char *c, int64_t **results, int *length)
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(int64_t));
- for (i = 0; (err = pa_message_params_read_int64(c, &(values[i]), &state)) > 0; i++)
+ state = NULL;
+ for (i = 0; (err = pa_message_params_read_int64(start_pos, &(values[i]), &state)) > 0; i++)
;
if (err < 0) {
@@ -458,12 +473,16 @@ int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length
void *state = NULL;
uint32_t element_count, i;
int err;
+ char *start_pos;
pa_assert(results);
pa_assert(length);
+ if ((err = split_list(c, &start_pos, NULL, state)) != PA_MESSAGE_PARAMS_OK)
+ return err;
+
/* Count elements, return if no element was found or parse error. */
- element_count = count_elements(c);
+ element_count = count_elements(start_pos);
if (element_count < 0) {
return PA_MESSAGE_PARAMS_PARSE_ERROR;
} else if (element_count == 0) {
@@ -474,7 +493,8 @@ int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(uint64_t));
- for (i = 0; (err = pa_message_params_read_uint64(c, &(values[i]), &state)) > 0; i++)
+ state = NULL;
+ for (i = 0; (err = pa_message_params_read_uint64(start_pos, &(values[i]), &state)) > 0; i++)
;
if (err < 0) {
From bd8ef73b913f050792017ce8772a99bc198ecff5 Mon Sep 17 00:00:00 2001
From: Jaechul Lee
Date: Mon, 16 Nov 2020 10:14:56 +0900
Subject: [PATCH 123/872] null-source: Add max_latency_msec argument
It takes much time when starting to capture because max latency is set
to 2 seconds as a initial value. null-source latency need to be set a
lower value than initial value to improve latency.
---
src/modules/module-null-source.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/src/modules/module-null-source.c b/src/modules/module-null-source.c
index 8d3796e9a..38e3c823e 100644
--- a/src/modules/module-null-source.c
+++ b/src/modules/module-null-source.c
@@ -52,6 +52,7 @@ PA_MODULE_USAGE(
"rate= "
"source_name= "
"channel_map= "
+ "max_latency_msec= "
"description= ");
#define DEFAULT_SOURCE_NAME "source.null"
@@ -79,6 +80,7 @@ static const char* const valid_modargs[] = {
"channels",
"source_name",
"channel_map",
+ "max_latency_msec",
"description",
NULL
};
@@ -123,6 +125,7 @@ static void source_update_requested_latency_cb(pa_source *s) {
pa_assert(u);
u->block_usec = pa_source_get_requested_latency_within_thread(s);
+
if (u->block_usec == (pa_usec_t)-1)
u->block_usec = u->source->thread_info.max_latency;
}
@@ -197,6 +200,8 @@ int pa__init(pa_module*m) {
pa_channel_map map;
pa_modargs *ma = NULL;
pa_source_new_data data;
+ pa_usec_t max_latency = MAX_LATENCY_USEC;
+ uint32_t max_latency_msec;
pa_assert(m);
@@ -247,7 +252,11 @@ int pa__init(pa_module*m) {
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
- pa_source_set_latency_range(u->source, MIN_LATENCY_USEC, MAX_LATENCY_USEC);
+ if (pa_modargs_get_value_u32(ma, "max_latency_msec", &max_latency_msec))
+ max_latency = max_latency_msec * PA_USEC_PER_MSEC;
+
+ pa_source_set_latency_range(u->source, MIN_LATENCY_USEC, max_latency);
+
u->block_usec = u->source->thread_info.max_latency;
u->source->thread_info.max_rewind =
From afc1a0e45b01fac363fee727256a2556aaf30e79 Mon Sep 17 00:00:00 2001
From: Jason Nader
Date: Mon, 7 Dec 2020 19:56:39 +0900
Subject: [PATCH 124/872] man: clarify pactl command arguments
---
man/pactl.1.xml.in | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/man/pactl.1.xml.in b/man/pactl.1.xml.in
index 1f094df42..197df7dee 100644
--- a/man/pactl.1.xml.in
+++ b/man/pactl.1.xml.in
@@ -135,7 +135,7 @@ License along with PulseAudio; if not, see .
suspend-sinkSINKtrue|false
Suspend or resume the specified sink (which may be
- specified either by its name or index), depending whether true
+ specified either by its symbolic name or numerical index), depending whether true
(suspend) or false (resume) is passed as last argument. Suspending
a sink will pause all playback. Depending on the module implementing
the sink this might have the effect that the underlying device is
@@ -147,7 +147,7 @@ License along with PulseAudio; if not, see .
suspend-sourceSOURCEtrue|false
Suspend or resume the specified source (which may be
- specified either by its name or index), depending whether true
+ specified either by its symbolic name or numerical index), depending whether true
(suspend) or false (resume) is passed as last argument. Suspending
a source will pause all capturing. Depending on the module implementing
the source this might have the effect that the underlying device is
@@ -163,7 +163,7 @@ License along with PulseAudio; if not, see .
set-default-sinkSINK
-
Make the specified sink (identified by its symbolic name) the default sink.
+
Make the specified sink (identified by its symbolic name or numerical index) the default sink.
@@ -173,7 +173,7 @@ License along with PulseAudio; if not, see .
set-default-sourceSOURCE
-
Make the specified source (identified by its symbolic name) the default source.
+
Make the specified source (identified by its symbolic name or numerical index) the default source.
From 71aa4720a4194e9602271634d9042b8e56a8217f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lauren=C8=9Biu=20Nicola?=
Date: Tue, 24 Nov 2020 18:57:41 +0200
Subject: [PATCH 125/872] alsa-mixer: Add OnePlus Bullets udev rule
---
src/modules/alsa/90-pulseaudio.rules | 3 ++
.../profile-sets/simple-headphones-mic.conf | 42 +++++++++++++++++++
2 files changed, 45 insertions(+)
create mode 100644 src/modules/alsa/mixer/profile-sets/simple-headphones-mic.conf
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
index 83b257df6..4de40127e 100644
--- a/src/modules/alsa/90-pulseaudio.rules
+++ b/src/modules/alsa/90-pulseaudio.rules
@@ -147,6 +147,9 @@ ATTRS{idVendor}=="0951", ATTRS{idProduct}=="16ff", ENV{ID_ID}="usb-HyperX_Cloud_
ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1702", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_Hi-Res_2Ch-$env{ID_USB_INTERFACE_NUM}"
ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_Orbit_S_3D_8Ch-$env{ID_USB_INTERFACE_NUM}"
+# OnePlus Type-C Bullets (ED117)
+ATTRS{idVendor}=="2a70", ATTRS{idProduct}=="1881", ENV{PULSE_PROFILE_SET}="simple-headphones-mic.conf"
+
GOTO="pulseaudio_end"
LABEL="pulseaudio_check_pci"
diff --git a/src/modules/alsa/mixer/profile-sets/simple-headphones-mic.conf b/src/modules/alsa/mixer/profile-sets/simple-headphones-mic.conf
new file mode 100644
index 000000000..809d01587
--- /dev/null
+++ b/src/modules/alsa/mixer/profile-sets/simple-headphones-mic.conf
@@ -0,0 +1,42 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+; This is a profile meant for simple (stereo + mic) headphones.
+; default.conf also works but using this one will hide some profiles
+; that don't make sense like IEC958 and multichannel inputs.
+
+[General]
+auto-profiles = yes
+
+[Mapping analog-stereo]
+device-strings = front:%f
+channel-map = left,right
+paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
+paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
+priority = 15
+
+# If everything else fails, try to use hw:0 as a stereo device...
+[Mapping stereo-fallback]
+device-strings = hw:%f
+fallback = yes
+channel-map = front-left,front-right
+paths-output = analog-output analog-output-lineout analog-output-speaker analog-output-headphones analog-output-headphones-2
+paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic
+priority = 1
+
+[Mapping analog-mono]
+device-strings = hw:%f,0,0
+channel-map = mono
+direction = input
From ea69288b76d94e61c1d2492d87d969f05357cec2 Mon Sep 17 00:00:00 2001
From: Sanchayan Maity
Date: Thu, 23 Jul 2020 20:33:36 +0530
Subject: [PATCH 126/872] module-match: Allow loading module more than once
As long as modules use different keys, multiple loading of this module
should be safe. Even in case of same keys, either the pa_proplist_update
should correctly update the property list based on the mode or for the
volume writable case, the last rule should win.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/942
Part-of:
---
src/modules/module-match.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/module-match.c b/src/modules/module-match.c
index 76f71256c..9b5e76cd7 100644
--- a/src/modules/module-match.c
+++ b/src/modules/module-match.c
@@ -47,7 +47,7 @@
PA_MODULE_AUTHOR("Lennart Poettering");
PA_MODULE_DESCRIPTION("Playback stream expression matching module");
PA_MODULE_VERSION(PACKAGE_VERSION);
-PA_MODULE_LOAD_ONCE(true);
+PA_MODULE_LOAD_ONCE(false);
PA_MODULE_USAGE("table= "
"key=");
From bbac2e6e2b6af61672200a7ca39a89886eaf5dd0 Mon Sep 17 00:00:00 2001
From: Dusan Kazik
Date: Tue, 24 Nov 2020 08:32:06 +0000
Subject: [PATCH 127/872] Translated using Weblate (Slovak)
Currently translated at 76.0% (400 of 526 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/sk/
Part-of:
---
po/sk.po | 111 +++++++++++++++++++++++++++++++++++--------------------
1 file changed, 71 insertions(+), 40 deletions(-)
diff --git a/po/sk.po b/po/sk.po
index 99f898351..a7b096d91 100644
--- a/po/sk.po
+++ b/po/sk.po
@@ -9,7 +9,7 @@ msgstr ""
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/"
"issues/new\n"
"POT-Creation-Date: 2016-06-22 13:54+0000\n"
-"PO-Revision-Date: 2020-10-07 02:48+0000\n"
+"PO-Revision-Date: 2020-11-25 08:35+0000\n"
"Last-Translator: Dusan Kazik \n"
"Language-Team: Slovak \n"
@@ -18,7 +18,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=3; plural=(n==1) ? 1 : (n>=2 && n<=4) ? 2 : 0;\n"
-"X-Generator: Weblate 4.2.2\n"
+"X-Generator: Weblate 4.3.2\n"
#: ../src/daemon/cmdline.c:113
#, c-format
@@ -95,11 +95,11 @@ msgstr ""
#: ../src/daemon/cmdline.c:246
msgid "--daemonize expects boolean argument"
-msgstr ""
+msgstr "Voľba --daemonize očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:254
msgid "--fail expects boolean argument"
-msgstr ""
+msgstr "Voľba --fail očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:265
msgid ""
@@ -109,23 +109,23 @@ msgstr ""
#: ../src/daemon/cmdline.c:277
msgid "--high-priority expects boolean argument"
-msgstr ""
+msgstr "Voľba --high-priority očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:285
msgid "--realtime expects boolean argument"
-msgstr ""
+msgstr "Voľba --realtime očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:293
msgid "--disallow-module-loading expects boolean argument"
-msgstr ""
+msgstr "Voľba --disallow-module-loading očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:301
msgid "--disallow-exit expects boolean argument"
-msgstr ""
+msgstr "Voľba --disallow-exit očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:309
msgid "--use-pid-file expects boolean argument"
-msgstr ""
+msgstr "Voľba --use-pid-file očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:328
msgid ""
@@ -141,11 +141,11 @@ msgstr ""
#: ../src/daemon/cmdline.c:338
msgid "--log-time expects boolean argument"
-msgstr ""
+msgstr "Voľba --log-time očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:346
msgid "--log-meta expects boolean argument"
-msgstr ""
+msgstr "Voľba --log-meta očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:366
#, c-format
@@ -158,11 +158,11 @@ msgstr "Voľba --system očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:381
msgid "--no-cpu-limit expects boolean argument"
-msgstr ""
+msgstr "Voľba --no-cpu-limit očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:389
msgid "--disable-shm expects boolean argument"
-msgstr ""
+msgstr "Voľba --disable-shm očakáva booleovský parameter"
#: ../src/daemon/cmdline.c:397
msgid "--enable-memfd expects boolean argument"
@@ -350,7 +350,7 @@ msgstr "Zlyhalo zmenenie UID: %s"
#: ../src/daemon/main.c:255
msgid "System wide mode unsupported on this platform."
-msgstr ""
+msgstr "Systémový režim nie je podporovaný na tejto platforme."
#: ../src/daemon/main.c:484
msgid "Failed to parse command line."
@@ -395,10 +395,12 @@ msgstr ""
#: ../src/daemon/main.c:712
msgid "Running in system mode, but --disallow-exit not set."
msgstr ""
+"Spustené v systémovom režime, ale voľba --disallow-exit nie je nastavená."
#: ../src/daemon/main.c:715
msgid "Running in system mode, but --disallow-module-loading not set."
msgstr ""
+"Spustené v systémovom režime, ale voľba --disallow-exit nie je nastavená."
#: ../src/daemon/main.c:718
msgid "Running in system mode, forcibly disabling SHM mode."
@@ -407,10 +409,11 @@ msgstr ""
#: ../src/daemon/main.c:723
msgid "Running in system mode, forcibly disabling exit idle time."
msgstr ""
+"Spustené v systémovom režime. Ukončenie pri nečinnosti je vynútene zakázané."
#: ../src/daemon/main.c:756
msgid "Failed to acquire stdio."
-msgstr ""
+msgstr "Zlyhalo získanie štandardného vstupu/výstupu."
#: ../src/daemon/main.c:762 ../src/daemon/main.c:833
#, c-format
@@ -866,11 +869,11 @@ msgstr "Vstup cez Bluetooth"
#: ../src/modules/bluetooth/module-bluez5-device.c:1786
msgid "High Fidelity Playback (A2DP Sink)"
-msgstr ""
+msgstr "HiFi prehrávanie (cieľ A2DP)"
#: ../src/modules/bluetooth/module-bluez5-device.c:1797
msgid "High Fidelity Capture (A2DP Source)"
-msgstr ""
+msgstr "HiFi zaznamenávanie (zdroj A2DP)"
#: ../src/modules/bluetooth/module-bluez5-device.c:1808
msgid "Headset Head Unit (HSP/HFP)"
@@ -926,7 +929,7 @@ msgstr ""
#: ../src/modules/module-ladspa-sink.c:51
msgid "Virtual LADSPA sink"
-msgstr ""
+msgstr "Virtuálny cieľ LADSPA"
#: ../src/modules/module-ladspa-sink.c:55
msgid ""
@@ -979,7 +982,7 @@ msgstr "Tunel do %s/%s"
#: ../src/modules/module-virtual-surround-sink.c:47
msgid "Virtual surround sink"
-msgstr ""
+msgstr "Virtuálny priestorový cieľ"
#: ../src/modules/module-virtual-surround-sink.c:51
msgid ""
@@ -1028,11 +1031,11 @@ msgstr "Basový reproduktor"
#: ../src/pulse/channelmap.c:115
msgid "Front Left-of-center"
-msgstr ""
+msgstr "Predný ľavý stredový"
#: ../src/pulse/channelmap.c:116
msgid "Front Right-of-center"
-msgstr ""
+msgstr "Predný pravý stredový"
#: ../src/pulse/channelmap.c:118
msgid "Side Left"
@@ -1553,7 +1556,7 @@ msgstr ""
#: ../src/utils/pacat.c:416
#, c-format
msgid "Stream buffer attributes changed.%s"
-msgstr ""
+msgstr "Atribúty zásobníka prúdu boli zmenené. %s"
#: ../src/utils/pacat.c:431
msgid "Cork request stack is empty: corking stream"
@@ -1759,7 +1762,7 @@ msgstr "Neznámy formát súboru %s."
#: ../src/utils/pacat.c:995
msgid "Failed to parse the argument for --monitor-stream"
-msgstr "Zlyhala analyzovanie argumentu pre --monitor-stream"
+msgstr "Zlyhala analyzovanie parametra pre voľbu --monitor-stream"
#: ../src/utils/pacat.c:1006
msgid "Invalid sample specification"
@@ -1856,7 +1859,7 @@ msgstr ""
#: ../src/utils/pacmd.c:51 ../src/utils/pactl.c:1570
msgid "NAME [ARGS ...]"
-msgstr "NÁZOV [ARGUMENTY ...]"
+msgstr "NÁZOV [PARAMETRE ...]"
#: ../src/utils/pacmd.c:52 ../src/utils/pacmd.c:60 ../src/utils/pactl.c:1571
msgid "NAME|#N"
@@ -1897,15 +1900,15 @@ msgstr "Č."
#: ../src/utils/pacmd.c:62
msgid "NAME SINK|#N"
-msgstr ""
+msgstr "NÁZOV CIEĽA|Č."
#: ../src/utils/pacmd.c:64 ../src/utils/pacmd.c:65
msgid "NAME FILENAME"
-msgstr "NÁZOV NÁZOV-SÚBORU"
+msgstr "NÁZOV NÁZOV_SÚBORU"
#: ../src/utils/pacmd.c:66
msgid "PATHNAME"
-msgstr "NÁZOV-CESTY"
+msgstr "NÁZOV_CESTY"
#: ../src/utils/pacmd.c:67
msgid "FILENAME SINK|#N"
@@ -1913,7 +1916,7 @@ msgstr ""
#: ../src/utils/pacmd.c:69 ../src/utils/pactl.c:1572
msgid "#N SINK|SOURCE"
-msgstr ""
+msgstr "Č. CIEĽU|ZDROJ"
#: ../src/utils/pacmd.c:71 ../src/utils/pacmd.c:77 ../src/utils/pacmd.c:78
msgid "1|0"
@@ -1929,7 +1932,7 @@ msgstr "NÁZOV|Č. PORTU"
#: ../src/utils/pacmd.c:74 ../src/utils/pactl.c:1582
msgid "CARD-NAME|CARD-#N PORT OFFSET"
-msgstr "NÁZOV-KARTY|KARTA-Č. PORT POSUNUTIE"
+msgstr "NÁZOV_KARTY|KARTA-Č. PORT POSUNUTIE"
#: ../src/utils/pacmd.c:75
msgid "TARGET"
@@ -2053,11 +2056,20 @@ msgid ""
"Default Source: %s\n"
"Cookie: %04x:%04x\n"
msgstr ""
+"Používateľské meno: %s\n"
+"Názov hostiteľa: %s\n"
+"Názov servera: %s\n"
+"Verzia servera: %s\n"
+"Predvolená špecifikácia snímky: %s\n"
+"Predvolená mapa kanálov: %s\n"
+"Predvolený cieľ: %s\n"
+"Predvolený zdroj: %s\n"
+"Cookie: %04x:%04x\n"
#: ../src/utils/pactl.c:255 ../src/utils/pactl.c:900 ../src/utils/pactl.c:978
#, c-format
msgid "Failed to get sink information: %s"
-msgstr ""
+msgstr "Zlyhalo získanie informácií o cieli: %s"
#: ../src/utils/pactl.c:281
#, c-format
@@ -2148,7 +2160,7 @@ msgid ""
msgstr ""
"Modul #%u\n"
"\tNázov: %s\n"
-"\tArgument: %s\n"
+"\tParameter: %s\n"
"\tPočítadlo použití: %s\n"
"\tVlastnosti:\n"
"\t\t%s\n"
@@ -2203,7 +2215,7 @@ msgstr "\tProfily:\n"
#: ../src/utils/pactl.c:581
#, c-format
msgid "\t\t%s: %s (sinks: %u, sources: %u, priority: %u, available: %s)\n"
-msgstr ""
+msgstr "\t\t%s: %s (ciele: %u, zdroje: %u, priorita: %u, dostupné: %s)\n"
#: ../src/utils/pactl.c:586
#, c-format
@@ -2250,6 +2262,23 @@ msgid ""
"\tProperties:\n"
"\t\t%s\n"
msgstr ""
+"Vstup cieľa č. %u\n"
+"\tOvládač: %s\n"
+"\tModul vlastníka: %s\n"
+"\tKlient: %s\n"
+"\tCieľ: %u\n"
+"\tŠpecifikácia snímky: %s\n"
+"\tMapa kanálov: %s\n"
+"\tFormát: %s\n"
+"\tBlokovanie: %s\n"
+"\tStlmenie: %s\n"
+"\tHlasitosť: %s\n"
+"\t vyváženie %0.2f\n"
+"\tOneskorenie zásobníka: %0.0f usek\n"
+"\tOneskorenie cieľa: %0.0f usek\n"
+"\tMetóda presnímkovania: %s\n"
+"\tVlastnosti:\n"
+"\t\t%s\n"
#: ../src/utils/pactl.c:692 ../src/utils/pactl.c:960 ../src/utils/pactl.c:1023
#, c-format
@@ -2308,7 +2337,7 @@ msgstr "Zlyhanie: %s"
#: ../src/utils/pactl.c:866
#, c-format
msgid "Failed to unload module: Module %s not loaded"
-msgstr ""
+msgstr "Zlyhalo uvoľnenie modulu: Modul %s nie je načítaný"
#: ../src/utils/pactl.c:884
#, c-format
@@ -2351,7 +2380,7 @@ msgstr "neznámy"
#: ../src/utils/pactl.c:1147
msgid "sink"
-msgstr ""
+msgstr "cieľ"
#: ../src/utils/pactl.c:1150
msgid "source"
@@ -2430,11 +2459,11 @@ msgstr "[TYP]"
#: ../src/utils/pactl.c:1567
msgid "FILENAME [NAME]"
-msgstr "NÁZOV-SÚBORU [NÁZOV]"
+msgstr "NÁZOV_SÚBORU [NÁZOV]"
#: ../src/utils/pactl.c:1568
msgid "NAME [SINK]"
-msgstr ""
+msgstr "NÁZOV [CIEĽ]"
#: ../src/utils/pactl.c:1577
msgid "NAME|#N VOLUME [VOLUME ...]"
@@ -2527,11 +2556,11 @@ msgstr "Musíte určiť číslo výstupu zdroja a zdroj"
#: ../src/utils/pactl.c:1775
msgid "You have to specify a module name and arguments."
-msgstr "Musíte určiť názov modulu a argumenty."
+msgstr "Musíte určiť názov modulu a parametre."
#: ../src/utils/pactl.c:1795
msgid "You have to specify a module index or name"
-msgstr ""
+msgstr "Musíte určiť číslo modulu alebo názov"
#: ../src/utils/pactl.c:1808
msgid ""
@@ -2558,7 +2587,7 @@ msgstr ""
#: ../src/utils/pactl.c:1867
msgid "You have to specify a sink name"
-msgstr ""
+msgstr "Musíte určiť názov cieľa"
#: ../src/utils/pactl.c:1877
msgid "You have to specify a source name/index and a port name"
@@ -2631,6 +2660,8 @@ msgid ""
"You have to specify a sink index and a semicolon-separated list of supported "
"formats"
msgstr ""
+"Musíte určiť číslo cieľa a bodkočiarkami oddelený zoznam podporovaných "
+"formátov"
#: ../src/utils/pactl.c:2038
msgid "You have to specify a card name/index, a port name and a latency offset"
@@ -2755,7 +2786,7 @@ msgstr "Zdroj: %s\n"
#: ../src/utils/pax11publish.c:114
#, c-format
msgid "Sink: %s\n"
-msgstr ""
+msgstr "Cieľ: %s\n"
#: ../src/utils/pax11publish.c:116
#, c-format
From 6bf178d794d1bca62b54a01a86a7c6bfc8c12813 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 8 Dec 2020 13:52:39 +0200
Subject: [PATCH 128/872] i18n: Update pulseaudio.pot
Part-of:
---
po/pulseaudio.pot | 515 +++++++++++++++++++++++++---------------------
1 file changed, 279 insertions(+), 236 deletions(-)
diff --git a/po/pulseaudio.pot b/po/pulseaudio.pot
index b02286acb..7e2f604dd 100644
--- a/po/pulseaudio.pot
+++ b/po/pulseaudio.pot
@@ -8,7 +8,7 @@ msgid ""
msgstr ""
"Project-Id-Version: pulseaudio\n"
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/new\n"
-"POT-Creation-Date: 2020-11-21 16:47+0300\n"
+"POT-Creation-Date: 2020-12-08 13:51+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
@@ -337,91 +337,91 @@ msgstr ""
msgid "System wide mode unsupported on this platform."
msgstr ""
-#: src/daemon/main.c:495
+#: src/daemon/main.c:501
msgid "Failed to parse command line."
msgstr ""
-#: src/daemon/main.c:534
+#: src/daemon/main.c:540
msgid ""
"System mode refused for non-root user. Only starting the D-Bus server lookup service."
msgstr ""
-#: src/daemon/main.c:633
+#: src/daemon/main.c:639
#, c-format
msgid "Failed to kill daemon: %s"
msgstr ""
-#: src/daemon/main.c:662
+#: src/daemon/main.c:668
msgid "This program is not intended to be run as root (unless --system is specified)."
msgstr ""
-#: src/daemon/main.c:665
+#: src/daemon/main.c:671
msgid "Root privileges required."
msgstr ""
-#: src/daemon/main.c:672
+#: src/daemon/main.c:678
msgid "--start not supported for system instances."
msgstr ""
-#: src/daemon/main.c:712
-#, c-format
-msgid "User-configured server at %s, refusing to start/autospawn."
-msgstr ""
-
#: src/daemon/main.c:718
#, c-format
+msgid "User-configured server at %s, refusing to start/autospawn."
+msgstr ""
+
+#: src/daemon/main.c:724
+#, c-format
msgid "User-configured server at %s, which appears to be local. Probing deeper."
msgstr ""
-#: src/daemon/main.c:723
+#: src/daemon/main.c:729
msgid "Running in system mode, but --disallow-exit not set."
msgstr ""
-#: src/daemon/main.c:726
+#: src/daemon/main.c:732
msgid "Running in system mode, but --disallow-module-loading not set."
msgstr ""
-#: src/daemon/main.c:729
+#: src/daemon/main.c:735
msgid "Running in system mode, forcibly disabling SHM mode."
msgstr ""
-#: src/daemon/main.c:734
+#: src/daemon/main.c:740
msgid "Running in system mode, forcibly disabling exit idle time."
msgstr ""
-#: src/daemon/main.c:767
+#: src/daemon/main.c:773
msgid "Failed to acquire stdio."
msgstr ""
-#: src/daemon/main.c:773 src/daemon/main.c:844
+#: src/daemon/main.c:779 src/daemon/main.c:850
#, c-format
msgid "pipe() failed: %s"
msgstr ""
-#: src/daemon/main.c:778 src/daemon/main.c:849
+#: src/daemon/main.c:784 src/daemon/main.c:855
#, c-format
msgid "fork() failed: %s"
msgstr ""
-#: src/daemon/main.c:793 src/daemon/main.c:864 src/utils/pacat.c:562
+#: src/daemon/main.c:799 src/daemon/main.c:870 src/utils/pacat.c:562
#, c-format
msgid "read() failed: %s"
msgstr ""
-#: src/daemon/main.c:799
+#: src/daemon/main.c:805
msgid "Daemon startup failed."
msgstr ""
-#: src/daemon/main.c:832
+#: src/daemon/main.c:838
#, c-format
msgid "setsid() failed: %s"
msgstr ""
-#: src/daemon/main.c:965
+#: src/daemon/main.c:971
msgid "Failed to get machine ID"
msgstr ""
-#: src/daemon/main.c:991
+#: src/daemon/main.c:997
msgid ""
"OK, so you are running PA in system mode. Please make sure that you actually do want to "
"do that.\n"
@@ -429,26 +429,26 @@ msgid ""
"WhatIsWrongWithSystemWide/ for an explanation why system mode is usually a bad idea."
msgstr ""
-#: src/daemon/main.c:1007
+#: src/daemon/main.c:1013
msgid "pa_pid_file_create() failed."
msgstr ""
-#: src/daemon/main.c:1039
+#: src/daemon/main.c:1045
msgid "pa_core_new() failed."
msgstr ""
-#: src/daemon/main.c:1114
+#: src/daemon/main.c:1120
msgid "command line arguments"
msgstr ""
-#: src/daemon/main.c:1121
+#: src/daemon/main.c:1127
#, c-format
msgid ""
"Failed to initialize daemon due to errors while executing startup commands. Source of "
"commands: %s"
msgstr ""
-#: src/daemon/main.c:1126
+#: src/daemon/main.c:1132
msgid "Daemon startup without any loaded modules, refusing to work."
msgstr ""
@@ -502,12 +502,12 @@ msgid "Internal Microphone"
msgstr ""
#: src/modules/alsa/alsa-mixer.c:2631 src/modules/alsa/alsa-mixer.c:2717
-#: src/utils/pactl.c:260
+#: src/utils/pactl.c:265
msgid "Radio"
msgstr ""
#: src/modules/alsa/alsa-mixer.c:2632 src/modules/alsa/alsa-mixer.c:2718
-#: src/utils/pactl.c:261
+#: src/utils/pactl.c:266
msgid "Video"
msgstr ""
@@ -544,12 +544,12 @@ msgid "No Bass Boost"
msgstr ""
#: src/modules/alsa/alsa-mixer.c:2641 src/modules/bluetooth/module-bluez5-device.c:1800
-#: src/utils/pactl.c:250
+#: src/utils/pactl.c:255
msgid "Speaker"
msgstr ""
#: src/modules/alsa/alsa-mixer.c:2642 src/modules/alsa/alsa-mixer.c:2720
-#: src/utils/pactl.c:251
+#: src/utils/pactl.c:256
msgid "Headphones"
msgstr ""
@@ -617,136 +617,153 @@ msgstr ""
msgid "Analog Mono"
msgstr ""
+#: src/modules/alsa/alsa-mixer.c:4395
+msgid "Analog Mono (Left)"
+msgstr ""
+
+#: src/modules/alsa/alsa-mixer.c:4396
+msgid "Analog Mono (Right)"
+msgstr ""
+
#. Note: Not translated to "Analog Stereo Input", because the source
#. * name gets "Input" appended to it automatically, so adding "Input"
#. * 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.
-#: src/modules/alsa/alsa-mixer.c:4395 src/modules/alsa/alsa-mixer.c:4403
-#: src/modules/alsa/alsa-mixer.c:4404
+#: src/modules/alsa/alsa-mixer.c:4397 src/modules/alsa/alsa-mixer.c:4405
+#: src/modules/alsa/alsa-mixer.c:4406
msgid "Analog Stereo"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4396 src/pulse/channelmap.c:103
+#: src/modules/alsa/alsa-mixer.c:4398 src/pulse/channelmap.c:103
#: src/pulse/channelmap.c:771
msgid "Mono"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4397 src/pulse/channelmap.c:775
+#: src/modules/alsa/alsa-mixer.c:4399 src/pulse/channelmap.c:775
msgid "Stereo"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4405 src/modules/alsa/alsa-mixer.c:4406
+#: src/modules/alsa/alsa-mixer.c:4407 src/modules/alsa/alsa-mixer.c:4565
+#: src/modules/bluetooth/module-bluez5-device.c:1780 src/utils/pactl.c:259
+msgid "Headset"
+msgstr ""
+
+#: src/modules/alsa/alsa-mixer.c:4408 src/modules/alsa/alsa-mixer.c:4566
+msgid "Speakerphone"
+msgstr ""
+
+#: src/modules/alsa/alsa-mixer.c:4409 src/modules/alsa/alsa-mixer.c:4410
msgid "Multichannel"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4407
+#: src/modules/alsa/alsa-mixer.c:4411
msgid "Analog Surround 2.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4408
+#: src/modules/alsa/alsa-mixer.c:4412
msgid "Analog Surround 3.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4409
+#: src/modules/alsa/alsa-mixer.c:4413
msgid "Analog Surround 3.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4410
+#: src/modules/alsa/alsa-mixer.c:4414
msgid "Analog Surround 4.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4411
+#: src/modules/alsa/alsa-mixer.c:4415
msgid "Analog Surround 4.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4412
+#: src/modules/alsa/alsa-mixer.c:4416
msgid "Analog Surround 5.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4413
+#: src/modules/alsa/alsa-mixer.c:4417
msgid "Analog Surround 5.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4414
+#: src/modules/alsa/alsa-mixer.c:4418
msgid "Analog Surround 6.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4415
+#: src/modules/alsa/alsa-mixer.c:4419
msgid "Analog Surround 6.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4416
+#: src/modules/alsa/alsa-mixer.c:4420
msgid "Analog Surround 7.0"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4417
+#: src/modules/alsa/alsa-mixer.c:4421
msgid "Analog Surround 7.1"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4418
+#: src/modules/alsa/alsa-mixer.c:4422
msgid "Digital Stereo (IEC958)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4419
+#: src/modules/alsa/alsa-mixer.c:4423
msgid "Digital Surround 4.0 (IEC958/AC3)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4420
+#: src/modules/alsa/alsa-mixer.c:4424
msgid "Digital Surround 5.1 (IEC958/AC3)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4421
+#: src/modules/alsa/alsa-mixer.c:4425
msgid "Digital Surround 5.1 (IEC958/DTS)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4422
+#: src/modules/alsa/alsa-mixer.c:4426
msgid "Digital Stereo (HDMI)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4423
+#: src/modules/alsa/alsa-mixer.c:4427
msgid "Digital Surround 5.1 (HDMI)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4424
+#: src/modules/alsa/alsa-mixer.c:4428
msgid "Chat"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4425
+#: src/modules/alsa/alsa-mixer.c:4429
msgid "Game"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4559
+#: src/modules/alsa/alsa-mixer.c:4563
msgid "Analog Mono Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4560
+#: src/modules/alsa/alsa-mixer.c:4564
msgid "Analog Stereo Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4561
+#: src/modules/alsa/alsa-mixer.c:4567
msgid "Digital Stereo Duplex (IEC958)"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4562
+#: src/modules/alsa/alsa-mixer.c:4568
msgid "Multichannel Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4563
+#: src/modules/alsa/alsa-mixer.c:4569
msgid "Stereo Duplex"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4564 src/modules/alsa/module-alsa-card.c:188
+#: src/modules/alsa/alsa-mixer.c:4570 src/modules/alsa/module-alsa-card.c:188
#: src/modules/bluetooth/module-bluez5-device.c:2053
msgid "Off"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4664
+#: src/modules/alsa/alsa-mixer.c:4670
#, c-format
msgid "%s Output"
msgstr ""
-#: src/modules/alsa/alsa-mixer.c:4672
+#: src/modules/alsa/alsa-mixer.c:4678
#, c-format
msgid "%s Input"
msgstr ""
@@ -831,11 +848,7 @@ msgstr ""
msgid "Bluetooth Output"
msgstr ""
-#: src/modules/bluetooth/module-bluez5-device.c:1780 src/utils/pactl.c:254
-msgid "Headset"
-msgstr ""
-
-#: src/modules/bluetooth/module-bluez5-device.c:1786 src/utils/pactl.c:265
+#: src/modules/bluetooth/module-bluez5-device.c:1786 src/utils/pactl.c:270
msgid "Handsfree"
msgstr ""
@@ -843,19 +856,19 @@ msgstr ""
msgid "Headphone"
msgstr ""
-#: src/modules/bluetooth/module-bluez5-device.c:1813 src/utils/pactl.c:264
+#: src/modules/bluetooth/module-bluez5-device.c:1813 src/utils/pactl.c:269
msgid "Portable"
msgstr ""
-#: src/modules/bluetooth/module-bluez5-device.c:1819 src/utils/pactl.c:266
+#: src/modules/bluetooth/module-bluez5-device.c:1819 src/utils/pactl.c:271
msgid "Car"
msgstr ""
-#: src/modules/bluetooth/module-bluez5-device.c:1825 src/utils/pactl.c:267
+#: src/modules/bluetooth/module-bluez5-device.c:1825 src/utils/pactl.c:272
msgid "HiFi"
msgstr ""
-#: src/modules/bluetooth/module-bluez5-device.c:1831 src/utils/pactl.c:268
+#: src/modules/bluetooth/module-bluez5-device.c:1831 src/utils/pactl.c:273
msgid "Phone"
msgstr ""
@@ -946,11 +959,11 @@ msgstr ""
msgid "Clocked NULL sink"
msgstr ""
-#: src/modules/module-null-sink.c:333
+#: src/modules/module-null-sink.c:334
msgid "Null Output"
msgstr ""
-#: src/modules/module-null-sink.c:345 src/utils/pactl.c:1096
+#: src/modules/module-null-sink.c:346 src/utils/pactl.c:1170
#, c-format
msgid "Failed to set format: invalid format string %s"
msgstr ""
@@ -981,17 +994,18 @@ msgstr ""
msgid "Tunnel to %s/%s"
msgstr ""
-#: src/modules/module-virtual-surround-sink.c:45
+#: src/modules/module-virtual-surround-sink.c:50
msgid "Virtual surround sink"
msgstr ""
-#: src/modules/module-virtual-surround-sink.c:49
+#: src/modules/module-virtual-surround-sink.c:54
msgid ""
"sink_name= sink_properties= master= sink_master= format= "
"rate= channels= channel_map= "
"use_volume_sharing= force_flat_volume= hrir=/path/to/left_hrir."
-"wav autoloaded= "
+"wav hrir_left=/path/to/left_hrir.wav hrir_right=/path/to/optional/right_hrir.wav "
+"autoloaded= "
msgstr ""
#: src/modules/raop/module-raop-discover.c:295
@@ -1588,7 +1602,7 @@ msgstr ""
msgid "pa_stream_connect_record() failed: %s"
msgstr ""
-#: src/utils/pacat.c:514 src/utils/pactl.c:1492
+#: src/utils/pacat.c:514 src/utils/pactl.c:1572
#, c-format
msgid "Connection failure: %s"
msgstr ""
@@ -1709,7 +1723,7 @@ msgid ""
"Linked with libpulse %s\n"
msgstr ""
-#: src/utils/pacat.c:852 src/utils/pactl.c:1694
+#: src/utils/pacat.c:852 src/utils/pactl.c:1775
#, c-format
msgid "Invalid client name '%s'"
msgstr ""
@@ -1780,7 +1794,7 @@ msgid ""
"file."
msgstr ""
-#: src/utils/pacat.c:1079 src/utils/pactl.c:1758
+#: src/utils/pacat.c:1079 src/utils/pactl.c:1840
msgid "Failed to determine sample specification from file."
msgstr ""
@@ -1813,7 +1827,7 @@ msgstr ""
msgid "Failed to set media name."
msgstr ""
-#: src/utils/pacat.c:1160 src/utils/pactl.c:2108
+#: src/utils/pacat.c:1160 src/utils/pactl.c:2206
msgid "pa_mainloop_new() failed."
msgstr ""
@@ -1821,11 +1835,11 @@ msgstr ""
msgid "io_new() failed."
msgstr ""
-#: src/utils/pacat.c:1190 src/utils/pactl.c:2120
+#: src/utils/pacat.c:1190 src/utils/pactl.c:2218
msgid "pa_context_new() failed."
msgstr ""
-#: src/utils/pacat.c:1198 src/utils/pactl.c:2126
+#: src/utils/pacat.c:1198 src/utils/pactl.c:2224
#, c-format
msgid "pa_context_connect() failed: %s"
msgstr ""
@@ -1834,19 +1848,19 @@ msgstr ""
msgid "pa_context_rttime_new() failed."
msgstr ""
-#: src/utils/pacat.c:1211 src/utils/pactl.c:2131
+#: src/utils/pacat.c:1211 src/utils/pactl.c:2229
msgid "pa_mainloop_run() failed."
msgstr ""
-#: src/utils/pacmd.c:51 src/utils/pactl.c:1616
+#: src/utils/pacmd.c:51 src/utils/pactl.c:1696
msgid "NAME [ARGS ...]"
msgstr ""
-#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1617
+#: src/utils/pacmd.c:52 src/utils/pacmd.c:60 src/utils/pactl.c:1697
msgid "NAME|#N"
msgstr ""
-#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1615 src/utils/pactl.c:1621
+#: src/utils/pacmd.c:53 src/utils/pacmd.c:63 src/utils/pactl.c:1695 src/utils/pactl.c:1701
msgid "NAME"
msgstr ""
@@ -1858,7 +1872,7 @@ msgstr ""
msgid "#N VOLUME"
msgstr ""
-#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1619
+#: src/utils/pacmd.c:56 src/utils/pacmd.c:70 src/utils/pactl.c:1699
msgid "NAME|#N 1|0"
msgstr ""
@@ -1894,7 +1908,7 @@ msgstr ""
msgid "FILENAME SINK|#N"
msgstr ""
-#: src/utils/pacmd.c:69 src/utils/pactl.c:1618
+#: src/utils/pacmd.c:69 src/utils/pactl.c:1698
msgid "#N SINK|SOURCE"
msgstr ""
@@ -1902,15 +1916,15 @@ msgstr ""
msgid "1|0"
msgstr ""
-#: src/utils/pacmd.c:72 src/utils/pactl.c:1620
+#: src/utils/pacmd.c:72 src/utils/pactl.c:1700
msgid "CARD PROFILE"
msgstr ""
-#: src/utils/pacmd.c:73 src/utils/pactl.c:1622
+#: src/utils/pacmd.c:73 src/utils/pactl.c:1702
msgid "NAME|#N PORT"
msgstr ""
-#: src/utils/pacmd.c:74 src/utils/pactl.c:1628
+#: src/utils/pacmd.c:74 src/utils/pactl.c:1708
msgid "CARD-NAME|CARD-#N PORT OFFSET"
msgstr ""
@@ -1926,7 +1940,11 @@ msgstr ""
msgid "FRAMES"
msgstr ""
-#: src/utils/pacmd.c:81
+#: src/utils/pacmd.c:80 src/utils/pactl.c:1709
+msgid "RECIPIENT MESSAGE [MESSAGE_PARAMETERS]"
+msgstr ""
+
+#: src/utils/pacmd.c:82
#, c-format
msgid ""
"\n"
@@ -1935,7 +1953,7 @@ msgid ""
"When no command is given pacmd starts in the interactive mode.\n"
msgstr ""
-#: src/utils/pacmd.c:128
+#: src/utils/pacmd.c:129
#, c-format
msgid ""
"pacmd %s\n"
@@ -1943,73 +1961,73 @@ msgid ""
"Linked with libpulse %s\n"
msgstr ""
-#: src/utils/pacmd.c:142
+#: src/utils/pacmd.c:143
msgid "No PulseAudio daemon running, or not running as session daemon."
msgstr ""
-#: src/utils/pacmd.c:147
+#: src/utils/pacmd.c:148
#, c-format
msgid "socket(PF_UNIX, SOCK_STREAM, 0): %s"
msgstr ""
-#: src/utils/pacmd.c:164
+#: src/utils/pacmd.c:165
#, c-format
msgid "connect(): %s"
msgstr ""
-#: src/utils/pacmd.c:172
+#: src/utils/pacmd.c:173
msgid "Failed to kill PulseAudio daemon."
msgstr ""
-#: src/utils/pacmd.c:180
+#: src/utils/pacmd.c:181
msgid "Daemon not responding."
msgstr ""
-#: src/utils/pacmd.c:212 src/utils/pacmd.c:321 src/utils/pacmd.c:339
+#: src/utils/pacmd.c:213 src/utils/pacmd.c:322 src/utils/pacmd.c:340
#, c-format
msgid "write(): %s"
msgstr ""
-#: src/utils/pacmd.c:268
+#: src/utils/pacmd.c:269
#, c-format
msgid "poll(): %s"
msgstr ""
-#: src/utils/pacmd.c:279 src/utils/pacmd.c:299
+#: src/utils/pacmd.c:280 src/utils/pacmd.c:300
#, c-format
msgid "read(): %s"
msgstr ""
-#: src/utils/pactl.c:164
+#: src/utils/pactl.c:169
#, c-format
msgid "Failed to get statistics: %s"
msgstr ""
-#: src/utils/pactl.c:170
+#: src/utils/pactl.c:175
#, c-format
msgid "Currently in use: %u block containing %s bytes total.\n"
msgid_plural "Currently in use: %u blocks containing %s bytes total.\n"
msgstr[0] ""
msgstr[1] ""
-#: src/utils/pactl.c:176
+#: src/utils/pactl.c:181
#, c-format
msgid "Allocated during whole lifetime: %u block containing %s bytes total.\n"
msgid_plural "Allocated during whole lifetime: %u blocks containing %s bytes total.\n"
msgstr[0] ""
msgstr[1] ""
-#: src/utils/pactl.c:182
+#: src/utils/pactl.c:187
#, c-format
msgid "Sample cache size: %s\n"
msgstr ""
-#: src/utils/pactl.c:191
+#: src/utils/pactl.c:196
#, c-format
msgid "Failed to get server information: %s"
msgstr ""
-#: src/utils/pactl.c:196
+#: src/utils/pactl.c:201
#, c-format
msgid ""
"Server String: %s\n"
@@ -2020,7 +2038,7 @@ msgid ""
"Tile Size: %zu\n"
msgstr ""
-#: src/utils/pactl.c:212
+#: src/utils/pactl.c:217
#, c-format
msgid ""
"User Name: %s\n"
@@ -2034,76 +2052,76 @@ msgid ""
"Cookie: %04x:%04x\n"
msgstr ""
-#: src/utils/pactl.c:237
+#: src/utils/pactl.c:242
msgid "availability unknown"
msgstr ""
-#: src/utils/pactl.c:238
+#: src/utils/pactl.c:243
msgid "available"
msgstr ""
-#: src/utils/pactl.c:239
+#: src/utils/pactl.c:244
msgid "not available"
msgstr ""
-#: src/utils/pactl.c:248 src/utils/pactl.c:272
+#: src/utils/pactl.c:253 src/utils/pactl.c:277
msgid "Unknown"
msgstr ""
-#: src/utils/pactl.c:249
+#: src/utils/pactl.c:254
msgid "Aux"
msgstr ""
-#: src/utils/pactl.c:252
+#: src/utils/pactl.c:257
msgid "Line"
msgstr ""
-#: src/utils/pactl.c:253
+#: src/utils/pactl.c:258
msgid "Mic"
msgstr ""
-#: src/utils/pactl.c:255
+#: src/utils/pactl.c:260
msgid "Handset"
msgstr ""
-#: src/utils/pactl.c:256
+#: src/utils/pactl.c:261
msgid "Earpiece"
msgstr ""
-#: src/utils/pactl.c:257
+#: src/utils/pactl.c:262
msgid "SPDIF"
msgstr ""
-#: src/utils/pactl.c:258
+#: src/utils/pactl.c:263
msgid "HDMI"
msgstr ""
-#: src/utils/pactl.c:259
+#: src/utils/pactl.c:264
msgid "TV"
msgstr ""
-#: src/utils/pactl.c:262
+#: src/utils/pactl.c:267
msgid "USB"
msgstr ""
-#: src/utils/pactl.c:263
+#: src/utils/pactl.c:268
msgid "Bluetooth"
msgstr ""
-#: src/utils/pactl.c:269
+#: src/utils/pactl.c:274
msgid "Network"
msgstr ""
-#: src/utils/pactl.c:270
+#: src/utils/pactl.c:275
msgid "Analog"
msgstr ""
-#: src/utils/pactl.c:294 src/utils/pactl.c:946 src/utils/pactl.c:1024
+#: src/utils/pactl.c:299 src/utils/pactl.c:1020 src/utils/pactl.c:1098
#, c-format
msgid "Failed to get sink information: %s"
msgstr ""
-#: src/utils/pactl.c:320
+#: src/utils/pactl.c:325
#, c-format
msgid ""
"Sink #%u\n"
@@ -2125,36 +2143,36 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:364 src/utils/pactl.c:472 src/utils/pactl.c:635
+#: src/utils/pactl.c:369 src/utils/pactl.c:477 src/utils/pactl.c:640
#, c-format
msgid "\tPorts:\n"
msgstr ""
-#: src/utils/pactl.c:366 src/utils/pactl.c:474
+#: src/utils/pactl.c:371 src/utils/pactl.c:479
#, c-format
msgid "\t\t%s: %s (type: %s, priority: %u%s%s, %s)\n"
msgstr ""
-#: src/utils/pactl.c:368 src/utils/pactl.c:476 src/utils/pactl.c:640
+#: src/utils/pactl.c:373 src/utils/pactl.c:481 src/utils/pactl.c:645
msgid ", availability group: "
msgstr ""
-#: src/utils/pactl.c:373 src/utils/pactl.c:481
+#: src/utils/pactl.c:378 src/utils/pactl.c:486
#, c-format
msgid "\tActive Port: %s\n"
msgstr ""
-#: src/utils/pactl.c:379 src/utils/pactl.c:487
+#: src/utils/pactl.c:384 src/utils/pactl.c:492
#, c-format
msgid "\tFormats:\n"
msgstr ""
-#: src/utils/pactl.c:403 src/utils/pactl.c:966 src/utils/pactl.c:1039
+#: src/utils/pactl.c:408 src/utils/pactl.c:1040 src/utils/pactl.c:1113
#, c-format
msgid "Failed to get source information: %s"
msgstr ""
-#: src/utils/pactl.c:429
+#: src/utils/pactl.c:434
#, c-format
msgid ""
"Source #%u\n"
@@ -2176,19 +2194,19 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:457 src/utils/pactl.c:529 src/utils/pactl.c:572 src/utils/pactl.c:614
-#: src/utils/pactl.c:713 src/utils/pactl.c:714 src/utils/pactl.c:725 src/utils/pactl.c:783
-#: src/utils/pactl.c:784 src/utils/pactl.c:795 src/utils/pactl.c:846 src/utils/pactl.c:847
-#: src/utils/pactl.c:853
+#: src/utils/pactl.c:462 src/utils/pactl.c:534 src/utils/pactl.c:577 src/utils/pactl.c:619
+#: src/utils/pactl.c:718 src/utils/pactl.c:719 src/utils/pactl.c:730 src/utils/pactl.c:788
+#: src/utils/pactl.c:789 src/utils/pactl.c:800 src/utils/pactl.c:851 src/utils/pactl.c:852
+#: src/utils/pactl.c:858
msgid "n/a"
msgstr ""
-#: src/utils/pactl.c:498 src/utils/pactl.c:903
+#: src/utils/pactl.c:503 src/utils/pactl.c:977
#, c-format
msgid "Failed to get module information: %s"
msgstr ""
-#: src/utils/pactl.c:521
+#: src/utils/pactl.c:526
#, c-format
msgid ""
"Module #%u\n"
@@ -2199,12 +2217,12 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:540
+#: src/utils/pactl.c:545
#, c-format
msgid "Failed to get client information: %s"
msgstr ""
-#: src/utils/pactl.c:566
+#: src/utils/pactl.c:571
#, c-format
msgid ""
"Client #%u\n"
@@ -2214,12 +2232,12 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:583
+#: src/utils/pactl.c:588
#, c-format
msgid "Failed to get card information: %s"
msgstr ""
-#: src/utils/pactl.c:606
+#: src/utils/pactl.c:611
#, c-format
msgid ""
"Card #%u\n"
@@ -2230,44 +2248,44 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:622
+#: src/utils/pactl.c:627
#, c-format
msgid "\tProfiles:\n"
msgstr ""
-#: src/utils/pactl.c:624
+#: src/utils/pactl.c:629
#, c-format
msgid "\t\t%s: %s (sinks: %u, sources: %u, priority: %u, available: %s)\n"
msgstr ""
-#: src/utils/pactl.c:629
+#: src/utils/pactl.c:634
#, c-format
msgid "\tActive Profile: %s\n"
msgstr ""
-#: src/utils/pactl.c:638
+#: src/utils/pactl.c:643
#, c-format
msgid "\t\t%s: %s (type: %s, priority: %u, latency offset: % usec%s%s, %s)\n"
msgstr ""
-#: src/utils/pactl.c:644
+#: src/utils/pactl.c:649
#, c-format
msgid ""
"\t\t\tProperties:\n"
"\t\t\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:649
+#: src/utils/pactl.c:654
#, c-format
msgid "\t\t\tPart of profile(s): %s"
msgstr ""
-#: src/utils/pactl.c:666 src/utils/pactl.c:986 src/utils/pactl.c:1054
+#: src/utils/pactl.c:671 src/utils/pactl.c:1060 src/utils/pactl.c:1128
#, c-format
msgid "Failed to get sink input information: %s"
msgstr ""
-#: src/utils/pactl.c:695
+#: src/utils/pactl.c:700
#, c-format
msgid ""
"Sink Input #%u\n"
@@ -2289,12 +2307,12 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:736 src/utils/pactl.c:1006 src/utils/pactl.c:1069
+#: src/utils/pactl.c:741 src/utils/pactl.c:1080 src/utils/pactl.c:1143
#, c-format
msgid "Failed to get source output information: %s"
msgstr ""
-#: src/utils/pactl.c:765
+#: src/utils/pactl.c:770
#, c-format
msgid ""
"Source Output #%u\n"
@@ -2316,12 +2334,12 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:806
+#: src/utils/pactl.c:811
#, c-format
msgid "Failed to get sample information: %s"
msgstr ""
-#: src/utils/pactl.c:833
+#: src/utils/pactl.c:838
#, c-format
msgid ""
"Sample #%u\n"
@@ -2338,17 +2356,31 @@ msgid ""
"\t\t%s\n"
msgstr ""
-#: src/utils/pactl.c:861 src/utils/pactl.c:871
+#: src/utils/pactl.c:866 src/utils/pactl.c:876
#, c-format
msgid "Failure: %s"
msgstr ""
-#: src/utils/pactl.c:910
+#: src/utils/pactl.c:889
+#, c-format
+msgid "Send message failed: %s"
+msgstr ""
+
+#: src/utils/pactl.c:906
+#, c-format
+msgid "list-handlers message failed: %s"
+msgstr ""
+
+#: src/utils/pactl.c:912 src/utils/pactl.c:947
+msgid "list-handlers message response could not be parsed correctly"
+msgstr ""
+
+#: src/utils/pactl.c:984
#, c-format
msgid "Failed to unload module: Module %s not loaded"
msgstr ""
-#: src/utils/pactl.c:928
+#: src/utils/pactl.c:1002
#, c-format
msgid ""
"Failed to set volume: You tried to set volumes for %d channel, whereas channel(s) "
@@ -2359,135 +2391,136 @@ msgid_plural ""
msgstr[0] ""
msgstr[1] ""
-#: src/utils/pactl.c:1139
+#: src/utils/pactl.c:1213
#, c-format
msgid "Failed to upload sample: %s"
msgstr ""
-#: src/utils/pactl.c:1156
+#: src/utils/pactl.c:1230
msgid "Premature end of file"
msgstr ""
-#: src/utils/pactl.c:1176
+#: src/utils/pactl.c:1250
msgid "new"
msgstr ""
-#: src/utils/pactl.c:1179
+#: src/utils/pactl.c:1253
msgid "change"
msgstr ""
-#: src/utils/pactl.c:1182
+#: src/utils/pactl.c:1256
msgid "remove"
msgstr ""
-#: src/utils/pactl.c:1185 src/utils/pactl.c:1220
+#: src/utils/pactl.c:1259 src/utils/pactl.c:1294
msgid "unknown"
msgstr ""
-#: src/utils/pactl.c:1193
+#: src/utils/pactl.c:1267
msgid "sink"
msgstr ""
-#: src/utils/pactl.c:1196
+#: src/utils/pactl.c:1270
msgid "source"
msgstr ""
-#: src/utils/pactl.c:1199
+#: src/utils/pactl.c:1273
msgid "sink-input"
msgstr ""
-#: src/utils/pactl.c:1202
+#: src/utils/pactl.c:1276
msgid "source-output"
msgstr ""
-#: src/utils/pactl.c:1205
+#: src/utils/pactl.c:1279
msgid "module"
msgstr ""
-#: src/utils/pactl.c:1208
+#: src/utils/pactl.c:1282
msgid "client"
msgstr ""
-#: src/utils/pactl.c:1211
+#: src/utils/pactl.c:1285
msgid "sample-cache"
msgstr ""
-#: src/utils/pactl.c:1214
+#: src/utils/pactl.c:1288
msgid "server"
msgstr ""
-#: src/utils/pactl.c:1217
+#: src/utils/pactl.c:1291
msgid "card"
msgstr ""
-#: src/utils/pactl.c:1226
+#: src/utils/pactl.c:1300
#, c-format
msgid "Event '%s' on %s #%u\n"
msgstr ""
-#: src/utils/pactl.c:1498
+#: src/utils/pactl.c:1578
msgid "Got SIGINT, exiting."
msgstr ""
-#: src/utils/pactl.c:1531
+#: src/utils/pactl.c:1611
msgid "Invalid volume specification"
msgstr ""
-#: src/utils/pactl.c:1554
+#: src/utils/pactl.c:1634
msgid "Volume outside permissible range.\n"
msgstr ""
-#: src/utils/pactl.c:1567
+#: src/utils/pactl.c:1647
msgid "Invalid number of volume specifications.\n"
msgstr ""
-#: src/utils/pactl.c:1579
+#: src/utils/pactl.c:1659
msgid "Inconsistent volume specification.\n"
msgstr ""
-#: src/utils/pactl.c:1609 src/utils/pactl.c:1610 src/utils/pactl.c:1611
-#: src/utils/pactl.c:1612 src/utils/pactl.c:1613 src/utils/pactl.c:1614
-#: src/utils/pactl.c:1615 src/utils/pactl.c:1616 src/utils/pactl.c:1617
-#: src/utils/pactl.c:1618 src/utils/pactl.c:1619 src/utils/pactl.c:1620
-#: src/utils/pactl.c:1621 src/utils/pactl.c:1622 src/utils/pactl.c:1623
-#: src/utils/pactl.c:1624 src/utils/pactl.c:1625 src/utils/pactl.c:1626
-#: src/utils/pactl.c:1627 src/utils/pactl.c:1628 src/utils/pactl.c:1629
+#: src/utils/pactl.c:1689 src/utils/pactl.c:1690 src/utils/pactl.c:1691
+#: src/utils/pactl.c:1692 src/utils/pactl.c:1693 src/utils/pactl.c:1694
+#: src/utils/pactl.c:1695 src/utils/pactl.c:1696 src/utils/pactl.c:1697
+#: src/utils/pactl.c:1698 src/utils/pactl.c:1699 src/utils/pactl.c:1700
+#: src/utils/pactl.c:1701 src/utils/pactl.c:1702 src/utils/pactl.c:1703
+#: src/utils/pactl.c:1704 src/utils/pactl.c:1705 src/utils/pactl.c:1706
+#: src/utils/pactl.c:1707 src/utils/pactl.c:1708 src/utils/pactl.c:1709
+#: src/utils/pactl.c:1710
msgid "[options]"
msgstr ""
-#: src/utils/pactl.c:1611
+#: src/utils/pactl.c:1691
msgid "[TYPE]"
msgstr ""
-#: src/utils/pactl.c:1613
+#: src/utils/pactl.c:1693
msgid "FILENAME [NAME]"
msgstr ""
-#: src/utils/pactl.c:1614
+#: src/utils/pactl.c:1694
msgid "NAME [SINK]"
msgstr ""
-#: src/utils/pactl.c:1623
+#: src/utils/pactl.c:1703
msgid "NAME|#N VOLUME [VOLUME ...]"
msgstr ""
-#: src/utils/pactl.c:1624
+#: src/utils/pactl.c:1704
msgid "#N VOLUME [VOLUME ...]"
msgstr ""
-#: src/utils/pactl.c:1625
+#: src/utils/pactl.c:1705
msgid "NAME|#N 1|0|toggle"
msgstr ""
-#: src/utils/pactl.c:1626
+#: src/utils/pactl.c:1706
msgid "#N 1|0|toggle"
msgstr ""
-#: src/utils/pactl.c:1627
+#: src/utils/pactl.c:1707
msgid "#N FORMATS"
msgstr ""
-#: src/utils/pactl.c:1630
+#: src/utils/pactl.c:1711
#, c-format
msgid ""
"\n"
@@ -2495,7 +2528,7 @@ msgid ""
"can be used to specify the default sink, source and monitor.\n"
msgstr ""
-#: src/utils/pactl.c:1633
+#: src/utils/pactl.c:1714
#, c-format
msgid ""
"\n"
@@ -2506,7 +2539,7 @@ msgid ""
" -n, --client-name=NAME How to call this client on the server\n"
msgstr ""
-#: src/utils/pactl.c:1674
+#: src/utils/pactl.c:1755
#, c-format
msgid ""
"pactl %s\n"
@@ -2514,146 +2547,156 @@ msgid ""
"Linked with libpulse %s\n"
msgstr ""
-#: src/utils/pactl.c:1730
+#: src/utils/pactl.c:1812
#, c-format
msgid "Specify nothing, or one of: %s"
msgstr ""
-#: src/utils/pactl.c:1740
+#: src/utils/pactl.c:1822
msgid "Please specify a sample file to load"
msgstr ""
-#: src/utils/pactl.c:1753
+#: src/utils/pactl.c:1835
msgid "Failed to open sound file."
msgstr ""
-#: src/utils/pactl.c:1765
+#: src/utils/pactl.c:1847
msgid "Warning: Failed to determine sample specification from file."
msgstr ""
-#: src/utils/pactl.c:1775
+#: src/utils/pactl.c:1857
msgid "You have to specify a sample name to play"
msgstr ""
-#: src/utils/pactl.c:1787
+#: src/utils/pactl.c:1869
msgid "You have to specify a sample name to remove"
msgstr ""
-#: src/utils/pactl.c:1796
+#: src/utils/pactl.c:1878
msgid "You have to specify a sink input index and a sink"
msgstr ""
-#: src/utils/pactl.c:1806
+#: src/utils/pactl.c:1888
msgid "You have to specify a source output index and a source"
msgstr ""
-#: src/utils/pactl.c:1821
+#: src/utils/pactl.c:1903
msgid "You have to specify a module name and arguments."
msgstr ""
-#: src/utils/pactl.c:1841
+#: src/utils/pactl.c:1923
msgid "You have to specify a module index or name"
msgstr ""
-#: src/utils/pactl.c:1854
+#: src/utils/pactl.c:1936
msgid "You may not specify more than one sink. You have to specify a boolean value."
msgstr ""
-#: src/utils/pactl.c:1859 src/utils/pactl.c:1879
+#: src/utils/pactl.c:1941 src/utils/pactl.c:1961
msgid "Invalid suspend specification."
msgstr ""
-#: src/utils/pactl.c:1874
+#: src/utils/pactl.c:1956
msgid "You may not specify more than one source. You have to specify a boolean value."
msgstr ""
-#: src/utils/pactl.c:1891
+#: src/utils/pactl.c:1973
msgid "You have to specify a card name/index and a profile name"
msgstr ""
-#: src/utils/pactl.c:1902
+#: src/utils/pactl.c:1984
msgid "You have to specify a sink name/index and a port name"
msgstr ""
-#: src/utils/pactl.c:1913
+#: src/utils/pactl.c:1995
msgid "You have to specify a sink name"
msgstr ""
-#: src/utils/pactl.c:1923
+#: src/utils/pactl.c:2005
msgid "You have to specify a source name/index and a port name"
msgstr ""
-#: src/utils/pactl.c:1934
+#: src/utils/pactl.c:2016
msgid "You have to specify a source name"
msgstr ""
-#: src/utils/pactl.c:1944
+#: src/utils/pactl.c:2026
msgid "You have to specify a sink name/index and a volume"
msgstr ""
-#: src/utils/pactl.c:1957
+#: src/utils/pactl.c:2039
msgid "You have to specify a source name/index and a volume"
msgstr ""
-#: src/utils/pactl.c:1970
+#: src/utils/pactl.c:2052
msgid "You have to specify a sink input index and a volume"
msgstr ""
-#: src/utils/pactl.c:1975
+#: src/utils/pactl.c:2057
msgid "Invalid sink input index"
msgstr ""
-#: src/utils/pactl.c:1986
+#: src/utils/pactl.c:2068
msgid "You have to specify a source output index and a volume"
msgstr ""
-#: src/utils/pactl.c:1991
+#: src/utils/pactl.c:2073
msgid "Invalid source output index"
msgstr ""
-#: src/utils/pactl.c:2002
+#: src/utils/pactl.c:2084
msgid "You have to specify a sink name/index and a mute action (0, 1, or 'toggle')"
msgstr ""
-#: src/utils/pactl.c:2007 src/utils/pactl.c:2022 src/utils/pactl.c:2042
-#: src/utils/pactl.c:2060
+#: src/utils/pactl.c:2089 src/utils/pactl.c:2104 src/utils/pactl.c:2124
+#: src/utils/pactl.c:2142
msgid "Invalid mute specification"
msgstr ""
-#: src/utils/pactl.c:2017
+#: src/utils/pactl.c:2099
msgid "You have to specify a source name/index and a mute action (0, 1, or 'toggle')"
msgstr ""
-#: src/utils/pactl.c:2032
+#: src/utils/pactl.c:2114
msgid "You have to specify a sink input index and a mute action (0, 1, or 'toggle')"
msgstr ""
-#: src/utils/pactl.c:2037
+#: src/utils/pactl.c:2119
msgid "Invalid sink input index specification"
msgstr ""
-#: src/utils/pactl.c:2050
+#: src/utils/pactl.c:2132
msgid "You have to specify a source output index and a mute action (0, 1, or 'toggle')"
msgstr ""
-#: src/utils/pactl.c:2055
+#: src/utils/pactl.c:2137
msgid "Invalid source output index specification"
msgstr ""
-#: src/utils/pactl.c:2072
+#: src/utils/pactl.c:2150
+msgid "You have to specify at least an object path and a message name"
+msgstr ""
+
+#: src/utils/pactl.c:2160
+msgid ""
+"Excess arguments given, they will be ignored. Note that all message parameters must be "
+"given as a single string."
+msgstr ""
+
+#: src/utils/pactl.c:2170
msgid ""
"You have to specify a sink index and a semicolon-separated list of supported formats"
msgstr ""
-#: src/utils/pactl.c:2084
+#: src/utils/pactl.c:2182
msgid "You have to specify a card name/index, a port name and a latency offset"
msgstr ""
-#: src/utils/pactl.c:2091
+#: src/utils/pactl.c:2189
msgid "Could not parse latency offset"
msgstr ""
-#: src/utils/pactl.c:2103
+#: src/utils/pactl.c:2201
msgid "No valid command specified."
msgstr ""
From a17d00c3d2e306e782524eccc9b5a516be3d2be7 Mon Sep 17 00:00:00 2001
From: Jaechul Lee
Date: Tue, 8 Dec 2020 11:20:14 +0900
Subject: [PATCH 129/872] null-source: Fix max_latency_msec argument is not
changed
This module uses 2 seconds for default max latency. If max_latency_msec
is set, max_latency value will be changed.
Part-of:
---
src/modules/module-null-source.c | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/modules/module-null-source.c b/src/modules/module-null-source.c
index 38e3c823e..3aefbf2c5 100644
--- a/src/modules/module-null-source.c
+++ b/src/modules/module-null-source.c
@@ -200,7 +200,6 @@ int pa__init(pa_module*m) {
pa_channel_map map;
pa_modargs *ma = NULL;
pa_source_new_data data;
- pa_usec_t max_latency = MAX_LATENCY_USEC;
uint32_t max_latency_msec;
pa_assert(m);
@@ -252,10 +251,13 @@ int pa__init(pa_module*m) {
pa_source_set_asyncmsgq(u->source, u->thread_mq.inq);
pa_source_set_rtpoll(u->source, u->rtpoll);
- if (pa_modargs_get_value_u32(ma, "max_latency_msec", &max_latency_msec))
- max_latency = max_latency_msec * PA_USEC_PER_MSEC;
+ max_latency_msec = MAX_LATENCY_USEC / PA_USEC_PER_MSEC;
+ if (pa_modargs_get_value_u32(ma, "max_latency_msec", &max_latency_msec) < 0) {
+ pa_log("Failed to get max_latency_msec.");
+ goto fail;
+ }
- pa_source_set_latency_range(u->source, MIN_LATENCY_USEC, max_latency);
+ pa_source_set_latency_range(u->source, MIN_LATENCY_USEC, max_latency_msec * PA_USEC_PER_MSEC);
u->block_usec = u->source->thread_info.max_latency;
From 8342c1233977504f5e3d2d61b1bdb4c7884b1d8c Mon Sep 17 00:00:00 2001
From: Ben Buchwald
Date: Mon, 6 Jan 2020 18:03:42 -0500
Subject: [PATCH 130/872] jackdbus-detect: Passthrough more arguments to sink
and source
module-jackdbus-detect now accepts sink_name, sink_properties,
sink_client_name, sink_channel_map, source_name, source_properties,
source_client_name, and source_channel_map arguments that will be passed
through to module-jack-source and module-jack-sink (without the sink and
source prefixes, except where needed).
---
src/modules/jack/module-jackdbus-detect.c | 169 +++++++++++++++++++---
1 file changed, 148 insertions(+), 21 deletions(-)
diff --git a/src/modules/jack/module-jackdbus-detect.c b/src/modules/jack/module-jackdbus-detect.c
index 63c430748..0a9f24c96 100644
--- a/src/modules/jack/module-jackdbus-detect.c
+++ b/src/modules/jack/module-jackdbus-detect.c
@@ -25,12 +25,14 @@
#include
#endif
+#include
#include
#include
#include
#include
#include
+#include
PA_MODULE_AUTHOR("David Henningsson");
PA_MODULE_DESCRIPTION("Adds JACK sink/source ports when JACK is started");
@@ -38,8 +40,16 @@ PA_MODULE_LOAD_ONCE(true);
PA_MODULE_VERSION(PACKAGE_VERSION);
PA_MODULE_USAGE(
"channels= "
- "source_channels= "
+ "sink_name= "
+ "sink_properties= "
+ "sink_client_name= "
"sink_channels= "
+ "sink_channel_map= "
+ "source_name= "
+ "source_properties= "
+ "source_client_name= "
+ "source_channels= "
+ "source_channel_map= "
"connect=");
#define JACK_SERVICE_NAME "org.jackaudio.service"
@@ -61,8 +71,16 @@ PA_MODULE_USAGE(
static const char* const valid_modargs[] = {
"channels",
- "source_channels",
+ "sink_name",
+ "sink_properties",
+ "sink_client_name",
"sink_channels",
+ "sink_channel_map",
+ "source_name",
+ "source_properties",
+ "source_client_name",
+ "source_channels",
+ "source_channel_map",
"connect",
NULL
};
@@ -76,6 +94,19 @@ static const char* const modnames[JACK_SS_COUNT] = {
"module-jack-source"
};
+static const char* const modtypes[JACK_SS_COUNT] = {
+ "sink",
+ "source"
+};
+
+struct moddata {
+ char *name;
+ pa_proplist *proplist;
+ char *client_name;
+ uint32_t channels;
+ pa_channel_map channel_map;
+};
+
struct userdata {
pa_module *module;
pa_core *core;
@@ -83,13 +114,13 @@ struct userdata {
bool filter_added, match_added;
bool is_service_started;
bool autoconnect_ports;
- uint32_t channels[JACK_SS_COUNT];
+ struct moddata mod_args[JACK_SS_COUNT];
/* Using index here protects us from module unloading without us knowing */
int jack_module_index[JACK_SS_COUNT];
};
static void ensure_ports_stopped(struct userdata* u) {
- int i;
+ unsigned i;
pa_assert(u);
for (i = 0; i < JACK_SS_COUNT; i++)
@@ -100,19 +131,81 @@ static void ensure_ports_stopped(struct userdata* u) {
}
}
+static char* proplist_to_arg(pa_proplist *p) {
+ const char *key;
+ void *state = NULL;
+ pa_strbuf *buf;
+
+ pa_assert(p);
+
+ buf = pa_strbuf_new();
+
+ while ((key = pa_proplist_iterate(p, &state))) {
+ const char *v;
+ char *escaped;
+
+ if (!pa_strbuf_isempty(buf))
+ pa_strbuf_puts(buf, " ");
+
+ if ((v = pa_proplist_gets(p, key))) {
+ pa_strbuf_printf(buf, "%s=\"", key);
+
+ escaped = pa_escape(v, "\"'");
+ pa_strbuf_puts(buf, escaped);
+ pa_xfree(escaped);
+
+ pa_strbuf_puts(buf, "\"");
+ } else {
+ const void *value;
+ size_t nbytes;
+ char *c;
+
+ pa_assert_se(pa_proplist_get(p, key, &value, &nbytes) == 0);
+ c = pa_xmalloc(nbytes*2+1);
+ pa_hexstr((const uint8_t*) value, nbytes, c, nbytes*2+1);
+
+ pa_strbuf_printf(buf, "%s=hex:%s", key, c);
+ pa_xfree(c);
+ }
+ }
+
+ return pa_strbuf_to_string_free(buf);
+}
+
static void ensure_ports_started(struct userdata* u) {
- int i;
+ unsigned i;
+ char *escaped;
pa_assert(u);
for (i = 0; i < JACK_SS_COUNT; i++)
if (!u->jack_module_index[i]) {
- char* args;
- pa_module* m;
- if (u->channels[i] > 0) {
- args = pa_sprintf_malloc("connect=%s channels=%" PRIu32, pa_yes_no(u->autoconnect_ports), u->channels[i]);
- } else {
- args = pa_sprintf_malloc("connect=%s", pa_yes_no(u->autoconnect_ports));
+ pa_strbuf *args_buf = pa_strbuf_new();
+ char *args;
+ pa_module *m;
+ pa_strbuf_printf(args_buf, "connect=%s", pa_yes_no(u->autoconnect_ports));
+ if (u->mod_args[i].name) {
+ escaped = pa_escape(u->mod_args[i].name, "'");
+ pa_strbuf_printf(args_buf, " %s_name='%s'", modtypes[i], escaped);
+ pa_xfree(escaped);
}
+ if (!pa_proplist_isempty(u->mod_args[i].proplist)) {
+ escaped = proplist_to_arg(u->mod_args[i].proplist);
+ pa_strbuf_printf(args_buf, " %s_properties='%s'", modtypes[i], escaped);
+ pa_xfree(escaped);
+ }
+ if (u->mod_args[i].client_name) {
+ escaped = pa_escape(u->mod_args[i].client_name, "'");
+ pa_strbuf_printf(args_buf, " client_name='%s'", escaped);
+ pa_xfree(escaped);
+ }
+ if (u->mod_args[i].channels > 0)
+ pa_strbuf_printf(args_buf, " channels=%" PRIu32, u->mod_args[i].channels);
+ if (u->mod_args[i].channel_map.channels > 0) {
+ char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ pa_channel_map_snprint(cm, sizeof(cm), &u->mod_args[i].channel_map);
+ pa_strbuf_printf(args_buf, " channel_map='%s'", cm);
+ }
+ args = pa_strbuf_to_string_free(args_buf);
pa_module_load(&m, u->core, modnames[i], args);
pa_xfree(args);
@@ -218,7 +311,9 @@ int pa__init(pa_module *m) {
struct userdata *u = NULL;
pa_modargs *ma;
uint32_t channels = 0;
- int i;
+ unsigned i;
+ char argname[32];
+ const char *name;
pa_assert(m);
@@ -243,18 +338,40 @@ int pa__init(pa_module *m) {
pa_log("Failed to parse channels= argument.");
goto fail;
}
+
for (i = 0; i < JACK_SS_COUNT; i++) {
- u->channels[i] = channels;
- }
+ pa_snprintf(argname, sizeof(argname), "%s_name", modtypes[i]);
+ name = pa_modargs_get_value(ma, argname, NULL);
+ u->mod_args[i].name = pa_xstrdup(name);
- if (pa_modargs_get_value_u32(ma, "source_channels", &u->channels[JACK_SS_SOURCE]) < 0 || (u->channels[JACK_SS_SOURCE] > 0 && !pa_channels_valid(u->channels[JACK_SS_SOURCE]))) {
- pa_log("Failed to parse source_channels= argument.");
- goto fail;
- }
+ u->mod_args[i].proplist = pa_proplist_new();
+ pa_snprintf(argname, sizeof(argname), "%s_properties", modtypes[i]);
+ if (pa_modargs_get_proplist(ma, argname, u->mod_args[i].proplist, PA_UPDATE_REPLACE) < 0) {
+ pa_log("Invalid %s properties", modtypes[i]);
+ goto fail;
+ }
- if (pa_modargs_get_value_u32(ma, "sink_channels", &u->channels[JACK_SS_SINK]) < 0 || (u->channels[JACK_SS_SINK] > 0 && !pa_channels_valid(u->channels[JACK_SS_SINK]))) {
- pa_log("Failed to parse sink_channels= argument.");
- goto fail;
+ pa_snprintf(argname, sizeof(argname), "%s_client_name", modtypes[i]);
+ name = pa_modargs_get_value(ma, argname, NULL);
+ u->mod_args[i].client_name = pa_xstrdup(name);
+
+ u->mod_args[i].channels = channels;
+ pa_snprintf(argname, sizeof(argname), "%s_channels", modtypes[i]);
+ if (pa_modargs_get_value_u32(ma, argname, &u->mod_args[i].channels) < 0
+ || (u->mod_args[i].channels > 0 && !pa_channels_valid(u->mod_args[i].channels))) {
+ pa_log("Failed to parse %s= argument.", argname);
+ goto fail;
+ }
+
+ pa_channel_map_init(&u->mod_args[i].channel_map);
+ pa_snprintf(argname, sizeof(argname), "%s_channel_map", modtypes[i]);
+ if (pa_modargs_get_value(ma, argname, NULL)) {
+ if (pa_modargs_get_channel_map(ma, argname, &u->mod_args[i].channel_map) < 0
+ || (u->mod_args[i].channels > 0 && u->mod_args[i].channel_map.channels != u->mod_args[i].channels)) {
+ pa_log("Failed to parse %s= argument.", argname);
+ goto fail;
+ }
+ }
}
if (!(connection = pa_dbus_bus_get(m->core, DBUS_BUS_SESSION, &error)) || dbus_error_is_set(&error)) {
@@ -298,6 +415,7 @@ fail:
void pa__done(pa_module *m) {
struct userdata *u;
+ unsigned i;
pa_assert(m);
@@ -320,5 +438,14 @@ void pa__done(pa_module *m) {
pa_dbus_connection_unref(u->connection);
}
+ for (i = 0; i < JACK_SS_COUNT; i++) {
+ pa_xfree(u->mod_args[i].name);
+
+ if (u->mod_args[i].proplist)
+ pa_proplist_free(u->mod_args[i].proplist);
+
+ pa_xfree(u->mod_args[i].client_name);
+ }
+
pa_xfree(u);
}
From 05f3e8bf9ae7adeb4db8b77c0a92dbb5350d189a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Danis?=
Date: Tue, 28 May 2019 16:49:19 +0200
Subject: [PATCH 131/872] core, modules: Remove useless EINTR tests
Since commit ad447d14682 (in 2009) pa_read and pa_write take care of
handling EINTR error.
So, pa_read, pa_write, pa_iochannel_read and pa_iochannel_write can not
exit with errno set to EINTR, and testing it is useless.
---
src/modules/bluetooth/module-bluez5-device.c | 10 +---
src/modules/module-esound-sink.c | 4 +-
src/modules/module-pipe-sink.c | 17 +++----
src/modules/module-pipe-source.c | 4 +-
src/modules/module-solaris.c | 4 +-
src/modules/oss/module-oss.c | 10 +---
src/pulsecore/fdsem.c | 52 +++++---------------
src/pulsecore/iochannel.c | 2 +-
src/pulsecore/protocol-esound.c | 8 +--
src/pulsecore/protocol-simple.c | 2 +-
10 files changed, 31 insertions(+), 82 deletions(-)
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 402053a59..87a8809ff 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -279,10 +279,6 @@ static int sco_process_render(struct userdata *u) {
saved_errno = errno;
- if (saved_errno == EINTR)
- /* Retry right away if we got interrupted */
- continue;
-
pa_memblock_unref(memchunk.memblock);
if (saved_errno == EAGAIN) {
@@ -462,11 +458,7 @@ static int a2dp_write_buffer(struct userdata *u, size_t nbytes) {
if (l < 0) {
- if (errno == EINTR)
- /* Retry right away if we got interrupted */
- continue;
-
- else if (errno == EAGAIN) {
+ if (errno == EAGAIN) {
/* Hmm, apparently the socket was not writable, give up for now */
pa_log_debug("Got EAGAIN on write() after POLLOUT, probably there is a temporary connection loss.");
break;
diff --git a/src/modules/module-esound-sink.c b/src/modules/module-esound-sink.c
index 5ff04516a..f46dc3889 100644
--- a/src/modules/module-esound-sink.c
+++ b/src/modules/module-esound-sink.c
@@ -249,9 +249,7 @@ static void thread_func(void *userdata) {
if (l < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN) {
+ if (errno == EAGAIN) {
/* OK, we filled all socket buffers up
* now. */
diff --git a/src/modules/module-pipe-sink.c b/src/modules/module-pipe-sink.c
index 213924fdc..43595420f 100644
--- a/src/modules/module-pipe-sink.c
+++ b/src/modules/module-pipe-sink.c
@@ -199,14 +199,13 @@ static ssize_t pipe_sink_write(struct userdata *u, pa_memchunk *pchunk) {
if (l < 0) {
if (errno == EAGAIN)
break;
- else if (errno != EINTR) {
- if (!u->fifo_error) {
- pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
- u->fifo_error = true;
- }
- count = -1 - count;
- break;
+
+ if (!u->fifo_error) {
+ pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
+ u->fifo_error = true;
}
+ count = -1 - count;
+ break;
} else {
if (u->fifo_error) {
pa_log_debug("Recovered from FIFO error");
@@ -288,9 +287,7 @@ static int process_render(struct userdata *u) {
if (l < 0) {
- if (errno == EINTR)
- continue;
- else if (errno == EAGAIN)
+ if (errno == EAGAIN)
return 0;
else {
pa_log("Failed to write data to FIFO: %s", pa_cstrerror(errno));
diff --git a/src/modules/module-pipe-source.c b/src/modules/module-pipe-source.c
index 74ec0551a..32b35c163 100644
--- a/src/modules/module-pipe-source.c
+++ b/src/modules/module-pipe-source.c
@@ -155,9 +155,7 @@ static void thread_func(void *userdata) {
if (l < 0) {
- if (errno == EINTR)
- continue;
- else if (errno != EAGAIN) {
+ if (errno != EAGAIN) {
pa_log("Failed to read data from FIFO: %s", pa_cstrerror(errno));
goto fail;
}
diff --git a/src/modules/module-solaris.c b/src/modules/module-solaris.c
index 038aca114..ec9eb875f 100644
--- a/src/modules/module-solaris.c
+++ b/src/modules/module-solaris.c
@@ -714,9 +714,7 @@ static void thread_func(void *userdata) {
pa_memblock_release(u->memchunk.memblock);
if (w <= 0) {
- if (errno == EINTR) {
- continue;
- } else if (errno == EAGAIN) {
+ if (errno == EAGAIN) {
/* We may have realtime priority so yield the CPU to ensure that fd can become writable again. */
pa_log_debug("EAGAIN with %llu bytes buffered.", buffered_bytes);
break;
diff --git a/src/modules/oss/module-oss.c b/src/modules/oss/module-oss.c
index ed124cab4..6eb025489 100644
--- a/src/modules/oss/module-oss.c
+++ b/src/modules/oss/module-oss.c
@@ -980,10 +980,7 @@ static void thread_func(void *userdata) {
if (t < 0) {
- if (errno == EINTR)
- continue;
-
- else if (errno == EAGAIN) {
+ if (errno == EAGAIN) {
pa_log_debug("EAGAIN");
revents &= ~POLLOUT;
@@ -1087,10 +1084,7 @@ static void thread_func(void *userdata) {
if (t < 0) {
pa_memblock_unref(memchunk.memblock);
- if (errno == EINTR)
- continue;
-
- else if (errno == EAGAIN) {
+ if (errno == EAGAIN) {
pa_log_debug("EAGAIN");
revents &= ~POLLIN;
diff --git a/src/pulsecore/fdsem.c b/src/pulsecore/fdsem.c
index a7fbf95d2..5fc22975a 100644
--- a/src/pulsecore/fdsem.c
+++ b/src/pulsecore/fdsem.c
@@ -151,26 +151,16 @@ static void flush(pa_fdsem *f) {
uint64_t u;
if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) {
-
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
r = (ssize_t) u;
} else
#endif
if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) {
-
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
} while (pa_atomic_sub(&f->data->in_pipe, (int) r) > (int) r);
@@ -194,23 +184,15 @@ void pa_fdsem_post(pa_fdsem *f) {
uint64_t u = 1;
if ((r = pa_write(f->efd, &u, sizeof(u), &f->write_type)) != sizeof(u)) {
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid write to eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid write to eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
} else
#endif
if ((r = pa_write(f->fds[1], &x, 1, &f->write_type)) != 1) {
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid write to pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid write to pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
break;
@@ -238,13 +220,8 @@ void pa_fdsem_wait(pa_fdsem *f) {
uint64_t u;
if ((r = pa_read(f->efd, &u, sizeof(u), NULL)) != sizeof(u)) {
-
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid read from eventfd: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
r = (ssize_t) u;
@@ -252,13 +229,8 @@ void pa_fdsem_wait(pa_fdsem *f) {
#endif
if ((r = pa_read(f->fds[0], &x, sizeof(x), NULL)) <= 0) {
-
- if (r >= 0 || errno != EINTR) {
- pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
- pa_assert_not_reached();
- }
-
- continue;
+ pa_log_error("Invalid read from pipe: %s", r < 0 ? pa_cstrerror(errno) : "EOF");
+ pa_assert_not_reached();
}
pa_atomic_sub(&f->data->in_pipe, (int) r);
diff --git a/src/pulsecore/iochannel.c b/src/pulsecore/iochannel.c
index e25824b78..eb93176ec 100644
--- a/src/pulsecore/iochannel.c
+++ b/src/pulsecore/iochannel.c
@@ -227,7 +227,7 @@ ssize_t pa_iochannel_write(pa_iochannel*io, const void*data, size_t l) {
return r; /* Fast path - we almost always successfully write everything */
if (r < 0) {
- if (errno == EINTR || errno == EAGAIN)
+ if (errno == EAGAIN)
r = 0;
else
return r;
diff --git a/src/pulsecore/protocol-esound.c b/src/pulsecore/protocol-esound.c
index d54c7f845..cf0fe4fdf 100644
--- a/src/pulsecore/protocol-esound.c
+++ b/src/pulsecore/protocol-esound.c
@@ -1010,7 +1010,7 @@ static int do_read(connection *c) {
((uint8_t*) &c->request) + c->read_data_length,
sizeof(c->request) - c->read_data_length)) <= 0) {
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
+ if (r < 0 && errno == EAGAIN)
return 0;
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -1066,7 +1066,7 @@ static int do_read(connection *c) {
(uint8_t*) c->read_data + c->read_data_length,
handler->data_length - c->read_data_length)) <= 0) {
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
+ if (r < 0 && errno == EAGAIN)
return 0;
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -1097,7 +1097,7 @@ static int do_read(connection *c) {
pa_memblock_release(c->scache.memchunk.memblock);
if (r <= 0) {
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
+ if (r < 0 && errno == EAGAIN)
return 0;
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
@@ -1165,7 +1165,7 @@ static int do_read(connection *c) {
if (r <= 0) {
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
+ if (r < 0 && errno == EAGAIN)
return 0;
pa_log_debug("read(): %s", r < 0 ? pa_cstrerror(errno) : "EOF");
diff --git a/src/pulsecore/protocol-simple.c b/src/pulsecore/protocol-simple.c
index 77d05398c..ed6a402e7 100644
--- a/src/pulsecore/protocol-simple.c
+++ b/src/pulsecore/protocol-simple.c
@@ -183,7 +183,7 @@ static int do_read(connection *c) {
if (r <= 0) {
- if (r < 0 && (errno == EINTR || errno == EAGAIN))
+ if (r < 0 && errno == EAGAIN)
return 0;
pa_log_debug("read(): %s", r == 0 ? "EOF" : pa_cstrerror(errno));
From e43ca00d5255d81d2004bf33f30dab3843e8aa1d Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Tue, 11 Feb 2020 09:40:49 +0200
Subject: [PATCH 132/872] module: Check version before loading a module
Since there's no stable API for modules, all modules need to be compiled
together with the server. This version check tries to ensure that if
a version mismatch happens, there will be an informative error message
rather than a random crash.
---
src/pulsecore/module.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/src/pulsecore/module.c b/src/pulsecore/module.c
index 15a54b6ec..040886d2d 100644
--- a/src/pulsecore/module.c
+++ b/src/pulsecore/module.c
@@ -45,6 +45,7 @@
#define PA_SYMBOL_LOAD_ONCE "pa__load_once"
#define PA_SYMBOL_GET_N_USED "pa__get_n_used"
#define PA_SYMBOL_GET_DEPRECATE "pa__get_deprecated"
+#define PA_SYMBOL_GET_VERSION "pa__get_version"
bool pa_module_exists(const char *name) {
const char *paths, *state = NULL;
@@ -113,6 +114,7 @@ void pa_module_hook_connect(pa_module *m, pa_hook *hook, pa_hook_priority_t prio
int pa_module_load(pa_module** module, pa_core *c, const char *name, const char *argument) {
pa_module *m = NULL;
+ const char *(*get_version)(void);
bool (*load_once)(void);
const char* (*get_deprecated)(void);
pa_modinfo *mi;
@@ -147,6 +149,21 @@ int pa_module_load(pa_module** module, pa_core *c, const char *name, const char
goto fail;
}
+ if ((get_version = (const char *(*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_GET_VERSION))) {
+ const char *version = get_version();
+
+ if (!pa_safe_streq(version, PACKAGE_VERSION)) {
+ pa_log("Module \"%s\" version (%s) doesn't match the expected version (%s).",
+ name, pa_strnull(version), PACKAGE_VERSION);
+ errcode = -PA_ERR_IO;
+ goto fail;
+ }
+ } else {
+ pa_log("Symbol \"%s\" not found in module \"%s\".", PA_SYMBOL_GET_VERSION, name);
+ errcode = -PA_ERR_IO;
+ goto fail;
+ }
+
if ((load_once = (bool (*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_LOAD_ONCE))) {
m->load_once = load_once();
From dc79f304ddc4a2bfcaf7b2d69fa5f1c28dc95ce8 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Fri, 14 Feb 2020 07:29:33 +0200
Subject: [PATCH 133/872] build-sys: Add an option for enabling/disabling
Valgrind
In OpenEmbedded the PulseAudio recipe currently disables Valgrind
support by passing "ac_cv_header_valgrind_memcheck_h=no" to the
configure script (this was added to make it deterministic whether
Valgrdind support gets enabled or not). I'm converting the PulseAudio
recipe to use Meson, and I needed an option to disable Valgrind.
---
meson.build | 6 +++++-
meson_options.txt | 3 +++
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/meson.build b/meson.build
index 06c44d748..3adb876ff 100644
--- a/meson.build
+++ b/meson.build
@@ -221,7 +221,6 @@ check_headers = [
'sys/un.h',
'sys/wait.h',
'syslog.h',
- 'valgrind/memcheck.h',
'xlocale.h',
]
@@ -232,6 +231,10 @@ foreach h : check_headers
endif
endforeach
+if cc.has_header('valgrind/memcheck.h', required: get_option('valgrind'))
+ cdata.set('HAVE_VALGRIND_MEMCHECK_H', 1)
+endif
+
# FIXME: move this to the above set
if cc.has_header('pthread.h')
cdata.set('HAVE_PTHREAD', 1)
@@ -842,6 +845,7 @@ summary = [
'Enable SoXR (resampler): @0@'.format(soxr_dep.found()),
'Enable WebRTC echo canceller: @0@'.format(webrtc_dep.found()),
'Enable Gcov coverage: @0@'.format(get_option('gcov')),
+ 'Enable Valgrind: @0@'.format(cdata.has('HAVE_VALGRIND_MEMCHECK_H')),
'Enable man pages: @0@'.format(get_option('man')),
'Enable unit tests: @0@'.format(get_option('tests')),
'',
diff --git a/meson_options.txt b/meson_options.txt
index 5283a6d98..247f26a78 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -141,6 +141,9 @@ option('systemd',
option('udev',
type : 'feature', value : 'auto',
description : 'Optional udev support')
+option('valgrind',
+ type : 'feature', value : 'auto',
+ description : 'Optional Valgrind support')
option('x11',
type : 'feature', value : 'auto',
description : 'Optional X11 support')
From a8cb4edf7591bf3038769ea1cd2eae264c67ea51 Mon Sep 17 00:00:00 2001
From: Pierre Ossman
Date: Tue, 7 Jul 2015 13:01:22 +0200
Subject: [PATCH 134/872] tunnel-sink-new: log buffer events
Aids in tracking down exactly where in the chain underruns are
happening.
Signed-off-by: Pierre Ossman
---
src/modules/module-tunnel-sink-new.c | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/src/modules/module-tunnel-sink-new.c b/src/modules/module-tunnel-sink-new.c
index 802e6a59a..66a178717 100644
--- a/src/modules/module-tunnel-sink-new.c
+++ b/src/modules/module-tunnel-sink-new.c
@@ -280,6 +280,9 @@ static void stream_changed_buffer_attr_cb(pa_stream *stream, void *userdata) {
bufferattr = pa_stream_get_buffer_attr(u->stream);
pa_sink_set_max_request_within_thread(u->sink, bufferattr->tlength);
+
+ pa_log_debug("Server reports buffer attrs changed. tlength now at %lu.",
+ (unsigned long) bufferattr->tlength);
}
/* called after we requested a change of the stream buffer_attr */
@@ -287,6 +290,16 @@ static void stream_set_buffer_attr_cb(pa_stream *stream, int success, void *user
stream_changed_buffer_attr_cb(stream, userdata);
}
+/* called when the server experiences an underrun of our buffer */
+static void stream_underflow_callback(pa_stream *stream, void *userdata) {
+ pa_log_info("Server signalled buffer underrun.");
+}
+
+/* called when the server experiences an overrun of our buffer */
+static void stream_overflow_callback(pa_stream *stream, void *userdata) {
+ pa_log_info("Server signalled buffer overrun.");
+}
+
static void context_state_cb(pa_context *c, void *userdata) {
struct userdata *u = userdata;
pa_assert(u);
@@ -333,8 +346,12 @@ static void context_state_cb(pa_context *c, void *userdata) {
reset_bufferattr(&bufferattr);
bufferattr.tlength = pa_usec_to_bytes(requested_latency, &u->sink->sample_spec);
+ pa_log_debug("tlength requested at %lu.", (unsigned long) bufferattr.tlength);
+
pa_stream_set_state_callback(u->stream, stream_state_cb, userdata);
pa_stream_set_buffer_attr_callback(u->stream, stream_changed_buffer_attr_cb, userdata);
+ pa_stream_set_underflow_callback(u->stream, stream_underflow_callback, userdata);
+ pa_stream_set_overflow_callback(u->stream, stream_overflow_callback, userdata);
if (pa_stream_connect_playback(u->stream,
u->remote_sink_name,
&bufferattr,
@@ -383,6 +400,9 @@ static void sink_update_requested_latency_cb(pa_sink *s) {
if (pa_stream_get_buffer_attr(u->stream)->tlength == nbytes)
break;
+ pa_log_debug("Requesting new buffer attrs. tlength requested at %lu.",
+ (unsigned long) nbytes);
+
reset_bufferattr(&bufferattr);
bufferattr.tlength = nbytes;
if ((operation = pa_stream_set_buffer_attr(u->stream, &bufferattr, stream_set_buffer_attr_cb, u)))
From 7ec6ee4725a72b42ddcb38550efc968a06e6be2f Mon Sep 17 00:00:00 2001
From: Patrick McLean
Date: Wed, 26 Feb 2020 00:26:12 -0800
Subject: [PATCH 135/872] alsa-mixer: add support for Sennheiser GSX 1000
gaming DAC
This same profile should also work for the GSX 1200, but I don't know the USB id
for that.
Part-of:
---
src/Makefile.am | 7 ++-
src/modules/alsa/90-pulseaudio.rules | 7 +++
src/modules/alsa/alsa-mixer.c | 4 ++
.../alsa/mixer/paths/analog-output-chat.conf | 5 ++
.../mixer/paths/virtual-surround-7.1.conf | 5 ++
.../mixer/profile-sets/sennheiser-gsx.conf | 58 +++++++++++++++++++
6 files changed, 84 insertions(+), 2 deletions(-)
create mode 100644 src/modules/alsa/mixer/paths/analog-output-chat.conf
create mode 100644 src/modules/alsa/mixer/paths/virtual-surround-7.1.conf
create mode 100644 src/modules/alsa/mixer/profile-sets/sennheiser-gsx.conf
diff --git a/src/Makefile.am b/src/Makefile.am
index df912a8b3..eeec40b55 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1370,7 +1370,8 @@ dist_alsaprofilesets_DATA = \
modules/alsa/mixer/profile-sets/dell-dock-tb16-usb-audio.conf \
modules/alsa/mixer/profile-sets/cmedia-high-speed-true-hdaudio.conf \
modules/alsa/mixer/profile-sets/hp-tbt-dock-120w-g2.conf \
- modules/alsa/mixer/profile-sets/hp-tbt-dock-audio-module.conf
+ modules/alsa/mixer/profile-sets/hp-tbt-dock-audio-module.conf \
+ modules/alsa/mixer/profile-sets/sennheiser-gsx.conf
if HAVE_UDEV
dist_udevrules_DATA = \
@@ -1417,7 +1418,9 @@ dist_alsapaths_DATA = \
modules/alsa/mixer/paths/steelseries-arctis-output-game-common.conf \
modules/alsa/mixer/paths/usb-gaming-headset-input.conf \
modules/alsa/mixer/paths/usb-gaming-headset-output-mono.conf \
- modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
+ modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf \
+ modules/alsa/mixer/paths/analog-output-chat.conf \
+ modules/alsa/mixer/paths/virtual-surround-7.1.conf
endif
diff --git a/src/modules/alsa/90-pulseaudio.rules b/src/modules/alsa/90-pulseaudio.rules
index 4de40127e..cc5a3597a 100644
--- a/src/modules/alsa/90-pulseaudio.rules
+++ b/src/modules/alsa/90-pulseaudio.rules
@@ -150,6 +150,13 @@ ATTRS{idVendor}=="0951", ATTRS{idProduct}=="1703", ENV{ID_ID}="usb-HyperX_Cloud_
# OnePlus Type-C Bullets (ED117)
ATTRS{idVendor}=="2a70", ATTRS{idProduct}=="1881", ENV{PULSE_PROFILE_SET}="simple-headphones-mic.conf"
+# ID 1395:005e is for Sennheiser GSX 1000
+# ID 1395:00a0 is for Sennheiser GSX 1000
+# ID 1395:005f is for Sennheiser GSX 1200
+ATTRS{idVendor}=="1395", ATTRS{idProduct}=="005e", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
+ATTRS{idVendor}=="1395", ATTRS{idProduct}=="00a0", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
+ATTRS{idVendor}=="1395", ATTRS{idProduct}=="005f", ENV{PULSE_PROFILE_SET}="sennheiser-gsx.conf"
+
GOTO="pulseaudio_end"
LABEL="pulseaudio_check_pci"
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 937771d43..f978f71c3 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2729,6 +2729,9 @@ static int path_verify(pa_alsa_path *p) {
{ "multichannel-output", N_("Multichannel Output"), PA_DEVICE_PORT_TYPE_LINE },
{ "steelseries-arctis-output-game-common", N_("Game Output"), PA_DEVICE_PORT_TYPE_HEADSET },
{ "steelseries-arctis-output-chat-common", N_("Chat Output"), PA_DEVICE_PORT_TYPE_HEADSET },
+ { "analog-chat-output", N_("Chat Output"), PA_DEVICE_PORT_TYPE_HEADSET },
+ { "analog-chat-input", N_("Chat Input"), PA_DEVICE_PORT_TYPE_HEADSET },
+ { "virtual-surround-7.1", N_("Virtual Surround 7.1"), PA_DEVICE_PORT_TYPE_HEADPHONES },
};
pa_alsa_element *e;
@@ -4567,6 +4570,7 @@ static int profile_verify(pa_alsa_profile *p) {
{ "output:iec958-stereo+input:iec958-stereo", N_("Digital Stereo Duplex (IEC958)") },
{ "output:multichannel-output+input:multichannel-input", N_("Multichannel Duplex") },
{ "output:unknown-stereo+input:unknown-stereo", N_("Stereo Duplex") },
+ { "output:analog-output-surround71+output:analog-output-chat+input:analog-input", N_("Mono Chat + 7.1 Surround") },
{ "off", N_("Off") }
};
const char *description_key = p->description_key ? p->description_key : p->name;
diff --git a/src/modules/alsa/mixer/paths/analog-output-chat.conf b/src/modules/alsa/mixer/paths/analog-output-chat.conf
new file mode 100644
index 000000000..360a1fceb
--- /dev/null
+++ b/src/modules/alsa/mixer/paths/analog-output-chat.conf
@@ -0,0 +1,5 @@
+; Some gaming devices have a separate "chat" device, this is for voice chat
+; while playing games. This device is just a fairly standard analog mono
+; device, but it's nicer to make it clear that this is the "chat" device
+; as is mentioned in the marketing info and manual.
+.include analog-output.conf.common
diff --git a/src/modules/alsa/mixer/paths/virtual-surround-7.1.conf b/src/modules/alsa/mixer/paths/virtual-surround-7.1.conf
new file mode 100644
index 000000000..7f111f276
--- /dev/null
+++ b/src/modules/alsa/mixer/paths/virtual-surround-7.1.conf
@@ -0,0 +1,5 @@
+[Element PCM,1]
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
diff --git a/src/modules/alsa/mixer/profile-sets/sennheiser-gsx.conf b/src/modules/alsa/mixer/profile-sets/sennheiser-gsx.conf
new file mode 100644
index 000000000..0ac157685
--- /dev/null
+++ b/src/modules/alsa/mixer/profile-sets/sennheiser-gsx.conf
@@ -0,0 +1,58 @@
+# This file is part of PulseAudio.
+#
+# PulseAudio is free software; you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as
+# published by the Free Software Foundation; either version 2.1 of the
+# License, or (at your option) any later version.
+#
+# PulseAudio is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with PulseAudio; if not, see .
+
+; USB Gaming DAC.
+; These devices have two output devices. The first one is mono, meant for
+; voice audio, and the second one is 7.1 surround, meant for everything
+; else. The 7.1 surround is mapped to headphones within the device.
+; The purpose of the mono/7.1 design is to provide separate volume
+; controls for voice and other audio, which can be useful in gaming.
+;
+; Works with:
+; Sennheiser GSX 1000
+; Sennheiser GSX 1200
+;
+; See default.conf for an explanation on the directives used here.
+
+[General]
+auto-profiles = no
+
+[Mapping analog-chat-output]
+device-strings = hw:%f,0
+channel-map = mono
+paths-output = analog-chat-output
+direction = output
+priority = 4000
+intended-roles = phone
+
+[Mapping analog-output-surround71]
+device-strings = hw:%f,1
+channel-map = front-left,front-right,rear-left,rear-right,front-center,lfe,side-left,side-right
+paths-output = virtual-surround-7.1
+priority = 4100
+direction = output
+
+[Mapping analog-chat-input]
+device-strings = hw:%f,0
+channel-map = mono
+paths-input = analog-chat-input
+priority = 4100
+direction = input
+
+[Profile output:analog-output-surround71+output:analog-output-chat+input:analog-input]
+output-mappings = analog-output-surround71 analog-chat-output
+input-mappings = analog-chat-input
+priority = 5100
+skip-probe = yes
From 3afb7f8c08ab6ce8e47075f7484f470c8c561a11 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 14 Mar 2020 08:22:44 +0200
Subject: [PATCH 136/872] pstream: Log "Cannot send block reference..." only
once per pstream
Despite the ratelimiting, this error gets logged too much.
I fixed a typo (Fallig -> Falling) while at it.
Related: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/824
Part-of:
---
src/pulsecore/pstream.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/pulsecore/pstream.c b/src/pulsecore/pstream.c
index eb7050828..7147b776a 100644
--- a/src/pulsecore/pstream.c
+++ b/src/pulsecore/pstream.c
@@ -154,6 +154,7 @@ struct pa_pstream {
* @registered_memfd_ids: registered memfd pools SHM IDs. Check
* pa_pstream_register_memfd_mempool() for more information. */
bool use_shm, use_memfd;
+ bool non_registered_memfd_id_error_logged;
pa_idxset *registered_memfd_ids;
pa_memimport *import;
@@ -677,9 +678,11 @@ static void prepare_next_write_item(pa_pstream *p) {
flags |= PA_FLAG_SHMDATA_MEMFD_BLOCK;
send_payload = false;
} else {
- if (pa_log_ratelimit(PA_LOG_ERROR)) {
+ if (!p->non_registered_memfd_id_error_logged) {
pa_log("Cannot send block reference with non-registered memfd ID = %u", shm_id);
- pa_log("Fallig back to copying full block data over socket");
+ pa_log("Falling back to copying full block data over socket");
+ pa_log("There's a bug report about this: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/824");
+ p->non_registered_memfd_id_error_logged = true;
}
}
}
From 6b04e2a89e2a0a8b4f6aecb38fd00d82914f7050 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 14 Mar 2020 10:42:44 +0200
Subject: [PATCH 137/872] sink: Reduce chat sink priority
Some gaming sound cards have custom profiles with analog-game and
analog-chat mappings that exist simultaneously. The game sink should
have higher priority than the chat sink, but currently there's no way to
affect the sink priorities from the profile-set configuration (the
mapping priority is not propagated to the sink priority).
I first thought about adding the mapping priority to the sink priority,
but that could mess up the prioritization system in
pa_device_init_priority(). I ended up checking for the intended roles
property to reduce the chat sink priority. I also reduced the iec958
priority so that the chat and iec958 sinks don't end up with the same
priority.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/818
Part-of:
---
src/pulsecore/sink.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index e89b59655..8bb67f6d4 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -3609,10 +3609,18 @@ unsigned pa_device_init_priority(pa_proplist *p) {
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_PROFILE_NAME))) {
- if (pa_startswith(s, "analog-"))
+ if (pa_startswith(s, "analog-")) {
priority += 9;
+
+ /* If an analog device has an intended role of "phone", it probably
+ * co-exists with another device that is meant for everything else,
+ * and that other device should have higher priority than the phone
+ * device. */
+ if (pa_str_in_list_spaces(pa_proplist_gets(p, PA_PROP_DEVICE_INTENDED_ROLES), "phone"))
+ priority -= 1;
+ }
else if (pa_startswith(s, "iec958-"))
- priority += 8;
+ priority += 7;
}
return priority;
From 836ba89c4a3cd15efa33f9e70ed8e4764bcb3793 Mon Sep 17 00:00:00 2001
From: Mattias Jernberg
Date: Thu, 26 Mar 2020 19:53:08 +0100
Subject: [PATCH 138/872] alsa-mixer: Enable volume control of SteelSeries
Arctis stereo output
Since there is now support for specifying the index of an Element, add the
same config as is used for the output-mono variant, as they behave the same:
One volume control with no support for adjustments to the left and right
channels.
Part-of:
---
.../mixer/paths/usb-gaming-headset-output-stereo.conf | 10 ++++++----
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
index e3f91cd6c..1a1e7944e 100644
--- a/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
+++ b/src/modules/alsa/mixer/paths/usb-gaming-headset-output-stereo.conf
@@ -23,10 +23,12 @@
; Steelseries Arctis 7
; Steelseries Arctis Pro Wireless.
; Lucidsound LS31
-;
-; This path doesn't provide hardware volume control, because the stereo
-; output is controlled by the PCM element with index 1, and currently
-; PulseAudio only supports elements with index 0.
[General]
description-key = analog-output-headphones
+
+[Element PCM,1]
+volume = merge
+switch = mute
+override-map.1 = all
+override-map.2 = all-left,all-right
From 19e34d8d5bb9380ed70607b3f661c26df6d4836c Mon Sep 17 00:00:00 2001
From: Hui Wang
Date: Thu, 10 Dec 2020 15:36:40 +0800
Subject: [PATCH 139/872] alsa-mixer: disable the Auto-Mute once the system has
speaker
With the Auto-Mute enabled, if the headphone jack is plugged, the
alsa hda driver will mute the speaker and set pinctl of the speaker
to Hi-Z state, after this happens, even the pulseaudio unmute the
speaker, the speaker still couldn't output sound because the pinctl
is in Hi-Z state.
We found this issue on a Dell machine which has multi-function audio
jack, after the headphone is plugged in, the speaker's availability is
still unknown, users could select speaker from gnome-sound-setting,
but even the speaker is selected to be the active device, it couldn't
output sound.
The Auto-Mute is not useful if the pulseaudio is running since pa
could mute/unmute devices according to active port change, the ucm
for sof+hda already disabled the Auto-Mute, let us disable it for
hda audio if the machine has the internal speaker.
Signed-off-by: Hui Wang
Part-of:
---
src/modules/alsa/mixer/paths/analog-output-speaker.conf | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 1610b9a05..91a4bc163 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -88,6 +88,13 @@ override-map.2 = all-left,all-right
switch = off
volume = off
+; Make sure the internal speakers are not auto-muted once the system has speakers
+[Element Auto-Mute Mode]
+enumeration = select
+
+[Option Auto-Mute Mode:Disabled]
+name = analog-output-speaker
+
; This profile path is intended to control the speaker, let's mute headphones
; else there will be a spike when plugging in headphones
[Element Headphone]
From d15b31d751d90274fee303a87a4c8493f1a118eb Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 13 Dec 2020 13:09:19 +0300
Subject: [PATCH 140/872] module-alsa-card: handle udev PULSE_MODARGS
Allow adding module arguments using udev PULSE_MODARGS environment variable and
fail module loading if there is a problem with PULSE_MODARGS
This helps setting e.g. 'tsched=0' for specific devices without a need to create
full load module entry in default.pa.
Part-of:
---
src/modules/alsa/module-alsa-card.c | 44 +++++++++++++++++++++++++++++
src/pulsecore/modargs.c | 26 +++++++++++++++++
src/pulsecore/modargs.h | 7 +++++
3 files changed, 77 insertions(+)
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index de2fe9cc4..f2f50382a 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -104,6 +104,8 @@ static const char* const valid_modargs[] = {
#define DEFAULT_DEVICE_ID "0"
+#define PULSE_MODARGS "PULSE_MODARGS"
+
struct userdata {
pa_core *core;
pa_module *module;
@@ -820,6 +822,7 @@ int pa__init(pa_module *m) {
const char *description;
const char *profile_str = NULL;
char *fn = NULL;
+ char *udev_args = NULL;
bool namereg_fail = false;
int err = -PA_MODULE_ERR_UNSPECIFIED, rval;
@@ -849,6 +852,47 @@ int pa__init(pa_module *m) {
goto fail;
}
+#ifdef HAVE_UDEV
+ udev_args = pa_udev_get_property(u->alsa_card_index, PULSE_MODARGS);
+#endif
+
+ if (udev_args) {
+ bool udev_modargs_success = true;
+ pa_modargs *temp_ma = pa_modargs_new(udev_args, valid_modargs);
+
+ if (temp_ma) {
+ /* do not try to replace device_id */
+
+ if (pa_modargs_remove_key(temp_ma, "device_id") == 0) {
+ pa_log_warn("Unexpected 'device_id' module argument override ignored from udev " PULSE_MODARGS "='%s'", udev_args);
+ }
+
+ /* Implement modargs override by copying original module arguments
+ * over udev entry arguments ignoring duplicates. */
+
+ if (pa_modargs_merge_missing(temp_ma, u->modargs, valid_modargs) == 0) {
+ /* swap module arguments */
+ pa_modargs *old_ma = u->modargs;
+ u->modargs = temp_ma;
+ temp_ma = old_ma;
+
+ pa_log_info("Applied module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
+ } else {
+ pa_log("Failed to apply module arguments override from udev " PULSE_MODARGS "='%s'", udev_args);
+ udev_modargs_success = false;
+ }
+
+ pa_modargs_free(temp_ma);
+ } else {
+ pa_log("Failed to parse module arguments from udev " PULSE_MODARGS "='%s'", udev_args);
+ udev_modargs_success = false;
+ }
+ pa_xfree(udev_args);
+
+ if (!udev_modargs_success)
+ goto fail;
+ }
+
if (pa_modargs_get_value_boolean(u->modargs, "ignore_dB", &ignore_dB) < 0) {
pa_log("Failed to parse ignore_dB argument.");
goto fail;
diff --git a/src/pulsecore/modargs.c b/src/pulsecore/modargs.c
index bce5891db..a707f6c8d 100644
--- a/src/pulsecore/modargs.c
+++ b/src/pulsecore/modargs.c
@@ -272,6 +272,15 @@ int pa_modargs_append(pa_modargs *ma, const char *args, const char* const* valid
return parse(ma, args, valid_keys, true);
}
+int pa_modargs_remove_key(pa_modargs *ma, const char *key) {
+ if (pa_hashmap_remove_and_free(ma->unescaped, key) == 0) {
+ pa_hashmap_remove_and_free(ma->raw, key);
+ return 0;
+ }
+
+ return -1;
+}
+
void pa_modargs_free(pa_modargs*ma) {
pa_assert(ma);
@@ -544,3 +553,20 @@ const char *pa_modargs_iterate(pa_modargs *ma, void **state) {
return e->key;
}
+
+int pa_modargs_merge_missing(pa_modargs *dst, pa_modargs *src, const char* const valid_keys[]) {
+ void *state;
+ const char *key, *value;
+ int ret = 0;
+
+ for (state = NULL, key = pa_modargs_iterate(src, &state); key; key = pa_modargs_iterate(src, &state)) {
+ value = pa_modargs_get_value(src, key, NULL);
+ if (value && add_key_value(dst, pa_xstrdup(key), pa_xstrdup(value), valid_keys, true) < 0) {
+ pa_log_warn("Failed to add module argument '%s=%s'", key, value);
+ ret = -1;
+ /* continue to gather all errors */
+ }
+ }
+
+ return ret;
+}
diff --git a/src/pulsecore/modargs.h b/src/pulsecore/modargs.h
index 96132a3aa..abb16747d 100644
--- a/src/pulsecore/modargs.h
+++ b/src/pulsecore/modargs.h
@@ -95,4 +95,11 @@ int pa_modargs_get_proplist(pa_modargs *ma, const char *name, pa_proplist *p, pa
* have any particular order. */
const char *pa_modargs_iterate(pa_modargs *ma, void **state);
+/* Remove entry by key. Returns 0 if successful, -1 otherwise */
+int pa_modargs_remove_key(pa_modargs *ma, const char *key);
+
+/* Add all key/value pairs from src that are is not already present in dst, to dst.
+ * Returns 0 if there were no errors, -1 otherwise. */
+int pa_modargs_merge_missing(pa_modargs *dst, pa_modargs *src, const char* const valid_keys[]);
+
#endif
From cb91d7a12e6be0e2c720d47d2ceca322a7b21d2c Mon Sep 17 00:00:00 2001
From: Samuel Thibault
Date: Sun, 26 Apr 2020 19:55:08 +0200
Subject: [PATCH 141/872] alsa-sink: increase watermark when there is nothing
to rewind
If we do not manage to rewind at all because there is nothing to rewind
any more, it means the latency is too small, and we let audio escape our
control. We should thus increase the watermark to fix this.
Fixes #871
Part-of:
---
src/modules/alsa/alsa-sink.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/src/modules/alsa/alsa-sink.c b/src/modules/alsa/alsa-sink.c
index f7fef8a7e..bd8377ced 100644
--- a/src/modules/alsa/alsa-sink.c
+++ b/src/modules/alsa/alsa-sink.c
@@ -1877,8 +1877,11 @@ static int process_rewind(struct userdata *u) {
u->after_rewind = true;
return 0;
}
- } else
+ } else {
pa_log_debug("Mhmm, actually there is nothing to rewind.");
+ if (u->use_tsched)
+ increase_watermark(u);
+ }
rewind_done:
pa_sink_process_rewind(u->sink, 0);
From 9b0ae8327d990584bb9a966d8d7bee6badbdb8c0 Mon Sep 17 00:00:00 2001
From: SimonP
Date: Thu, 7 May 2020 16:13:27 +0100
Subject: [PATCH 142/872] alsa-mixer: Respect XDG base directory spec when
loading path configs
Try $XDG_DATA_HOME, then $XDG_DATA_DIRS, and finally fall back to old
behaviour (prefix-defined directory).
core-util: Ignore non-absolute XDG base dirs
These are invalid per the spec.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/862
Part-of:
---
src/modules/alsa/alsa-mixer.c | 68 ++++++++++++++++++++++++++++----
src/pulsecore/core-util.c | 64 ++++++++++++++++++++++++++++++
src/pulsecore/core-util.h | 3 ++
src/tests/alsa-mixer-path-test.c | 1 -
4 files changed, 127 insertions(+), 9 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index f978f71c3..c40629712 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2763,13 +2763,66 @@ static int path_verify(pa_alsa_path *p) {
return 0;
}
-static const char *get_default_paths_dir(void) {
+static char *get_path_config_path(const char *paths_dir, const char *fname) {
+ char *path_config_path;
+ char *dir;
+ char *data_home;
+ pa_dynarray *data_dirs;
+
+ if (paths_dir) {
+ path_config_path = pa_maybe_prefix_path(fname, paths_dir);
+ if (access(path_config_path, R_OK) == 0)
+ return path_config_path;
+ else
+ pa_xfree(path_config_path);
+ }
+
#ifdef HAVE_RUNNING_FROM_BUILD_TREE
- if (pa_run_from_build_tree())
- return PA_SRCDIR "/modules/alsa/mixer/paths/";
- else
+ if (pa_run_from_build_tree()) {
+ path_config_path = pa_maybe_prefix_path(fname, PA_SRCDIR "/modules/alsa/mixer/paths/");
+ if (access(path_config_path, R_OK) == 0)
+ return path_config_path;
+ else
+ pa_xfree(path_config_path);
+ }
#endif
- return PA_ALSA_PATHS_DIR;
+
+ if (pa_get_data_home_dir(&data_home) == 0) {
+ dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", data_home);
+ pa_xfree(data_home);
+
+ path_config_path = pa_maybe_prefix_path(fname, dir);
+ pa_xfree(dir);
+
+ if (access(path_config_path, R_OK) == 0)
+ return path_config_path;
+ else
+ pa_xfree(path_config_path);
+ }
+
+ if (pa_get_data_dirs(&data_dirs) == 0) {
+ int idx;
+ const char *n;
+
+ PA_DYNARRAY_FOREACH(n, data_dirs, idx) {
+ dir = pa_sprintf_malloc("%s" PA_PATH_SEP "alsa-mixer" PA_PATH_SEP "paths", n);
+ path_config_path = pa_maybe_prefix_path(fname, dir);
+ pa_xfree(dir);
+
+ if (access(path_config_path, R_OK) == 0) {
+ pa_dynarray_free(data_dirs);
+ return path_config_path;
+ }
+ else {
+ pa_xfree(path_config_path);
+ }
+ }
+
+ pa_dynarray_free(data_dirs);
+ }
+
+ path_config_path = pa_maybe_prefix_path(fname, PA_ALSA_PATHS_DIR);
+ return path_config_path;
}
pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa_direction_t direction) {
@@ -2827,10 +2880,9 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
items[2].data = &p->description;
items[3].data = &mute_during_activation;
- if (!paths_dir)
- paths_dir = get_default_paths_dir();
+ fn = get_path_config_path(paths_dir, fname);
- fn = pa_maybe_prefix_path(fname, paths_dir);
+ pa_log_info("Loading path config: %s", fn);
r = pa_config_parse(fn, NULL, items, p->proplist, false, p);
pa_xfree(fn);
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 25498c5a0..0da5c093e 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -1568,6 +1568,70 @@ int pa_get_config_home_dir(char **_r) {
return 0;
}
+int pa_get_data_home_dir(char **_r) {
+ const char *e;
+ char *home_dir;
+
+ pa_assert(_r);
+
+ e = getenv("XDG_DATA_HOME");
+ if (e && *e) {
+ if (pa_is_path_absolute(e)) {
+ *_r = pa_sprintf_malloc("%s" PA_PATH_SEP "pulseaudio", e);
+ return 0;
+ }
+ else
+ pa_log_warn("Ignored non-absolute XDG_DATA_HOME value '%s'", e);
+ }
+
+ home_dir = pa_get_home_dir_malloc();
+ if (!home_dir)
+ return -PA_ERR_NOENTITY;
+
+ *_r = pa_sprintf_malloc("%s" PA_PATH_SEP ".local" PA_PATH_SEP "share" PA_PATH_SEP "pulseaudio", home_dir);
+ pa_xfree(home_dir);
+ return 0;
+}
+
+int pa_get_data_dirs(pa_dynarray **_r) {
+ const char *e;
+ const char *def = "/usr/local/share/:/usr/share/";
+ const char *p;
+ const char *split_state = NULL;
+ char *n;
+ pa_dynarray *paths;
+
+ pa_assert(_r);
+
+ e = getenv("XDG_DATA_DIRS");
+ p = e && *e ? e : def;
+
+ paths = pa_dynarray_new((pa_free_cb_t) pa_xfree);
+
+ while ((n = pa_split(p, ":", &split_state))) {
+ char *path;
+
+ if (!pa_is_path_absolute(n)) {
+ pa_log_warn("Ignored non-absolute path '%s' in XDG_DATA_DIRS", n);
+ pa_xfree(n);
+ continue;
+ }
+
+ path = pa_sprintf_malloc("%s" PA_PATH_SEP "pulseaudio", n);
+ pa_xfree(n);
+ pa_dynarray_append(paths, path);
+ }
+
+ if (pa_dynarray_size(paths) == 0) {
+ pa_log_warn("XDG_DATA_DIRS contains no valid paths");
+ pa_dynarray_free(paths);
+ return -PA_ERR_INVALID;
+ }
+
+ *_r = paths;
+ return 0;
+}
+
int pa_append_to_config_home_dir(const char *path, char **_r) {
int r;
char *config_home_dir;
diff --git a/src/pulsecore/core-util.h b/src/pulsecore/core-util.h
index 3117df882..ed123c796 100644
--- a/src/pulsecore/core-util.h
+++ b/src/pulsecore/core-util.h
@@ -37,6 +37,7 @@
#include
#include
#include
+#include
#ifndef PACKAGE
#error "Please include config.h before including this file!"
@@ -142,6 +143,8 @@ char *pa_get_state_dir(void);
char *pa_get_home_dir_malloc(void);
int pa_append_to_home_dir(const char *path, char **_r);
int pa_get_config_home_dir(char **_r);
+int pa_get_data_home_dir(char **_r);
+int pa_get_data_dirs(pa_dynarray **_r);
int pa_append_to_config_home_dir(const char *path, char **_r);
char *pa_get_binary_name_malloc(void);
char *pa_runtime_path(const char *fn);
diff --git a/src/tests/alsa-mixer-path-test.c b/src/tests/alsa-mixer-path-test.c
index 75cf08613..91e4d0dfa 100644
--- a/src/tests/alsa-mixer-path-test.c
+++ b/src/tests/alsa-mixer-path-test.c
@@ -17,7 +17,6 @@
* Meson. */
#ifndef MESON_BUILD
-/* This function was copied from alsa-mixer.c */
static const char *get_default_paths_dir(void) {
if (pa_run_from_build_tree())
return PA_SRCDIR "/modules/alsa/mixer/paths/";
From e3f2c25face8f964827f75dbc8fd766fc02aaf6d Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 6 Jun 2020 17:00:01 +0300
Subject: [PATCH 143/872] alsa-mixer: Pick at most one fallback mapping
The old behaviour was such that if none of the normal mappings worked,
we would probe ALL fallbacks. I don't think that makes sense, and it
caused concrete issues: let's say we have a regular stereo mic device,
but there's no "front" PCM defined for it. In this situation we would
probe the stereo-fallback mapping (which uses "hw" instead of "front"),
and it would work, but then we'd also probe the "multichannel-input"
mapping, which would also work, so we end up with two mappings that
don't have any difference in behaviour.
I think it's better to simply pick the first working fallback and ignore
the rest.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/901
(issue is marked as confidential due to unreleased hardware)
Part-of:
---
src/modules/alsa/alsa-mixer.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index c40629712..8b9ccfbf6 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -5155,14 +5155,14 @@ void pa_alsa_profile_set_probe(
if (p->output_mappings)
PA_IDXSET_FOREACH(m, p->output_mappings, idx)
if (m->output_pcm) {
- found_output |= !p->fallback_output;
+ found_output = true;
mapping_paths_probe(m, p, PA_ALSA_DIRECTION_OUTPUT, used_paths, mixers);
}
if (p->input_mappings)
PA_IDXSET_FOREACH(m, p->input_mappings, idx)
if (m->input_pcm) {
- found_input |= !p->fallback_input;
+ found_input = true;
mapping_paths_probe(m, p, PA_ALSA_DIRECTION_INPUT, used_paths, mixers);
}
}
From d285b00a168e830c1e837513b7442a48c69d9937 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Mon, 14 Dec 2020 08:48:11 +0300
Subject: [PATCH 144/872] build-sys: meson: change oss-output boolean to Meson
feature
Part-of:
---
meson.build | 7 +++----
meson_options.txt | 2 +-
src/modules/meson.build | 2 +-
src/utils/meson.build | 2 +-
4 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/meson.build b/meson.build
index 3adb876ff..437fc802c 100644
--- a/meson.build
+++ b/meson.build
@@ -616,8 +616,7 @@ if x11_dep.found()
endif
# Module dependencies
-if get_option('oss-output')
- assert(cc.has_header('sys/soundcard.h'), 'Need header file for OSS support')
+if cc.has_header('sys/soundcard.h', required: get_option('oss-output'))
cdata.set('HAVE_OSS_OUTPUT', 1)
cdata.set('HAVE_OSS_WRAPPER', 1)
cdata.set('PULSEDSP_LOCATION', pulsedsp_location)
@@ -811,8 +810,8 @@ summary = [
'',
'Enable memfd shared memory: @0@'.format(cdata.has('HAVE_MEMFD')),
'Enable X11: @0@'.format(x11_dep.found()),
- 'Enable OSS Output: @0@'.format(get_option('oss-output')),
-# 'Enable OSS Wrapper: @0@'.format(${ENABLE_OSS_WRAPPER}),
+ 'Enable OSS Output: @0@'.format(cdata.has('HAVE_OSS_OUTPUT')),
+ 'Enable OSS Wrapper: @0@'.format(cdata.has('HAVE_OSS_WRAPPER')),
# 'Enable EsounD: @0@'.format(${ENABLE_ESOUND}),
'Enable Alsa: @0@'.format(alsa_dep.found()),
# 'Enable CoreAudio: @0@'.format(${ENABLE_COREAUDIO}),
diff --git a/meson_options.txt b/meson_options.txt
index 247f26a78..ccfa2f7eb 100644
--- a/meson_options.txt
+++ b/meson_options.txt
@@ -124,7 +124,7 @@ option('orc',
type : 'feature', value : 'auto',
description : 'Optimized Inner Loop Runtime Compiler')
option('oss-output',
- type : 'boolean',
+ type : 'feature', value : 'auto',
description : 'Optional OSS output support')
option('samplerate',
type : 'feature', value : 'disabled',
diff --git a/src/modules/meson.build b/src/modules/meson.build
index 9df6d0e61..a4da633bb 100644
--- a/src/modules/meson.build
+++ b/src/modules/meson.build
@@ -73,7 +73,7 @@ if cc.has_header('linux/input.h')
]
endif
-if get_option('oss-output')
+if cdata.has('HAVE_OSS_OUTPUT')
subdir('oss')
all_modules += [
[ 'module-oss', 'oss/module-oss.c', [], [], [], liboss_util ],
diff --git a/src/utils/meson.build b/src/utils/meson.build
index 934abb850..a0701987b 100644
--- a/src/utils/meson.build
+++ b/src/utils/meson.build
@@ -84,7 +84,7 @@ if x11_dep.found()
)
endif
-if get_option('oss-output')
+if cdata.has('HAVE_OSS_WRAPPER')
libpulsecommon_sources = [
'padsp.c',
]
From c0779b28b84640736807cd562553d9f517ea0a72 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Thu, 17 Sep 2020 17:36:37 +0300
Subject: [PATCH 145/872] sink: Increase JACK device priority
The JACK sink and source priority was 0, but I believe the common case
is that when a JACK sink or source is loaded, the user wants to make it
the default device.
Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/issues/983
Part-of:
---
src/pulsecore/sink.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/pulsecore/sink.c b/src/pulsecore/sink.c
index 8bb67f6d4..e8aeb17fa 100644
--- a/src/pulsecore/sink.c
+++ b/src/pulsecore/sink.c
@@ -3577,6 +3577,14 @@ unsigned pa_device_init_priority(pa_proplist *p) {
pa_assert(p);
+ /* JACK sinks and sources get very high priority so that we'll switch the
+ * default devices automatically when jackd starts and
+ * module-jackdbus-detect creates the jack sink and source. */
+ if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_API))) {
+ if (pa_streq(s, "jack"))
+ priority += 10000;
+ }
+
if ((s = pa_proplist_gets(p, PA_PROP_DEVICE_CLASS))) {
if (pa_streq(s, "sound"))
From 4552fe15b3578219d7e21cb77018a5f9425cd593 Mon Sep 17 00:00:00 2001
From: Sebastian Krzyszkowiak
Date: Thu, 29 Oct 2020 02:11:22 +0100
Subject: [PATCH 146/872] filter-apply: Look for filter parameters also in
device properties
Some filters take parameters that effectively describe the hardware
they're being applied to (like echo-cancel allowing to specify the
mic array parameters for better noise filtering). This allows system
integrators to set default parameters for such modules per-device,
which will get used when the stream doesn't specify their own.
Part-of:
---
src/modules/module-filter-apply.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
diff --git a/src/modules/module-filter-apply.c b/src/modules/module-filter-apply.c
index c9f3f3932..1c1278218 100644
--- a/src/modules/module-filter-apply.c
+++ b/src/modules/module-filter-apply.c
@@ -146,15 +146,20 @@ static const char* get_filter_name(pa_object *o, bool is_sink_input) {
static const char* get_filter_parameters(pa_object *o, const char *want, bool is_sink_input) {
const char *parameters;
char *prop_parameters;
- pa_proplist *pl;
+ pa_proplist *pl, *device_pl;
- if (is_sink_input)
+ if (is_sink_input) {
pl = PA_SINK_INPUT(o)->proplist;
- else
+ device_pl = PA_SINK_INPUT(o)->sink->proplist;
+ } else {
pl = PA_SOURCE_OUTPUT(o)->proplist;
+ device_pl = PA_SOURCE_OUTPUT(o)->source->proplist;
+ }
prop_parameters = pa_sprintf_malloc(PA_PROP_FILTER_APPLY_PARAMETERS, want);
parameters = pa_proplist_gets(pl, prop_parameters);
+ if (!parameters)
+ parameters = pa_proplist_gets(device_pl, prop_parameters);
pa_xfree(prop_parameters);
return parameters;
From 9c774c62950928b62cf60c697909842708393378 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 09:39:54 -0400
Subject: [PATCH 147/872] win32: Handle (WSA)EWOULDBLOCK as EAGAIN.
Part-of:
---
src/pulsecore/core-util.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/src/pulsecore/core-util.c b/src/pulsecore/core-util.c
index 0da5c093e..1c9746dbf 100644
--- a/src/pulsecore/core-util.c
+++ b/src/pulsecore/core-util.c
@@ -407,6 +407,8 @@ ssize_t pa_read(int fd, void *buf, size_t count, int *type) {
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
+ if (errno == WSAEWOULDBLOCK)
+ errno = EAGAIN;
return r;
}
@@ -448,6 +450,8 @@ ssize_t pa_write(int fd, const void *buf, size_t count, int *type) {
#ifdef OS_IS_WIN32
if (WSAGetLastError() != WSAENOTSOCK) {
errno = WSAGetLastError();
+ if (errno == WSAEWOULDBLOCK)
+ errno = EAGAIN;
return r;
}
#else
From 68cb06b5fd8f7201153c47dc566bd2e33f2cf484 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 09:56:45 -0400
Subject: [PATCH 148/872] win32: Fix (interim) esound paths in
module-protocol-stub.c
Part-of:
---
src/modules/module-protocol-stub.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/modules/module-protocol-stub.c b/src/modules/module-protocol-stub.c
index a228208dc..5dd3fe079 100644
--- a/src/modules/module-protocol-stub.c
+++ b/src/modules/module-protocol-stub.c
@@ -300,7 +300,9 @@ int pa__init(pa_module*m) {
# if defined(USE_PROTOCOL_ESOUND)
-# if defined(USE_PER_USER_ESOUND_SOCKET)
+ /* Windows doesn't support getuid(), so we ignore the per-user Esound socket compile flag.
+ * Moreover, Esound Unix sockets haven't been supported on Windows historically. */
+# if defined(USE_PER_USER_ESOUND_SOCKET) && !defined(OS_IS_WIN32)
u->socket_path = pa_sprintf_malloc("/tmp/.esd-%lu/socket", (unsigned long) getuid());
# else
u->socket_path = pa_xstrdup("/tmp/.esd/socket");
From 4e5786ffdd5eb8eaf3934d5f8b372151787e4a6c Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 10:10:19 -0400
Subject: [PATCH 149/872] win32: Check WSAGetLastError() in
pa_is_unix_socket_stale.
Part-of:
---
src/pulsecore/socket-util.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/src/pulsecore/socket-util.c b/src/pulsecore/socket-util.c
index e389ef203..83d4c9c6c 100644
--- a/src/pulsecore/socket-util.c
+++ b/src/pulsecore/socket-util.c
@@ -239,8 +239,13 @@ int pa_unix_socket_is_stale(const char *fn) {
sa.sun_path[sizeof(sa.sun_path) - 1] = 0;
if (connect(fd, (struct sockaddr*) &sa, sizeof(sa)) < 0) {
+#if !defined(OS_IS_WIN32)
if (errno == ECONNREFUSED)
ret = 1;
+#else
+ if (WSAGetLastError() == WSAECONNREFUSED)
+ ret = 1;
+#endif
} else
ret = 0;
From 4b3cc2df8d4b099d8804d76b18c2998701e3e3e4 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 10:11:09 -0400
Subject: [PATCH 150/872] win32: (Temporarily) Add sockaddr_un definition from
This is a temporary addition, until ships with the
MinGW toolchain.
Part-of:
---
src/pulsecore/socket.h | 25 +++++++++++++++++++++++++
1 file changed, 25 insertions(+)
diff --git a/src/pulsecore/socket.h b/src/pulsecore/socket.h
index 72f222818..982901b0e 100644
--- a/src/pulsecore/socket.h
+++ b/src/pulsecore/socket.h
@@ -11,6 +11,31 @@
typedef long suseconds_t;
+/** Windows 10 supports AF_UNIX as of build 17603, with
+ support provided in the header file . However,
+ only the latest Windows SDK provides this file; older SDKs and
+ MinGW do not.
+
+ Hence we define SOCKADDR_UN here. We do not expect this definition to change
+ as Windows has some pretty good binary backwards-compatibility guarantees.
+
+ This shouldn't pose a problem for older versions of Windows; we expect them to
+ fail with an error whenever we try to make a socket of type AF_UNIX. */
+#define UNIX_PATH_MAX 108
+
+typedef struct sockaddr_un
+{
+ ADDRESS_FAMILY sun_family; /* AF_UNIX */
+ char sun_path[UNIX_PATH_MAX]; /* pathname */
+} SOCKADDR_UN, *PSOCKADDR_UN;
+
+#ifndef SUN_LEN
+#define SUN_LEN(ptr) \
+ ((size_t)(((struct sockaddr_un *) 0)->sun_path) + strlen((ptr)->sun_path))
+#endif
+
+#define HAVE_SYS_UN_H
+
#endif
#ifdef HAVE_WS2TCPIP_H
From 3c51930b6165c2cd48e8f04e01c267f34f1942f2 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 10:14:08 -0400
Subject: [PATCH 151/872] win32: Add support for Unix sockets in autoconf
build.
Part-of:
---
configure.ac | 3 +++
src/Makefile.am | 3 +++
2 files changed, 6 insertions(+)
diff --git a/configure.ac b/configure.ac
index fb1b518e9..357b6d7f7 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,6 +434,9 @@ AC_CHECK_HEADERS([netinet/ip.h], [], [],
AC_CHECK_HEADERS([sys/resource.h], [HAVE_SYS_RESOURCE_H=1], [HAVE_SYS_RESOURCE_H=0])
AC_SUBST(HAVE_SYS_RESOURCE_H)
AC_CHECK_HEADERS([sys/un.h], [HAVE_AF_UNIX=1], [HAVE_AF_UNIX=0])
+# In principle we would test for , but that doesn't ship (yet) with the
+# MinGW headers.
+AC_CHECK_HEADERS([winsock2.h], [HAVE_AF_UNIX=1], [])
AM_CONDITIONAL(HAVE_AF_UNIX, test "x$HAVE_AF_UNIX" = "x1")
AC_SUBST(HAVE_AF_UNIX)
diff --git a/src/Makefile.am b/src/Makefile.am
index eeec40b55..97c9dce9f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -206,8 +206,11 @@ bin_PROGRAMS += pasuspender
endif
if HAVE_AF_UNIX
+if !OS_IS_WIN32
+# pacmd relies on Unix signals, which are not present on Windows.
bin_PROGRAMS += pacmd
endif
+endif
if HAVE_X11
bin_PROGRAMS += pax11publish
From 7bc559fe26633c0d97557ca192bceea084d3a540 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 10:22:20 -0400
Subject: [PATCH 152/872] win32: Change linkage of lt_preloaded_symbols to
match definition in libtool in daemon/main.c.
Part-of:
---
src/daemon/main.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/daemon/main.c b/src/daemon/main.c
index c7c434288..1032390ca 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -101,7 +101,7 @@
#ifdef DISABLE_LIBTOOL_PRELOAD
/* FIXME: work around a libtool bug by making sure we have 2 elements. Bug has
* been reported: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=29576 */
-const lt_dlsymlist lt_preloaded_symbols[] = {
+LT_DLSYM_CONST lt_dlsymlist lt_preloaded_symbols[] = {
{ "@PROGRAM@", NULL },
{ NULL, NULL }
};
From b892e327a960e46ac4a377a95d274a5dc75cdf99 Mon Sep 17 00:00:00 2001
From: Edward Lee
Date: Thu, 1 Oct 2020 10:24:40 -0400
Subject: [PATCH 153/872] win32: Fix meson build system for Windows.
Part-of:
---
meson.build | 47 +++++++++++++++++++++++++---
src/daemon/meson.build | 2 +-
src/meson.build | 18 +++++++++--
src/modules/meson.build | 35 +++++++++++++++------
src/pulse/meson.build | 2 +-
src/pulsecore/meson.build | 14 +++++----
src/utils/meson.build | 64 +++++++++++++++++++++------------------
7 files changed, 127 insertions(+), 55 deletions(-)
diff --git a/meson.build b/meson.build
index 437fc802c..cd617c602 100644
--- a/meson.build
+++ b/meson.build
@@ -158,6 +158,10 @@ cdata.set('top_srcdir', meson.source_root())
# First some defaults to keep config file generation happy
cdata.set('HAVE_COREAUDIO', 0)
cdata.set('HAVE_WAVEOUT', 0)
+
+platform_socket_dep = []
+platform_dep = []
+
# FIXME: This was not tested. Maybe some flags should better be CFLAGS,
# rather than ending up in the config.h file?
if host_machine.system() == 'darwin'
@@ -165,7 +169,20 @@ if host_machine.system() == 'darwin'
cdata.set('_DARWIN_C_SOURCE', '200112L') # Needed to get NSIG on Mac OS
elif host_machine.system() == 'windows'
cdata.set('OS_IS_WIN32', 1)
+ cdata.set('HAVE_WINDOWS_H', 1)
+ cdata.set('HAVE_WAVEOUT', 1)
+ cdata.set('HAVE_WINSOCK2_H', 1)
+ cdata.set('HAVE_WS2TCPIP_H', 1)
cdata.set('WIN32_LEAN_AND_MEAN', 1) # Needed to avoid including unnecessary headers on Windows
+ cdata.set('gid_t', 'int')
+ cdata.set('uid_t', 'int')
+ ws2_32_dep = meson.get_compiler('c').find_library('ws2_32')
+ winsock_dep = meson.get_compiler('c').find_library('wsock32')
+ ole32_dep = meson.get_compiler('c').find_library('ole32')
+ ssp_dep = meson.get_compiler('c').find_library('ssp')
+ pcreposix_dep = meson.get_compiler('c').find_library('pcreposix')
+ platform_socket_dep = [ws2_32_dep, winsock_dep]
+ platform_dep = [ole32_dep, ssp_dep, pcreposix_dep]
#elif host_machine.system() == 'solaris'
# # Apparently meson has no solaris support?
# # Needed to get declarations for msg_control and msg_controllen on Solaris
@@ -236,8 +253,10 @@ if cc.has_header('valgrind/memcheck.h', required: get_option('valgrind'))
endif
# FIXME: move this to the above set
-if cc.has_header('pthread.h')
- cdata.set('HAVE_PTHREAD', 1)
+if host_machine.system() != 'windows'
+ if cc.has_header('pthread.h')
+ cdata.set('HAVE_PTHREAD', 1)
+ endif
endif
if cc.has_header_symbol('pthread.h', 'PTHREAD_PRIO_INHERIT')
@@ -297,7 +316,16 @@ check_functions = [
foreach f : check_functions
if cc.has_function(f)
define = 'HAVE_' + f.underscorify().to_upper()
- cdata.set(define, 1)
+
+ if f == 'posix_memalign' and host_machine.system() == 'windows'
+ message('Win32/mingw32 does not properly define posix_memalign.')
+ elif f == 'fork' and host_machine.system() == 'windows'
+ # __builtin_fork is defined and compiles properly, but calling __builtin_fork() does not.
+ # This causes Meson to think that Windows has a fork() which causes a link error...
+ message('Win32/mingw32 does not properly define fork.')
+ else
+ cdata.set(define, 1)
+ endif
endif
endforeach
@@ -306,7 +334,11 @@ if cc.has_header_symbol('sys/syscall.h', 'SYS_memfd_create')
endif
if cc.has_function('dgettext')
- libintl_dep = []
+ if host_machine.system() != 'windows'
+ libintl_dep = []
+ else
+ libintl_dep = cc.find_library('intl')
+ endif
else
libintl_dep = cc.find_library('intl')
endif
@@ -357,7 +389,12 @@ cdata.set('MESON_BUILD', 1)
# On ELF systems we don't want the libraries to be unloaded since we don't clean them up properly,
# so we request the nodelete flag to be enabled.
# On other systems, we don't really know how to do that, but it's welcome if somebody can tell.
-nodelete_link_args = ['-Wl,-z,nodelete']
+# Windows doesn't support this flag.
+if host_machine.system() != 'windows'
+ nodelete_link_args = ['-Wl,-z,nodelete']
+else
+ nodelete_link_args = []
+endif
# Code coverage
diff --git a/src/daemon/meson.build b/src/daemon/meson.build
index 9c9f807e7..4a57d7baa 100644
--- a/src/daemon/meson.build
+++ b/src/daemon/meson.build
@@ -31,7 +31,7 @@ executable('pulseaudio',
include_directories : [configinc, topinc],
link_args : ['-ffast-math'],
link_with : [libpulsecore, libpulsecommon, libpulse],
- dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep],
+ dependencies : [ltdl_dep, cap_dep, dbus_dep, libsystemd_dep, dl_dep, libintl_dep, platform_dep, platform_socket_dep],
c_args : pa_c_args,
)
diff --git a/src/meson.build b/src/meson.build
index b84112eee..0842db297 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -39,7 +39,6 @@ libpulsecommon_sources = [
'pulsecore/memblock.c',
'pulsecore/memblockq.c',
'pulsecore/memchunk.c',
- 'pulsecore/mutex-posix.c',
'pulsecore/native-common.c',
'pulsecore/once.c',
'pulsecore/packet.c',
@@ -56,7 +55,6 @@ libpulsecommon_sources = [
'pulsecore/random.c',
'pulsecore/srbchannel.c',
'pulsecore/sample-util.c',
- 'pulsecore/semaphore-posix.c',
'pulsecore/shm.c',
'pulsecore/bitset.c',
'pulsecore/socket-client.c',
@@ -65,7 +63,6 @@ libpulsecommon_sources = [
'pulsecore/strbuf.c',
'pulsecore/strlist.c',
'pulsecore/tagstruct.c',
- 'pulsecore/thread-posix.c',
'pulsecore/time-smoother.c',
'pulsecore/tokenizer.c',
'pulsecore/usergroup.c',
@@ -177,6 +174,20 @@ if x11_dep.found()
endif
# FIXME: Do non-POSIX thread things
+if host_machine.system() == 'windows'
+ libpulsecommon_sources += [
+ 'pulsecore/mutex-win32.c',
+ 'pulsecore/poll-win32.c',
+ 'pulsecore/semaphore-win32.c',
+ 'pulsecore/thread-win32.c',
+ ]
+else
+ libpulsecommon_sources += [
+ 'pulsecore/mutex-posix.c',
+ 'pulsecore/semaphore-posix.c',
+ 'pulsecore/thread-posix.c'
+ ]
+endif
# FIXME: Do SIMD things
libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
@@ -190,6 +201,7 @@ libpulsecommon = shared_library('pulsecommon-' + pa_version_major_minor,
dependencies : [
libm_dep, thread_dep, dl_dep, shm_dep, iconv_dep, sndfile_dep, dbus_dep,
x11_dep, libsystemd_dep, glib_dep, gtk_dep, asyncns_dep, libintl_dep,
+ platform_dep, platform_socket_dep,
],
implicit_include_directories : false)
diff --git a/src/modules/meson.build b/src/modules/meson.build
index a4da633bb..dcfc432d8 100644
--- a/src/modules/meson.build
+++ b/src/modules/meson.build
@@ -1,4 +1,6 @@
-subdir('rtp')
+if host_machine.system() != 'windows'
+ subdir('rtp')
+endif
# module name, sources, [headers, extra flags, extra deps, extra libs]
all_modules = [
@@ -44,8 +46,6 @@ all_modules = [
[ 'module-rescue-streams', 'module-rescue-streams.c' ],
[ 'module-role-cork', ['module-role-cork.c', 'stream-interaction.c'], 'stream-interaction.h' ],
[ 'module-role-ducking', ['module-role-ducking.c', 'stream-interaction.c'], 'stream-interaction.h' ],
- [ 'module-rtp-recv', 'rtp/module-rtp-recv.c', [], [], [], librtp ],
- [ 'module-rtp-send', 'rtp/module-rtp-send.c' , [], [], [], librtp ],
[ 'module-simple-protocol-tcp', 'module-protocol-stub.c', [], ['-DUSE_PROTOCOL_SIMPLE', '-DUSE_TCP_SOCKETS'], [], libprotocol_simple ],
[ 'module-simple-protocol-unix', 'module-protocol-stub.c', [], ['-DUSE_PROTOCOL_SIMPLE', '-DUSE_UNIX_SOCKETS'], [], libprotocol_simple ],
[ 'module-sine', 'module-sine.c' ],
@@ -62,9 +62,23 @@ all_modules = [
[ 'module-virtual-sink', 'module-virtual-sink.c' ],
[ 'module-virtual-source', 'module-virtual-source.c' ],
[ 'module-volume-restore', 'module-volume-restore.c' ],
-# [ 'module-waveout', 'module-waveout.c' ],
]
+if host_machine.system() == 'windows'
+ winmm_dep = meson.get_compiler('c').find_library('winmm')
+ ksuser_dep = meson.get_compiler('c').find_library('ksuser')
+ all_modules += [
+ [ 'module-waveout', 'module-waveout.c', [], [], [winmm_dep, ksuser_dep] ],
+ ]
+endif
+
+if host_machine.system() != 'windows'
+ all_modules += [
+ [ 'module-rtp-recv', 'rtp/module-rtp-recv.c', [], [], [], librtp ],
+ [ 'module-rtp-send', 'rtp/module-rtp-send.c' , [], [], [], librtp ],
+ ]
+endif
+
# Modules enabled by headers
if cc.has_header('linux/input.h')
@@ -176,10 +190,13 @@ if lirc_dep.found()
endif
if openssl_dep.found()
- subdir('raop')
- all_modules += [
- [ 'module-raop-sink', 'raop/module-raop-sink.c', [], [], [], libraop ],
- ]
+ if host_machine.system() != 'windows'
+ subdir('raop')
+ all_modules += [
+ [ 'module-raop-sink', 'raop/module-raop-sink.c', [], [], [], libraop ],
+ ]
+ endif
+
if avahi_dep.found()
all_modules += [
[ 'module-raop-discover', 'raop/module-raop-discover.c', [], [], [avahi_dep], libavahi_wrap ],
@@ -289,7 +306,7 @@ foreach m : all_modules
install : true,
install_rpath : rpath_dirs,
install_dir : modlibexecdir,
- dependencies : [thread_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libintl_dep] + extra_deps,
+ dependencies : [thread_dep, libpulse_dep, libpulsecommon_dep, libpulsecore_dep, libintl_dep, platform_dep, platform_socket_dep] + extra_deps,
link_args : [nodelete_link_args, '-Wl,--no-undefined' ],
link_with : extra_libs,
name_prefix : '',
diff --git a/src/pulse/meson.build b/src/pulse/meson.build
index abc1e7921..8341bfcf0 100644
--- a/src/pulse/meson.build
+++ b/src/pulse/meson.build
@@ -83,7 +83,7 @@ libpulse = shared_library('pulse',
link_args : [nodelete_link_args, versioning_link_args],
install : true,
install_rpath : privlibdir,
- dependencies : [libm_dep, thread_dep, libpulsecommon_dep, dbus_dep, dl_dep, iconv_dep, libintl_dep],
+ dependencies : [libm_dep, thread_dep, libpulsecommon_dep, dbus_dep, dl_dep, iconv_dep, libintl_dep, platform_dep, platform_socket_dep],
implicit_include_directories : false)
libpulse_dep = declare_dependency(link_with: libpulse)
diff --git a/src/pulsecore/meson.build b/src/pulsecore/meson.build
index 5f78be012..e8ce2931c 100644
--- a/src/pulsecore/meson.build
+++ b/src/pulsecore/meson.build
@@ -182,11 +182,13 @@ libpulsecore_simd = simd.check('libpulsecore_simd',
libpulsecore_simd_lib = libpulsecore_simd[0]
cdata.merge_from(libpulsecore_simd[1])
-# FIXME: Implement Windows support
-#'mutex-win32.c',
-#'poll-win32.c',
-#'semaphore-win32.c',
-#'thread-win32.c',
+if host_machine.system() == 'windows'
+ libpulsecore_sources += ['mutex-win32.c',
+ 'poll-win32.c',
+ 'semaphore-win32.c',
+ 'thread-win32.c',
+ ]
+endif
libpulsecore = shared_library('pulsecore-' + pa_version_major_minor,
libpulsecore_sources, libpulsecore_headers,
@@ -198,7 +200,7 @@ libpulsecore = shared_library('pulsecore-' + pa_version_major_minor,
install_rpath : privlibdir,
install_dir : privlibdir,
link_with : libpulsecore_simd_lib,
- dependencies : [libm_dep, libpulsecommon_dep, ltdl_dep, shm_dep, sndfile_dep, database_dep, dbus_dep, libatomic_ops_dep, orc_dep, samplerate_dep, soxr_dep, speex_dep, x11_dep, libintl_dep],
+ dependencies : [libm_dep, libpulsecommon_dep, ltdl_dep, shm_dep, sndfile_dep, database_dep, dbus_dep, libatomic_ops_dep, orc_dep, samplerate_dep, soxr_dep, speex_dep, x11_dep, libintl_dep, platform_dep, platform_socket_dep,],
implicit_include_directories : false)
libpulsecore_dep = declare_dependency(link_with: libpulsecore)
diff --git a/src/utils/meson.build b/src/utils/meson.build
index a0701987b..f40eaff95 100644
--- a/src/utils/meson.build
+++ b/src/utils/meson.build
@@ -19,12 +19,14 @@ executable('pacat',
c_args : pa_c_args,
)
-foreach alias : pacat_aliases
- # FIXME How to handle extension (.exe on windows)?
- dst = join_paths(bindir, alias)
- cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pacat', dst)
- meson.add_install_script('sh', '-c', cmd)
-endforeach
+# Windows doesn't support symbolic links.
+if host_machine.system() != 'windows'
+ foreach alias : pacat_aliases
+ dst = join_paths(bindir, alias)
+ cmd = 'ln -fs @0@ $DESTDIR@1@'.format('pacat', dst)
+ meson.add_install_script('sh', '-c', cmd)
+ endforeach
+endif
pactl_sources = [
'pactl.c',
@@ -40,33 +42,35 @@ executable('pactl',
c_args : pa_c_args,
)
-pasuspender_sources = [
- 'pasuspender.c',
-]
+if host_machine.system() != 'windows'
+ pasuspender_sources = [
+ 'pasuspender.c',
+ ]
-executable('pasuspender',
- pasuspender_sources,
- install: true,
- install_rpath : privlibdir,
- include_directories : [configinc, topinc],
- link_with : [libpulsecommon, libpulse],
- dependencies: [libintl_dep],
- c_args : pa_c_args,
-)
+ executable('pasuspender',
+ pasuspender_sources,
+ install: true,
+ install_rpath : privlibdir,
+ include_directories : [configinc, topinc],
+ link_with : [libpulsecommon, libpulse],
+ dependencies: [libintl_dep],
+ c_args : pa_c_args,
+ )
-pacmd_sources = [
- 'pacmd.c',
-]
+ pacmd_sources = [
+ 'pacmd.c',
+ ]
-executable('pacmd',
- pacmd_sources,
- install: true,
- install_rpath : privlibdir,
- include_directories : [configinc, topinc],
- link_with : [libpulsecommon, libpulse],
- dependencies: [libintl_dep],
- c_args : pa_c_args,
-)
+ executable('pacmd',
+ pacmd_sources,
+ install: true,
+ install_rpath : privlibdir,
+ include_directories : [configinc, topinc],
+ link_with : [libpulsecommon, libpulse],
+ dependencies: [libintl_dep],
+ c_args : pa_c_args,
+ )
+endif
if x11_dep.found()
pax11publish_sources = [
From e4e507802ccfa7cb13183b53bcdaec772846432d Mon Sep 17 00:00:00 2001
From: David
Date: Sun, 20 Dec 2020 11:32:02 +0000
Subject: [PATCH 154/872] Capitalize jack in module-jack-source.c
Part-of:
---
src/modules/jack/module-jack-source.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/jack/module-jack-source.c b/src/modules/jack/module-jack-source.c
index eaf2cd81c..c4541913c 100644
--- a/src/modules/jack/module-jack-source.c
+++ b/src/modules/jack/module-jack-source.c
@@ -342,7 +342,7 @@ int pa__init(pa_module*m) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
if (server_name)
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
- pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack source (%s)", jack_get_client_name(u->client));
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "JACK source (%s)", jack_get_client_name(u->client));
pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
if (pa_modargs_get_proplist(ma, "source_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
From ee1391860fa597c26eb6d2ee27b09c0eac659eb7 Mon Sep 17 00:00:00 2001
From: David
Date: Sun, 20 Dec 2020 11:35:30 +0000
Subject: [PATCH 155/872] Capitalize jack in module-jack-sink.c
Part-of:
---
src/modules/jack/module-jack-sink.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/jack/module-jack-sink.c b/src/modules/jack/module-jack-sink.c
index effa0dd01..a7c723073 100644
--- a/src/modules/jack/module-jack-sink.c
+++ b/src/modules/jack/module-jack-sink.c
@@ -400,7 +400,7 @@ int pa__init(pa_module*m) {
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_API, "jack");
if (server_name)
pa_proplist_sets(data.proplist, PA_PROP_DEVICE_STRING, server_name);
- pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "Jack sink (%s)", jack_get_client_name(u->client));
+ pa_proplist_setf(data.proplist, PA_PROP_DEVICE_DESCRIPTION, "JACK sink (%s)", jack_get_client_name(u->client));
pa_proplist_sets(data.proplist, "jack.client_name", jack_get_client_name(u->client));
if (pa_modargs_get_proplist(ma, "sink_properties", data.proplist, PA_UPDATE_REPLACE) < 0) {
From e67af95830a5f1b9930ecfdd4e32e0027b7a902f Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela
Date: Sat, 24 Oct 2020 18:20:59 +0200
Subject: [PATCH 156/872] alsa: mixer - use safe dB range values when the
override mask is unset
Use safe values for the min_dB and max_dB fields when the position mask
is unset to avoid breakage for the upper levels.
If the range is incorrect, the volume range shown in pavucontrol shows
strange values.
(Thanks to Wim Taymans for the idea.)
Signed-off-by: Jaroslav Kysela
Part-of:
---
src/modules/alsa/alsa-mixer.c | 19 ++++++++++++++++---
1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 8b9ccfbf6..3a2913245 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -3072,6 +3072,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
double min_dB[PA_CHANNEL_POSITION_MAX], max_dB[PA_CHANNEL_POSITION_MAX];
pa_channel_position_t t;
pa_channel_position_mask_t path_volume_channels = 0;
+ bool min_dB_set, max_dB_set;
char buf[64];
pa_assert(p);
@@ -3102,7 +3103,7 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
pa_log_debug("Probe of element %s failed.", buf);
return -1;
}
- pa_log_debug("Probe of element %s succeeded (volume=%d, switch=%d, enumeration=%d).", buf, e->volume_use, e->switch_use, e->enumeration_use);
+ pa_log_debug("Probe of element %s succeeded (volume=%d, switch=%d, enumeration=%d, has_dB=%d).", buf, e->volume_use, e->switch_use, e->enumeration_use, e->has_dB);
if (ignore_dB)
e->has_dB = false;
@@ -3166,18 +3167,30 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
p->supported = true;
p->min_dB = INFINITY;
+ min_dB_set = false;
p->max_dB = -INFINITY;
+ max_dB_set = false;
for (t = 0; t < PA_CHANNEL_POSITION_MAX; t++) {
if (path_volume_channels & PA_CHANNEL_POSITION_MASK(t)) {
- if (p->min_dB > min_dB[t])
+ if (p->min_dB > min_dB[t]) {
p->min_dB = min_dB[t];
+ min_dB_set = true;
+ }
- if (p->max_dB < max_dB[t])
+ if (p->max_dB < max_dB[t]) {
p->max_dB = max_dB[t];
+ max_dB_set = true;
+ }
}
}
+ /* this is probably a wrong prediction, but it should be safe */
+ if (!min_dB_set)
+ p->min_dB = -INFINITY;
+ if (!max_dB_set)
+ p->max_dB = 0;
+
return 0;
}
From b530aa4681087bcb315890df31ec91b4eb3cd4cc Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela
Date: Wed, 14 Oct 2020 22:20:37 +0200
Subject: [PATCH 157/872] alsa: mixer - add support up 8 mixer channels
We have at least one USB hardware which supports the 8
channels in one mixer element:
https://github.com/alsa-project/alsa-ucm-conf/pull/25
POSITION_MASK_CHANNELS define was added for the future extensions.
The override_map variable was changed from bool to mask (unsigned int).
The channel map override settings is handled for channels up to eight now.
Also added missing override-map.3 .. override-map.8 to the configuration
parser array.
The driver channel position was added to the override mask arguments
(syntax is driver:pulseaudio like left:all-left). If ommited, the ALSA's
channel positions are guessed by index.
Link: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/-/merge_requests/292
Signed-off-by: Jaroslav Kysela
Part-of:
---
src/modules/alsa/alsa-mixer.c | 118 ++++++++++++++++++++++++++++------
src/modules/alsa/alsa-mixer.h | 6 +-
2 files changed, 103 insertions(+), 21 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 3a2913245..8cd17cc35 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -689,6 +689,20 @@ static const snd_mixer_selem_channel_id_t alsa_channel_ids[PA_CHANNEL_POSITION_M
[PA_CHANNEL_POSITION_TOP_REAR_RIGHT] = SND_MIXER_SCHN_UNKNOWN
};
+static snd_mixer_selem_channel_id_t alsa_channel_positions[POSITION_MASK_CHANNELS] = {
+ SND_MIXER_SCHN_FRONT_LEFT,
+ SND_MIXER_SCHN_FRONT_RIGHT,
+ SND_MIXER_SCHN_REAR_LEFT,
+ SND_MIXER_SCHN_REAR_RIGHT,
+ SND_MIXER_SCHN_FRONT_CENTER,
+ SND_MIXER_SCHN_WOOFER,
+ SND_MIXER_SCHN_SIDE_LEFT,
+ SND_MIXER_SCHN_SIDE_RIGHT,
+#if POSITION_MASK_CHANNELS > 8
+#error "Extend alsa_channel_positions[] array (9+)"
+#endif
+};
+
static void setting_free(pa_alsa_setting *s) {
pa_assert(s);
@@ -1767,7 +1781,11 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
if (is_mono) {
e->n_channels = 1;
- if (!e->override_map) {
+ if ((e->override_map & (1 << (e->n_channels-1))) && e->masks[SND_MIXER_SCHN_MONO][e->n_channels-1] == 0) {
+ pa_log_warn("Override map for mono element %s is invalid, ignoring override map", e->path->name);
+ e->override_map &= ~(1 << (e->n_channels-1));
+ }
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p < PA_CHANNEL_POSITION_MAX; p++) {
if (alsa_channel_ids[p] == SND_MIXER_SCHN_UNKNOWN)
continue;
@@ -1794,24 +1812,25 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
alsa_id_str(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume element %s with no channels?", buf);
return false;
- } else if (e->n_channels > 2) {
+ } else if (e->n_channels > POSITION_MASK_CHANNELS) {
/* FIXME: In some places code like this is used:
*
* e->masks[alsa_channel_ids[p]][e->n_channels-1]
*
* The definition of e->masks is
*
- * pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
+ * pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][POSITION_MASK_CHANNELS];
*
- * Since the array size is fixed at 2, we obviously
- * don't support elements with more than two
+ * Since the array size is fixed at POSITION_MASK_CHANNELS, we obviously
+ * don't support elements with more than POSITION_MASK_CHANNELS
* channels... */
alsa_id_str(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", buf, e->n_channels);
return false;
}
- if (!e->override_map) {
+retry:
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
for (p = PA_CHANNEL_POSITION_FRONT_LEFT; p < PA_CHANNEL_POSITION_MAX; p++) {
bool has_channel;
@@ -1834,6 +1853,17 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
e->merged_mask |= e->masks[alsa_channel_ids[p]][e->n_channels-1];
}
+
+ if (e->merged_mask == 0) {
+ if (!(e->override_map & (1 << (e->n_channels-1)))) {
+ pa_log_warn("Channel map for element %s is invalid", e->path->name);
+ return false;
+ }
+ pa_log_warn("Override map for element %s has empty result, ignoring override map", e->path->name);
+ e->override_map &= ~(1 << (e->n_channels-1));
+ goto retry;
+ }
+
return true;
}
@@ -2427,6 +2457,16 @@ static int element_parse_volume_limit(pa_config_parser_state *state) {
return 0;
}
+static unsigned int parse_channel_position(const char *m)
+{
+ pa_channel_position_t p;
+
+ if ((p = pa_channel_position_from_string(m)) == PA_CHANNEL_POSITION_INVALID)
+ return SND_MIXER_SCHN_UNKNOWN;
+
+ return alsa_channel_ids[p];
+}
+
static pa_channel_position_mask_t parse_mask(const char *m) {
pa_channel_position_mask_t v;
@@ -2464,7 +2504,9 @@ static int element_parse_override_map(pa_config_parser_state *state) {
pa_alsa_path *p;
pa_alsa_element *e;
const char *split_state = NULL;
+ char *s;
unsigned i = 0;
+ int channel_count = 0;
char *n;
pa_assert(state);
@@ -2476,31 +2518,60 @@ static int element_parse_override_map(pa_config_parser_state *state) {
return -1;
}
+ s = strstr(state->lvalue, ".");
+ if (s) {
+ pa_atoi(s + 1, &channel_count);
+ if (channel_count < 1 || channel_count > POSITION_MASK_CHANNELS) {
+ pa_log("[%s:%u] Override map index '%s' invalid in '%s'", state->filename, state->lineno, state->lvalue, state->section);
+ return 0;
+ }
+ } else {
+ pa_log("[%s:%u] Invalid override map syntax '%s' in '%s'", state->filename, state->lineno, state->lvalue, state->section);
+ return -1;
+ }
+
while ((n = pa_split(state->rvalue, ",", &split_state))) {
pa_channel_position_mask_t m;
+ snd_mixer_selem_channel_id_t channel_position;
+
+ if (i >= (unsigned)channel_count) {
+ pa_log("[%s:%u] Invalid override map size (>%d) in '%s'", state->filename, state->lineno, channel_count, state->section);
+ return -1;
+ }
+ channel_position = alsa_channel_positions[i];
if (!*n)
m = 0;
else {
- if ((m = parse_mask(n)) == 0) {
- pa_log("[%s:%u] Override map '%s' invalid in '%s'", state->filename, state->lineno, n, state->section);
+ s = strstr(n, ":");
+ if (s) {
+ *s = '\0';
+ s++;
+ channel_position = parse_channel_position(n);
+ if (channel_position == SND_MIXER_SCHN_UNKNOWN) {
+ pa_log("[%s:%u] Override map position '%s' invalid in '%s'", state->filename, state->lineno, n, state->section);
+ pa_xfree(n);
+ return -1;
+ }
+ }
+ if ((m = parse_mask(s ? s : n)) == 0) {
+ pa_log("[%s:%u] Override map '%s' invalid in '%s'", state->filename, state->lineno, s ? s : n, state->section);
pa_xfree(n);
return -1;
}
}
- if (pa_streq(state->lvalue, "override-map.1"))
- e->masks[i++][0] = m;
- else
- e->masks[i++][1] = m;
-
- /* Later on we might add override-map.3 and so on here ... */
-
+ if (e->masks[channel_position][channel_count-1]) {
+ pa_log("[%s:%u] Override map '%s' duplicate position '%s' in '%s'", state->filename, state->lineno, s ? s : n, snd_mixer_selem_channel_name(channel_position), state->section);
+ pa_xfree(n);
+ return -1;
+ }
+ e->override_map |= (1 << (channel_count - 1));
+ e->masks[channel_position][channel_count-1] = m;
pa_xfree(n);
+ i++;
}
- e->override_map = true;
-
return 0;
}
@@ -2856,6 +2927,15 @@ pa_alsa_path* pa_alsa_path_new(const char *paths_dir, const char *fname, pa_alsa
{ "enumeration", element_parse_enumeration, NULL, NULL },
{ "override-map.1", element_parse_override_map, NULL, NULL },
{ "override-map.2", element_parse_override_map, NULL, NULL },
+ { "override-map.3", element_parse_override_map, NULL, NULL },
+ { "override-map.4", element_parse_override_map, NULL, NULL },
+ { "override-map.5", element_parse_override_map, NULL, NULL },
+ { "override-map.6", element_parse_override_map, NULL, NULL },
+ { "override-map.7", element_parse_override_map, NULL, NULL },
+ { "override-map.8", element_parse_override_map, NULL, NULL },
+#if POSITION_MASK_CHANNELS > 8
+#error "Add override-map.9+ definitions"
+#endif
/* ... later on we might add override-map.3 and so on here ... */
{ "required", element_parse_required, NULL, NULL },
{ "required-any", element_parse_required, NULL, NULL },
@@ -3227,7 +3307,7 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
pa_assert(e);
alsa_id_str(buf, sizeof(buf), &e->alsa_id);
- pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%s",
+ pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%02x",
buf,
e->direction,
e->switch_use,
@@ -3239,7 +3319,7 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
e->required_absent,
(long long unsigned) e->merged_mask,
e->n_channels,
- pa_yes_no(e->override_map));
+ e->override_map);
PA_LLIST_FOREACH(o, e->options)
pa_alsa_option_dump(o);
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 905e3128b..81519551d 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -50,6 +50,8 @@ typedef struct pa_alsa_port_data pa_alsa_port_data;
#include "alsa-util.h"
#include "alsa-ucm.h"
+#define POSITION_MASK_CHANNELS 8
+
typedef enum pa_alsa_switch_use {
PA_ALSA_SWITCH_IGNORE,
PA_ALSA_SWITCH_MUTE, /* make this switch follow mute status */
@@ -152,7 +154,7 @@ struct pa_alsa_element {
long constant_volume;
- bool override_map:1;
+ unsigned int override_map;
bool direction_try_other:1;
bool has_dB:1;
@@ -160,7 +162,7 @@ struct pa_alsa_element {
long volume_limit; /* -1 for no configured limit */
double min_dB, max_dB;
- pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][2];
+ pa_channel_position_mask_t masks[SND_MIXER_SCHN_LAST + 1][POSITION_MASK_CHANNELS];
unsigned n_channels;
pa_channel_position_mask_t merged_mask;
From 8f6029077a0c18f4d12105e9bd8c093c25ad7b38 Mon Sep 17 00:00:00 2001
From: Hui Wang
Date: Mon, 23 Nov 2020 11:25:51 +0800
Subject: [PATCH 158/872] switch-on-port-available: Switch to headset or mic on
unknown avail
On some Dell AIO machines, there is no internal mic, only a multi
function audio jack, so the only input devices are headphone-mic and
headset-mic, and they share the Jack with headphone.
When there is no headset plugged in that Jack, the headphone-mic
and headset-mic are off. And since there is no available port under
the analog input source, this source is unlinked (if there is
internal mic, the source will not be unlinked). so the only pa-source
left in the PA is analog-stereo-monitor.
After the headset is plugged, we need to let switch_to_port() handle
headset-mic and headphone-mic conditionally, this will guarantee the
source will be created if it is unlinked before plugging, and then the
input profile could be selected correctly.
Signed-off-by: Hui Wang
Part-of:
---
src/modules/module-switch-on-port-available.c | 32 ++++++++++++-------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/src/modules/module-switch-on-port-available.c b/src/modules/module-switch-on-port-available.c
index 84b856659..f450004ca 100644
--- a/src/modules/module-switch-on-port-available.c
+++ b/src/modules/module-switch-on-port-available.c
@@ -228,9 +228,7 @@ static struct port_pointers find_port_pointers(pa_device_port *port) {
}
/* Switches to a port, switching profiles if necessary or preferred */
-static void switch_to_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
-
+static void switch_to_port(pa_device_port *port, struct port_pointers pp) {
if (pp.is_port_active)
return; /* Already selected */
@@ -252,8 +250,7 @@ static void switch_to_port(pa_device_port *port) {
}
/* Switches away from a port, switching profiles if necessary or preferred */
-static void switch_from_port(pa_device_port *port) {
- struct port_pointers pp = find_port_pointers(port);
+static void switch_from_port(pa_device_port *port, struct port_pointers pp) {
pa_device_port *p, *best_port = NULL;
void *state;
@@ -282,12 +279,12 @@ static void switch_from_port(pa_device_port *port) {
* PA_CORE_HOOK_CARD_PROFILE_AVAILABLE_CHANGED callback, as at this point
* the profile availability hasn't been updated yet. */
if (best_port)
- switch_to_port(best_port);
+ switch_to_port(best_port, pp);
}
static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port *port, void* userdata) {
- pa_assert(port);
+ struct port_pointers pp = find_port_pointers(port);
if (!port->card) {
pa_log_warn("Port %s does not have a card", port->name);
@@ -314,6 +311,15 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
* functionality for setups that can't trigger this kind of
* interaction.
*
+ * For headset or microphone, if they are part of some availability group
+ * and they become unknown from off, it needs to check if their source is
+ * unlinked or not, if their source is unlinked, let switch_to_port()
+ * process them, then with the running of pa_card_set_profile(), their
+ * source will be created, otherwise the headset or microphone can't be used
+ * to record sound since there is no source for these 2 ports. This issue
+ * is observed on Dell machines which have multi-function audio jack but no
+ * internal mic.
+ *
* We should make this configurable so that users can optionally
* override the default to a headset or mic. */
@@ -323,20 +329,22 @@ static pa_hook_result_t port_available_hook_callback(pa_core *c, pa_device_port
break;
}
- /* For no we only switch the headphone port */
- if (port->direction != PA_DIRECTION_OUTPUT) {
+ /* Switch the headphone port, the input ports without source and the
+ * input ports their source->active_port is part of a group of ports.
+ */
+ if (port->direction == PA_DIRECTION_INPUT && pp.source && !pp.source->active_port->availability_group) {
pa_log_debug("Not switching to input port %s, its availability is unknown.", port->name);
break;
}
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_YES:
- switch_to_port(port);
+ switch_to_port(port, pp);
break;
case PA_AVAILABLE_NO:
- switch_from_port(port);
+ switch_from_port(port, pp);
break;
default:
break;
From dd7593b83669d84d3aa02597a61e37c74123da50 Mon Sep 17 00:00:00 2001
From: morrishoresh
Date: Thu, 24 Dec 2020 23:58:54 +0200
Subject: [PATCH 159/872] bluetooth: correct possible segmentation fault
Part-of:
---
src/modules/bluetooth/backend-ofono.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/src/modules/bluetooth/backend-ofono.c b/src/modules/bluetooth/backend-ofono.c
index 0e5bbe8b7..d7a13efd0 100644
--- a/src/modules/bluetooth/backend-ofono.c
+++ b/src/modules/bluetooth/backend-ofono.c
@@ -627,8 +627,6 @@ static DBusMessage *hf_audio_agent_new_connection(DBusConnection *c, DBusMessage
card = pa_hashmap_get(backend->cards, path);
- card->connecting = false;
-
if (!card || codec != HFP_AUDIO_CODEC_CVSD || card->fd >= 0) {
pa_log_warn("New audio connection invalid arguments (path=%s fd=%d, codec=%d)", path, fd, codec);
pa_assert_se(r = dbus_message_new_error(m, "org.ofono.Error.InvalidArguments", "Invalid arguments in method call"));
@@ -639,6 +637,7 @@ static DBusMessage *hf_audio_agent_new_connection(DBusConnection *c, DBusMessage
pa_log_debug("New audio connection on card %s (fd=%d, codec=%d)", path, fd, codec);
+ card->connecting = false;
card->fd = fd;
card->transport->codec = codec;
From 4874f8a607b62b496aa0a1f6c1f0c3e8570195ae Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Wed, 30 Dec 2020 00:00:50 +0300
Subject: [PATCH 160/872] bluetooth: align max renderable block size to frame
size
When bluez5 device I/O thread detects it is too slow sending data, allow it to
skip up to max rendered block size bytes which must be aligned to frame size.
Part-of:
---
src/modules/bluetooth/module-bluez5-device.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/src/modules/bluetooth/module-bluez5-device.c b/src/modules/bluetooth/module-bluez5-device.c
index 87a8809ff..9440084a6 100644
--- a/src/modules/bluetooth/module-bluez5-device.c
+++ b/src/modules/bluetooth/module-bluez5-device.c
@@ -1484,7 +1484,7 @@ static void thread_func(void *userdata) {
if (bytes_to_send > 2 * u->write_block_size) {
uint64_t skip_bytes;
pa_memchunk tmp;
- size_t mempool_max_block_size = pa_mempool_block_size_max(u->core->mempool);
+ size_t max_render_size = pa_frame_align(pa_mempool_block_size_max(u->core->mempool), &u->encoder_sample_spec);
pa_usec_t skip_usec;
skip_bytes = bytes_to_send - 2 * u->write_block_size;
@@ -1497,8 +1497,8 @@ static void thread_func(void *userdata) {
while (skip_bytes > 0) {
size_t bytes_to_render;
- if (skip_bytes > mempool_max_block_size)
- bytes_to_render = mempool_max_block_size;
+ if (skip_bytes > max_render_size)
+ bytes_to_render = max_render_size;
else
bytes_to_render = skip_bytes;
From 3ecea410d79d398126b54579b422e2f16baede5f Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Tue, 29 Dec 2020 00:03:41 +0300
Subject: [PATCH 161/872] context: add property to forcefully disable shared
memory channels
If application wants last bits of virtual memory, allow it to forcefully disable
shared memory communication channels via PA_PROP_CONTEXT_FORCE_DISABLE_SHM=yes
Part-of:
---
src/pulse/context.c | 11 +++++++++++
src/pulse/proplist.h | 3 +++
2 files changed, 14 insertions(+)
diff --git a/src/pulse/context.c b/src/pulse/context.c
index 1d1bb9ee8..05b6633aa 100644
--- a/src/pulse/context.c
+++ b/src/pulse/context.c
@@ -128,6 +128,7 @@ static void reset_callbacks(pa_context *c) {
pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *name, const pa_proplist *p) {
pa_context *c;
pa_mem_type_t type;
+ const char *force_disable_shm_str;
pa_assert(mainloop);
@@ -173,6 +174,16 @@ pa_context *pa_context_new_with_proplist(pa_mainloop_api *mainloop, const char *
c->conf = pa_client_conf_new();
pa_client_conf_load(c->conf, true, true);
+ force_disable_shm_str = pa_proplist_gets(c->proplist, PA_PROP_CONTEXT_FORCE_DISABLE_SHM);
+ if (force_disable_shm_str) {
+ int b = pa_parse_boolean(force_disable_shm_str);
+ if (b < 0) {
+ pa_log_warn("Ignored invalid value for '%s' property: %s", PA_PROP_CONTEXT_FORCE_DISABLE_SHM, force_disable_shm_str);
+ } else if (b) {
+ c->conf->disable_shm = true;
+ }
+ }
+
c->srb_template.readfd = -1;
c->srb_template.writefd = -1;
diff --git a/src/pulse/proplist.h b/src/pulse/proplist.h
index e50518b37..5da01664b 100644
--- a/src/pulse/proplist.h
+++ b/src/pulse/proplist.h
@@ -267,6 +267,9 @@ PA_C_DECL_BEGIN
/** For PCM formats: the channel map of the stream as returned by pa_channel_map_snprint() \since 1.0 */
#define PA_PROP_FORMAT_CHANNEL_MAP "format.channel_map"
+/** For context: whether to forcefully disable data transfer via POSIX or memfd shared memory. This property overrides any other client configuration which would otherwise enable SHM communication channels. \since 15.0 */
+#define PA_PROP_CONTEXT_FORCE_DISABLE_SHM "context.force.disable.shm"
+
/** A property list object. Basically a dictionary with ASCII strings
* as keys and arbitrary data as values. \since 0.9.11 */
typedef struct pa_proplist pa_proplist;
From aad2fca0c90ef72c6f5d72e16073238eba9051a8 Mon Sep 17 00:00:00 2001
From: Kai-Heng Feng
Date: Tue, 22 Dec 2020 13:39:05 +0800
Subject: [PATCH 162/872] alsa-mixer: Handle the index for ALSA mixer jack
identifiers
Some systems have two jacks with same name but different index, we need
to take index into consideration to use both jacks.
Part-of:
---
src/modules/alsa/alsa-mixer.c | 109 +++++++++++++++-------------
src/modules/alsa/alsa-mixer.h | 6 +-
src/modules/alsa/alsa-ucm.c | 4 +-
src/modules/alsa/alsa-util.c | 4 +-
src/modules/alsa/alsa-util.h | 2 +-
src/modules/alsa/module-alsa-card.c | 6 +-
6 files changed, 73 insertions(+), 58 deletions(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 8cd17cc35..58c33bf48 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -113,7 +113,7 @@ struct description2_map {
pa_device_port_type_t type;
};
-static char *alsa_id_str(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
+char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id) {
if (id->index > 0) {
snprintf(dst, dst_len, "'%s',%d", id->name, id->index);
} else {
@@ -153,7 +153,7 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
return 0;
}
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name) {
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index) {
pa_alsa_jack *jack;
pa_assert(name);
@@ -162,7 +162,8 @@ pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name
jack->path = path;
jack->mixer_device_name = pa_xstrdup(mixer_device_name);
jack->name = pa_xstrdup(name);
- jack->alsa_name = pa_sprintf_malloc("%s Jack", name);
+ jack->alsa_id.name = pa_sprintf_malloc("%s Jack", name);
+ jack->alsa_id.index = index;
jack->state_unplugged = PA_AVAILABLE_NO;
jack->state_plugged = PA_AVAILABLE_YES;
jack->ucm_devices = pa_dynarray_new(NULL);
@@ -177,7 +178,7 @@ void pa_alsa_jack_free(pa_alsa_jack *jack) {
pa_dynarray_free(jack->ucm_hw_mute_devices);
pa_dynarray_free(jack->ucm_devices);
- pa_xfree(jack->alsa_name);
+ pa_xfree(jack->alsa_id.name);
pa_xfree(jack->name);
pa_xfree(jack->mixer_device_name);
pa_xfree(jack);
@@ -835,7 +836,7 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -861,14 +862,14 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
if (value < e->db_fix->min_step) {
value = e->db_fix->min_step;
snd_mixer_selem_set_playback_volume(me, c, value);
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_debug("Playback volume for element %s channel %i was below the dB fix limit. "
"Volume reset to %0.2f dB.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
} else if (value > e->db_fix->max_step) {
value = e->db_fix->max_step;
snd_mixer_selem_set_playback_volume(me, c, value);
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_debug("Playback volume for element %s channel %i was over the dB fix limit. "
"Volume reset to %0.2f dB.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -891,14 +892,14 @@ static int element_get_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
if (value < e->db_fix->min_step) {
value = e->db_fix->min_step;
snd_mixer_selem_set_capture_volume(me, c, value);
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_debug("Capture volume for element %s channel %i was below the dB fix limit. "
"Volume reset to %0.2f dB.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
} else if (value > e->db_fix->max_step) {
value = e->db_fix->max_step;
snd_mixer_selem_set_capture_volume(me, c, value);
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_debug("Capture volume for element %s channel %i was over the dB fix limit. "
"Volume reset to %0.2f dB.", buf, c,
e->db_fix->db_values[value - e->db_fix->min_step] / 100.0);
@@ -1006,7 +1007,7 @@ static int element_get_switch(pa_alsa_element *e, snd_mixer_t *m, bool *b) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1172,7 +1173,7 @@ static int element_set_volume(pa_alsa_element *e, snd_mixer_t *m, const pa_chann
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1364,7 +1365,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1375,7 +1376,7 @@ static int element_set_switch(pa_alsa_element *e, snd_mixer_t *m, bool b) {
r = snd_mixer_selem_set_capture_switch_all(me, b);
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -1419,7 +1420,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -1464,7 +1465,7 @@ static int element_set_constant_volume(pa_alsa_element *e, snd_mixer_t *m) {
}
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set volume of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -1670,19 +1671,19 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
r = snd_mixer_selem_get_capture_volume_range(me, &e->min_volume, &e->max_volume);
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to get volume range of %s: %s", buf, pa_alsa_strerror(r));
return false;
}
if (e->min_volume >= e->max_volume) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Your kernel driver is broken for element %s: it reports a volume range from %li to %li which makes no sense.",
buf, e->min_volume, e->max_volume);
return false;
}
if (e->volume_use == PA_ALSA_VOLUME_CONSTANT && (e->min_volume > e->constant_volume || e->max_volume < e->constant_volume)) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Constant volume %li configured for element %s, but the available range is from %li to %li.",
e->constant_volume, buf, e->min_volume, e->max_volume);
return false;
@@ -1690,7 +1691,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
if (e->db_fix && ((e->min_volume > e->db_fix->min_step) || (e->max_volume < e->db_fix->max_step))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("The step range of the decibel fix for element %s (%li-%li) doesn't fit to the "
"real hardware range (%li-%li). Disabling the decibel fix.", buf,
e->db_fix->min_step, e->db_fix->max_step, e->min_volume, e->max_volume);
@@ -1717,19 +1718,19 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
long max_dB_checked = 0;
if (element_ask_vol_dB(me, e->direction, e->min_volume, &min_dB_checked) < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->min_volume);
return false;
}
if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB_checked) < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to query the dB value for %s at volume level %li", buf, e->max_volume);
return false;
}
if (min_dB != min_dB_checked || max_dB != max_dB_checked) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Your kernel driver is broken: the reported dB range for %s (from %0.2f dB to %0.2f dB) "
"doesn't match the dB values at minimum and maximum volume levels: %0.2f dB at level %li, "
"%0.2f dB at level %li.", buf, min_dB / 100.0, max_dB / 100.0,
@@ -1752,7 +1753,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
if (e->volume_limit >= 0) {
if (e->volume_limit <= e->min_volume || e->volume_limit > e->max_volume) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume limit for element %s of path %s is invalid: %li isn't within the valid range "
"%li-%li. The volume limit is ignored.",
buf, e->path->name, e->volume_limit, e->min_volume + 1, e->max_volume);
@@ -1764,7 +1765,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
e->db_fix->max_step = e->max_volume;
e->max_dB = ((double) e->db_fix->db_values[e->db_fix->max_step - e->db_fix->min_step]) / 100.0;
} else if (element_ask_vol_dB(me, e->direction, e->max_volume, &max_dB) < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to get dB value of %s: %s", buf, pa_alsa_strerror(r));
e->has_dB = false;
} else
@@ -1809,7 +1810,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
}
if (e->n_channels <= 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume element %s with no channels?", buf);
return false;
} else if (e->n_channels > POSITION_MASK_CHANNELS) {
@@ -1824,7 +1825,7 @@ static bool element_probe_volume(pa_alsa_element *e, snd_mixer_elem_t *me) {
* Since the array size is fixed at POSITION_MASK_CHANNELS, we obviously
* don't support elements with more than POSITION_MASK_CHANNELS
* channels... */
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Volume element %s has %u channels. That's too much! I can't handle that!", buf, e->n_channels);
return false;
}
@@ -1973,12 +1974,12 @@ static int jack_probe(pa_alsa_jack *j, pa_alsa_mapping *mapping, snd_mixer_t *m)
}
new_name = pa_sprintf_malloc("%s,pcm=%i Jack", j->name, mapping->hw_device_index);
- pa_xfree(j->alsa_name);
- j->alsa_name = new_name;
+ pa_xfree(j->alsa_id.name);
+ j->alsa_id.name = new_name;
j->append_pcm_to_name = false;
}
- has_control = pa_alsa_mixer_find_card(m, j->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find_card(m, &j->alsa_id, 0) != NULL;
pa_alsa_jack_set_has_control(j, has_control);
if (j->has_control) {
@@ -2041,19 +2042,26 @@ finish:
static pa_alsa_jack* jack_get(pa_alsa_path *p, const char *section) {
pa_alsa_jack *j;
+ char *name;
+ int index;
if (!pa_startswith(section, "Jack "))
return NULL;
section += 5;
- if (p->last_jack && pa_streq(p->last_jack->name, section))
+ name = alloca(strlen(section) + 1);
+ if (alsa_id_decode(section, name, &index))
+ return NULL;
+
+ if (p->last_jack && pa_streq(p->last_jack->name, name) &&
+ p->last_jack->alsa_id.index == index)
return p->last_jack;
PA_LLIST_FOREACH(j, p->jacks)
- if (pa_streq(j->name, section))
+ if (pa_streq(j->name, name) && j->alsa_id.index == index)
goto finish;
- j = pa_alsa_jack_new(p, NULL, section);
+ j = pa_alsa_jack_new(p, NULL, name, index);
PA_LLIST_INSERT_AFTER(pa_alsa_jack, p->jacks, p->last_jack, j);
finish:
@@ -2645,7 +2653,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return -1;
}
@@ -2658,7 +2666,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
r = snd_mixer_selem_set_capture_switch_all(me, alsa_idx);
if (r < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set switch of %s: %s", buf, pa_alsa_strerror(errno));
}
@@ -2666,7 +2674,7 @@ static int element_set_option(pa_alsa_element *e, snd_mixer_t *m, int alsa_idx)
pa_assert(e->enumeration_use == PA_ALSA_ENUMERATION_SELECT);
if ((r = snd_mixer_selem_set_enum_item(me, 0, alsa_idx)) < 0) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Failed to set enumeration of %s: %s", buf, pa_alsa_strerror(errno));
}
}
@@ -2723,7 +2731,7 @@ static int option_verify(pa_alsa_option *o) {
if (o->element->enumeration_use != PA_ALSA_ENUMERATION_SELECT &&
o->element->switch_use != PA_ALSA_SWITCH_SELECT) {
- alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
pa_log("Element %s of option %s not set for select.", buf, o->name);
return -1;
}
@@ -2731,7 +2739,7 @@ static int option_verify(pa_alsa_option *o) {
if (o->element->switch_use == PA_ALSA_SWITCH_SELECT &&
!pa_streq(o->alsa_name, "on") &&
!pa_streq(o->alsa_name, "off")) {
- alsa_id_str(buf, sizeof(buf), &o->element->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &o->element->alsa_id);
pa_log("Switch %s options need be named off or on ", buf);
return -1;
}
@@ -2757,13 +2765,13 @@ static int element_verify(pa_alsa_element *e) {
(e->required_any != PA_ALSA_REQUIRED_IGNORE && e->required_any == e->required_absent) ||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required_any != PA_ALSA_REQUIRED_IGNORE) ||
(e->required_absent == PA_ALSA_REQUIRED_ANY && e->required != PA_ALSA_REQUIRED_IGNORE)) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log("Element %s cannot be required and absent at the same time.", buf);
return -1;
}
if (e->switch_use == PA_ALSA_SWITCH_SELECT && e->enumeration_use == PA_ALSA_ENUMERATION_SELECT) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log("Element %s cannot set select for both switch and enumeration.", buf);
return -1;
}
@@ -3168,16 +3176,17 @@ int pa_alsa_path_probe(pa_alsa_path *p, pa_alsa_mapping *mapping, snd_mixer_t *m
pa_log_debug("Probing path '%s'", p->name);
PA_LLIST_FOREACH(j, p->jacks) {
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &j->alsa_id);
if (jack_probe(j, mapping, m) < 0) {
p->supported = false;
- pa_log_debug("Probe of jack '%s' failed.", j->alsa_name);
+ pa_log_debug("Probe of jack %s failed.", buf);
return -1;
}
- pa_log_debug("Probe of jack '%s' succeeded (%s)", j->alsa_name, j->has_control ? "found!" : "not found");
+ pa_log_debug("Probe of jack %s succeeded (%s)", buf, j->has_control ? "found!" : "not found");
}
PA_LLIST_FOREACH(e, p->elements) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
if (element_probe(e, m) < 0) {
p->supported = false;
pa_log_debug("Probe of element %s failed.", buf);
@@ -3286,7 +3295,7 @@ void pa_alsa_setting_dump(pa_alsa_setting *s) {
void pa_alsa_jack_dump(pa_alsa_jack *j) {
pa_assert(j);
- pa_log_debug("Jack %s, alsa_name='%s', detection %s", j->name, j->alsa_name, j->has_control ? "possible" : "unavailable");
+ pa_log_debug("Jack %s, alsa_name='%s', index='%d', detection %s", j->name, j->alsa_id.name, j->alsa_id.index, j->has_control ? "possible" : "unavailable");
}
void pa_alsa_option_dump(pa_alsa_option *o) {
@@ -3306,7 +3315,7 @@ void pa_alsa_element_dump(pa_alsa_element *e) {
pa_alsa_option *o;
pa_assert(e);
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_debug("Element %s, direction=%i, switch=%i, volume=%i, volume_limit=%li, enumeration=%i, required=%i, required_any=%i, required_absent=%i, mask=0x%llx, n_channels=%u, override_map=%02x",
buf,
e->direction,
@@ -3366,7 +3375,7 @@ static void element_set_callback(pa_alsa_element *e, snd_mixer_t *m, snd_mixer_e
SELEM_INIT(sid, &e->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &e->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &e->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return;
}
@@ -3661,7 +3670,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
SELEM_INIT(sid, &a->alsa_id);
if (!(me = snd_mixer_find_selem(m, sid))) {
- alsa_id_str(buf, sizeof(buf), &a->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &a->alsa_id);
pa_log_warn("Element %s seems to have disappeared.", buf);
return false;
}
@@ -3692,7 +3701,7 @@ static bool element_is_subset(pa_alsa_element *a, pa_alsa_element *b, snd_mixer_
return false;
for (s = 0; s <= SND_MIXER_SCHN_LAST; s++)
if (a->masks[s][a->n_channels-1] != b->masks[s][b->n_channels-1]) {
- alsa_id_str(buf, sizeof(buf), &a->alsa_id);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &a->alsa_id);
pa_log_debug("Element %s is not a subset - mask a: 0x%" PRIx64 ", mask b: 0x%" PRIx64 ", at channel %d",
buf, a->masks[s][a->n_channels-1], b->masks[s][b->n_channels-1], s);
return false;
@@ -3769,7 +3778,8 @@ static void path_set_condense(pa_alsa_path_set *ps, snd_mixer_t *m) {
continue;
PA_LLIST_FOREACH(jb, p2->jacks) {
- if (jb->has_control && pa_streq(jb->alsa_name, ja->alsa_name) &&
+ if (jb->has_control && pa_streq(ja->alsa_id.name, jb->alsa_id.name) &&
+ (ja->alsa_id.index == jb->alsa_id.index) &&
(ja->state_plugged == jb->state_plugged) &&
(ja->state_unplugged == jb->state_unplugged)) {
exists = true;
@@ -4459,7 +4469,8 @@ static void profile_set_set_availability_groups(pa_alsa_profile_set *ps) {
PA_LLIST_FOREACH(j2, p2->jacks) {
if (!j2->has_control || j2->state_plugged == PA_AVAILABLE_NO)
continue;
- if (pa_streq(j->alsa_name, j2->alsa_name)) {
+ if (pa_streq(j->alsa_id.name, j2->alsa_id.name) &&
+ j->alsa_id.index == j2->alsa_id.index) {
j->state_plugged = PA_AVAILABLE_UNKNOWN;
j2->state_plugged = PA_AVAILABLE_UNKNOWN;
found = p2->availability_group;
diff --git a/src/modules/alsa/alsa-mixer.h b/src/modules/alsa/alsa-mixer.h
index 81519551d..db8310258 100644
--- a/src/modules/alsa/alsa-mixer.h
+++ b/src/modules/alsa/alsa-mixer.h
@@ -115,6 +115,8 @@ struct pa_alsa_mixer_id {
int index;
};
+char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id);
+
/* An option belongs to an element and refers to one enumeration item
* of the element is an enumeration item, or a switch status if the
* element is a switch item. */
@@ -179,8 +181,8 @@ struct pa_alsa_jack {
snd_mixer_t *mixer_handle;
char *mixer_device_name;
+ struct pa_alsa_mixer_id alsa_id;
char *name; /* E g "Headphone" */
- char *alsa_name; /* E g "Headphone Jack" */
bool has_control; /* is the jack itself present? */
bool plugged_in; /* is this jack currently plugged in? */
snd_mixer_elem_t *melem; /* Jack detection handle */
@@ -196,7 +198,7 @@ struct pa_alsa_jack {
bool append_pcm_to_name;
};
-pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name);
+pa_alsa_jack *pa_alsa_jack_new(pa_alsa_path *path, const char *mixer_device_name, const char *name, int index);
void pa_alsa_jack_free(pa_alsa_jack *jack);
void pa_alsa_jack_set_has_control(pa_alsa_jack *jack, bool has_control);
void pa_alsa_jack_set_plugged_in(pa_alsa_jack *jack, bool plugged_in);
diff --git a/src/modules/alsa/alsa-ucm.c b/src/modules/alsa/alsa-ucm.c
index 18925b792..d9cea6105 100644
--- a/src/modules/alsa/alsa-ucm.c
+++ b/src/modules/alsa/alsa-ucm.c
@@ -1719,7 +1719,7 @@ static pa_alsa_jack* ucm_get_jack(pa_alsa_ucm_config *ucm, pa_alsa_ucm_device *d
pa_log("[%s] No mixer device name for JackControl \"%s\"", device_name, jack_control);
return NULL;
}
- j = pa_alsa_jack_new(NULL, mixer_device_name, name);
+ j = pa_alsa_jack_new(NULL, mixer_device_name, name, 0);
PA_LLIST_PREPEND(pa_alsa_jack, ucm->jacks, j);
finish:
@@ -1953,7 +1953,7 @@ static void ucm_mapping_jack_probe(pa_alsa_mapping *m, pa_hashmap *mixers) {
continue;
}
- has_control = pa_alsa_mixer_find_card(mixer_handle, dev->jack->alsa_name, 0) != NULL;
+ has_control = pa_alsa_mixer_find_card(mixer_handle, &dev->jack->alsa_id, 0) != NULL;
pa_alsa_jack_set_has_control(dev->jack, has_control);
pa_log_info("UCM jack %s has_control=%d", dev->jack->name, dev->jack->has_control);
}
diff --git a/src/modules/alsa/alsa-util.c b/src/modules/alsa/alsa-util.c
index bf35b6112..172a7bb51 100644
--- a/src/modules/alsa/alsa-util.c
+++ b/src/modules/alsa/alsa-util.c
@@ -1635,8 +1635,8 @@ static snd_mixer_elem_t *pa_alsa_mixer_find(snd_mixer_t *mixer,
return NULL;
}
-snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device) {
- return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, name, 0, device);
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device) {
+ return pa_alsa_mixer_find(mixer, SND_CTL_ELEM_IFACE_CARD, alsa_id->name, alsa_id->index, device);
}
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device) {
diff --git a/src/modules/alsa/alsa-util.h b/src/modules/alsa/alsa-util.h
index cb8be22fb..2eed3eac3 100644
--- a/src/modules/alsa/alsa-util.h
+++ b/src/modules/alsa/alsa-util.h
@@ -148,7 +148,7 @@ const char* pa_alsa_strerror(int errnum);
bool pa_alsa_may_tsched(bool want);
-snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, const char *name, unsigned int device);
+snd_mixer_elem_t *pa_alsa_mixer_find_card(snd_mixer_t *mixer, struct pa_alsa_mixer_id *alsa_id, unsigned int device);
snd_mixer_elem_t *pa_alsa_mixer_find_pcm(snd_mixer_t *mixer, const char *name, unsigned int device);
snd_mixer_t *pa_alsa_open_mixer(pa_hashmap *mixers, int alsa_card_index, bool probe);
diff --git a/src/modules/alsa/module-alsa-card.c b/src/modules/alsa/module-alsa-card.c
index f2f50382a..7ff82395f 100644
--- a/src/modules/alsa/module-alsa-card.c
+++ b/src/modules/alsa/module-alsa-card.c
@@ -623,6 +623,7 @@ static void init_jacks(struct userdata *u) {
void *state;
pa_alsa_path* path;
pa_alsa_jack* jack;
+ char buf[64];
u->jacks = pa_hashmap_new(pa_idxset_trivial_hash_func, pa_idxset_trivial_compare_func);
@@ -665,9 +666,10 @@ static void init_jacks(struct userdata *u) {
}
}
pa_alsa_mixer_set_fdlist(u->mixers, jack->mixer_handle, u->core->mainloop);
- jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, jack->alsa_name, 0);
+ jack->melem = pa_alsa_mixer_find_card(jack->mixer_handle, &jack->alsa_id, 0);
if (!jack->melem) {
- pa_log_warn("Jack '%s' seems to have disappeared.", jack->alsa_name);
+ pa_alsa_mixer_id_to_string(buf, sizeof(buf), &jack->alsa_id);
+ pa_log_warn("Jack %s seems to have disappeared.", buf);
pa_alsa_jack_set_has_control(jack, false);
continue;
}
From 2a0fa78d18895ed283e9a36ba9af5a6102cceb4f Mon Sep 17 00:00:00 2001
From: Kai-Heng Feng
Date: Wed, 25 Mar 2020 18:08:56 +0800
Subject: [PATCH 163/872] alsa-mixer: Support dual Front Headphone Jack
There are dual Front Headphone Jacks with different indices or with
different names, they can be found on HP EliteDesk 800 SFF and HP
EliteDesk 800 DM, respectively.
Part-of:
---
.../alsa/mixer/paths/analog-output-headphones.conf | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index 14fb81481..d5a9a327b 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -35,6 +35,18 @@ state.unplugged = unknown
[Jack Front Headphone]
required-any = any
+; HP EliteDesk 800 SFF Headphone
+[Jack Front Headphone,1]
+required-any = any
+
+; HP EliteDesk 800 DM Headset
+[Jack Front Headphone Front]
+required-any = any
+
+; HP EliteDesk 800 DM Headphone
+[Jack Front Headphone Surround]
+required-any = any
+
[Jack Front Headphone Phantom]
required-any = any
state.plugged = unknown
From d51870d4f0f559102cb3860f32522bf163729419 Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 26 Dec 2020 22:15:20 +0200
Subject: [PATCH 164/872] alsa-mixer: Use unambiguous descriptions with dual
headphone outputs
Previously both paths had description "Headphones", which I assume can
cause confusion with users who see two ports with identical names. I
don't have this kind of hardware myself nor have I heard complaints from
users, this is just something I noticed while reading the configuration
files.
Part-of:
---
src/modules/alsa/alsa-mixer.c | 1 +
src/modules/alsa/mixer/paths/analog-output-headphones-2.conf | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/modules/alsa/alsa-mixer.c b/src/modules/alsa/alsa-mixer.c
index 58c33bf48..a6e6672ad 100644
--- a/src/modules/alsa/alsa-mixer.c
+++ b/src/modules/alsa/alsa-mixer.c
@@ -2797,6 +2797,7 @@ static int path_verify(pa_alsa_path *p) {
{ "analog-input-video", N_("Video"), PA_DEVICE_PORT_TYPE_VIDEO },
{ "analog-output", N_("Analog Output"), PA_DEVICE_PORT_TYPE_ANALOG },
{ "analog-output-headphones", N_("Headphones"), PA_DEVICE_PORT_TYPE_HEADPHONES },
+ { "analog-output-headphones-2", N_("Headphones 2"), PA_DEVICE_PORT_TYPE_HEADPHONES },
{ "analog-output-headphones-mono", N_("Headphones Mono Output"), PA_DEVICE_PORT_TYPE_HEADPHONES },
{ "analog-output-lineout", N_("Line Out"), PA_DEVICE_PORT_TYPE_LINE },
{ "analog-output-mono", N_("Analog Mono Output"), PA_DEVICE_PORT_TYPE_ANALOG },
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
index 30815d0a8..33f1cfd2e 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
@@ -19,7 +19,6 @@
[General]
priority = 98
-description-key = analog-output-headphones
[Properties]
device.icon_name = audio-headphones
From 0c14f89b8403c78ff6938359c9885f0a27f071ec Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 26 Dec 2020 22:22:06 +0200
Subject: [PATCH 165/872] alsa-mixer: Move HP EliteDesk 800 SFF/DM second
headphone output to path analog-output-headphones-2
The two headphone outputs should be handled in separate paths so that
volume control can be implemented properly for both outputs.
Part-of:
---
.../alsa/mixer/paths/analog-output-headphones-2.conf | 12 ++++++++++--
.../alsa/mixer/paths/analog-output-headphones.conf | 8 --------
2 files changed, 10 insertions(+), 10 deletions(-)
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
index 33f1cfd2e..f88f8a0b0 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
@@ -13,7 +13,7 @@
# You should have received a copy of the GNU Lesser General Public License
# along with PulseAudio; if not, see .
-; Path for mixers that have a 'Headphone2' control
+; Path for the second headphone output on dual-headphone machines.
;
; See analog-output.conf.common for an explanation on the directives
@@ -23,6 +23,14 @@ priority = 98
[Properties]
device.icon_name = audio-headphones
+; HP EliteDesk 800 SFF Headphone
+[Jack Front Headphone,1]
+required-any = any
+
+; HP EliteDesk 800 DM Headphone
+[Jack Front Headphone Surround]
+required-any = any
+
[Element Hardware Master]
switch = mute
volume = merge
@@ -55,7 +63,7 @@ switch = off
volume = off
[Element Headphone2]
-required = any
+required-any = any
switch = mute
volume = merge
override-map.1 = all
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index d5a9a327b..1c7611fc1 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -35,18 +35,10 @@ state.unplugged = unknown
[Jack Front Headphone]
required-any = any
-; HP EliteDesk 800 SFF Headphone
-[Jack Front Headphone,1]
-required-any = any
-
; HP EliteDesk 800 DM Headset
[Jack Front Headphone Front]
required-any = any
-; HP EliteDesk 800 DM Headphone
-[Jack Front Headphone Surround]
-required-any = any
-
[Jack Front Headphone Phantom]
required-any = any
state.plugged = unknown
From 21a531041ab0b5e52dbde1e3ed4ab8fb49198fda Mon Sep 17 00:00:00 2001
From: Tanu Kaskinen
Date: Sat, 26 Dec 2020 22:29:06 +0200
Subject: [PATCH 166/872] alsa-mixer: Add support for the Headphone,1 element
This is seen at least on HP EliteDesk 800 DM and HP EliteDesk 800 SFF.
This is used by the analog-output-headphones-2 path, but all other paths
on the same sink need to handle the element too. The existing
configuration is inconsistent between files regarding whether headphone
outputs should be muted or not when not using them. I chose to be
consistent within files, which means that Headphone,1 handling is
inconsistent between files in the same way that the existing Headphone
and Headphone2 handling is. (My opinion is that unused paths should be
always muted, but I didn't want to do that policy change in this patch.)
Part-of:
---
.../alsa/mixer/paths/analog-output-headphones-2.conf | 7 +++++++
src/modules/alsa/mixer/paths/analog-output-headphones.conf | 7 +++++++
src/modules/alsa/mixer/paths/analog-output-lineout.conf | 4 ++++
src/modules/alsa/mixer/paths/analog-output-mono.conf | 4 ++++
.../alsa/mixer/paths/analog-output-speaker-always.conf | 4 ++++
src/modules/alsa/mixer/paths/analog-output-speaker.conf | 4 ++++
6 files changed, 30 insertions(+)
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
index f88f8a0b0..178999088 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones-2.conf
@@ -54,6 +54,13 @@ volume = off
switch = mute
volume = zero
+[Element Headphone,1]
+required-any = any
+switch = mute
+volume = merge
+override-map.1 = all
+override-map.2 = all-left,all-right
+
[Element Headphone+LO]
switch = mute
volume = zero
diff --git a/src/modules/alsa/mixer/paths/analog-output-headphones.conf b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
index 1c7611fc1..c808e19e1 100644
--- a/src/modules/alsa/mixer/paths/analog-output-headphones.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-headphones.conf
@@ -93,6 +93,13 @@ volume = merge
override-map.1 = all
override-map.2 = all-left,all-right
+; This path is intended to control the first headphones, not
+; the second headphones. But it should not hurt if we leave the second
+; headphone jack enabled nonetheless.
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headset]
required-any = any
switch = mute
diff --git a/src/modules/alsa/mixer/paths/analog-output-lineout.conf b/src/modules/alsa/mixer/paths/analog-output-lineout.conf
index 61df49965..1ffce2225 100644
--- a/src/modules/alsa/mixer/paths/analog-output-lineout.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-lineout.conf
@@ -127,6 +127,10 @@ required-any = any
switch = off
volume = off
+[Element Headphone,1]
+switch = off
+volume = off
+
[Element Headphone2]
switch = off
volume = off
diff --git a/src/modules/alsa/mixer/paths/analog-output-mono.conf b/src/modules/alsa/mixer/paths/analog-output-mono.conf
index 989654334..5e4940598 100644
--- a/src/modules/alsa/mixer/paths/analog-output-mono.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-mono.conf
@@ -44,6 +44,10 @@ override-map.2 = all-left,all-right
switch = mute
volume = zero
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headphone+LO]
switch = mute
volume = zero
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
index bf781c671..756afa954 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker-always.conf
@@ -76,6 +76,10 @@ volume = off
switch = mute
volume = zero
+[Element Headphone,1]
+switch = mute
+volume = zero
+
[Element Headphone2]
switch = mute
volume = zero
diff --git a/src/modules/alsa/mixer/paths/analog-output-speaker.conf b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
index 91a4bc163..72f928fd9 100644
--- a/src/modules/alsa/mixer/paths/analog-output-speaker.conf
+++ b/src/modules/alsa/mixer/paths/analog-output-speaker.conf
@@ -101,6 +101,10 @@ name = analog-output-speaker
switch = off
volume = off
+[Element Headphone,1]
+switch = off
+volume = off
+
[Element Headphone2]
switch = off
volume = off
From 81ebd8ba3f644e95a7f858ede9fc65d340ab06e2 Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Fri, 1 Jan 2021 21:35:41 +0100
Subject: [PATCH 167/872] message-params: Fix array reading functions
The array read functions need the state pointer as an additional argument because the
array may be in the middle of a parameter list and the state pointer must be advanced
to the element after the array.
Additionally fixes some compiler warnings.
Part-of:
---
src/pulse/message-params.c | 36 ++++++++++++++++--------------------
src/pulse/message-params.h | 8 ++++----
2 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/src/pulse/message-params.c b/src/pulse/message-params.c
index ae2ed8b68..99402ebc2 100644
--- a/src/pulse/message-params.c
+++ b/src/pulse/message-params.c
@@ -345,9 +345,9 @@ int pa_message_params_read_bool(char *c, bool *result, void **state) {
}
/* Converts a parameter list to a string array. */
-int pa_message_params_read_string_array(char *c, const char ***results, int *length) {
- void *state = NULL;
- uint32_t element_count, i;
+int pa_message_params_read_string_array(char *c, const char ***results, int *length, void **state) {
+ void *state1 = NULL;
+ int element_count, i;
int err;
const char **values;
char *start_pos;
@@ -370,8 +370,7 @@ int pa_message_params_read_string_array(char *c, const char ***results, int *len
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(char *));
- state = NULL;
- for (i = 0; (err = pa_message_params_read_string(start_pos, &(values[i]), &state)) > 0; i++)
+ for (i = 0; (err = pa_message_params_read_string(start_pos, &(values[i]), &state1)) > 0; i++)
;
if (err < 0) {
@@ -386,10 +385,10 @@ int pa_message_params_read_string_array(char *c, const char ***results, int *len
}
/* Converts a parameter list to a double array. */
-int pa_message_params_read_double_array(char *c, double **results, int *length) {
+int pa_message_params_read_double_array(char *c, double **results, int *length, void **state) {
double *values;
- void *state = NULL;
- uint32_t element_count, i;
+ void *state1 = NULL;
+ int element_count, i;
int err;
char *start_pos;
@@ -411,8 +410,7 @@ int pa_message_params_read_double_array(char *c, double **results, int *length)
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(double));
- state = NULL;
- for (i = 0; (err = pa_message_params_read_double(start_pos, &(values[i]), &state)) > 0; i++)
+ for (i = 0; (err = pa_message_params_read_double(start_pos, &(values[i]), &state1)) > 0; i++)
;
if (err < 0) {
@@ -427,10 +425,10 @@ int pa_message_params_read_double_array(char *c, double **results, int *length)
}
/* Converts a parameter list to an int64 array. */
-int pa_message_params_read_int64_array(char *c, int64_t **results, int *length) {
+int pa_message_params_read_int64_array(char *c, int64_t **results, int *length, void **state) {
int64_t *values;
- void *state = NULL;
- uint32_t element_count, i;
+ void *state1 = NULL;
+ int element_count, i;
int err;
char *start_pos;
@@ -452,8 +450,7 @@ int pa_message_params_read_int64_array(char *c, int64_t **results, int *length)
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(int64_t));
- state = NULL;
- for (i = 0; (err = pa_message_params_read_int64(start_pos, &(values[i]), &state)) > 0; i++)
+ for (i = 0; (err = pa_message_params_read_int64(start_pos, &(values[i]), &state1)) > 0; i++)
;
if (err < 0) {
@@ -468,10 +465,10 @@ int pa_message_params_read_int64_array(char *c, int64_t **results, int *length)
}
/* Converts a parameter list to an uint64 array. */
-int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length) {
+int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length, void **state) {
uint64_t *values;
- void *state = NULL;
- uint32_t element_count, i;
+ void *state1 = NULL;
+ int element_count, i;
int err;
char *start_pos;
@@ -493,8 +490,7 @@ int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length
/* Allocate array */
values = pa_xmalloc0(element_count * sizeof(uint64_t));
- state = NULL;
- for (i = 0; (err = pa_message_params_read_uint64(start_pos, &(values[i]), &state)) > 0; i++)
+ for (i = 0; (err = pa_message_params_read_uint64(start_pos, &(values[i]), &state1)) > 0; i++)
;
if (err < 0) {
diff --git a/src/pulse/message-params.h b/src/pulse/message-params.h
index 18addee96..3e53c1e84 100644
--- a/src/pulse/message-params.h
+++ b/src/pulse/message-params.h
@@ -77,7 +77,7 @@ int pa_message_params_read_double(char *c, double *result, void **state);
/** Converts a parameter list to a double array. Empty elements in the parameter
* list are treated as error. Returns allocated array in *results and array size in *length.
* The returned array must be freed with pa_xfree(). \since 15.0 */
-int pa_message_params_read_double_array(char *c, double **results, int *length);
+int pa_message_params_read_double_array(char *c, double **results, int *length, void **state);
/** Read an integer from parameter list in c. \since 15.0 */
int pa_message_params_read_int64(char *c, int64_t *result, void **state);
@@ -85,7 +85,7 @@ int pa_message_params_read_int64(char *c, int64_t *result, void **state);
/** Converts a parameter list to an int64 array. Empty elements in the parameter
* list are treated as error. Returns allocated array in *results and array size in *length.
* The returned array must be freed with pa_xfree(). \since 15.0 */
-int pa_message_params_read_int64_array(char *c, int64_t **results, int *length);
+int pa_message_params_read_int64_array(char *c, int64_t **results, int *length, void **state);
/** Read raw data from parameter list in c. Used to split a message parameter
* string into list elements. The string returned in *result must not be freed. \since 15.0 */
@@ -99,7 +99,7 @@ int pa_message_params_read_string(char *c, const char **result, void **state);
* the strings. Returns allocated array of pointers to sub-strings within c in
* *results and stores array size in *length. The returned array must be
* freed with pa_xfree(), but not the strings within the array. \since 15.0 */
-int pa_message_params_read_string_array(char *c, const char ***results, int *length);
+int pa_message_params_read_string_array(char *c, const char ***results, int *length, void **state);
/** Read an unsigned integer from parameter list in c. \since 15.0 */
int pa_message_params_read_uint64(char *c, uint64_t *result, void **state);
@@ -107,7 +107,7 @@ int pa_message_params_read_uint64(char *c, uint64_t *result, void **state);
/** Converts a parameter list to an uint64 array. Empty elements in the parameter
* list are treated as error. Returns allocated array in *results and array size in *length.
* The returned array must be freed with pa_xfree(). \since 15.0 */
-int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length);
+int pa_message_params_read_uint64_array(char *c, uint64_t **results, int *length, void **state);
/** @} */
From b76d835e590b8aa10d724c857ea7d135ba53d94e Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 27 Dec 2020 15:25:40 +0300
Subject: [PATCH 168/872] ladspa-sink: do not call pa_sink_suspend if
PA_SINK_IS_LINKED is false
While module-ladspa-sink is still being loaded and before pa_sink_put() is
called there may be an attempt to reconfigure master sink when avoid-resampling
is true. This breaks attempting to suspend ladspa-sink which is still in INIT
state.
Fix this by skipping pa_sink_suspend if PA_SINK_IS_LINKED is false.
Part-of:
---
src/modules/module-ladspa-sink.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/modules/module-ladspa-sink.c b/src/modules/module-ladspa-sink.c
index f4fed6d64..5726d0818 100644
--- a/src/modules/module-ladspa-sink.c
+++ b/src/modules/module-ladspa-sink.c
@@ -714,6 +714,9 @@ static void sink_input_suspend_cb(pa_sink_input *i, pa_sink_state_t old_state, p
pa_sink_input_assert_ref(i);
pa_assert_se(u = i->userdata);
+ if (!PA_SINK_IS_LINKED(u->sink->state))
+ return;
+
if (i->sink->state != PA_SINK_SUSPENDED || i->sink->suspend_cause == PA_SUSPEND_IDLE)
pa_sink_suspend(u->sink, false, PA_SUSPEND_UNAVAILABLE);
else
From 28f646fd87e824ba5e89377cd9aedde74e6be96c Mon Sep 17 00:00:00 2001
From: Arun Raghavan
Date: Fri, 25 Dec 2020 11:10:30 -0500
Subject: [PATCH 169/872] doc: Add some contributor guidelines
Document some things that should be helpful to at least new
contributors. Since we don't have a way to show this when people are
creating MRs, also copy over the next to a merge request template so
that creates a dropdown that folks might look at when creating an MR.
Part-of:
---
.gitlab/merge_request_templates/Guidelines.md | 67 +++++++++++++++++++
CONTRIBUTING.md | 67 +++++++++++++++++++
2 files changed, 134 insertions(+)
create mode 100644 .gitlab/merge_request_templates/Guidelines.md
create mode 100644 CONTRIBUTING.md
diff --git a/.gitlab/merge_request_templates/Guidelines.md b/.gitlab/merge_request_templates/Guidelines.md
new file mode 100644
index 000000000..2fb9a626b
--- /dev/null
+++ b/.gitlab/merge_request_templates/Guidelines.md
@@ -0,0 +1,67 @@
+# Contribution Guidelines
+
+## A note for contributors
+
+Thank you for your contribution!
+
+Please make sure you tick the box labelled `Allow commits from members who can
+merge to the target branch`. This allows us to make minor edits ourselves, and
+then automatically rebase and merge your changes.
+
+PulseAudio is currently maintained by three volunteer developers in their free
+time (probably amounting to less than one full time developer), which is not
+really enough, given the project size and scope. For this reason bug reports
+and patch submissions are sometimes handled very slowly.
+
+For non-trivial patches, we meet biweekly on IRC to discuss and prioritise
+outstanding MRs. If you haven't heard from us a few days after you create the
+MR, please take a look at [the patch status
+page](https://www.freedesktop.org/wiki/Software/PulseAudio/PatchStatus/).
+
+If you don't see your MR in that list either, please don't hesitate to drop a
+comment pinging us, and we'll try to at least respond and make sure your
+request is tracked on that list.
+
+## Coding Style
+
+Please take a look at the [coding style
+documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/CodingStyle/)
+on our wiki.
+
+## Commit messagse
+
+We follow the standard git commit message format of a summary on the first line
+(<=50 characterss for preference, <=72 characters otherwise), followed by a new
+line, followed by a detailed commit message. An additional line at the end may
+link to an issue being fixed by this MR.
+
+The first line is usually a short description of "what" your commit does, and
+the rest of the message describes the "why", along with any additional
+information that readers might need to understand the rationale for the change.
+If in doubt, more verbose is better than less.
+
+If you need to describe the "how" of the commit, that is usually best
+documented along with the code itself.
+
+Commit messages are prefixed with the subsystem being affected. Your best bet
+to figure out what is appropriate is to look at previous commit messages. An
+example:
+
+```
+sink: Reduce chat sink priority
+
+Some gaming sound cards have custom profiles with analog-game and
+analog-chat mappings that exist simultaneously. The game sink should
+have higher priority than the chat sink, but currently there's no way to
+affect the sink priorities from the profile-set configuration (the
+mapping priority is not propagated to the sink priority).
+
+I first thought about adding the mapping priority to the sink priority,
+but that could mess up the prioritization system in
+pa_device_init_priority(). I ended up checking for the intended roles
+property to reduce the chat sink priority. I also reduced the iec958
+priority so that the chat and iec958 sinks don't end up with the same
+priority.
+
+Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/818
+```
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 000000000..2fb9a626b
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,67 @@
+# Contribution Guidelines
+
+## A note for contributors
+
+Thank you for your contribution!
+
+Please make sure you tick the box labelled `Allow commits from members who can
+merge to the target branch`. This allows us to make minor edits ourselves, and
+then automatically rebase and merge your changes.
+
+PulseAudio is currently maintained by three volunteer developers in their free
+time (probably amounting to less than one full time developer), which is not
+really enough, given the project size and scope. For this reason bug reports
+and patch submissions are sometimes handled very slowly.
+
+For non-trivial patches, we meet biweekly on IRC to discuss and prioritise
+outstanding MRs. If you haven't heard from us a few days after you create the
+MR, please take a look at [the patch status
+page](https://www.freedesktop.org/wiki/Software/PulseAudio/PatchStatus/).
+
+If you don't see your MR in that list either, please don't hesitate to drop a
+comment pinging us, and we'll try to at least respond and make sure your
+request is tracked on that list.
+
+## Coding Style
+
+Please take a look at the [coding style
+documentation](https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/Developer/CodingStyle/)
+on our wiki.
+
+## Commit messagse
+
+We follow the standard git commit message format of a summary on the first line
+(<=50 characterss for preference, <=72 characters otherwise), followed by a new
+line, followed by a detailed commit message. An additional line at the end may
+link to an issue being fixed by this MR.
+
+The first line is usually a short description of "what" your commit does, and
+the rest of the message describes the "why", along with any additional
+information that readers might need to understand the rationale for the change.
+If in doubt, more verbose is better than less.
+
+If you need to describe the "how" of the commit, that is usually best
+documented along with the code itself.
+
+Commit messages are prefixed with the subsystem being affected. Your best bet
+to figure out what is appropriate is to look at previous commit messages. An
+example:
+
+```
+sink: Reduce chat sink priority
+
+Some gaming sound cards have custom profiles with analog-game and
+analog-chat mappings that exist simultaneously. The game sink should
+have higher priority than the chat sink, but currently there's no way to
+affect the sink priorities from the profile-set configuration (the
+mapping priority is not propagated to the sink priority).
+
+I first thought about adding the mapping priority to the sink priority,
+but that could mess up the prioritization system in
+pa_device_init_priority(). I ended up checking for the intended roles
+property to reduce the chat sink priority. I also reduced the iec958
+priority so that the chat and iec958 sinks don't end up with the same
+priority.
+
+Fixes: https://gitlab.freedesktop.org/pulseaudio/pulseaudio/issues/818
+```
From b6396dbe9c97be844553dd748e7cf9c3efdc0086 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Tue, 22 Dec 2020 20:54:40 +0300
Subject: [PATCH 170/872] x11: gracefully handle X11 connection error
Perform X11 connection recovery via XSetIOErrorExitHandler mechanism.
Implementation is largely inspired by this change to GNOME/mutter
https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1447
Part-of:
---
configure.ac | 12 ++++-
meson.build | 4 ++
src/modules/x11/module-x11-bell.c | 2 +
src/modules/x11/module-x11-cork-request.c | 2 +
src/modules/x11/module-x11-publish.c | 2 +
src/modules/x11/module-x11-xsmp.c | 2 +-
src/pulsecore/x11wrap.c | 59 ++++++++++++++++++++++-
src/pulsecore/x11wrap.h | 4 +-
8 files changed, 81 insertions(+), 6 deletions(-)
diff --git a/configure.ac b/configure.ac
index 357b6d7f7..bd3a53367 100644
--- a/configure.ac
+++ b/configure.ac
@@ -633,8 +633,14 @@ AC_ARG_ENABLE([x11],
AS_HELP_STRING([--disable-x11],[Disable optional X11 support]))
AS_IF([test "x$enable_x11" != "xno"],
- [PKG_CHECK_MODULES(X11, [ x11-xcb xcb >= 1.6 ice sm xtst ], HAVE_X11=1, HAVE_X11=0)],
- HAVE_X11=0)
+ [
+ PKG_CHECK_MODULES(X11, [ x11-xcb xcb >= 1.6 ice sm xtst ], HAVE_X11=1, HAVE_X11=0)
+ AC_CHECK_LIB(X11, XSetIOErrorExitHandler, [HAVE_XSETIOERROREXITHANDLER=yes], [HAVE_XSETIOERROREXITHANDLER=no])
+ ],
+ [
+ HAVE_X11=0
+ HAVE_XSETIOERROREXITHANDLER=no
+ ])
AS_IF([test "x$enable_x11" = "xyes" && test "x$HAVE_X11" = "x0"],
[AC_MSG_ERROR([*** X11 not found])])
@@ -642,6 +648,7 @@ AS_IF([test "x$enable_x11" = "xyes" && test "x$HAVE_X11" = "x0"],
AC_SUBST(HAVE_X11)
AM_CONDITIONAL([HAVE_X11], [test "x$HAVE_X11" = x1])
AS_IF([test "x$HAVE_X11" = "x1"], AC_DEFINE([HAVE_X11], 1, [Have X11?]))
+AS_IF([test "x$HAVE_XSETIOERROREXITHANDLER" = "xyes"], AC_DEFINE([HAVE_XSETIOERROREXITHANDLER], 1, [Have XSetIOErrorExitHandler function.]))
#### Capabilities (optional) ####
@@ -1687,6 +1694,7 @@ echo "
Enable memfd shared memory: ${ENABLE_MEMFD}
Enable X11: ${ENABLE_X11}
+ Safe X11 I/O errors: ${HAVE_XSETIOERROREXITHANDLER}
Enable OSS Output: ${ENABLE_OSS_OUTPUT}
Enable OSS Wrapper: ${ENABLE_OSS_WRAPPER}
Enable EsounD: ${ENABLE_ESOUND}
diff --git a/meson.build b/meson.build
index cd617c602..23e04ef46 100644
--- a/meson.build
+++ b/meson.build
@@ -650,6 +650,9 @@ if x11_dep.found()
sm_dep = dependency('sm', required : true)
xtst_dep = dependency('xtst', required : true)
cdata.set('HAVE_X11', 1)
+ if cc.has_function('XSetIOErrorExitHandler', dependencies: x11_dep)
+ cdata.set('HAVE_XSETIOERROREXITHANDLER', 1)
+ endif
endif
# Module dependencies
@@ -847,6 +850,7 @@ summary = [
'',
'Enable memfd shared memory: @0@'.format(cdata.has('HAVE_MEMFD')),
'Enable X11: @0@'.format(x11_dep.found()),
+ ' Safe X11 I/O errors: @0@'.format(cdata.has('HAVE_XSETIOERROREXITHANDLER')),
'Enable OSS Output: @0@'.format(cdata.has('HAVE_OSS_OUTPUT')),
'Enable OSS Wrapper: @0@'.format(cdata.has('HAVE_OSS_WRAPPER')),
# 'Enable EsounD: @0@'.format(${ENABLE_ESOUND}),
diff --git a/src/modules/x11/module-x11-bell.c b/src/modules/x11/module-x11-bell.c
index eab1e6c3a..058a93316 100644
--- a/src/modules/x11/module-x11-bell.c
+++ b/src/modules/x11/module-x11-bell.c
@@ -93,6 +93,8 @@ static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
pa_assert(u);
pa_assert(u->x11_wrapper == w);
+ pa_log_debug("X11 client kill callback called");
+
if (u->x11_client)
pa_x11_client_free(u->x11_client);
diff --git a/src/modules/x11/module-x11-cork-request.c b/src/modules/x11/module-x11-cork-request.c
index 6b1a86b9f..b9378f568 100644
--- a/src/modules/x11/module-x11-cork-request.c
+++ b/src/modules/x11/module-x11-cork-request.c
@@ -66,6 +66,8 @@ static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
pa_assert(u);
pa_assert(u->x11_wrapper == w);
+ pa_log_debug("X11 client kill callback called");
+
if (u->x11_client) {
pa_x11_client_free(u->x11_client);
u->x11_client = NULL;
diff --git a/src/modules/x11/module-x11-publish.c b/src/modules/x11/module-x11-publish.c
index 68adf1574..da619f83c 100644
--- a/src/modules/x11/module-x11-publish.c
+++ b/src/modules/x11/module-x11-publish.c
@@ -116,6 +116,8 @@ static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
pa_assert(u);
pa_assert(u->x11_wrapper == w);
+ pa_log_debug("X11 client kill callback called");
+
if (u->x11_client)
pa_x11_client_free(u->x11_client);
diff --git a/src/modules/x11/module-x11-xsmp.c b/src/modules/x11/module-x11-xsmp.c
index 459da1302..eb18b4312 100644
--- a/src/modules/x11/module-x11-xsmp.c
+++ b/src/modules/x11/module-x11-xsmp.c
@@ -64,7 +64,7 @@ static void die_cb(SmcConn connection, SmPointer client_data) {
pa_log_debug("Got die message from XSMP.");
- pa_x11_wrapper_kill(u->x11);
+ pa_x11_wrapper_kill_deferred(u->x11);
pa_x11_wrapper_unref(u->x11);
u->x11 = NULL;
diff --git a/src/pulsecore/x11wrap.c b/src/pulsecore/x11wrap.c
index 0c040cf57..635d21e00 100644
--- a/src/pulsecore/x11wrap.c
+++ b/src/pulsecore/x11wrap.c
@@ -33,6 +33,8 @@
#include "x11wrap.h"
+#include
+
typedef struct pa_x11_internal pa_x11_internal;
struct pa_x11_internal {
@@ -51,6 +53,7 @@ struct pa_x11_wrapper {
pa_defer_event* defer_event;
pa_io_event* io_event;
+ pa_defer_event* cleanup_event;
PA_LLIST_HEAD(pa_x11_client, clients);
PA_LLIST_HEAD(pa_x11_internal, internals);
@@ -64,6 +67,8 @@ struct pa_x11_client {
void *userdata;
};
+static void x11_wrapper_kill(pa_x11_wrapper *w);
+
/* Dispatch all pending X11 events */
static void work(pa_x11_wrapper *w) {
pa_assert(w);
@@ -167,6 +172,38 @@ static void x11_watch(Display *display, XPointer userdata, int fd, Bool opening,
x11_internal_remove(w, (pa_x11_internal*) *watch_data);
}
+static int x11_error_handler(Display* display, XErrorEvent* error_event) {
+ pa_log_warn("X11 error handler called");
+ return 0;
+}
+
+static int x11_io_error_handler(Display* display) {
+ pa_log_warn("X11 I/O error handler called");
+ return 0;
+}
+
+static void deferred_x11_teardown(pa_mainloop_api *m, pa_defer_event *e, void *userdata) {
+ pa_x11_wrapper *w = userdata;
+
+ m->defer_enable(e, 0);
+
+ pa_log_debug("Start tearing down X11 modules after X11 I/O error");
+
+ x11_wrapper_kill(w);
+
+ pa_log_debug("Done tearing down X11 modules after X11 I/O error");
+}
+
+#ifdef HAVE_XSETIOERROREXITHANDLER
+static void x11_io_error_exit_handler(Display* display, void *userdata) {
+ pa_x11_wrapper *w = userdata;
+
+ pa_log_warn("X11 I/O error exit handler called, preparing to tear down X11 modules");
+
+ pa_x11_wrapper_kill_deferred(w);
+}
+#endif
+
static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char *t) {
pa_x11_wrapper*w;
Display *d;
@@ -187,11 +224,20 @@ static pa_x11_wrapper* x11_wrapper_new(pa_core *c, const char *name, const char
w->defer_event = c->mainloop->defer_new(c->mainloop, defer_event, w);
w->io_event = c->mainloop->io_new(c->mainloop, ConnectionNumber(d), PA_IO_EVENT_INPUT, display_io_event, w);
+ w->cleanup_event = c->mainloop->defer_new(c->mainloop, deferred_x11_teardown, w);
+ w->core->mainloop->defer_enable(w->cleanup_event, 0);
+ XSetErrorHandler(x11_error_handler);
+ XSetIOErrorHandler(x11_io_error_handler);
+#ifdef HAVE_XSETIOERROREXITHANDLER
+ XSetIOErrorExitHandler(d, x11_io_error_exit_handler, w);
+#endif
XAddConnectionWatch(d, x11_watch, (XPointer) w);
pa_assert_se(pa_shared_set(c, w->property_name, w) >= 0);
+ pa_log_debug("Created X11 connection wrapper '%s'", w->property_name);
+
return w;
}
@@ -202,9 +248,12 @@ static void x11_wrapper_free(pa_x11_wrapper*w) {
pa_assert(!w->clients);
+ pa_log_debug("Destroying X11 connection wrapper '%s'", w->property_name);
+
XRemoveConnectionWatch(w->display, x11_watch, (XPointer) w);
XCloseDisplay(w->display);
+ w->core->mainloop->defer_free(w->cleanup_event);
w->core->mainloop->io_free(w->io_event);
w->core->mainloop->defer_free(w->defer_event);
@@ -261,7 +310,15 @@ xcb_connection_t *pa_x11_wrapper_get_xcb_connection(pa_x11_wrapper *w) {
return XGetXCBConnection(pa_x11_wrapper_get_display(w));
}
-void pa_x11_wrapper_kill(pa_x11_wrapper *w) {
+void pa_x11_wrapper_kill_deferred(pa_x11_wrapper *w) {
+ pa_assert(w);
+
+ /* schedule X11 display teardown */
+ w->core->mainloop->defer_enable(w->cleanup_event, 1);
+}
+
+/* Kill the connection to the X11 display */
+static void x11_wrapper_kill(pa_x11_wrapper *w) {
pa_x11_client *c, *n;
pa_assert(w);
diff --git a/src/pulsecore/x11wrap.h b/src/pulsecore/x11wrap.h
index 0539303c2..2d81705c2 100644
--- a/src/pulsecore/x11wrap.h
+++ b/src/pulsecore/x11wrap.h
@@ -48,8 +48,8 @@ Display *pa_x11_wrapper_get_display(pa_x11_wrapper *w);
/* Return the XCB connection object for this connection */
xcb_connection_t *pa_x11_wrapper_get_xcb_connection(pa_x11_wrapper *w);
-/* Kill the connection to the X11 display */
-void pa_x11_wrapper_kill(pa_x11_wrapper *w);
+/* Initiate X11 connection teardown. */
+void pa_x11_wrapper_kill_deferred(pa_x11_wrapper *w);
/* Register an X11 client, that is called for each X11 event */
pa_x11_client* pa_x11_client_new(pa_x11_wrapper *w, pa_x11_event_cb_t event_cb, pa_x11_kill_cb_t kill_cb, void *userdata);
From 6bfd9c809e1a679043c6c4bfdd1e117ed7b5fc2a Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Wed, 23 Dec 2020 10:31:18 +0300
Subject: [PATCH 171/872] x11: gracefully handle ICE connection error
Implementation is largely inspired by GNOME/mutter ICE session handling.
Part-of:
---
src/modules/x11/module-x11-xsmp.c | 82 ++++++++++++++++++++++++++-----
1 file changed, 69 insertions(+), 13 deletions(-)
diff --git a/src/modules/x11/module-x11-xsmp.c b/src/modules/x11/module-x11-xsmp.c
index eb18b4312..1ff6cc770 100644
--- a/src/modules/x11/module-x11-xsmp.c
+++ b/src/modules/x11/module-x11-xsmp.c
@@ -55,21 +55,50 @@ struct userdata {
pa_module *module;
pa_client *client;
SmcConn connection;
- pa_x11_wrapper *x11;
+
+ pa_x11_wrapper *x11_wrapper;
+ pa_x11_client *x11_client;
};
+static void x11_kill_cb(pa_x11_wrapper *w, void *userdata) {
+ struct userdata *u = userdata;
+
+ pa_assert(w);
+ pa_assert(u);
+ pa_assert(u->x11_wrapper == w);
+
+ pa_log_debug("X11 client kill callback called");
+
+ if (u->connection) {
+ SmcCloseConnection(u->connection, 0, NULL);
+ u->connection = NULL;
+ }
+
+ if (u->x11_client) {
+ pa_x11_client_free(u->x11_client);
+ u->x11_client = NULL;
+ }
+
+ if (u->x11_wrapper) {
+ pa_x11_wrapper_unref(u->x11_wrapper);
+ u->x11_wrapper = NULL;
+ }
+
+ pa_module_unload_request(u->module, true);
+}
+
static void die_cb(SmcConn connection, SmPointer client_data) {
struct userdata *u = client_data;
pa_assert(u);
pa_log_debug("Got die message from XSMP.");
- pa_x11_wrapper_kill_deferred(u->x11);
+ if (u->connection) {
+ SmcCloseConnection(u->connection, 0, NULL);
+ u->connection = NULL;
+ }
- pa_x11_wrapper_unref(u->x11);
- u->x11 = NULL;
-
- pa_module_unload_request(u->module, true);
+ pa_x11_wrapper_kill_deferred(u->x11_wrapper);
}
static void save_complete_cb(SmcConn connection, SmPointer client_data) {
@@ -87,6 +116,7 @@ static void ice_io_cb(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_fla
IceConn connection = userdata;
if (IceProcessMessages(connection, NULL, NULL) == IceProcessMessagesIOError) {
+ pa_log_debug("IceProcessMessages: I/O error, closing ICE connection");
IceSetShutdownNegotiation(connection, False);
IceCloseConnection(connection);
}
@@ -106,6 +136,17 @@ static void new_ice_connection(IceConn connection, IcePointer client_data, Bool
c->mainloop->io_free(*watch_data);
}
+static IceIOErrorHandler ice_installed_handler;
+
+/* We call any handler installed before (or after) module is loaded but
+ avoid calling the default libICE handler which does an exit() */
+
+static void ice_io_error_handler(IceConn iceConn) {
+ pa_log_warn("ICE I/O error handler called");
+ if (ice_installed_handler)
+ (*ice_installed_handler) (iceConn);
+}
+
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
@@ -123,17 +164,27 @@ int pa__init(pa_module*m) {
if (ice_in_use) {
pa_log("module-x11-xsmp may not be loaded twice.");
return -1;
- }
+ } else {
+ IceIOErrorHandler default_handler;
- IceAddConnectionWatch(new_ice_connection, m->core);
- ice_in_use = true;
+ ice_installed_handler = IceSetIOErrorHandler (NULL);
+ default_handler = IceSetIOErrorHandler (ice_io_error_handler);
+
+ if (ice_installed_handler == default_handler)
+ ice_installed_handler = NULL;
+
+ IceSetIOErrorHandler(ice_io_error_handler);
+
+ IceAddConnectionWatch(new_ice_connection, m->core);
+ ice_in_use = true;
+ }
m->userdata = u = pa_xnew(struct userdata, 1);
u->core = m->core;
u->module = m;
u->client = NULL;
u->connection = NULL;
- u->x11 = NULL;
+ u->x11_wrapper = NULL;
if (!(ma = pa_modargs_new(m->argument, valid_modargs))) {
pa_log("Failed to parse module arguments");
@@ -147,9 +198,11 @@ int pa__init(pa_module*m) {
}
}
- if (!(u->x11 = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
+ if (!(u->x11_wrapper = pa_x11_wrapper_get(m->core, pa_modargs_get_value(ma, "display", NULL))))
goto fail;
+ u->x11_client = pa_x11_client_new(u->x11_wrapper, NULL, x11_kill_cb, u);
+
e = pa_modargs_get_value(ma, "session_manager", NULL);
if (!e && !getenv("SESSION_MANAGER")) {
@@ -253,8 +306,11 @@ void pa__done(pa_module*m) {
if (u->client)
pa_client_free(u->client);
- if (u->x11)
- pa_x11_wrapper_unref(u->x11);
+ if (u->x11_client)
+ pa_x11_client_free(u->x11_client);
+
+ if (u->x11_wrapper)
+ pa_x11_wrapper_unref(u->x11_wrapper);
pa_xfree(u);
}
From f18f55bb5ee4391370e59528ff0aa93068299252 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 27 Dec 2020 12:40:18 +0300
Subject: [PATCH 172/872] daemon: fix default daemon.conf when running from
build tree
Part-of:
---
src/daemon/daemon-conf.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/daemon/daemon-conf.c b/src/daemon/daemon-conf.c
index bcf7329f1..ffef554be 100644
--- a/src/daemon/daemon-conf.c
+++ b/src/daemon/daemon-conf.c
@@ -665,9 +665,21 @@ int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
pa_xfree(c->config_file);
c->config_file = NULL;
+ const char *default_config_file = DEFAULT_CONFIG_FILE;
+#ifdef HAVE_RUNNING_FROM_BUILD_TREE
+ if (pa_run_from_build_tree()) {
+ pa_log_notice("Detected that we are run from the build tree, fixing default daemon.conf file path.");
+#ifdef MESON_BUILD
+ default_config_file = PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "daemon" PA_PATH_SEP "daemon.conf";
+#else
+ default_config_file = PA_BUILDDIR PA_PATH_SEP "daemon.conf";
+#endif // Endof #ifdef MESON_BUILD
+ }
+#endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE
+
f = filename ?
pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
- pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
+ pa_open_config_file(default_config_file, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
if (!f && errno != ENOENT) {
pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
From 0efae0488ccd4536926f5fa2b4cf524e63da9095 Mon Sep 17 00:00:00 2001
From: Georg Chini
Date: Mon, 4 Jan 2021 21:08:05 +0100
Subject: [PATCH 173/872] loopback: Fix sink latency calculation if source is
alsa source with fixed latency
When an alsa source with fixed latency is used, the actual latency of the source
will only be one fragment size. This is not taken into account when the required
sink latency is calculated.
This patch fixes the issue.
Part-of:
---
src/modules/module-loopback.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/modules/module-loopback.c b/src/modules/module-loopback.c
index 871f01166..4f8ceec46 100644
--- a/src/modules/module-loopback.c
+++ b/src/modules/module-loopback.c
@@ -1016,6 +1016,14 @@ static void set_sink_input_latency(struct userdata *u, pa_sink *sink) {
if (u->min_source_latency > requested_latency) {
latency = PA_MAX(u->latency, u->minimum_latency);
requested_latency = (latency - u->min_source_latency) / 2;
+ /* In the case of a fixed alsa source, u->minimum_latency is calculated from
+ * the default fragment size while u->min_source_latency is the reported minimum
+ * of the source latency (nr_of_fragments * fragment_size). This can lead to a
+ * situation where u->minimum_latency < u->min_source_latency. We only fall
+ * back to use the fragment size instead of min_source_latency if the calculation
+ * above does not deliver a usable result. */
+ if (u->fixed_alsa_source && u->min_source_latency >= latency)
+ requested_latency = (latency - u->core->default_fragment_size_msec * PA_USEC_PER_MSEC) / 2;
}
latency = PA_CLAMP(requested_latency , u->min_sink_latency, u->max_sink_latency);
From 0ac6b16787b201025498063d3b48db4a86f48d2b Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 29 Nov 2020 11:21:29 +0300
Subject: [PATCH 174/872] database: extract common method to handle machine id
and architecture
Part-of:
---
src/Makefile.am | 2 +-
src/modules/module-card-restore.c | 12 ++---
src/modules/module-device-manager.c | 12 ++---
src/modules/module-device-restore.c | 12 ++---
src/modules/module-equalizer-sink.c | 24 +++++-----
src/modules/module-stream-restore.c | 12 ++---
src/pulsecore/database-gdbm.c | 25 ++++++----
src/pulsecore/database-simple.c | 17 ++++---
src/pulsecore/database-tdb.c | 17 ++++---
src/pulsecore/database.c | 72 +++++++++++++++++++++++++++++
src/pulsecore/database.h | 13 +++++-
src/pulsecore/meson.build | 1 +
12 files changed, 154 insertions(+), 65 deletions(-)
create mode 100644 src/pulsecore/database.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 97c9dce9f..14c59566f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1042,7 +1042,7 @@ libpulsecore_@PA_MAJORMINOR@_la_SOURCES = \
pulsecore/source.c pulsecore/source.h \
pulsecore/start-child.c pulsecore/start-child.h \
pulsecore/thread-mq.c pulsecore/thread-mq.h \
- pulsecore/database.h
+ pulsecore/database.c pulsecore/database.h
libpulsecore_@PA_MAJORMINOR@_la_CFLAGS = $(AM_CFLAGS) $(SERVER_CFLAGS) $(LIBSNDFILE_CFLAGS) $(WINSOCK_CFLAGS)
libpulsecore_@PA_MAJORMINOR@_la_LDFLAGS = $(AM_LDFLAGS) $(AM_LIBLDFLAGS) -avoid-version
diff --git a/src/modules/module-card-restore.c b/src/modules/module-card-restore.c
index 80506cd04..b35cf3e7e 100644
--- a/src/modules/module-card-restore.c
+++ b/src/modules/module-card-restore.c
@@ -618,7 +618,7 @@ static pa_hook_result_t card_preferred_port_changed_callback(pa_core *core, pa_c
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
bool restore_bluetooth_profile;
pa_assert(m);
@@ -648,17 +648,15 @@ int pa__init(pa_module*m) {
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_CARD_PROFILE_ADDED], PA_HOOK_NORMAL, (pa_hook_cb_t) card_profile_added_callback, u);
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_PORT_LATENCY_OFFSET_CHANGED], PA_HOOK_NORMAL, (pa_hook_cb_t) port_offset_change_callback, u);
- if (!(fname = pa_state_path("card-database", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "card-database", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
pa_modargs_free(ma);
return 0;
diff --git a/src/modules/module-device-manager.c b/src/modules/module-device-manager.c
index 308ef0b57..b51b6c8a0 100644
--- a/src/modules/module-device-manager.c
+++ b/src/modules/module-device-manager.c
@@ -1544,7 +1544,7 @@ struct prioritised_indexes {
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink *sink;
pa_source *source;
uint32_t idx;
@@ -1601,17 +1601,15 @@ int pa__init(pa_module*m) {
u->source_unlink_hook_slot = pa_hook_connect(&m->core->hooks[PA_CORE_HOOK_SOURCE_UNLINK], PA_HOOK_LATE+5, (pa_hook_cb_t) source_unlink_hook_callback, u);
}
- if (!(fname = pa_state_path("device-manager", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "device-manager", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
/* Attempt to inject the devices into the list in priority order */
total_devices = PA_MAX(pa_idxset_size(m->core->sinks), pa_idxset_size(m->core->sources));
diff --git a/src/modules/module-device-restore.c b/src/modules/module-device-restore.c
index 684c8360d..9ca2a7cd5 100644
--- a/src/modules/module-device-restore.c
+++ b/src/modules/module-device-restore.c
@@ -1202,7 +1202,7 @@ static pa_hook_result_t connection_unlink_hook_cb(pa_native_protocol *p, pa_nati
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink *sink;
pa_source *source;
uint32_t idx;
@@ -1259,17 +1259,15 @@ int pa__init(pa_module*m) {
if (restore_formats)
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SINK_PUT], PA_HOOK_EARLY, (pa_hook_cb_t) sink_put_hook_callback, u);
- if (!(fname = pa_state_path("device-volumes", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "device-volumes", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
PA_IDXSET_FOREACH(sink, m->core->sinks, idx)
subscribe_callback(m->core, PA_SUBSCRIPTION_EVENT_SINK|PA_SUBSCRIPTION_EVENT_NEW, sink->index, u);
diff --git a/src/modules/module-equalizer-sink.c b/src/modules/module-equalizer-sink.c
index 4cfe3ed48..f8a9e9514 100644
--- a/src/modules/module-equalizer-sink.c
+++ b/src/modules/module-equalizer-sink.c
@@ -946,7 +946,7 @@ static void save_state(struct userdata *u) {
float *H;
pa_datum key, data;
pa_database *database;
- char *dbname;
+ char *state_path;
char *packed;
size_t packed_length;
@@ -969,9 +969,9 @@ static void save_state(struct userdata *u) {
data.data = state;
data.size = filter_state_size + packed_length;
//thread safety for 0.9.17?
- pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
- pa_assert_se(database = pa_database_open(dbname, true));
- pa_xfree(dbname);
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ pa_assert_se(database = pa_database_open(state_path, EQ_STATE_DB, false, true));
+ pa_xfree(state_path);
pa_database_set(database, &key, &data, true);
pa_database_sync(database);
@@ -1020,10 +1020,10 @@ static void load_state(struct userdata *u) {
float *H;
pa_datum key, value;
pa_database *database;
- char *dbname;
- pa_assert_se(dbname = pa_state_path(EQ_STATE_DB, false));
- database = pa_database_open(dbname, false);
- pa_xfree(dbname);
+ char *state_path;
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ database = pa_database_open(state_path, EQ_STATE_DB, false, false);
+ pa_xfree(state_path);
if (!database) {
pa_log("No resume state");
return;
@@ -1626,12 +1626,12 @@ void dbus_init(struct userdata *u) {
sink_list = pa_shared_get(u->sink->core, SINKLIST);
u->database = pa_shared_get(u->sink->core, EQDB);
if (sink_list == NULL) {
- char *dbname;
+ char *state_path;
sink_list=pa_idxset_new(&pa_idxset_trivial_hash_func, &pa_idxset_trivial_compare_func);
pa_shared_set(u->sink->core, SINKLIST, sink_list);
- pa_assert_se(dbname = pa_state_path("equalizer-presets", false));
- pa_assert_se(u->database = pa_database_open(dbname, true));
- pa_xfree(dbname);
+ pa_assert_se(state_path = pa_state_path(NULL, false));
+ pa_assert_se(u->database = pa_database_open(state_path, "equalizer-presets", false, true));
+ pa_xfree(state_path);
pa_shared_set(u->sink->core, EQDB, u->database);
pa_dbus_protocol_add_interface(u->dbus_protocol, MANAGER_PATH, &manager_info, u->sink->core);
pa_dbus_protocol_register_extension(u->dbus_protocol, EXTNAME);
diff --git a/src/modules/module-stream-restore.c b/src/modules/module-stream-restore.c
index d26543bde..315360740 100644
--- a/src/modules/module-stream-restore.c
+++ b/src/modules/module-stream-restore.c
@@ -2266,7 +2266,7 @@ static void clean_up_db(struct userdata *u) {
int pa__init(pa_module*m) {
pa_modargs *ma = NULL;
struct userdata *u;
- char *fname;
+ char *state_path;
pa_sink_input *si;
pa_source_output *so;
uint32_t idx;
@@ -2324,17 +2324,15 @@ int pa__init(pa_module*m) {
pa_module_hook_connect(m, &m->core->hooks[PA_CORE_HOOK_SOURCE_OUTPUT_FIXATE], PA_HOOK_EARLY, (pa_hook_cb_t) source_output_fixate_hook_callback, u);
}
- if (!(fname = pa_state_path("stream-volumes", true)))
+ if (!(state_path = pa_state_path(NULL, true)))
goto fail;
- if (!(u->database = pa_database_open(fname, true))) {
- pa_log("Failed to open volume database '%s': %s", fname, pa_cstrerror(errno));
- pa_xfree(fname);
+ if (!(u->database = pa_database_open(state_path, "stream-volumes", true, true))) {
+ pa_xfree(state_path);
goto fail;
}
- pa_log_info("Successfully opened database file '%s'.", fname);
- pa_xfree(fname);
+ pa_xfree(state_path);
clean_up_db(u);
diff --git a/src/pulsecore/database-gdbm.c b/src/pulsecore/database-gdbm.c
index b1da9df9f..cd03405f5 100644
--- a/src/pulsecore/database-gdbm.c
+++ b/src/pulsecore/database-gdbm.c
@@ -59,17 +59,24 @@ void pa_datum_free(pa_datum *d) {
pa_zero(d);
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
- GDBM_FILE f;
- int gdbm_cache_size;
- char *path;
-
- pa_assert(fn);
-
+const char* pa_database_get_arch_suffix(void) {
/* We include the host identifier in the file name because gdbm
* files are CPU dependent, and we don't want things to go wrong
* if we are on a multiarch system. */
- path = pa_sprintf_malloc("%s."CANONICAL_HOST".gdbm", fn);
+
+ return CANONICAL_HOST;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+ return ".gdbm";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
+ GDBM_FILE f;
+ int gdbm_cache_size;
+
+ pa_assert(path);
+
errno = 0;
/* We need to set the block size explicitly here, since otherwise
@@ -80,8 +87,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
if (f)
pa_log_debug("Opened GDBM database '%s'", path);
- pa_xfree(path);
-
if (!f) {
if (errno == 0)
errno = EIO;
diff --git a/src/pulsecore/database-simple.c b/src/pulsecore/database-simple.c
index 387648769..ebfbe4c61 100644
--- a/src/pulsecore/database-simple.c
+++ b/src/pulsecore/database-simple.c
@@ -222,14 +222,21 @@ static int fill_data(simple_data *db, FILE *f) {
return pa_hashmap_size(db->map);
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_arch_suffix(void) {
+ /* Simple database binary file format is CPU dependent. */
+ return CANONICAL_HOST;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+ return ".simple";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
FILE *f;
- char *path;
simple_data *db;
- pa_assert(fn);
+ pa_assert(path);
- path = pa_sprintf_malloc("%s."CANONICAL_HOST".simple", fn);
errno = 0;
f = pa_fopen_cloexec(path, "r");
@@ -251,8 +258,6 @@ pa_database* pa_database_open(const char *fn, bool for_write) {
db = NULL;
}
- pa_xfree(path);
-
return (pa_database*) db;
}
diff --git a/src/pulsecore/database-tdb.c b/src/pulsecore/database-tdb.c
index 282f58061..5e7315901 100644
--- a/src/pulsecore/database-tdb.c
+++ b/src/pulsecore/database-tdb.c
@@ -97,18 +97,23 @@ finish:
return c;
}
-pa_database* pa_database_open(const char *fn, bool for_write) {
+const char* pa_database_get_arch_suffix(void) {
+ /* TDB binary file format is not dependent on system architecture */
+ return NULL;
+}
+
+const char* pa_database_get_filename_suffix(void) {
+ return ".tdb";
+}
+
+pa_database* pa_database_open_internal(const char *path, bool for_write) {
struct tdb_context *c;
- char *path;
- pa_assert(fn);
+ pa_assert(path);
- path = pa_sprintf_malloc("%s.tdb", fn);
if ((c = tdb_open_cloexec(path, 0, TDB_NOSYNC|TDB_NOLOCK, (for_write ? O_RDWR|O_CREAT : O_RDONLY), 0644)))
pa_log_debug("Opened TDB database '%s'", path);
- pa_xfree(path);
-
if (!c) {
if (errno == 0)
errno = EIO;
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
new file mode 100644
index 000000000..11f3d03c9
--- /dev/null
+++ b/src/pulsecore/database.c
@@ -0,0 +1,72 @@
+/***
+ This file is part of PulseAudio.
+
+ Copyright 2020 Igor V. Kovalenko
+
+ PulseAudio is free software; you can redistribute it and/or modify
+ it under the terms of the GNU Lesser General Public License as
+ published by the Free Software Foundation; either version 2.1 of the
+ License, or (at your option) any later version.
+
+ PulseAudio is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with PulseAudio; if not, see .
+***/
+
+#ifdef HAVE_CONFIG_H
+#include
+#endif
+
+#include
+
+#include
+#include
+#include
+
+#include "database.h"
+#include "core-error.h"
+
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write) {
+
+ const char *arch_suffix = pa_database_get_arch_suffix();
+ const char *filename_suffix = pa_database_get_filename_suffix();
+
+ char *machine_id = NULL, *filename_prefix, *full_path;
+
+ pa_database *f;
+
+ pa_assert(!arch_suffix || arch_suffix[0]);
+ pa_assert(filename_suffix && filename_suffix[0]);
+
+ if (prependmid && !(machine_id = pa_machine_id())) {
+ return NULL;
+ }
+
+ /* We include the host identifier in the file name because some database files are
+ * CPU dependent, and we don't want things to go wrong if we are on a multiarch system. */
+ filename_prefix = pa_sprintf_malloc("%s%s%s%s%s",
+ machine_id?:"", machine_id?"-":"",
+ fn,
+ arch_suffix?".":"", arch_suffix?:"");
+
+ full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
+
+ f = pa_database_open_internal(full_path, for_write);
+
+ if (f)
+ pa_log_info("Successfully opened '%s' database file '%s'.", fn, full_path);
+ else
+ pa_log("Failed to open '%s' database file '%s': %s", fn, full_path, pa_cstrerror(errno));
+
+ pa_xfree(full_path);
+ pa_xfree(filename_prefix);
+
+ /* deallocate machine_id if it was used to construct file name */
+ pa_xfree(machine_id);
+
+ return f;
+}
diff --git a/src/pulsecore/database.h b/src/pulsecore/database.h
index 3a1c7ceaf..fe2890577 100644
--- a/src/pulsecore/database.h
+++ b/src/pulsecore/database.h
@@ -38,8 +38,17 @@ typedef struct pa_datum {
void pa_datum_free(pa_datum *d);
-/* This will append a suffix to the filename */
-pa_database* pa_database_open(const char *fn, bool for_write);
+/* Database implementation; returns non-empty system architecture name string if database file format depends on system architecture, or NULL otherwise. */
+const char* pa_database_get_arch_suffix(void);
+/* Database implementation; returns non-empty database filename extension string */
+const char* pa_database_get_filename_suffix(void);
+
+/* This will attempt opening database file matching compiled CANONICAL_HOST identifier.
+ * If prependmid is true, file name is augmented with machine id prefix. */
+pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);
+
+/* Database implementation; opens specified database file using provided path. */
+pa_database* pa_database_open_internal(const char *path, bool for_write);
void pa_database_close(pa_database *db);
pa_datum* pa_database_get(pa_database *db, const pa_datum *key, pa_datum* data);
diff --git a/src/pulsecore/meson.build b/src/pulsecore/meson.build
index e8ce2931c..608273a17 100644
--- a/src/pulsecore/meson.build
+++ b/src/pulsecore/meson.build
@@ -14,6 +14,7 @@ libpulsecore_sources = [
'cpu-orc.c',
'cpu-x86.c',
'device-port.c',
+ 'database.c',
'ffmpeg/resample2.c',
'filter/biquad.c',
'filter/crossover.c',
From ae9d0cf307e731a02cdde38fb1632b20322f9f68 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 29 Nov 2020 15:16:26 +0300
Subject: [PATCH 175/872] database: use existing database matching same
architecture prefix
State database binary file format may depend on system architecture,
for instance gdbm binary format depends on architecture word size,
making x86 and x64 gdbm files incompatible.
If this is the case, it is handled by adding system architecture name to
database file name using automatically configured CANONICAL_HOST string.
Meson build define CANONICAL_HOST to be system architecture name, while
autotools build extends this with vendor and and operating system components.
Switch autotools build to use host_cpu for CANONICAL_HOST to match Meson
configuration. For backwards compatibility always use existing database file
matching CANONICAL_HOST prefix if it exists.
Part-of:
---
configure.ac | 2 +-
src/pulsecore/database.c | 38 ++++++++++++++++++++++++++++++++++++++
src/pulsecore/database.h | 3 ++-
3 files changed, 41 insertions(+), 2 deletions(-)
diff --git a/configure.ac b/configure.ac
index bd3a53367..2bc4b9002 100644
--- a/configure.ac
+++ b/configure.ac
@@ -57,7 +57,7 @@ AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [1:1:1])
AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:6:0])
AC_CANONICAL_HOST
-AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host", [Canonical host string.])
+AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host_cpu", [Canonical host system architecture string.])
AC_CHECK_PROG([STOW], [stow], [yes], [no])
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
index 11f3d03c9..43af6fc76 100644
--- a/src/pulsecore/database.c
+++ b/src/pulsecore/database.c
@@ -22,6 +22,7 @@
#endif
#include
+#include
#include
#include
@@ -37,6 +38,9 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
char *machine_id = NULL, *filename_prefix, *full_path;
+ DIR *database_dir = NULL;
+ struct dirent *de;
+
pa_database *f;
pa_assert(!arch_suffix || arch_suffix[0]);
@@ -53,6 +57,40 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
fn,
arch_suffix?".":"", arch_suffix?:"");
+ /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
+ database_dir = opendir(path);
+
+ if (database_dir) {
+ for (;;) {
+ errno = 0;
+ de = readdir(database_dir);
+ if (!de) {
+ if (errno) {
+ pa_log_warn("Unable to search for compatible database file, readdir() failed: %s", pa_cstrerror(errno));
+ /* can continue as if there is no matching database file candidate */
+ }
+
+ break;
+ }
+
+ if (pa_startswith(de->d_name, filename_prefix) && pa_endswith(de->d_name + strlen(filename_prefix), filename_suffix)) {
+ /* candidate filename found, replace filename_prefix with this one if match is not exact */
+
+ if (strlen(de->d_name) != strlen(filename_prefix) + strlen(filename_suffix)) {
+ pa_log_debug("Found compatible database file '%s/%s', using it", path, de->d_name);
+ pa_xfree(filename_prefix);
+ filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
+ }
+
+ break;
+ }
+ }
+
+ closedir(database_dir);
+ } else {
+ pa_log_warn("Unable to search for compatible database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+ }
+
full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
f = pa_database_open_internal(full_path, for_write);
diff --git a/src/pulsecore/database.h b/src/pulsecore/database.h
index fe2890577..cc16e535d 100644
--- a/src/pulsecore/database.h
+++ b/src/pulsecore/database.h
@@ -43,7 +43,8 @@ const char* pa_database_get_arch_suffix(void);
/* Database implementation; returns non-empty database filename extension string */
const char* pa_database_get_filename_suffix(void);
-/* This will attempt opening database file matching compiled CANONICAL_HOST identifier.
+/* This will attempt opening database file matching compiled CANONICAL_HOST implementation architecture name prefix,
+ * or new database file will be created and opened with implementation architecture name suffix if required.
* If prependmid is true, file name is augmented with machine id prefix. */
pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);
From 4ca8997aa0a7116cc60cf375a198e3e4dad7a4e6 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Sun, 20 Dec 2020 21:36:21 +0300
Subject: [PATCH 176/872] database: drop arch from newly created database file
name
Part-of:
---
src/pulsecore/database.c | 56 +++++++++++++++++++++-------------------
1 file changed, 29 insertions(+), 27 deletions(-)
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
index 43af6fc76..3e6f102f4 100644
--- a/src/pulsecore/database.c
+++ b/src/pulsecore/database.c
@@ -50,45 +50,47 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
return NULL;
}
- /* We include the host identifier in the file name because some database files are
- * CPU dependent, and we don't want things to go wrong if we are on a multiarch system. */
- filename_prefix = pa_sprintf_malloc("%s%s%s%s%s",
- machine_id?:"", machine_id?"-":"",
- fn,
- arch_suffix?".":"", arch_suffix?:"");
+ /* Database file name starts with ${machine_id}-${fn} */
+ if (machine_id)
+ filename_prefix = pa_sprintf_malloc("%s-%s", machine_id, fn);
+ else
+ filename_prefix = pa_xstrdup(fn);
- /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
- database_dir = opendir(path);
+ if (arch_suffix) {
+ /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
+ database_dir = opendir(path);
- if (database_dir) {
- for (;;) {
- errno = 0;
- de = readdir(database_dir);
- if (!de) {
- if (errno) {
- pa_log_warn("Unable to search for compatible database file, readdir() failed: %s", pa_cstrerror(errno));
- /* can continue as if there is no matching database file candidate */
+ if (database_dir) {
+ for (;;) {
+ errno = 0;
+ de = readdir(database_dir);
+ if (!de) {
+ if (errno) {
+ pa_log_warn("Unable to search for compatible database file, readdir() failed: %s", pa_cstrerror(errno));
+ /* can continue as if there is no matching database file candidate */
+ }
+
+ break;
}
- break;
- }
+ if (pa_startswith(de->d_name, filename_prefix)
+ && de->d_name[strlen(filename_prefix)] == '.'
+ && pa_startswith(de->d_name + strlen(filename_prefix) + 1, arch_suffix)
+ && pa_endswith(de->d_name + strlen(filename_prefix) + 1 + strlen(arch_suffix), filename_suffix)) {
- if (pa_startswith(de->d_name, filename_prefix) && pa_endswith(de->d_name + strlen(filename_prefix), filename_suffix)) {
- /* candidate filename found, replace filename_prefix with this one if match is not exact */
+ /* candidate filename found, replace filename_prefix with this one */
- if (strlen(de->d_name) != strlen(filename_prefix) + strlen(filename_suffix)) {
pa_log_debug("Found compatible database file '%s/%s', using it", path, de->d_name);
pa_xfree(filename_prefix);
filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
+ break;
}
-
- break;
}
- }
- closedir(database_dir);
- } else {
- pa_log_warn("Unable to search for compatible database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+ closedir(database_dir);
+ } else {
+ pa_log_warn("Unable to search for compatible database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+ }
}
full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
From 7115023c510690e473c03f51e3e5eaff9c73f8b7 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Mon, 21 Dec 2020 19:27:53 +0300
Subject: [PATCH 177/872] database: pick old database file from any arch
Part-of:
---
src/pulsecore/database-gdbm.c | 8 -----
src/pulsecore/database-simple.c | 5 ---
src/pulsecore/database-tdb.c | 5 ---
src/pulsecore/database.c | 57 +++++++++++++++------------------
src/pulsecore/database.h | 21 +++++++++---
5 files changed, 42 insertions(+), 54 deletions(-)
diff --git a/src/pulsecore/database-gdbm.c b/src/pulsecore/database-gdbm.c
index cd03405f5..b39f7dee2 100644
--- a/src/pulsecore/database-gdbm.c
+++ b/src/pulsecore/database-gdbm.c
@@ -59,14 +59,6 @@ void pa_datum_free(pa_datum *d) {
pa_zero(d);
}
-const char* pa_database_get_arch_suffix(void) {
- /* We include the host identifier in the file name because gdbm
- * files are CPU dependent, and we don't want things to go wrong
- * if we are on a multiarch system. */
-
- return CANONICAL_HOST;
-}
-
const char* pa_database_get_filename_suffix(void) {
return ".gdbm";
}
diff --git a/src/pulsecore/database-simple.c b/src/pulsecore/database-simple.c
index ebfbe4c61..96af8e098 100644
--- a/src/pulsecore/database-simple.c
+++ b/src/pulsecore/database-simple.c
@@ -222,11 +222,6 @@ static int fill_data(simple_data *db, FILE *f) {
return pa_hashmap_size(db->map);
}
-const char* pa_database_get_arch_suffix(void) {
- /* Simple database binary file format is CPU dependent. */
- return CANONICAL_HOST;
-}
-
const char* pa_database_get_filename_suffix(void) {
return ".simple";
}
diff --git a/src/pulsecore/database-tdb.c b/src/pulsecore/database-tdb.c
index 5e7315901..6605ed8fc 100644
--- a/src/pulsecore/database-tdb.c
+++ b/src/pulsecore/database-tdb.c
@@ -97,11 +97,6 @@ finish:
return c;
}
-const char* pa_database_get_arch_suffix(void) {
- /* TDB binary file format is not dependent on system architecture */
- return NULL;
-}
-
const char* pa_database_get_filename_suffix(void) {
return ".tdb";
}
diff --git a/src/pulsecore/database.c b/src/pulsecore/database.c
index 3e6f102f4..8b3b89c56 100644
--- a/src/pulsecore/database.c
+++ b/src/pulsecore/database.c
@@ -33,7 +33,6 @@
pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write) {
- const char *arch_suffix = pa_database_get_arch_suffix();
const char *filename_suffix = pa_database_get_filename_suffix();
char *machine_id = NULL, *filename_prefix, *full_path;
@@ -43,7 +42,6 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
pa_database *f;
- pa_assert(!arch_suffix || arch_suffix[0]);
pa_assert(filename_suffix && filename_suffix[0]);
if (prependmid && !(machine_id = pa_machine_id())) {
@@ -56,41 +54,38 @@ pa_database* pa_database_open(const char *path, const char *fn, bool prependmid,
else
filename_prefix = pa_xstrdup(fn);
- if (arch_suffix) {
- /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
- database_dir = opendir(path);
+ /* Search for existing database directory entry name matching architecture suffix and filename suffix. */
+ database_dir = opendir(path);
- if (database_dir) {
- for (;;) {
- errno = 0;
- de = readdir(database_dir);
- if (!de) {
- if (errno) {
- pa_log_warn("Unable to search for compatible database file, readdir() failed: %s", pa_cstrerror(errno));
- /* can continue as if there is no matching database file candidate */
- }
-
- break;
+ if (database_dir) {
+ for (;;) {
+ errno = 0;
+ de = readdir(database_dir);
+ if (!de) {
+ if (errno) {
+ pa_log_warn("Unable to search for existing database file, readdir() failed: %s", pa_cstrerror(errno));
+ /* can continue as if there is no matching database file candidate */
}
- if (pa_startswith(de->d_name, filename_prefix)
- && de->d_name[strlen(filename_prefix)] == '.'
- && pa_startswith(de->d_name + strlen(filename_prefix) + 1, arch_suffix)
- && pa_endswith(de->d_name + strlen(filename_prefix) + 1 + strlen(arch_suffix), filename_suffix)) {
-
- /* candidate filename found, replace filename_prefix with this one */
-
- pa_log_debug("Found compatible database file '%s/%s', using it", path, de->d_name);
- pa_xfree(filename_prefix);
- filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
- break;
- }
+ break;
}
- closedir(database_dir);
- } else {
- pa_log_warn("Unable to search for compatible database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
+ if (pa_startswith(de->d_name, filename_prefix)
+ && de->d_name[strlen(filename_prefix)] == '.'
+ && pa_endswith(de->d_name + strlen(filename_prefix) + 1, filename_suffix)) {
+
+ /* candidate filename found, replace filename_prefix with this one */
+
+ pa_log_debug("Found existing database file '%s/%s', using it", path, de->d_name);
+ pa_xfree(filename_prefix);
+ filename_prefix = pa_xstrndup(de->d_name, strlen(de->d_name) - strlen(filename_suffix));
+ break;
+ }
}
+
+ closedir(database_dir);
+ } else {
+ pa_log_warn("Unable to search for existing database file, failed to open directory %s: %s", path, pa_cstrerror(errno));
}
full_path = pa_sprintf_malloc("%s" PA_PATH_SEP "%s%s", path, filename_prefix, filename_suffix);
diff --git a/src/pulsecore/database.h b/src/pulsecore/database.h
index cc16e535d..7fa489c67 100644
--- a/src/pulsecore/database.h
+++ b/src/pulsecore/database.h
@@ -38,14 +38,25 @@ typedef struct pa_datum {
void pa_datum_free(pa_datum *d);
-/* Database implementation; returns non-empty system architecture name string if database file format depends on system architecture, or NULL otherwise. */
-const char* pa_database_get_arch_suffix(void);
/* Database implementation; returns non-empty database filename extension string */
const char* pa_database_get_filename_suffix(void);
-/* This will attempt opening database file matching compiled CANONICAL_HOST implementation architecture name prefix,
- * or new database file will be created and opened with implementation architecture name suffix if required.
- * If prependmid is true, file name is augmented with machine id prefix. */
+/* Opens a database file. The file is loaded from the directory indicated by
+ * path. The file name is constructed by using fn as the base and then adding
+ * several parts:
+ * 1) If prependmid is true, the machine id is prepended to the file name.
+ * 2) The database implementation specific suffix is added.
+ * 3) Older versions of PulseAudio in some cases added the CPU architecture
+ * to the file name, which was later deemed unnecessary, but for
+ * compatibility reasons we still need to look for those files, so we scan
+ * the directory for files that match the prefix (possible machine id plus
+ * fn) and the suffix, and if any matches are found, we use the first one.
+ *
+ * When no existing file is found, we create a new file for the database
+ * (without the CPU architecture part in the name).
+ *
+ * For a read-only database, set for_write to false. */
+
pa_database* pa_database_open(const char *path, const char *fn, bool prependmid, bool for_write);
/* Database implementation; opens specified database file using provided path. */
From c2ae56a73cac813c95973e534a011d38a6a9e891 Mon Sep 17 00:00:00 2001
From: "Igor V. Kovalenko"
Date: Mon, 21 Dec 2020 19:55:00 +0300
Subject: [PATCH 178/872] database: clean up remaining references to
CANONICAL_HOST
Part-of:
---
configure.ac | 3 ---
meson.build | 1 -
src/daemon/main.c | 1 -
3 files changed, 5 deletions(-)
diff --git a/configure.ac b/configure.ac
index 2bc4b9002..155e5653e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -56,9 +56,6 @@ AC_SUBST(LIBPULSE_SIMPLE_VERSION_INFO, [1:1:1])
# info x:y:z always will hold x=z
AC_SUBST(LIBPULSE_MAINLOOP_GLIB_VERSION_INFO, [0:6:0])
-AC_CANONICAL_HOST
-AC_DEFINE_UNQUOTED([CANONICAL_HOST], "$host_cpu", [Canonical host system architecture string.])
-
AC_CHECK_PROG([STOW], [stow], [yes], [no])
AS_IF([test "x$STOW" = "xyes" && test -d /usr/local/stow], [
diff --git a/meson.build b/meson.build
index 23e04ef46..bff13cc16 100644
--- a/meson.build
+++ b/meson.build
@@ -125,7 +125,6 @@ cdata = configuration_data()
cdata.set_quoted('PACKAGE', 'pulseaudio')
cdata.set_quoted('PACKAGE_NAME', 'pulseaudio')
cdata.set_quoted('PACKAGE_VERSION', pa_version_str)
-cdata.set_quoted('CANONICAL_HOST', target_machine.cpu_family())
cdata.set('PA_MAJOR', pa_version_major)
cdata.set('PA_MINOR', pa_version_minor)
cdata.set('PA_API_VERSION', pa_api_version)
diff --git a/src/daemon/main.c b/src/daemon/main.c
index 1032390ca..a424d9ef9 100644
--- a/src/daemon/main.c
+++ b/src/daemon/main.c
@@ -922,7 +922,6 @@ int main(int argc, char *argv[]) {
pa_set_env_and_record("PULSE_SYSTEM", conf->system_instance ? "1" : "0");
pa_log_info("This is PulseAudio %s", PACKAGE_VERSION);
- pa_log_debug("Compilation host: %s", CANONICAL_HOST);
pa_log_debug("Compilation CFLAGS: %s", PA_CFLAGS);
#ifdef HAVE_LIBSAMPLERATE
From b1bdd27a6c7828ed4c055986b89fb17e90e02c2a Mon Sep 17 00:00:00 2001
From: Patrick Gaskin
Date: Sun, 3 Jan 2021 03:29:35 -0500
Subject: [PATCH 179/872] cli: Fix crash when using .include with an empty
directory
This would previously fail the size > 0 assertion in pa_xmalloc.
Part-of:
---
src/pulsecore/cli-command.c | 44 ++++++++++++++++++-------------------
1 file changed, 22 insertions(+), 22 deletions(-)
diff --git a/src/pulsecore/cli-command.c b/src/pulsecore/cli-command.c
index c5a21ed93..5dc2ac6b9 100644
--- a/src/pulsecore/cli-command.c
+++ b/src/pulsecore/cli-command.c
@@ -2118,34 +2118,34 @@ int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *b
}
closedir(d);
+ if ((count = pa_dynarray_size(files))) {
+ sorted_files = pa_xnew(char*, count);
+ for (i = 0; i < count; ++i)
+ sorted_files[i] = pa_dynarray_get(files, i);
+ pa_dynarray_free(files);
- count = pa_dynarray_size(files);
- sorted_files = pa_xnew(char*, count);
- for (i = 0; i < count; ++i)
- sorted_files[i] = pa_dynarray_get(files, i);
- pa_dynarray_free(files);
-
- for (i = 0; i < count; ++i) {
- for (unsigned j = 0; j < count; ++j) {
- if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
- char *tmp = sorted_files[i];
- sorted_files[i] = sorted_files[j];
- sorted_files[j] = tmp;
+ for (i = 0; i < count; ++i) {
+ for (unsigned j = 0; j < count; ++j) {
+ if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
+ char *tmp = sorted_files[i];
+ sorted_files[i] = sorted_files[j];
+ sorted_files[j] = tmp;
+ }
}
}
- }
- for (i = 0; i < count; ++i) {
- if (!failed) {
- if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
- failed = true;
+ for (i = 0; i < count; ++i) {
+ if (!failed) {
+ if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
+ failed = true;
+ }
+
+ pa_xfree(sorted_files[i]);
}
-
- pa_xfree(sorted_files[i]);
+ pa_xfree(sorted_files);
+ if (failed)
+ return -1;
}
- pa_xfree(sorted_files);
- if (failed)
- return -1;
}
} else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
return -1;
From 5d42d861e320c2e4c1f9bca7556cddc16250f5f0 Mon Sep 17 00:00:00 2001
From: Fabian Affolter
Date: Sat, 12 Dec 2020 16:44:16 +0000
Subject: [PATCH 180/872] Translated using Weblate (German)
Currently translated at 100.0% (526 of 526 strings)
Translation: pulseaudio/pulseaudio
Translate-URL: https://translate.fedoraproject.org/projects/pulseaudio/pulseaudio/de/
Part-of: