2022-01-07 07:05:37 +00:00
|
|
|
use crate::debug_log::{log, LogLevel, LogState};
|
2021-12-15 05:30:02 +00:00
|
|
|
use std::io::{self, Read, Write};
|
2021-12-14 09:30:02 +00:00
|
|
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
|
|
|
|
use std::str::FromStr;
|
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
2021-12-30 13:16:12 +00:00
|
|
|
use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
|
2021-12-14 09:30:02 +00:00
|
|
|
use std::thread;
|
|
|
|
use std::time::{Duration, Instant};
|
|
|
|
|
|
|
|
const SLEEP_DURATION: Duration = Duration::from_millis(100);
|
2021-12-15 05:30:02 +00:00
|
|
|
const POLL_DURATION: Duration = Duration::from_secs(5);
|
2021-12-14 09:30:02 +00:00
|
|
|
const BUF_SIZE: usize = 1024 * 4;
|
|
|
|
|
2022-03-23 11:56:11 +00:00
|
|
|
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
|
2021-12-14 09:30:02 +00:00
|
|
|
enum PollState {
|
|
|
|
None,
|
|
|
|
Password,
|
|
|
|
CurrentSong,
|
|
|
|
Status,
|
|
|
|
ReadPicture,
|
|
|
|
ReadPictureInDir,
|
|
|
|
}
|
|
|
|
|
2022-03-23 11:56:11 +00:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
|
|
|
pub enum MPDPlayState {
|
|
|
|
Playing,
|
|
|
|
Paused,
|
|
|
|
Stopped,
|
|
|
|
}
|
|
|
|
|
2021-12-14 09:30:02 +00:00
|
|
|
#[derive(Debug, Clone)]
|
|
|
|
pub struct InfoFromShared {
|
2021-12-15 05:30:02 +00:00
|
|
|
pub filename: String,
|
|
|
|
pub title: String,
|
|
|
|
pub artist: String,
|
|
|
|
pub length: f64,
|
|
|
|
pub pos: f64,
|
|
|
|
pub error_text: String,
|
2022-03-23 11:56:11 +00:00
|
|
|
pub mpd_play_state: MPDPlayState,
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
#[derive(Clone)]
|
2021-12-14 09:30:02 +00:00
|
|
|
pub struct MPDHandler {
|
2021-12-30 13:16:12 +00:00
|
|
|
state: Arc<RwLock<MPDHandlerState>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub struct MPDHandlerState {
|
2021-12-14 09:30:02 +00:00
|
|
|
art_data: Vec<u8>,
|
|
|
|
art_data_size: usize,
|
2021-12-15 07:34:30 +00:00
|
|
|
art_data_type: String,
|
2021-12-14 09:30:02 +00:00
|
|
|
current_song_filename: String,
|
|
|
|
current_song_title: String,
|
|
|
|
current_song_artist: String,
|
|
|
|
current_song_length: f64,
|
|
|
|
current_song_position: f64,
|
|
|
|
current_binary_size: usize,
|
|
|
|
poll_state: PollState,
|
|
|
|
stream: TcpStream,
|
|
|
|
password: String,
|
|
|
|
error_text: String,
|
|
|
|
can_authenticate: bool,
|
|
|
|
is_authenticated: bool,
|
|
|
|
can_get_album_art: bool,
|
|
|
|
can_get_album_art_in_dir: bool,
|
|
|
|
can_get_status: bool,
|
|
|
|
is_init: bool,
|
|
|
|
did_check_overtime: bool,
|
|
|
|
force_get_status: bool,
|
|
|
|
force_get_current_song: bool,
|
|
|
|
song_title_get_time: Instant,
|
|
|
|
song_pos_get_time: Instant,
|
|
|
|
song_length_get_time: Instant,
|
|
|
|
self_thread: Option<Arc<Mutex<thread::JoinHandle<Result<(), String>>>>>,
|
|
|
|
dirty_flag: Arc<AtomicBool>,
|
2021-12-14 10:39:09 +00:00
|
|
|
pub stop_flag: Arc<AtomicBool>,
|
2022-01-07 07:05:37 +00:00
|
|
|
log_level: LogLevel,
|
2022-03-23 11:56:11 +00:00
|
|
|
mpd_play_state: MPDPlayState,
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn check_next_chars(
|
|
|
|
buf: &[u8],
|
|
|
|
idx: usize,
|
|
|
|
saved: &mut Vec<u8>,
|
|
|
|
) -> Result<(char, u8), (String, u8)> {
|
|
|
|
if idx >= buf.len() {
|
|
|
|
return Err((String::from("idx out of bounds"), 0u8));
|
|
|
|
}
|
|
|
|
if buf[idx] & 0b10000000 == 0 {
|
|
|
|
let result_str = String::from_utf8(vec![buf[idx]]);
|
|
|
|
if let Ok(mut s) = result_str {
|
|
|
|
let popped_char = s.pop();
|
|
|
|
if s.is_empty() {
|
|
|
|
Ok((popped_char.unwrap(), 1u8))
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not one-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not one-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else if buf[idx] & 0b11100000 == 0b11000000 {
|
|
|
|
if idx + 1 >= buf.len() {
|
|
|
|
saved.push(buf[idx]);
|
|
|
|
return Err((
|
|
|
|
String::from("Is two-byte UTF-8, but not enough bytes provided"),
|
|
|
|
1u8,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1]]);
|
|
|
|
if let Ok(mut s) = result_str {
|
|
|
|
let popped_char = s.pop();
|
|
|
|
if s.is_empty() {
|
|
|
|
Ok((popped_char.unwrap(), 2u8))
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not two-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not two-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else if buf[idx] & 0b11110000 == 0b11100000 {
|
|
|
|
if idx + 2 >= buf.len() {
|
|
|
|
for c in buf.iter().skip(idx) {
|
|
|
|
saved.push(*c);
|
|
|
|
}
|
|
|
|
return Err((
|
|
|
|
String::from("Is three-byte UTF-8, but not enough bytes provided"),
|
|
|
|
(idx + 3 - buf.len()) as u8,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]);
|
|
|
|
if let Ok(mut s) = result_str {
|
|
|
|
let popped_char = s.pop();
|
|
|
|
if s.is_empty() {
|
|
|
|
Ok((popped_char.unwrap(), 3u8))
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not three-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not three-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else if buf[idx] & 0b11111000 == 0b11110000 {
|
|
|
|
if idx + 3 >= buf.len() {
|
|
|
|
for c in buf.iter().skip(idx) {
|
|
|
|
saved.push(*c);
|
|
|
|
}
|
|
|
|
return Err((
|
|
|
|
String::from("Is four-byte UTF-8, but not enough bytes provided"),
|
|
|
|
(idx + 4 - buf.len()) as u8,
|
|
|
|
));
|
|
|
|
}
|
|
|
|
let result_str = String::from_utf8(vec![buf[idx], buf[idx + 1], buf[idx + 2]]);
|
|
|
|
if let Ok(mut s) = result_str {
|
|
|
|
let popped_char = s.pop();
|
|
|
|
if s.is_empty() {
|
|
|
|
Ok((popped_char.unwrap(), 4u8))
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not four-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err((String::from("Not four-byte UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
Err((String::from("Invalid UTF-8 char"), 0u8))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn read_line(
|
|
|
|
buf: &mut Vec<u8>,
|
|
|
|
saved: &mut Vec<u8>,
|
|
|
|
init: bool,
|
|
|
|
) -> Result<String, (String, String)> {
|
|
|
|
let count = buf.len();
|
|
|
|
let mut result = String::new();
|
|
|
|
|
2021-12-15 05:30:02 +00:00
|
|
|
if count == 0 {
|
|
|
|
return Err((
|
|
|
|
String::from("Empty string passed to read_line"),
|
|
|
|
String::new(),
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
2021-12-14 09:30:02 +00:00
|
|
|
let mut buf_to_read: Vec<u8> = Vec::with_capacity(saved.len() + buf.len());
|
|
|
|
|
|
|
|
if !saved.is_empty() {
|
|
|
|
buf_to_read.append(saved);
|
|
|
|
}
|
|
|
|
buf_to_read.append(buf);
|
|
|
|
|
|
|
|
let mut prev_three: Vec<char> = Vec::with_capacity(4);
|
|
|
|
|
|
|
|
let mut skip_count = 0;
|
|
|
|
for idx in 0..count {
|
|
|
|
if skip_count > 0 {
|
|
|
|
skip_count -= 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
let next_char_result = check_next_chars(&buf_to_read, idx, saved);
|
|
|
|
if let Ok((c, s)) = next_char_result {
|
|
|
|
if !init {
|
|
|
|
prev_three.push(c);
|
|
|
|
if prev_three.len() > 3 {
|
|
|
|
prev_three.remove(0);
|
|
|
|
}
|
|
|
|
if ['O', 'K', '\n'] == prev_three.as_slice() && idx + 1 == count {
|
|
|
|
buf_to_read = buf_to_read.split_off(2);
|
|
|
|
result = String::from("OK");
|
|
|
|
buf.append(&mut buf_to_read);
|
2022-01-13 01:07:01 +00:00
|
|
|
//println!("Warning: OK was reached"); // DEBUG
|
2021-12-14 09:30:02 +00:00
|
|
|
return Ok(result);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if c == '\n' {
|
|
|
|
buf_to_read = buf_to_read.split_off(idx + s as usize);
|
|
|
|
buf.append(&mut buf_to_read);
|
|
|
|
return Ok(result);
|
|
|
|
}
|
|
|
|
result.push(c);
|
|
|
|
skip_count = s - 1;
|
|
|
|
} else if let Err((msg, count)) = next_char_result {
|
2022-01-13 01:07:01 +00:00
|
|
|
//println!("Error: {}", msg); // DEBUG
|
2021-12-14 09:30:02 +00:00
|
|
|
for i in 0..count {
|
|
|
|
saved.push(buf_to_read[idx + i as usize]);
|
|
|
|
}
|
|
|
|
buf_to_read = buf_to_read.split_off(idx);
|
|
|
|
buf.append(&mut buf_to_read);
|
|
|
|
return Err((msg, result));
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*saved = buf_to_read;
|
|
|
|
Err((String::from("Newline not reached"), result))
|
|
|
|
}
|
|
|
|
|
|
|
|
impl MPDHandler {
|
2021-12-20 08:41:03 +00:00
|
|
|
pub fn new(
|
|
|
|
host: Ipv4Addr,
|
|
|
|
port: u16,
|
|
|
|
password: String,
|
2022-01-07 07:05:37 +00:00
|
|
|
log_level: LogLevel,
|
2021-12-30 13:16:12 +00:00
|
|
|
) -> Result<Self, String> {
|
2021-12-14 09:30:02 +00:00
|
|
|
let stream = TcpStream::connect_timeout(
|
|
|
|
&SocketAddr::new(IpAddr::V4(host), port),
|
|
|
|
Duration::from_secs(5),
|
|
|
|
)
|
2022-05-16 04:57:24 +00:00
|
|
|
.map_err(|_| String::from("Failed to get TCP connection (is MPD running?)"))?;
|
2021-12-14 09:30:02 +00:00
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
let s = MPDHandler {
|
|
|
|
state: Arc::new(RwLock::new(MPDHandlerState {
|
|
|
|
art_data: Vec::new(),
|
|
|
|
art_data_size: 0,
|
|
|
|
art_data_type: String::new(),
|
|
|
|
current_song_filename: String::new(),
|
|
|
|
current_song_title: String::new(),
|
|
|
|
current_song_artist: String::new(),
|
|
|
|
current_song_length: 0.0,
|
|
|
|
current_song_position: 0.0,
|
|
|
|
current_binary_size: 0,
|
|
|
|
poll_state: PollState::None,
|
|
|
|
stream,
|
|
|
|
password,
|
|
|
|
error_text: String::new(),
|
|
|
|
can_authenticate: true,
|
|
|
|
is_authenticated: false,
|
|
|
|
can_get_album_art: true,
|
|
|
|
can_get_album_art_in_dir: true,
|
|
|
|
can_get_status: true,
|
|
|
|
is_init: true,
|
|
|
|
did_check_overtime: false,
|
|
|
|
force_get_status: false,
|
|
|
|
force_get_current_song: false,
|
|
|
|
song_title_get_time: Instant::now() - Duration::from_secs(10),
|
|
|
|
song_pos_get_time: Instant::now() - Duration::from_secs(10),
|
|
|
|
song_length_get_time: Instant::now() - Duration::from_secs(10),
|
|
|
|
self_thread: None,
|
|
|
|
dirty_flag: Arc::new(AtomicBool::new(true)),
|
|
|
|
stop_flag: Arc::new(AtomicBool::new(false)),
|
|
|
|
log_level,
|
2022-03-23 11:56:11 +00:00
|
|
|
mpd_play_state: MPDPlayState::Stopped,
|
2021-12-30 13:16:12 +00:00
|
|
|
})),
|
|
|
|
};
|
2021-12-14 09:30:02 +00:00
|
|
|
|
2021-12-14 10:49:31 +00:00
|
|
|
let s_clone = s.clone();
|
2021-12-30 13:16:12 +00:00
|
|
|
let thread = Arc::new(Mutex::new(thread::spawn(|| s_clone.handler_loop())));
|
2021-12-14 09:30:02 +00:00
|
|
|
|
2021-12-15 05:30:02 +00:00
|
|
|
loop {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(mut write_handle) = s.state.try_write() {
|
2021-12-15 05:30:02 +00:00
|
|
|
write_handle.self_thread = Some(thread);
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
thread::sleep(Duration::from_millis(1));
|
|
|
|
}
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
|
|
|
|
Ok(s)
|
|
|
|
}
|
|
|
|
|
2022-03-23 11:56:11 +00:00
|
|
|
pub fn get_mpd_handler_shared_state(&self) -> Result<InfoFromShared, ()> {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(read_lock) = self.state.try_read() {
|
2021-12-14 09:30:02 +00:00
|
|
|
return Ok(InfoFromShared {
|
|
|
|
filename: read_lock.current_song_filename.clone(),
|
|
|
|
title: read_lock.current_song_title.clone(),
|
|
|
|
artist: read_lock.current_song_artist.clone(),
|
|
|
|
length: read_lock.current_song_length,
|
2021-12-16 02:10:10 +00:00
|
|
|
pos: read_lock.current_song_position
|
|
|
|
+ read_lock.song_pos_get_time.elapsed().as_secs_f64(),
|
2021-12-14 09:30:02 +00:00
|
|
|
error_text: read_lock.error_text.clone(),
|
2022-03-23 11:56:11 +00:00
|
|
|
mpd_play_state: read_lock.mpd_play_state,
|
2021-12-14 09:30:02 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn get_dirty_flag(&self) -> Result<Arc<AtomicBool>, ()> {
|
|
|
|
if let Ok(read_lock) = self.state.try_read() {
|
2021-12-15 05:30:02 +00:00
|
|
|
return Ok(read_lock.dirty_flag.clone());
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn is_dirty(&self) -> Result<bool, ()> {
|
|
|
|
if let Ok(write_lock) = self.state.try_write() {
|
2021-12-14 10:39:09 +00:00
|
|
|
return Ok(write_lock.dirty_flag.swap(false, Ordering::Relaxed));
|
|
|
|
}
|
|
|
|
|
|
|
|
Err(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:31:59 +00:00
|
|
|
pub fn force_get_current_song(&self) {
|
2021-12-15 05:30:02 +00:00
|
|
|
loop {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(mut write_lock) = self.state.try_write() {
|
2021-12-15 05:30:02 +00:00
|
|
|
write_lock.force_get_current_song = true;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
thread::sleep(Duration::from_millis(10));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn is_authenticated(&self) -> Result<bool, ()> {
|
|
|
|
let read_handle = self.state.try_read().map_err(|_| ())?;
|
|
|
|
Ok(read_handle.is_authenticated)
|
2021-12-18 06:37:50 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn failed_to_authenticate(&self) -> Result<bool, ()> {
|
|
|
|
let read_handle = self.state.try_read().map_err(|_| ())?;
|
|
|
|
Ok(!read_handle.can_authenticate)
|
2021-12-18 06:52:50 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn has_image_data(&self) -> Result<bool, ()> {
|
|
|
|
let read_handle = self.state.try_read().map_err(|_| ())?;
|
|
|
|
Ok(read_handle.is_art_data_ready())
|
2021-12-18 06:37:50 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:31:59 +00:00
|
|
|
pub fn get_state_read_guard(&self) -> Result<RwLockReadGuard<'_, MPDHandlerState>, ()> {
|
|
|
|
self.state.try_read().map_err(|_| ())
|
2021-12-20 08:41:03 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
pub fn stop_thread(&self) -> Result<(), ()> {
|
|
|
|
let read_handle = self.state.try_read().map_err(|_| ())?;
|
|
|
|
read_handle.stop_flag.store(true, Ordering::Relaxed);
|
|
|
|
Ok(())
|
2021-12-20 08:41:03 +00:00
|
|
|
}
|
|
|
|
|
2022-01-12 11:25:26 +00:00
|
|
|
pub fn force_try_other_album_art(&self) -> Result<(), ()> {
|
|
|
|
let mut write_handle = self.state.try_write().map_err(|_| ())?;
|
|
|
|
write_handle.art_data.clear();
|
|
|
|
write_handle.art_data_size = 0;
|
|
|
|
write_handle.can_get_album_art = false;
|
|
|
|
write_handle.can_get_album_art_in_dir = true;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
fn handler_loop(self) -> Result<(), String> {
|
|
|
|
let log_level = self
|
|
|
|
.state
|
|
|
|
.read()
|
|
|
|
.expect("Failed to get log_level")
|
|
|
|
.log_level;
|
2021-12-14 09:30:02 +00:00
|
|
|
let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
|
|
|
|
let mut saved: Vec<u8> = Vec::new();
|
|
|
|
let mut saved_str: String = String::new();
|
2021-12-15 05:30:02 +00:00
|
|
|
|
|
|
|
loop {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(write_handle) = self.state.try_write() {
|
2021-12-15 05:30:02 +00:00
|
|
|
write_handle
|
|
|
|
.stream
|
|
|
|
.set_nonblocking(true)
|
|
|
|
.map_err(|_| String::from("Failed to set non-blocking on TCP stream"))?;
|
|
|
|
break;
|
|
|
|
} else {
|
|
|
|
thread::sleep(POLL_DURATION);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-12-14 09:30:02 +00:00
|
|
|
'main: loop {
|
2022-01-13 02:17:32 +00:00
|
|
|
if !self.is_reading_picture()
|
2022-01-14 01:55:47 +00:00
|
|
|
&& self.is_authenticated().unwrap_or(true)
|
|
|
|
&& !self.failed_to_authenticate().unwrap_or(false)
|
2022-01-13 02:17:32 +00:00
|
|
|
{
|
2021-12-14 09:30:02 +00:00
|
|
|
thread::sleep(SLEEP_DURATION);
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(write_handle) = self.state.try_write() {
|
2021-12-14 10:49:31 +00:00
|
|
|
if write_handle.self_thread.is_none() {
|
|
|
|
// main thread failed to store handle to this thread
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"MPDHandle thread stopping due to failed handle storage",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 10:49:31 +00:00
|
|
|
break 'main;
|
|
|
|
}
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Err(err_string) = self.handler_read_block(&mut buf, &mut saved, &mut saved_str) {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("read_block error: {}", err_string),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
log_level,
|
|
|
|
);
|
2021-12-30 13:16:12 +00:00
|
|
|
} else if let Err(err_string) = self.handler_write_block() {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("write_block error: {}", err_string),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(read_handle) = self.state.try_read() {
|
2022-01-13 02:17:32 +00:00
|
|
|
if read_handle.stop_flag.load(Ordering::Relaxed) || !read_handle.can_authenticate {
|
2021-12-14 09:30:02 +00:00
|
|
|
break 'main;
|
|
|
|
}
|
|
|
|
}
|
2021-12-15 05:30:02 +00:00
|
|
|
|
|
|
|
io::stdout().flush().unwrap();
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"MPDHandler thread entering exit loop",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2021-12-20 08:41:03 +00:00
|
|
|
log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
'exit: loop {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(mut write_handle) = self.state.try_write() {
|
2021-12-14 09:30:02 +00:00
|
|
|
write_handle.self_thread = None;
|
|
|
|
break 'exit;
|
|
|
|
}
|
|
|
|
thread::sleep(SLEEP_DURATION);
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn handler_read_block(
|
2021-12-30 13:16:12 +00:00
|
|
|
&self,
|
2021-12-14 09:30:02 +00:00
|
|
|
buf: &mut [u8; BUF_SIZE],
|
|
|
|
saved: &mut Vec<u8>,
|
|
|
|
saved_str: &mut String,
|
|
|
|
) -> Result<(), String> {
|
2021-12-30 13:16:12 +00:00
|
|
|
let mut write_handle = self
|
|
|
|
.state
|
2021-12-15 05:30:02 +00:00
|
|
|
.try_write()
|
2021-12-14 09:30:02 +00:00
|
|
|
.map_err(|_| String::from("Failed to get MPDHandler write lock (read_block)"))?;
|
2021-12-15 05:30:02 +00:00
|
|
|
let mut read_amount: usize = 0;
|
|
|
|
let read_result = write_handle.stream.read(buf);
|
|
|
|
if let Err(io_err) = read_result {
|
|
|
|
if io_err.kind() != io::ErrorKind::WouldBlock {
|
|
|
|
return Err(format!("TCP stream error: {}", io_err));
|
|
|
|
} else {
|
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
} else if let Ok(read_amount_result) = read_result {
|
|
|
|
if read_amount_result == 0 {
|
|
|
|
return Err(String::from("Got zero bytes from TCP stream"));
|
|
|
|
}
|
|
|
|
read_amount = read_amount_result;
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
2021-12-15 05:30:02 +00:00
|
|
|
let mut buf_vec: Vec<u8> = Vec::from(&buf[0..read_amount]);
|
2021-12-14 09:30:02 +00:00
|
|
|
|
2022-03-23 11:56:11 +00:00
|
|
|
let mut got_mpd_state: MPDPlayState = MPDPlayState::Playing;
|
|
|
|
|
2021-12-14 09:30:02 +00:00
|
|
|
'handle_buf: loop {
|
|
|
|
if write_handle.current_binary_size > 0 {
|
2021-12-15 07:34:30 +00:00
|
|
|
if write_handle.current_binary_size <= buf_vec.len() {
|
2021-12-14 09:30:02 +00:00
|
|
|
let count = write_handle.current_binary_size;
|
|
|
|
write_handle.art_data.extend_from_slice(&buf_vec[0..count]);
|
2021-12-15 05:30:02 +00:00
|
|
|
buf_vec = buf_vec.split_off(count + 1);
|
2021-12-14 09:30:02 +00:00
|
|
|
write_handle.current_binary_size = 0;
|
|
|
|
write_handle.poll_state = PollState::None;
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!(
|
|
|
|
"Album art recv progress: {}/{}",
|
|
|
|
write_handle.art_data.len(),
|
|
|
|
write_handle.art_data_size
|
|
|
|
),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-15 07:38:02 +00:00
|
|
|
if write_handle.art_data.len() == write_handle.art_data_size {
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
} else {
|
|
|
|
write_handle.art_data.extend_from_slice(&buf_vec);
|
|
|
|
write_handle.current_binary_size -= buf_vec.len();
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!(
|
|
|
|
"Album art recv progress: {}/{}",
|
|
|
|
write_handle.art_data.len(),
|
|
|
|
write_handle.art_data_size
|
|
|
|
),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-15 07:34:30 +00:00
|
|
|
if write_handle.art_data.len() == write_handle.art_data_size {
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
break 'handle_buf;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
let read_line_result = read_line(&mut buf_vec, saved, write_handle.is_init);
|
|
|
|
if let Ok(mut line) = read_line_result {
|
|
|
|
line = saved_str.clone() + &line;
|
|
|
|
*saved_str = String::new();
|
|
|
|
if write_handle.is_init {
|
|
|
|
if line.starts_with("OK MPD ") {
|
|
|
|
write_handle.is_init = false;
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Got initial \"OK\" from MPD",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
write_handle.poll_state = PollState::None;
|
|
|
|
break 'handle_buf;
|
|
|
|
} else {
|
|
|
|
return Err(String::from("Did not get expected init message from MPD"));
|
|
|
|
}
|
|
|
|
} // write_handle.is_init
|
|
|
|
|
|
|
|
if line.starts_with("OK") {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Got OK when poll state is {:?}", write_handle.poll_state),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
match write_handle.poll_state {
|
|
|
|
PollState::Password => write_handle.is_authenticated = true,
|
|
|
|
PollState::ReadPicture => {
|
|
|
|
if write_handle.art_data.is_empty() {
|
|
|
|
write_handle.can_get_album_art = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"No embedded album art",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
PollState::ReadPictureInDir => {
|
|
|
|
if write_handle.art_data.is_empty() {
|
|
|
|
write_handle.can_get_album_art_in_dir = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"No album art in dir",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
write_handle.poll_state = PollState::None;
|
|
|
|
break 'handle_buf;
|
|
|
|
} else if line.starts_with("ACK") {
|
2022-01-13 02:17:32 +00:00
|
|
|
log(&line, LogState::Warning, write_handle.log_level);
|
2021-12-14 09:30:02 +00:00
|
|
|
match write_handle.poll_state {
|
|
|
|
PollState::Password => {
|
|
|
|
write_handle.can_authenticate = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-14 10:15:23 +00:00
|
|
|
write_handle.error_text = "Failed to authenticate to MPD".into();
|
2021-12-15 05:45:34 +00:00
|
|
|
write_handle.stop_flag.store(true, Ordering::Relaxed);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
PollState::CurrentSong | PollState::Status => {
|
|
|
|
write_handle.can_get_status = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-14 10:15:23 +00:00
|
|
|
write_handle.error_text = "Failed to get MPD status".into();
|
2022-01-13 02:17:32 +00:00
|
|
|
if line.contains("don't have permission") {
|
|
|
|
write_handle.can_authenticate = false;
|
2022-05-16 04:57:24 +00:00
|
|
|
write_handle.error_text.push_str(" (not authenticated?)");
|
2022-01-13 02:17:32 +00:00
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
PollState::ReadPicture => {
|
|
|
|
write_handle.can_get_album_art = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to get readpicture",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 10:15:23 +00:00
|
|
|
// Not setting error_text here since
|
|
|
|
// ReadPictureInDir is tried next
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
PollState::ReadPictureInDir => {
|
|
|
|
write_handle.can_get_album_art_in_dir = false;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to get albumart",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 10:15:23 +00:00
|
|
|
write_handle.error_text = "Failed to get album art from MPD".into();
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
_ => (),
|
|
|
|
}
|
|
|
|
write_handle.poll_state = PollState::None;
|
2022-03-23 11:56:11 +00:00
|
|
|
} else if line.starts_with("state: ") {
|
|
|
|
let remaining = line.split_off(7);
|
|
|
|
let remaining = remaining.trim();
|
|
|
|
if remaining == "stop" {
|
|
|
|
write_handle.current_song_filename.clear();
|
|
|
|
write_handle.art_data.clear();
|
|
|
|
write_handle.art_data_size = 0;
|
|
|
|
write_handle.art_data_type.clear();
|
|
|
|
write_handle.can_get_album_art = true;
|
|
|
|
write_handle.can_get_album_art_in_dir = true;
|
|
|
|
write_handle.current_song_title.clear();
|
|
|
|
write_handle.current_song_artist.clear();
|
|
|
|
write_handle.current_song_length = 0.0;
|
|
|
|
write_handle.current_song_position = 0.0;
|
|
|
|
write_handle.did_check_overtime = false;
|
|
|
|
write_handle.force_get_status = true;
|
|
|
|
}
|
|
|
|
if remaining == "stop" || remaining == "pause" {
|
|
|
|
got_mpd_state = if remaining == "stop" {
|
|
|
|
MPDPlayState::Stopped
|
|
|
|
} else {
|
|
|
|
MPDPlayState::Paused
|
|
|
|
};
|
|
|
|
write_handle.error_text.clear();
|
|
|
|
write_handle
|
|
|
|
.error_text
|
|
|
|
.push_str(&format!("MPD has {:?}", got_mpd_state));
|
|
|
|
log(
|
|
|
|
format!("MPD is {:?}", got_mpd_state),
|
|
|
|
LogState::Warning,
|
|
|
|
write_handle.log_level,
|
|
|
|
);
|
|
|
|
break 'handle_buf;
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
} else if line.starts_with("file: ") {
|
|
|
|
let song_file = line.split_off(6);
|
|
|
|
if song_file != write_handle.current_song_filename {
|
|
|
|
write_handle.current_song_filename = song_file;
|
|
|
|
write_handle.art_data.clear();
|
|
|
|
write_handle.art_data_size = 0;
|
2021-12-15 07:40:56 +00:00
|
|
|
write_handle.art_data_type.clear();
|
2021-12-14 09:30:02 +00:00
|
|
|
write_handle.can_get_album_art = true;
|
|
|
|
write_handle.can_get_album_art_in_dir = true;
|
|
|
|
write_handle.current_song_title.clear();
|
|
|
|
write_handle.current_song_artist.clear();
|
|
|
|
write_handle.current_song_length = 0.0;
|
|
|
|
write_handle.current_song_position = 0.0;
|
|
|
|
write_handle.did_check_overtime = false;
|
|
|
|
write_handle.force_get_status = true;
|
2021-12-14 10:15:23 +00:00
|
|
|
write_handle.error_text.clear();
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
write_handle.song_title_get_time = Instant::now();
|
|
|
|
} else if line.starts_with("elapsed: ") {
|
|
|
|
let parse_pos_result = f64::from_str(&line.split_off(9));
|
|
|
|
if let Ok(value) = parse_pos_result {
|
|
|
|
write_handle.current_song_position = value;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
write_handle.song_pos_get_time = Instant::now();
|
|
|
|
} else {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to parse current song position",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if line.starts_with("duration: ") {
|
|
|
|
let parse_pos_result = f64::from_str(&line.split_off(10));
|
|
|
|
if let Ok(value) = parse_pos_result {
|
|
|
|
write_handle.current_song_length = value;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
write_handle.song_length_get_time = Instant::now();
|
|
|
|
} else {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to parse current song duration",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if line.starts_with("size: ") {
|
|
|
|
let parse_artsize_result = usize::from_str(&line.split_off(6));
|
|
|
|
if let Ok(value) = parse_artsize_result {
|
|
|
|
write_handle.art_data_size = value;
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
} else {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to parse album art byte size",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if line.starts_with("binary: ") {
|
|
|
|
let parse_artbinarysize_result = usize::from_str(&line.split_off(8));
|
|
|
|
if let Ok(value) = parse_artbinarysize_result {
|
|
|
|
write_handle.current_binary_size = value;
|
|
|
|
} else {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
"Failed to parse album art chunk byte size",
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if line.starts_with("Title: ") {
|
|
|
|
write_handle.current_song_title = line.split_off(7);
|
|
|
|
} else if line.starts_with("Artist: ") {
|
|
|
|
write_handle.current_song_artist = line.split_off(8);
|
2021-12-15 07:34:30 +00:00
|
|
|
} else if line.starts_with("type: ") {
|
|
|
|
write_handle.art_data_type = line.split_off(6);
|
2021-12-14 09:30:02 +00:00
|
|
|
} else {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Got unrecognized/ignored line: {}", line),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if let Err((msg, read_line_in_progress)) = read_line_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!(
|
|
|
|
"read_line: {}, saved size == {}, in_progress size == {}",
|
|
|
|
msg,
|
|
|
|
saved.len(),
|
|
|
|
read_line_in_progress.len()
|
|
|
|
),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Warning,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
*saved_str = read_line_in_progress;
|
|
|
|
break 'handle_buf;
|
|
|
|
} else {
|
|
|
|
unreachable!();
|
|
|
|
}
|
|
|
|
} // 'handle_buf: loop
|
|
|
|
|
2022-03-23 11:56:11 +00:00
|
|
|
if got_mpd_state != write_handle.mpd_play_state {
|
|
|
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
|
|
|
if got_mpd_state == MPDPlayState::Playing {
|
|
|
|
write_handle.error_text.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
write_handle.mpd_play_state = got_mpd_state;
|
|
|
|
if got_mpd_state != MPDPlayState::Playing {
|
|
|
|
write_handle.poll_state = PollState::None;
|
|
|
|
write_handle.song_pos_get_time = Instant::now();
|
|
|
|
write_handle.current_song_length = 30.0;
|
|
|
|
write_handle.current_song_position = 0.0;
|
|
|
|
}
|
|
|
|
|
2021-12-14 09:30:02 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
fn handler_write_block(&self) -> Result<(), String> {
|
|
|
|
let mut write_handle = self
|
|
|
|
.state
|
2021-12-15 05:30:02 +00:00
|
|
|
.try_write()
|
2021-12-14 09:30:02 +00:00
|
|
|
.map_err(|_| String::from("Failed to get MPDHandler write lock (write_block)"))?;
|
|
|
|
if write_handle.poll_state == PollState::None {
|
|
|
|
if !write_handle.did_check_overtime
|
|
|
|
&& write_handle.current_song_position
|
|
|
|
+ write_handle.song_pos_get_time.elapsed().as_secs_f64()
|
|
|
|
- 0.2
|
|
|
|
> write_handle.current_song_length
|
|
|
|
{
|
|
|
|
write_handle.did_check_overtime = true;
|
|
|
|
write_handle.force_get_current_song = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if !write_handle.is_authenticated
|
|
|
|
&& !write_handle.password.is_empty()
|
|
|
|
&& write_handle.can_authenticate
|
|
|
|
{
|
|
|
|
let p = write_handle.password.clone();
|
|
|
|
let write_result = write_handle
|
|
|
|
.stream
|
|
|
|
.write(format!("password {}\n", p).as_bytes());
|
|
|
|
if write_result.is_ok() {
|
|
|
|
write_handle.poll_state = PollState::Password;
|
|
|
|
} else if let Err(e) = write_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Failed to send password for authentication: {}", e),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if write_handle.can_get_status
|
|
|
|
&& (write_handle.song_title_get_time.elapsed() > POLL_DURATION
|
|
|
|
|| write_handle.force_get_current_song)
|
2022-03-23 11:56:11 +00:00
|
|
|
&& write_handle.mpd_play_state == MPDPlayState::Playing
|
2021-12-14 09:30:02 +00:00
|
|
|
{
|
|
|
|
write_handle.force_get_current_song = false;
|
|
|
|
let write_result = write_handle.stream.write(b"currentsong\n");
|
|
|
|
if write_result.is_ok() {
|
|
|
|
write_handle.poll_state = PollState::CurrentSong;
|
|
|
|
} else if let Err(e) = write_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Failed to request song info over stream: {}", e),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if write_handle.can_get_status
|
|
|
|
&& (write_handle.song_length_get_time.elapsed() > POLL_DURATION
|
|
|
|
|| write_handle.song_pos_get_time.elapsed() > POLL_DURATION
|
|
|
|
|| write_handle.force_get_status)
|
|
|
|
{
|
|
|
|
write_handle.force_get_status = false;
|
|
|
|
let write_result = write_handle.stream.write(b"status\n");
|
|
|
|
if write_result.is_ok() {
|
|
|
|
write_handle.poll_state = PollState::Status;
|
|
|
|
} else if let Err(e) = write_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Failed to request status over stream: {}", e),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if (write_handle.art_data.is_empty()
|
|
|
|
|| write_handle.art_data.len() != write_handle.art_data_size)
|
|
|
|
&& !write_handle.current_song_filename.is_empty()
|
|
|
|
{
|
|
|
|
let title = write_handle.current_song_filename.clone();
|
|
|
|
let art_data_length = write_handle.art_data.len();
|
|
|
|
if write_handle.can_get_album_art {
|
|
|
|
let write_result = write_handle.stream.write(
|
|
|
|
format!("readpicture \"{}\" {}\n", title, art_data_length).as_bytes(),
|
|
|
|
);
|
|
|
|
if write_result.is_ok() {
|
|
|
|
write_handle.poll_state = PollState::ReadPicture;
|
|
|
|
} else if let Err(e) = write_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Failed to request album art: {}", e),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
} else if write_handle.can_get_album_art_in_dir {
|
|
|
|
let write_result = write_handle
|
|
|
|
.stream
|
|
|
|
.write(format!("albumart \"{}\" {}\n", title, art_data_length).as_bytes());
|
|
|
|
if write_result.is_ok() {
|
|
|
|
write_handle.poll_state = PollState::ReadPictureInDir;
|
|
|
|
} else if let Err(e) = write_result {
|
2021-12-20 08:41:03 +00:00
|
|
|
log(
|
|
|
|
format!("Failed to request album art in dir: {}", e),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Error,
|
2021-12-20 08:41:03 +00:00
|
|
|
write_handle.log_level,
|
|
|
|
);
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2021-12-30 13:16:12 +00:00
|
|
|
fn is_reading_picture(&self) -> bool {
|
2021-12-15 05:30:02 +00:00
|
|
|
loop {
|
2021-12-30 13:16:12 +00:00
|
|
|
if let Ok(read_handle) = self.state.try_read() {
|
2021-12-15 05:30:02 +00:00
|
|
|
return read_handle.poll_state == PollState::ReadPicture
|
|
|
|
|| read_handle.poll_state == PollState::ReadPictureInDir;
|
|
|
|
} else {
|
|
|
|
thread::sleep(Duration::from_millis(5));
|
|
|
|
}
|
2021-12-14 09:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-12-30 13:16:12 +00:00
|
|
|
|
|
|
|
impl MPDHandlerState {
|
|
|
|
pub fn get_art_type(&self) -> String {
|
|
|
|
self.art_data_type.clone()
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn is_art_data_ready(&self) -> bool {
|
2022-01-12 11:25:26 +00:00
|
|
|
log(
|
|
|
|
format!(
|
|
|
|
"is_art_data_ready(): art_data_size == {}, art_data.len() == {}",
|
|
|
|
self.art_data_size,
|
|
|
|
self.art_data.len()
|
|
|
|
),
|
2022-01-13 01:07:01 +00:00
|
|
|
LogState::Debug,
|
2022-01-12 11:25:26 +00:00
|
|
|
self.log_level,
|
|
|
|
);
|
2021-12-30 13:16:12 +00:00
|
|
|
self.art_data_size != 0 && self.art_data.len() == self.art_data_size
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn get_art_data(&self) -> &[u8] {
|
|
|
|
&self.art_data
|
|
|
|
}
|
|
|
|
}
|