jellyfin-radio/src/main.rs

110 lines
3.2 KiB
Rust
Raw Normal View History

2024-03-17 19:22:12 +00:00
use envconfig::Envconfig;
use hyper::server::conn::http1;
use hyper_util::rt::TokioIo;
use std::{net::SocketAddr, time::Duration};
use tokio::net::TcpListener;
mod jellyfin;
mod player;
mod streamer;
#[derive(Envconfig, Clone)]
struct Config {
#[envconfig(from = "JELLYFIN_URL")]
pub jellyfin_url: String,
#[envconfig(from = "JELLYFIN_API_KEY")]
pub jellyfin_api_key: String,
#[envconfig(from = "JELLYFIN_COLLECTION_NAME")]
pub jellyfin_collection_name: String,
#[envconfig(from = "PORT", default = "3000")]
pub port: u16,
#[envconfig(from = "HOST", default = "0.0.0.0")]
pub host: String,
#[envconfig(from = "SONG_PREFETCH", default = "2")]
pub song_prefetch: u32,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let config = Config::init_from_env().unwrap();
let client =
jellyfin::JellyfinClient::new(config.jellyfin_url.into(), config.jellyfin_api_key.into());
let admin_user = client
.users()
.await?
.into_iter()
.filter(|u| u.policy.is_administrator)
.next()
.expect("No Admin user found!");
let matched_collection = client
.views(&admin_user.id)
.await?
.into_iter()
.filter(|c| c.name == config.jellyfin_collection_name)
.next()
.expect("Collection not found!");
let addr: SocketAddr = SocketAddr::from((
config.host.parse::<std::net::Ipv4Addr>().unwrap(),
config.port,
));
let (streamer_backend, mut streamer_manager) = streamer::StreamerBackend::start()?;
tokio::task::spawn(async move {
let (player, mut controller) = player::Player::new(config.song_prefetch);
let player = Box::new(player);
streamer_manager.play(player);
loop {
controller.wait_for_queue().await;
println!("Queuing song");
loop {
let result = async {
let item = client
.random_audio(&admin_user.id, &matched_collection.id)
.await?;
println!("Fetching {} - {}", item.artists.join(","), item.name);
let sound = client.fetch_audio(item).await?;
println!("Fetched Song!");
if sound.channel_count() > 2 {
anyhow::bail!("Too many channels");
}
2024-03-17 19:22:12 +00:00
controller.add(Box::new(sound));
anyhow::Ok(())
}
.await;
if let Err(e) = result {
println!("Error fetching new song: {}", e);
tokio::time::sleep(Duration::from_secs(1)).await;
} else {
break;
}
}
}
});
let listener = TcpListener::bind(addr).await?;
println!("Listening on http://{}", addr);
loop {
let (tcp, _) = listener.accept().await?;
let io = TokioIo::new(tcp);
let backend = streamer_backend.clone();
tokio::task::spawn(async move {
if let Err(err) = http1::Builder::new().serve_connection(io, backend).await {
println!("Error serving connection: {:?}", err);
}
});
}
}