Skip to main content

Pipewire experiments

Architettura di OSS

diagramma OSS

Open Sound System offriva un'interfaccia in puro stile "è tutto un file": le applicazioni OSS utilizzavano /dev/dsp e /dev/audio, esposti dal modulo kernel, per accedere direttamente all'hardware, in modo esclusivo e in formato grezzo. Niente mixing software, niente volume... niente, insomma.

Architettura di ALSA

diagramma OSS

ALSA (Advanced Linux Sound Architecture) aggiunge un livello di astrazione allo stack audio Linux: le applicazioni possono usare una libreria per parlare con l'interfaccia esposta dal kernel (una API, in gergo tecnico), che a sua volta comunica con l'hardware audio.

Supporta hardware MIDI, fino a 8 schede audio simultaneamente e un sistema di plugin che lo rende molto più versatile del predecessore.

Demo: ALSA riconosce una scheda audio

su Debian Testing, installa i pacchetti libasound2, alsa-tools e alsa-utils.

Poi esegui

$ aplay -l

Demo: registrazione e playback con aplay/arecord

$ arecord -f cd > prova.wav
$ aplay prova.wav

Mettiamo che io voglia avere più applicazioni che riproducono audio nello stesso momento: uno scenario piuttosto normale, e.g. un player musicale e una scheda del browser, o una notifica del sistema.

Demo: (tentativo di) riproduzione di due file audio in contemporanea

Per riprodurre l'esperimento occorre bypassare il plugin dmix (mixing software, attivo di default).

Crea il file /etc/asound.conf:

pcm.!default {
type plug
slave.pcm hw
}

Ora prova ad eseguire aplay prova.wav in due sessioni parallele

PulseAudio e JACK

La principale novità dei server audio è nell'architettura.

diagramma OSS

C'è un processo principale, il server appunto, che esegue in background, e i diversi client (le applicazioni) vi si connettono per avere accesso alle risorse audio.

Il server si interfaccia a sua volta con il backend audio, come ALSA, per parlare con l'hardware. In questo modo c'è un singolo processo che parla con l'hardware, e il problema di mixare insieme l'audio di più applicazioni si sposta nel server audio.

Le due implementazioni di server audio più diffuse sono PulseAudio e JACK, e non a caso si concentrano su priorità differenti.

PulseAudio è più per il consumer [il comune mortale]. Offre diversi tool grafici per gestire al volo le applicazioni connesse, con funzionalità comode come la regolazione del volume per ogni processo.

Demo: interfaccia grafica di `pavucontrol` per il controllo del volume dei singoli processi

Attraverso i moduli, PulseAudio implementa anche qualche funzionalità in più, come il supporto al bluetooth e la creazione di input/output audio virtuali.

Demo: modulo loopback di PA per collegare tra loro un source e un sink

Ottenere il source da usare (e.g. un microfono):

$ pactl list sources short

55	alsa_output.pci-0000_05_00.6.HiFi__Speaker__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
56	alsa_input.pci-0000_05_00.6.HiFi__Mic2__source	PipeWire	s32le 2ch 48000Hz	SUSPENDED
57	alsa_input.pci-0000_05_00.6.HiFi__Mic1__source	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4506	alsa_output.pci-0000_05_00.1.HiFi__HDMI4__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4507	alsa_output.pci-0000_05_00.1.HiFi__HDMI3__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4508	alsa_output.pci-0000_05_00.1.HiFi__HDMI2__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4509	alsa_output.pci-0000_05_00.1.HiFi__HDMI1__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4804	bluez_input.80:C3:BA:4B:D9:88	PipeWire	float32le 1ch 48000Hz	SUSPENDED
4807	bluez_output.80_C3_BA_4B_D9_88.1.monitor	PipeWire	s24le 2ch 48000Hz	RUNNING

...in questo caso sarebbe alsa_input.pci-0000_05_00.6.HiFi__Mic2__source

Ottenere il sink da usare (e.g. altoparlanti/cuffie):

$ pactl list sinks short

55	alsa_output.pci-0000_05_00.6.HiFi__Speaker__sink	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4506	alsa_output.pci-0000_05_00.1.HiFi__HDMI4__sink	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4507	alsa_output.pci-0000_05_00.1.HiFi__HDMI3__sink	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4508	alsa_output.pci-0000_05_00.1.HiFi__HDMI2__sink	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4509	alsa_output.pci-0000_05_00.1.HiFi__HDMI1__sink	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4807	bluez_output.80_C3_BA_4B_D9_88.1	PipeWire	s24le 2ch 48000Hz	RUNNING

...in questo caso sarebbe alsa_output.pci-0000_05_00.6.HiFi__Speaker__sink

Collegarli tra loro (in questo caso ottenendo l'effetto echo/feedback):

$ pactl load-module module-loopback source=alsa_input.pci-0000_05_00.6.HiFi__Mic2__source sink=alsa_output.pci-0000_05_00.6.HiFi__Speaker__sink

JACK è un altro sound server e si rivolge al mondo del pro-audio. è incentrato su bassa latenza e gestione patchbay dei dispositivi (ovvero con modello a grafo).

Demo: grafo di JACK

Puoi mostrare il grafo di JACK con qjackctl

PipeWire: l'anello di congiunzione

PipeWire nasce nel 2015 da un progetto già iniziato in precedenza chiamato PulseVideo, che prometteva di uniformare la gestione audio e video su Linux.

L'architettura di PipeWire è simile a quella di PulseAudio: c'è un processo centrale che fa da server chiamato demone, e i vari processi che vi si connettono fanno da client.

diagramma OSS

I client in questo caso possono essere applicazioni PipeWire native, applicazioni PulseAudio o anche JACK, e tutto sarà gestito dallo stesso server di PipeWire.

La comunicazione client/server di PipeWire viaggia su un socket Unix e i messaggi seguono un protocollo chiamato PipeWire Native Protocol. Questo può incapsulare un messaggio PulseAudio, ALSA, JACK o chicchessia, e verrà poi decodificato dal modulo apposito caricato dal demone PipeWire.

Demo: installazione dei pacchetti pw e output di pactl

  • installare pipewire pipewire-alsa pipewire-pulse pipewire-jack
  • mostrare l'output di pactl list sources short e/o pactl list sinks short
55	alsa_output.pci-0000_05_00.6.HiFi__Speaker__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
56	alsa_input.pci-0000_05_00.6.HiFi__Mic2__source	PipeWire	s32le 2ch 48000Hz	SUSPENDED
57	alsa_input.pci-0000_05_00.6.HiFi__Mic1__source	PipeWire	s32le 2ch 48000Hz	RUNNING
4506	alsa_output.pci-0000_05_00.1.HiFi__HDMI4__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4507	alsa_output.pci-0000_05_00.1.HiFi__HDMI3__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4508	alsa_output.pci-0000_05_00.1.HiFi__HDMI2__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4509	alsa_output.pci-0000_05_00.1.HiFi__HDMI1__sink.monitor	PipeWire	s32le 2ch 48000Hz	SUSPENDED
4804	bluez_input.80:C3:BA:4B:D9:88	PipeWire	float32le 1ch 48000Hz	SUSPENDED
4807	bluez_output.80_C3_BA_4B_D9_88.1.monitor	PipeWire	s24le 2ch 48000Hz	RUNNING
Demo: grafo PipeWire

Dipendenze da installare: pipewire, pipewire-pulse, pipewire-jack, pipewire-alsa e helvum o qpwgraph

Per mostrare il grafo di PipeWire, usiamo Helvum o qpwgraph:

Demo: lancio di una applicazione JACK e cambiamento del grafo PW

Installa e lancia qtractor

PipeWire si è configurato come se fosse una scheda audio fisica, e come server PulseAudio a tutti gli effetti, quindi è pronto per scambiare audio in modo trasparente con client nativi ALSA e PulseAudio, che non si accorgeranno neanche della differenza.

Demo: alsamixer mostra una scheda audio pw

  • eseguire alsamixer e se necessario switchare scheda audio con F6, fino a mostrare una scheda chiamata PipeWire

Tutto molto bello.

Entità di pw

Sotto la scocca, PipeWire mantiene una lista di oggetti che rappresentano tutte le entità che abbiamo visto nel grafo e le relazioni tra di loro. Vediamo le più importanti con un esempio.

diagramma entità pw

Ho un'applicazione che riproduce dell'audio, per esempio una scheda di Firefox. Per prima cosa, PipeWire crea un nodo per il client, in questo caso il processo di Firefox. In generale, un nodo è una qualunque entità che riproduce o genera audio. Può essere un microfono, una cuffia, una scheda audio [device], o anche un'applicazione [client] come in questo caso. Mettiamo appunto che l'audio venga riprodotto attraverso la scheda audio integrata: per PipeWire, anche questa sarà un nodo. I nodi possono comunicare tra loro attraverso le porte, cioè punti di ingresso o di uscita. Il nodo Firefox avrà quindi una porta per far uscire l'audio, mentre il nodo della scheda audio avrà una porta per far entrare audio negli altoparlanti e un'altra per far uscire l'audio proveniente dal microfono. Tra due porte si può creare un link, in modo che l'audio in uscita da un nodo entri in un altro o viceversa. In questo caso vogliamo che l'audio che esce da Firefox entri nella scheda audio, quindi vogliamo che ci sia un link tra la porta in uscita del nodo di Firefox e la porta in entrata del nodo della scheda audio.

Session management

Vi potreste star chiedendo come fa PipeWire a decidere quali nodi, quali porte e soprattutto quali link creare. Come vi avevo anticipato, PipeWire non gestisce direttamente il grafo: se ne occupa ilIl session manager, che ha il compito di rilevare i dispositivi e i client connessi e configurarli per poterli usare con PipeWire. ÈCollateralmente, è la componente che può implementare il un pezzosistema di software separato da PipeWire ma fondamentalepermessi per ildecidere suoquali correttoprocessi funzionamento.possono Gliavere sviluppatoriaccesso offronoa quali risorse.

Esiste un'implementazione dimostrativa [un po' come Weston per Wayland] chiamata pipewire-session-manager,manager, e ognuno è libero di utilizzare la propria. Lo standard de facto, almeno sulle distro che ad oggi adottano PipeWire come sistema audio/video di default,facto è Wireplumber.wireplumber.

Demo: il session manager crea nodi, porte e link quando si collega un nuovo dispositivo

Per darvi un'idea di quello che fa WirePlumber dietro le quinte, teniamoTeniamo d'occhio l'output di pw-cli mentre Firefox riproduce dell'audio e colleghiamo un nuovo dispositivo audio, in questo caso degli auricolari Bluetooth.

Come vedete

PipeWire rileva un nuovo device e WirePlumber inizia il suo "sporco lavorolavoro" di configurazione: si collega a PipeWire come client e crea i nodi per il nuovo dispositivo, e infatti eccoli qui anche nel grafo. Fatemi un attimo fare qualche magheggio in modo che ci logghi solo gli oggetti creati e rimossi [altrimenti non si capisce una ceppa]. Se ora dico al SO di switchare l'output audio al nuovo dispositivo, ecco di nuovo WirePlumber all'opera: ha rimosso i link tra Firefox e il vecchio output e li ha creati con il nuovo output. Tac [si vede anche nel grafo]. Stessa cosa chiaramente quando lo vado a disconnettere. Tac [non ci sono più i nodi nel grafo].

Dato che si occupa di collegare tra loro client

Portals e dispositivi audio, il session manager decide anche quali processi possono avere accesso a quali risorse: in pratica implementa un sistema di permessi, molto più granulare rispetto a PulseAudio e JACK.

Il modello di PulseAudio è una sorta di fiducia implicita: c'è un'istanza per ogni utente e tutti i processi lanciati da quell'utente possono accedere a tutte le risorse. JACK è ancora più liberale perché il focus è sulla performance, quindi ognuno fa un po' quello che vuole quando si tratta di riprodurre o registrare.

PipeWire tenta di superare questo meccanismo "sulla fiducia" implementando un vero e proprio sistema di permessi, perché quando si tratta di accedere alle risorse di sistema, è sempre meglio non fidarsi di nessuno. Sapete a chi voi non dovreste mai dare la vostra fiducia, implicita o esplicita? A una rete non protetta, o al vostro ISP poco discreto, ed è per questo che esiste NordVPN che ha sponsorizzato questa porzione di video.

permessi

Diversamente dai suoi cugini più datati, in PipeWire ogni client può avere o non avere il permesso di accedere a ogni singolo oggetto. Questo almeno in teoria. In pratica, allo stato attuale, ci sono solo due casi:

accesso
  1. Accesso diretto, senza restrizioni, che funziona un po' come PulseAudio ["sulla fiducia"], e
  2. accesso
  3. Accesso da sandbox., Sì perché, ora che ci sono i permessi di mezzo, come fannoper le applicazioni inSnap, sandbox come SnapFlatpak e Flatpakcompagnia.
  4. ad
accedere alle risorse audio/video?

È per risolvere questoil 2' problema che gli sviluppatori di PipeWire hanno introdotto il supporto ai portals, letteralmente "portali" che danno accesso a svariate risorse del SO, dal filesystem al network, fino alla cattura dello schermo, che altrimenti non sarebbe possibile.schermo.

Un portal è un servizio che esegue nel SO e che fa da ponte tra una app in sandbox e, in questo caso, il server di PipeWire. In questo modo le app isolate sannosi sempre di doversi rivolgererivolgono al portal, e quest'ultimoche può gestire come vuole i permessi,permessi consentendo o negando l'accesso alle risorse aper ciascuna applicazione.

PipeWire per il video

Ritroviamo il meccanismo dei portals anche per la gestione del video in PipeWire. Come ricorderete, infatti, uniformare audio e video era un po' il pallino degli sviluppatori, almeno agli albori del progetto. Già nel grafo noterete che, in effetti, un nodo per la webcam io lo vedo. Vediamo un attimo come funziona accederci tramite portal.

Demo: c'C'è un nodo webcam nel grafo
  • aprire

    Apri Helvum/qpwgraph e ricordarenota la presenza di un nodo relativo a una webcam collegata al PC,webcam, inizialmente non connesso ad altri nodi

Prendiamo

Demo: Firefox chiede il permesso di usare la webcam

Il supporto per esempiola [camera via PipeWire è ancora opt-in in Firefox, così come in Chrome/Chromium.

Firefox è nativa,generalmente nativa e non esegue in sandbox, ma può essere configurato per accedere a webcam e schermo tramite portal, quindi ce lo facciamo andare bene per questo esempio].portal

Demo: Firefox chiede il permesso di usare la webcam
  • [senza mostrare, lo si riprende dopo] visitareVisita about:config in FF e impostareimposta la variabile media.webrtc.camera.allow-pipewire a true
  • visitareVisita una pagina web che richiede l'accesso alla webcam, come quella di test di Mozilla [linkata]
  • notareNota che viene richiesto il permesso all'uso di una webcam
  • tornareTorna su Helvum/qpwgraph e notarenota il collegamento del nodo webcam a FF

Quando una pagina richiede l'accesso alla webcam, Firefox fa una richiesta D-Bus al camera portal.

[una specie di mega socket condivisa da tutti i processi su Linux, semplificando al massimo]: prima chiede quali siano le webcam disponibili, e poi chiede di poterci accedere.

Se l'utente accetta, il portal comunica a PipeWire di creare un link tra il nodo della webcam e Firefox, in modo che quest'ultimo riceva lo stream video.

E il bello è che se apro un'altra scheda, posso fare la stessa cosa un'altra volta.

Demo: posso aprire un'altra scheda e avere accesso simultaneo alla webcam da due schede
  • aprire la stessa pagina web su un'altra scheda e notare come ho accesso alla webcam su entrambe

PipeWire si occupa di sdoppiare il video e distribuirlo ai nodi connessi, esattamente come fa per l'audio, ed esattamente come ci aspetteremmo che fosse normale (!). I permessi sono gestiti dal portal, che fa da mediatore tra il client (Firefox) e la risorsa richiesta (la webcam), chiedendo conferma all'utente prima di concedere l'accesso.

Se vi state chiedendo come mai voi osserviate un comportamento diverso se provate a fare la stessa cosa, ve lo spiego subito. Il supporto per la camera via PipeWire è ancora opt-in in Firefox, così come in Chrome/Chromium.

Demo: come impostareImpostare FF per usare pw per la webcam

  • mostrare

    Notare come si imposta la variabile media.webrtc.camera.allow-pipewire a true in about:config, come sopra

Demo: Condivisione schermo con FF

QuestioneIn diversaquesto per la condivisione dello schermo, dovecaso, PipeWire è invece già il default, poichédefault: è l'unico modo per convidividere lo schermo sui sistemi che utilizzanosu Wayland.

Anche in questo caso l'accesso avviene tramite portal, stavolta un desktop portal, che tra le altre cose gestisce la possibilità di catturare lo schermo.

[opzionale] Demo: condivisione schermo con FF

  • mostrare brevemente la condivisione dello schermo, sempre con la stessa pagina di test di Mozilla su FF

Qui purtroppo si apre una parentesi piuttosto ampia sulla compatibilità dei diversi compositor/DE alla condivisione delle risorse tramite portal.

Ogni compositor/DE implementa il proprio backend per il desktop portal, e diversi backend supportano diverse funzionalità di condivisione: alcuni permettono la condivisione di singole finestre, altri solo dell'intero schermo o di una porzione, altri meno gettonati non ne vogliono ancora sapere.porzione.

Conclusioni

Ad oggi, PipeWire è in forte crescita. È già ormai il default nelle distribuzioni più diffuse: in Fedora dalla versione 34, nel 2021, in Ubuntu dalla 22.10, nel 2022. Il progetto è ancora lontano dalle promesse di gestione unificata

Fonti e trasparente di audio e video, e mancano alcuni pezzi che dovrebbero contraddistinguerlo dalle soluzioni che va a rimpiazzare, come la gestione dei permessi, che nessun session manager ha ancora implementato in maniera stabile. Aggiungendoci il fatto che esiste un solo session manager mantenuto [WirePlumber] e che il supporto al video e alla condivisione schermo è ancora frammentato e dipendente dal compositor, la sua adozione non è così smooth come voleva essere. Per quanto acerbo, sta ricevendo però costante attenzione e sviluppo, attestandosi come uno di quei rari casi nel mondo Linux in cui un progetto aspira a diventare lo standard, e magari ci riesce pure, invece di diventare l'ennesimo tassello di un puzzle sempre più grande e di cui non si vede più l'immagine completa.

Risorse

  • immagine per copertina https://pipewire.org/assets/pipewire.gif (dominio pubblico CC0), già upscaled sulla

    homepage del progetto

  • spiegone audio su Linux che include anche cenni a PCM, resampling, mixing e altro

    https://www.reddit.com/r/headphones/comments/k8nom8/a_complete_guide_of_and_debunking_of_audio_on/
  • pagina test di Mozilla per camera/schermo https://mozilla.github.io/webrtc-landing/gum_test.html
  • Wiki

    wiki di Arch sui desktop-portal, con tabella di compatibilità

    https://wiki.archlinux.org/title/XDG_Desktop_Portal

Referenze