Initial implementation of Wayland AirPlay desktop sharing

This commit is contained in:
Niklas Haiden
2026-09-09 22:04:30 +02:00
commit 7cda80d840
18 changed files with 11044 additions and 0 deletions
+42
View File
@@ -0,0 +1,42 @@
//! Interactive pairing smoke test, sharing the GUI's exact protocol implementation.
use airplay_discovery::{Discovery, ServiceBrowser};
use anyhow::Context;
use spielab::pairing::{ControlSession, CredentialStore};
use std::{
io::{self, Write},
path::PathBuf,
time::Duration,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let name = std::env::args()
.nth(1)
.context("Usage: cargo run --example pair -- 'Receiver name'")?;
let state = std::env::var_os("SPIELAB_STATE_DIR")
.map(PathBuf::from)
.context("Set SPIELAB_STATE_DIR to the same credential directory as the GUI")?;
let store = CredentialStore::new(state)?;
let browser = ServiceBrowser::new()?;
let device = browser
.scan(Duration::from_secs(5))
.await?
.into_iter()
.find(|device| device.name == name)
.context("Receiver not found")?;
let mut session = ControlSession::open(device).await?;
if let Some(credentials) = store.load(&session.device)? {
session.verify(&credentials).await?;
} else {
session.request_pin().await?;
print!("Enter the code shown on Apple TV: ");
io::stdout().flush()?;
let mut pin = String::new();
io::stdin().read_line(&mut pin)?;
let credentials = session.pair(pin.trim()).await?;
store.save(&session.device, &credentials)?;
}
println!("Authenticated: encrypted OPTIONS round trip succeeded.");
session.transport.close().await?;
Ok(())
}