tunein-cli 0.6.0

Browse and listen to thousands of radio stations across the globe right from your terminal 🌎 📻 🎵✨
use std::sync::{Arc, Mutex};

use crate::player::{Player, PlayerCommand};
use tokio::sync::mpsc;
use tunein_cli::provider::{tunein::Tunein, Provider};
use tunein_cli::{
    api::tunein::v1alpha1::{
        playback_service_server::PlaybackService, PlayOrPauseRequest, PlayOrPauseResponse,
        PlayRequest, PlayResponse, StopRequest, StopResponse,
    },
    provider::radiobrowser::Radiobrowser,
};

pub struct Playback {
    player: Player,
    cmd_tx: mpsc::UnboundedSender<PlayerCommand>,
}

impl Default for Playback {
    fn default() -> Self {
        let (cmd_tx, cmd_rx) = mpsc::unbounded_channel::<PlayerCommand>();
        let cmd_rx = Arc::new(Mutex::new(cmd_rx));
        let player = Player::new(cmd_rx);
        Self { player, cmd_tx }
    }
}

#[tonic::async_trait]
impl PlaybackService for Playback {
    async fn play(
        &self,
        request: tonic::Request<PlayRequest>,
    ) -> Result<tonic::Response<PlayResponse>, tonic::Status> {
        let req = request.into_inner();

        let provider = req.provider.as_deref();

        let client: Box<dyn Provider + Send + Sync> = match provider {
            Some("tunein") => Box::new(Tunein::new()),
            Some("radiobrowser") => Box::new(Radiobrowser::new().await),
            None => Box::new(Tunein::new()),
            _ => {
                return Err(tonic::Status::internal("Unsupported provider"));
            }
        };

        let station = client
            .get_station(req.station_name_or_id.clone())
            .await
            .map_err(|e| tonic::Status::internal(e.to_string()))?;

        if station.is_none() {
            return Err(tonic::Status::internal("No station found"));
        }

        let station = station.unwrap();
        let stream_url = station.stream_url.clone();
        println!("{}", stream_url);

        self.cmd_tx.send(PlayerCommand::Play(stream_url)).unwrap();
        Ok(tonic::Response::new(PlayResponse {}))
    }

    async fn stop(
        &self,
        _request: tonic::Request<StopRequest>,
    ) -> Result<tonic::Response<StopResponse>, tonic::Status> {
        self.cmd_tx.send(PlayerCommand::Stop).unwrap();
        Ok(tonic::Response::new(StopResponse {}))
    }

    async fn play_or_pause(
        &self,
        _request: tonic::Request<PlayOrPauseRequest>,
    ) -> Result<tonic::Response<PlayOrPauseResponse>, tonic::Status> {
        self.cmd_tx.send(PlayerCommand::PlayOrPause).unwrap();
        Ok(tonic::Response::new(PlayOrPauseResponse {}))
    }
}