selene-daemon 0.9.0-alpha.2

Official music player daemon for Selene
Documentation
use std::{
    ops::{Deref, DerefMut},
    sync::{Arc, OnceLock, atomic::AtomicU32},
};

use crate::{
    cpal_thread::{AtomicLoudnormMode, CpalHandle, PlaybackError},
    session::{SessionEventThread, SessionHandle},
};

pub(crate) mod cpal_stream;

pub(crate) struct LocalSessionHandle {
    pub session: SessionHandle,
    pub loudnorm_mode: Arc<AtomicLoudnormMode>,
    pub volume: Arc<AtomicU32>,
}

#[cfg(feature = "plugin-support")]
pub use selene_plugin_sdk::{
    self as sdk, Arc as SessionArc, local_session::StableEventListenerDynMut,
};
#[cfg(not(feature = "plugin-support"))]
pub use std::sync::Arc as SessionArc;

static LOCAL_SESSION: OnceLock<SessionArc<LocalSessionHandle>> = OnceLock::new();
pub(crate) fn local_session() -> &'static LocalSessionHandle {
    LOCAL_SESSION.get().unwrap()
}

#[cfg(feature = "plugin-support")]
pub(crate) fn plugin_session() -> sdk::local_session::LocalSessionHandle {
    LOCAL_SESSION.get().unwrap().clone().into()
}

impl LocalSessionHandle {
    pub(crate) fn init() -> Result<(), PlaybackError> {
        let cpal_handle = CpalHandle::open()?;
        let volume = cpal_handle.volume();

        let loudnorm_mode = cpal_handle.loudnorm_mode.clone();

        let handle = SessionHandle::open_local(cpal_handle);
        let session = Self {
            session: handle,
            volume,
            loudnorm_mode,
        };
        assert!(LOCAL_SESSION.set(SessionArc::new(session)).is_ok());
        Ok(())
    }

    #[cfg(feature = "plugin-support")]
    pub(crate) fn init_with_plugins(
        event_callbacks: Vec<sdk::local_session::EventListener>,
    ) -> Result<(), PlaybackError> {
        let cpal_handle = CpalHandle::open()?;
        let volume = cpal_handle.volume();

        let loudnorm_mode = cpal_handle.loudnorm_mode.clone();

        let handle = SessionHandle::open_local_with_plugins(cpal_handle, event_callbacks);
        let session = Self {
            session: handle,
            volume,
            loudnorm_mode,
        };
        assert!(LOCAL_SESSION.set(SessionArc::new(session)).is_ok());
        Ok(())
    }
}

impl Deref for LocalSessionHandle {
    type Target = SessionHandle;

    fn deref(&self) -> &Self::Target {
        &self.session
    }
}

impl DerefMut for LocalSessionHandle {
    fn deref_mut(&mut self) -> &mut Self::Target {
        &mut self.session
    }
}

lunar_lib::make_runner_event_ext!(SessionEventThread => pub(crate) trait LocalSessionEventExt {
    fn volume_changed(&mut self, volume: f32) {
            #[cfg(feature = "plugin-support")]
            {
                if let Some(items) = &mut self.plugin_event_callbacks {
                    for event_callback in items {
                        event_callback.volume_changed(volume);
                    }
                }
            }
    }
});