pub struct MPDDisplay {
opts: Opt,
- mpd_handler: Option<Arc<RwLock<MPDHandler>>>,
+ mpd_handler: Option<MPDHandler>,
is_valid: bool,
is_initialized: bool,
is_authenticated: bool,
self.is_initialized = true;
loop {
self.dirty_flag =
- MPDHandler::get_dirty_flag(self.mpd_handler.as_ref().unwrap().clone())
+ MPDHandler::get_dirty_flag(&self.mpd_handler.as_ref().unwrap().clone())
.map_or(None, |f| Some(f));
if self.dirty_flag.is_some() {
break;
}
fn get_image_from_data(&mut self, ctx: &mut Context) -> Result<(), String> {
- let mpd_handle = self.mpd_handler.clone().unwrap();
- let read_handle = mpd_handle
- .try_read()
- .map_err(|_| String::from("ERROR get_image_from_data: Failed to get read_handle"))?;
-
- if !read_handle.is_art_data_ready() {
- return Err(String::from(
- "ERROR get_image_from_data: art data not ready",
- ));
+ let read_guard = self
+ .mpd_handler
+ .as_ref()
+ .unwrap()
+ .get_state_read_guard()
+ .map_err(|_| String::from("Failed to get read_guard of MPDHandlerState"))?;
+ if !read_guard.is_art_data_ready() {
+ return Err(String::from("MPDHandlerState does not have album art data"));
}
+ let image_ref = read_guard.get_art_data();
let mut image_format: image::ImageFormat = image::ImageFormat::Png;
- match read_handle.get_art_type().as_str() {
+ match read_guard.get_art_type().as_str() {
"image/png" => image_format = image::ImageFormat::Png,
"image/jpg" | "image/jpeg" => image_format = image::ImageFormat::Jpeg,
"image/gif" => image_format = image::ImageFormat::Gif,
_ => (),
}
- let img = ImageReader::with_format(Cursor::new(read_handle.get_art_data()), image_format)
+ let img = ImageReader::with_format(Cursor::new(&image_ref), image_format)
.decode()
.map_err(|e| format!("ERROR: Failed to decode album art image: {}", e))?;
let rgba8 = img.to_rgba8();
}
} else if self.password_entered {
'check_state: loop {
- let result = MPDHandler::is_authenticated(self.mpd_handler.clone().unwrap());
+ let result = self.mpd_handler.as_ref().unwrap().is_authenticated();
if let Ok(true) = result {
self.is_authenticated = true;
break;
} else {
loop {
let check_fail_result =
- MPDHandler::failed_to_authenticate(self.mpd_handler.clone().unwrap());
+ self.mpd_handler.as_ref().unwrap().failed_to_authenticate();
if let Ok(true) = check_fail_result {
{
let mpd_handler = self.mpd_handler.clone().unwrap();
loop {
- let write_handle_result = mpd_handler.try_write();
- if let Ok(write_handle) = write_handle_result {
- write_handle.stop_flag.store(true, Ordering::Relaxed);
+ let stop_thread_result = mpd_handler.stop_thread();
+ if stop_thread_result.is_ok() {
break;
}
}
debug_log::LogState::DEBUG,
self.opts.log_level,
);
- self.shared = MPDHandler::get_current_song_info(self.mpd_handler.clone().unwrap())
+ self.shared = self
+ .mpd_handler
+ .as_ref()
+ .unwrap()
+ .get_current_song_info()
.map_or(None, |f| Some(f));
if let Some(shared) = &self.shared {
if self.notice_text.contents() != shared.error_text {
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
use std::str::FromStr;
use std::sync::atomic::{AtomicBool, Ordering};
-use std::sync::{Arc, Mutex, RwLock};
+use std::sync::{Arc, Mutex, RwLock, RwLockReadGuard};
use std::thread;
use std::time::{Duration, Instant};
pub error_text: String,
}
+#[derive(Clone)]
pub struct MPDHandler {
+ state: Arc<RwLock<MPDHandlerState>>,
+}
+
+pub struct MPDHandlerState {
art_data: Vec<u8>,
art_data_size: usize,
art_data_type: String,
port: u16,
password: String,
log_level: LogState,
- ) -> Result<Arc<RwLock<Self>>, String> {
+ ) -> Result<Self, String> {
let stream = TcpStream::connect_timeout(
&SocketAddr::new(IpAddr::V4(host), port),
Duration::from_secs(5),
)
.map_err(|_| String::from("Failed to get TCP connection"))?;
- let s = Arc::new(RwLock::new(Self {
- 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,
- }));
+ 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,
+ })),
+ };
let s_clone = s.clone();
- let thread = Arc::new(Mutex::new(thread::spawn(|| Self::handler_loop(s_clone))));
+ let thread = Arc::new(Mutex::new(thread::spawn(|| s_clone.handler_loop())));
loop {
- if let Ok(mut write_handle) = s.try_write() {
+ if let Ok(mut write_handle) = s.state.try_write() {
write_handle.self_thread = Some(thread);
break;
} else {
Ok(s)
}
- pub fn get_current_song_info(h: Arc<RwLock<Self>>) -> Result<InfoFromShared, ()> {
- if let Ok(read_lock) = h.try_read() {
+ pub fn get_current_song_info(&self) -> Result<InfoFromShared, ()> {
+ if let Ok(read_lock) = self.state.try_read() {
return Ok(InfoFromShared {
filename: read_lock.current_song_filename.clone(),
title: read_lock.current_song_title.clone(),
Err(())
}
- pub fn get_dirty_flag(h: Arc<RwLock<Self>>) -> Result<Arc<AtomicBool>, ()> {
- if let Ok(read_lock) = h.try_read() {
+ pub fn get_dirty_flag(&self) -> Result<Arc<AtomicBool>, ()> {
+ if let Ok(read_lock) = self.state.try_read() {
return Ok(read_lock.dirty_flag.clone());
}
Err(())
}
- pub fn is_dirty(h: Arc<RwLock<Self>>) -> Result<bool, ()> {
- if let Ok(write_lock) = h.try_write() {
+ pub fn is_dirty(&self) -> Result<bool, ()> {
+ if let Ok(write_lock) = self.state.try_write() {
return Ok(write_lock.dirty_flag.swap(false, Ordering::Relaxed));
}
Err(())
}
- pub fn force_get_current_song(h: Arc<RwLock<Self>>) -> () {
+ pub fn force_get_current_song(&self) -> () {
loop {
- if let Ok(mut write_lock) = h.try_write() {
+ if let Ok(mut write_lock) = self.state.try_write() {
write_lock.force_get_current_song = true;
break;
} else {
}
}
- pub fn get_art_type(&self) -> String {
- self.art_data_type.clone()
+ pub fn is_authenticated(&self) -> Result<bool, ()> {
+ let read_handle = self.state.try_read().map_err(|_| ())?;
+ Ok(read_handle.is_authenticated)
}
- pub fn is_art_data_ready(&self) -> bool {
- self.art_data_size != 0 && self.art_data.len() == self.art_data_size
+ pub fn failed_to_authenticate(&self) -> Result<bool, ()> {
+ let read_handle = self.state.try_read().map_err(|_| ())?;
+ Ok(!read_handle.can_authenticate)
}
- pub fn get_art_data(&self) -> &[u8] {
- &self.art_data
+ pub fn has_image_data(&self) -> Result<bool, ()> {
+ let read_handle = self.state.try_read().map_err(|_| ())?;
+ Ok(read_handle.is_art_data_ready())
}
- pub fn is_authenticated(h: Arc<RwLock<Self>>) -> Result<bool, ()> {
- let read_handle = h.try_read().map_err(|_| ())?;
- Ok(read_handle.is_authenticated)
+ pub fn get_state_read_guard<'a>(&'a self) -> Result<RwLockReadGuard<'a, MPDHandlerState>, ()> {
+ Ok(self.state.try_read().map_err(|_| ())?)
}
- pub fn failed_to_authenticate(h: Arc<RwLock<Self>>) -> Result<bool, ()> {
- let read_handle = h.try_read().map_err(|_| ())?;
- Ok(!read_handle.can_authenticate)
+ pub fn stop_thread(&self) -> Result<(), ()> {
+ let read_handle = self.state.try_read().map_err(|_| ())?;
+ read_handle.stop_flag.store(true, Ordering::Relaxed);
+ Ok(())
}
- fn handler_loop(h: Arc<RwLock<Self>>) -> Result<(), String> {
- let log_level = h.read().expect("Failed to get log_level").log_level;
+ fn handler_loop(self) -> Result<(), String> {
+ let log_level = self
+ .state
+ .read()
+ .expect("Failed to get log_level")
+ .log_level;
let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
let mut saved: Vec<u8> = Vec::new();
let mut saved_str: String = String::new();
loop {
- if let Ok(write_handle) = h.try_write() {
+ if let Ok(write_handle) = self.state.try_write() {
write_handle
.stream
.set_nonblocking(true)
}
'main: loop {
- if !Self::is_reading_picture(h.clone()) {
+ if !self.is_reading_picture() {
thread::sleep(SLEEP_DURATION);
- if let Ok(write_handle) = h.try_write() {
+ if let Ok(write_handle) = self.state.try_write() {
if write_handle.self_thread.is_none() {
// main thread failed to store handle to this thread
log(
}
}
- if let Err(err_string) =
- Self::handler_read_block(h.clone(), &mut buf, &mut saved, &mut saved_str)
- {
+ if let Err(err_string) = self.handler_read_block(&mut buf, &mut saved, &mut saved_str) {
log(
format!("read_block error: {}", err_string),
LogState::WARNING,
log_level,
);
- } else if let Err(err_string) = Self::handler_write_block(h.clone()) {
+ } else if let Err(err_string) = self.handler_write_block() {
log(
format!("write_block error: {}", err_string),
LogState::WARNING,
);
}
- if let Ok(read_handle) = h.try_read() {
+ if let Ok(read_handle) = self.state.try_read() {
if read_handle.stop_flag.load(Ordering::Relaxed) {
break 'main;
}
log_level,
);
'exit: loop {
- if let Ok(mut write_handle) = h.try_write() {
+ if let Ok(mut write_handle) = self.state.try_write() {
write_handle.self_thread = None;
break 'exit;
}
}
fn handler_read_block(
- h: Arc<RwLock<Self>>,
+ &self,
buf: &mut [u8; BUF_SIZE],
saved: &mut Vec<u8>,
saved_str: &mut String,
) -> Result<(), String> {
- let mut write_handle = h
+ let mut write_handle = self
+ .state
.try_write()
.map_err(|_| String::from("Failed to get MPDHandler write lock (read_block)"))?;
let mut read_amount: usize = 0;
Ok(())
}
- fn handler_write_block(h: Arc<RwLock<MPDHandler>>) -> Result<(), String> {
- let mut write_handle = h
+ fn handler_write_block(&self) -> Result<(), String> {
+ let mut write_handle = self
+ .state
.try_write()
.map_err(|_| String::from("Failed to get MPDHandler write lock (write_block)"))?;
if write_handle.poll_state == PollState::None {
Ok(())
}
- fn is_reading_picture(h: Arc<RwLock<MPDHandler>>) -> bool {
+ fn is_reading_picture(&self) -> bool {
loop {
- if let Ok(read_handle) = h.try_read() {
+ if let Ok(read_handle) = self.state.try_read() {
return read_handle.poll_state == PollState::ReadPicture
|| read_handle.poll_state == PollState::ReadPictureInDir;
} else {
}
}
}
+
+impl MPDHandlerState {
+ pub fn get_art_type(&self) -> String {
+ self.art_data_type.clone()
+ }
+
+ pub fn is_art_data_ready(&self) -> bool {
+ self.art_data_size != 0 && self.art_data.len() == self.art_data_size
+ }
+
+ pub fn get_art_data(&self) -> &[u8] {
+ &self.art_data
+ }
+}