use std::{io, sync::Arc};
use crate::{LoopMode, ShuffleMode, dto};
use bitflags::bitflags;
use lunar_lib::id::Id;
use selene_core::library::{collectable::Collectable, track::Track};
use serde::{Deserialize, Serialize};
pub(crate) trait Packetable: Serialize + for<'a> Deserialize<'a> {
fn serialize_packet(&self) -> Vec<u8> {
let data = vec![0u8; 4];
let mut data = postcard::to_extend(&self, data).expect("Serialization should never fail");
let payload_len = (data.len() as u32 - 4).to_be_bytes();
data[0..4].copy_from_slice(&payload_len);
data
}
fn serialize_into_arc(&self) -> Arc<[u8]> {
Arc::from(self.serialize_packet())
}
fn serialize_into_writer<W: io::Write + ?Sized>(&self, writer: &mut W) -> io::Result<()> {
let data = self.serialize_packet();
writer.write_all(&data)
}
fn deserialize_packet(bytes: &[u8]) -> io::Result<Self> {
postcard::from_bytes(bytes).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
}
}
impl<T: Serialize + for<'a> Deserialize<'a>> Packetable for T {}
bitflags! {
#[derive(Debug, Clone, Copy, Serialize, Deserialize)]
pub struct PlayerQueryFlags: u16 {
const PLAYBACK_STATE = 1 << 0;
const CURRENTLY_PLAYING = 1 << 1;
const TIME = 1 << 2;
const QUEUE = 1 << 3;
const PLAYLIST = 1 << 4;
const TRACKLIST = 1 << 5;
const TRACKLIST_POSITION = 1 << 6;
const SHUFFLE_MODE = 1 << 7;
const LOOP_MODE = 1 << 8;
}
}
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
pub struct QueryResult {
pub playback_state: Option<bool>,
pub currently_playing: Option<Option<(Id<Track>, Option<u32>)>>,
pub time: Option<Option<f64>>,
pub queue: Option<Vec<Id<Track>>>,
pub playlist: Option<Vec<Collectable>>,
pub tracklist: Option<Vec<Id<Track>>>,
pub tracklist_position: Option<Option<u32>>,
pub shuffle_mode: Option<ShuffleMode>,
pub loop_mode: Option<LoopMode>,
}
#[derive(Debug, Serialize, Deserialize)]
pub enum RemoteEvent {
CurrentlyPlayingChanged {
currently_playing: Box<dto::Track>,
position: Option<u32>,
},
PlaybackIsPlayingChanged {
is_playing: bool,
changed_at: f64,
},
PlaybackStopped,
ShuffleModeChanged {
shuffle_mode: ShuffleMode,
},
LoopModeChanged {
loop_mode: LoopMode,
},
VolumeChanged {
volume: f32,
},
SeekOccured {
time: Option<f64>,
},
QueueChanged {
length: u32,
},
PlaylistChanged {
length: u32,
},
TracklistChanged {
length: u32,
position: Option<usize>,
},
Shutdown,
Scrobble {
start_time: u64,
},
NowPlaying,
}
#[derive(Debug, Serialize, Deserialize, Clone, Copy)]
pub struct TrackInfo {
pub sample_rate: u32,
pub channels: u16,
pub track_gain: Option<f32>,
pub album_gain: Option<f32>,
}
impl TrackInfo {
pub fn new(
sample_rate: u32,
channels: u16,
track_gain: Option<f32>,
album_gain: Option<f32>,
) -> Self {
Self {
sample_rate,
channels,
track_gain,
album_gain,
}
}
}
#[derive(Debug, Serialize, Deserialize, Clone)]
pub(crate) enum AudioPacket {
TrackInfo(TrackInfo),
Audio(Vec<f32>),
Disconnect,
}