soundcloud-tui 0.3.15

A minimalist terminal SoundCloud & YouTube player for Linux in Rust, crafted with @ttype aesthetic.
use souvlaki::{MediaControlEvent, MediaControls, MediaMetadata, MediaPlayback, PlatformConfig};
use std::sync::mpsc::{channel, Receiver};
use std::time::Duration;

pub enum MprisEvent {
    Play,
    Pause,
    Toggle,
    Next,
    Previous,
}

pub struct MprisManager {
    controls: Option<MediaControls>,
    event_rx: Receiver<MprisEvent>,
}

impl MprisManager {
    pub fn new() -> Self {
        let (tx, rx) = channel::<MprisEvent>();

        #[cfg(not(target_os = "windows"))]
        let hwnd = None;
        #[cfg(target_os = "windows")]
        let hwnd = None;

        let config = PlatformConfig {
            dbus_name: "soundcloud-tui",
            display_name: "SoundCloud TUI",
            hwnd,
        };

        let mut controls = MediaControls::new(config).ok();

        if let Some(ref mut c) = controls {
            let tx_clone = tx;
            let res = c.attach(move |event: MediaControlEvent| {
                match event {
                    MediaControlEvent::Play => {
                        let _ = tx_clone.send(MprisEvent::Play);
                    }
                    MediaControlEvent::Pause => {
                        let _ = tx_clone.send(MprisEvent::Pause);
                    }
                    MediaControlEvent::Toggle => {
                        let _ = tx_clone.send(MprisEvent::Toggle);
                    }
                    MediaControlEvent::Next => {
                        let _ = tx_clone.send(MprisEvent::Next);
                    }
                    MediaControlEvent::Previous => {
                        let _ = tx_clone.send(MprisEvent::Previous);
                    }
                    _ => {}
                }
            });
            if res.is_err() {
                controls = None;
            }
        }

        Self {
            controls,
            event_rx: rx,
        }
    }

    pub fn update(
        &mut self,
        title: &str,
        artist: &str,
        artwork_url: Option<&str>,
        duration: f64,
        is_paused: bool,
    ) {
        if let Some(ref mut c) = self.controls {
            let dur = if duration > 0.0 {
                Some(Duration::from_secs_f64(duration))
            } else {
                None
            };

            let _ = c.set_metadata(MediaMetadata {
                title: Some(title),
                artist: Some(artist),
                album: Some("SoundCloud"),
                cover_url: artwork_url,
                duration: dur,
            });

            let playback = if is_paused {
                MediaPlayback::Paused { progress: None }
            } else {
                MediaPlayback::Playing { progress: None }
            };
            let _ = c.set_playback(playback);
        }
    }

    pub fn poll_event(&self) -> Option<MprisEvent> {
        self.event_rx.try_recv().ok()
    }
}