use std::{
sync::{
atomic::Ordering,
mpsc::{Receiver, Sender, channel},
},
thread,
};
use lunar_lib::trace;
use crate::{
SHUTDOWN,
listener::{IpcListener, Listener},
player::{PlayerError, PlayerEvent, PlayerRequest},
};
pub struct EventHandler {
rx: Receiver<PlayerEvent>,
listener_tx: Sender<PlayerEvent>,
#[cfg(feature = "mpris")]
mpris_tx: tokio::sync::mpsc::Sender<crate::mpris::MprisEvent>,
}
impl EventHandler {
pub fn open(player_tx: Sender<PlayerRequest>) -> Result<Sender<PlayerEvent>, PlayerError> {
let (tx, rx) = channel();
let listener_tx = Listener::open(player_tx.clone())?;
#[cfg(feature = "mpris")]
let mpris_tx = crate::mpris::MprisConnector::open(player_tx);
let event_handler = Self {
rx,
listener_tx,
#[cfg(feature = "mpris")]
mpris_tx,
};
thread::spawn(move || {
event_handler.run();
SHUTDOWN.store(true, Ordering::Relaxed);
});
Ok(tx)
}
fn run(self) {
while let Ok(event) = self.rx.recv() {
trace!("Sending event: {event}");
let _ = self.listener_tx.send(event.clone());
#[cfg(feature = "mpris")]
{
use crate::mpris::MprisEvent;
let mpris_event = match event {
PlayerEvent::CurrentlyPlayingChanged {
ref currently_playing,
} => Some(MprisEvent::CurrentlyPlayingChanged {
currently_playing: currently_playing.clone(),
}),
PlayerEvent::PlaybackStopped => Some(MprisEvent::PlaybackStopped),
PlayerEvent::PlaybackIsPlayingChanged {
is_playing,
changed_at,
} => Some(MprisEvent::IsPlayingChanged {
is_playing,
changed_at,
}),
PlayerEvent::ShuffleModeChanged { shuffle_mode } => {
Some(MprisEvent::ShuffleStatusChanged { shuffle_mode })
}
PlayerEvent::LoopModeChanged { loop_mode } => {
Some(MprisEvent::LoopStatusChanged { loop_mode })
}
PlayerEvent::VolumeChanged { volume } => {
Some(MprisEvent::VolumeChanged { volume })
}
PlayerEvent::SeekOccured { time } => Some(MprisEvent::Seeked { time }),
_ => None,
};
if let Some(mpris_event) = mpris_event {
let _ = self.mpris_tx.blocking_send(mpris_event);
}
}
}
}
}
pub trait EventTx {
fn event(&self, event: PlayerEvent);
}
impl EventTx for Sender<PlayerEvent> {
fn event(&self, event: PlayerEvent) {
let _ = self.send(event);
}
}