use std::{
ffi::CStr,
path::PathBuf,
time::{Duration, SystemTime, UNIX_EPOCH},
};
use mpdclient_sys::{
mpd_playlist, mpd_playlist_get_last_modified, mpd_playlist_get_path, mpd_recv_playlist,
};
use crate::{Connection, error::Result};
#[derive(Debug)]
pub struct Playlist {
inner: *mut mpd_playlist,
}
impl Playlist {
pub(super) fn new(mpd_playlist: *mut mpd_playlist) -> Self {
Self {
inner: mpd_playlist,
}
}
#[must_use]
pub fn path(&self) -> PathBuf {
let path = unsafe {
let ptr = mpd_playlist_get_path(self.inner);
CStr::from_ptr(ptr).to_string_lossy().to_string()
};
PathBuf::from(path)
}
#[allow(clippy::cast_sign_loss)]
#[must_use]
pub fn last_modified(&self) -> Option<SystemTime> {
let time = unsafe { mpd_playlist_get_last_modified(self.inner) };
if time == 0 {
None
} else {
Some(UNIX_EPOCH + Duration::from_secs(time as u64))
}
}
}
unsafe impl Send for Playlist {}
#[derive(Debug)]
pub struct PlaylistReceiver<'a> {
connection: &'a Connection,
}
impl<'a> PlaylistReceiver<'a> {
pub(crate) fn new(connection: &'a Connection) -> Self {
Self { connection }
}
pub fn receive_all(self) -> Result<Vec<Playlist>> {
self.collect()
}
}
impl Iterator for PlaylistReceiver<'_> {
type Item = Result<Playlist>;
fn next(&mut self) -> Option<Self::Item> {
unsafe {
let playlist = self
.connection
.get_error(|| mpd_recv_playlist(self.connection.connection()));
let playlist = match playlist {
Ok(playlist) => playlist,
Err(err) => return Some(Err(err)),
};
if playlist.is_null() {
return None;
}
Some(Ok(Playlist::new(playlist)))
}
}
}