Skip to main content

selene_daemon/
event_handler.rs

1use std::{
2    sync::{
3        atomic::Ordering,
4        mpsc::{Receiver, Sender, channel},
5    },
6    thread,
7};
8
9use lunar_lib::trace;
10
11use crate::{
12    SHUTDOWN,
13    listener::{IpcListener, Listener},
14    player::{PlayerError, PlayerEvent, PlayerRequest},
15};
16
17pub struct EventHandler {
18    rx: Receiver<PlayerEvent>,
19
20    listener_tx: Sender<PlayerEvent>,
21
22    #[cfg(feature = "mpris")]
23    mpris_tx: tokio::sync::mpsc::Sender<crate::mpris::MprisEvent>,
24}
25
26impl EventHandler {
27    pub fn open(player_tx: Sender<PlayerRequest>) -> Result<Sender<PlayerEvent>, PlayerError> {
28        let (tx, rx) = channel();
29
30        let listener_tx = Listener::open(player_tx.clone())?;
31
32        #[cfg(feature = "mpris")]
33        let mpris_tx = crate::mpris::MprisConnector::open(player_tx);
34
35        let event_handler = Self {
36            rx,
37
38            listener_tx,
39
40            #[cfg(feature = "mpris")]
41            mpris_tx,
42        };
43
44        thread::spawn(move || {
45            event_handler.run();
46            SHUTDOWN.store(true, Ordering::Relaxed);
47        });
48
49        Ok(tx)
50    }
51
52    fn run(self) {
53        while let Ok(event) = self.rx.recv() {
54            trace!("Sending event: {event}");
55
56            let _ = self.listener_tx.send(event.clone());
57
58            #[cfg(feature = "mpris")]
59            {
60                use crate::mpris::MprisEvent;
61
62                let mpris_event = match event {
63                    PlayerEvent::CurrentlyPlayingChanged {
64                        ref currently_playing,
65                    } => Some(MprisEvent::CurrentlyPlayingChanged {
66                        currently_playing: currently_playing.clone(),
67                    }),
68                    PlayerEvent::PlaybackStopped => Some(MprisEvent::PlaybackStopped),
69                    PlayerEvent::PlaybackIsPlayingChanged {
70                        is_playing,
71                        changed_at,
72                    } => Some(MprisEvent::IsPlayingChanged {
73                        is_playing,
74                        changed_at,
75                    }),
76                    PlayerEvent::ShuffleModeChanged { shuffle_mode } => {
77                        Some(MprisEvent::ShuffleStatusChanged { shuffle_mode })
78                    }
79                    PlayerEvent::LoopModeChanged { loop_mode } => {
80                        Some(MprisEvent::LoopStatusChanged { loop_mode })
81                    }
82                    PlayerEvent::VolumeChanged { volume } => {
83                        Some(MprisEvent::VolumeChanged { volume })
84                    }
85                    PlayerEvent::SeekOccured { time } => Some(MprisEvent::Seeked { time }),
86                    _ => None,
87                };
88
89                if let Some(mpris_event) = mpris_event {
90                    let _ = self.mpris_tx.blocking_send(mpris_event);
91                }
92            }
93        }
94    }
95}
96
97pub trait EventTx {
98    fn event(&self, event: PlayerEvent);
99}
100
101impl EventTx for Sender<PlayerEvent> {
102    fn event(&self, event: PlayerEvent) {
103        let _ = self.send(event);
104    }
105}