WIP several fixes
info output not implemented yet
This commit is contained in:
parent
70ecefaf30
commit
866e88ba2a
3 changed files with 244 additions and 51 deletions
111
src/display.rs
111
src/display.rs
|
@ -1,11 +1,16 @@
|
||||||
use crate::mpd_handler::MPDHandler;
|
use crate::debug_log::log;
|
||||||
|
use crate::mpd_handler::{InfoFromShared, MPDHandler};
|
||||||
use crate::Opt;
|
use crate::Opt;
|
||||||
use ggez::event::{self, EventHandler};
|
use ggez::event::{self, EventHandler};
|
||||||
use ggez::graphics::{self, Color, DrawParam, Drawable, Rect, Text, TextFragment};
|
use ggez::graphics::{self, Color, DrawParam, Drawable, Text, TextFragment};
|
||||||
use ggez::timer::{check_update_time, fps};
|
|
||||||
use ggez::Context;
|
use ggez::Context;
|
||||||
use ggez::GameError;
|
use ggez::GameError;
|
||||||
|
use std::sync::atomic::AtomicBool;
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
use std::thread;
|
||||||
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
|
const POLL_TIME: Duration = Duration::from_millis(333);
|
||||||
|
|
||||||
pub struct MPDDisplay {
|
pub struct MPDDisplay {
|
||||||
opts: Opt,
|
opts: Opt,
|
||||||
|
@ -13,23 +18,84 @@ pub struct MPDDisplay {
|
||||||
is_valid: bool,
|
is_valid: bool,
|
||||||
is_initialized: bool,
|
is_initialized: bool,
|
||||||
notice_text: Text,
|
notice_text: Text,
|
||||||
|
poll_instant: Instant,
|
||||||
|
shared: Option<InfoFromShared>,
|
||||||
|
password_entered: bool,
|
||||||
|
dirty_flag: Option<Arc<AtomicBool>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MPDDisplay {
|
impl MPDDisplay {
|
||||||
pub fn new(ctx: &mut Context, opts: Opt) -> Self {
|
pub fn new(_ctx: &mut Context, opts: Opt) -> Self {
|
||||||
Self {
|
Self {
|
||||||
opts,
|
opts,
|
||||||
mpd_handler: None,
|
mpd_handler: None,
|
||||||
is_valid: true,
|
is_valid: true,
|
||||||
is_initialized: false,
|
is_initialized: false,
|
||||||
notice_text: Text::new(""),
|
notice_text: Text::new(""),
|
||||||
|
poll_instant: Instant::now() - POLL_TIME,
|
||||||
|
shared: None,
|
||||||
|
password_entered: false,
|
||||||
|
dirty_flag: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn init_mpd_handler(&mut self) -> () {
|
||||||
|
self.mpd_handler = MPDHandler::new(
|
||||||
|
self.opts.host,
|
||||||
|
self.opts.port,
|
||||||
|
self.opts.password.clone().map_or(String::new(), |s| s),
|
||||||
|
)
|
||||||
|
.map_or_else(|_| None, |v| Some(v));
|
||||||
|
if self.mpd_handler.is_some() {
|
||||||
|
self.is_initialized = true;
|
||||||
|
loop {
|
||||||
|
self.dirty_flag =
|
||||||
|
MPDHandler::get_dirty_flag(self.mpd_handler.as_ref().unwrap().clone())
|
||||||
|
.map_or(None, |f| Some(f));
|
||||||
|
if self.dirty_flag.is_some() {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
thread::sleep(POLL_TIME);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log("Successfully initialized MPDHandler");
|
||||||
|
} else {
|
||||||
|
self.is_valid = false;
|
||||||
|
log("Failed to initialize MPDHandler");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler for MPDDisplay {
|
impl EventHandler for MPDDisplay {
|
||||||
fn update(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> {
|
fn update(&mut self, _ctx: &mut ggez::Context) -> Result<(), GameError> {
|
||||||
self.notice_text = Text::new(TextFragment::new(format!("fps is {}", fps(ctx))));
|
if !self.is_valid {
|
||||||
|
return Err(GameError::EventLoopError(
|
||||||
|
"Failed to initialize MPDHandler".into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
if !self.is_initialized {
|
||||||
|
if self.opts.enable_prompt_password {
|
||||||
|
if self.notice_text.contents().is_empty() {
|
||||||
|
self.notice_text = Text::new(TextFragment::new("password: "));
|
||||||
|
} else if self.password_entered {
|
||||||
|
self.init_mpd_handler();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.init_mpd_handler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.is_valid && self.is_initialized && self.poll_instant.elapsed() > POLL_TIME {
|
||||||
|
self.poll_instant = Instant::now();
|
||||||
|
self.shared = MPDHandler::get_current_song_info(self.mpd_handler.clone().unwrap())
|
||||||
|
.map_or(None, |f| Some(f));
|
||||||
|
if let Some(shared) = &self.shared {
|
||||||
|
if self.notice_text.contents() != shared.error_text {
|
||||||
|
self.notice_text = Text::new(TextFragment::new(shared.error_text.clone()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -41,4 +107,37 @@ impl EventHandler for MPDDisplay {
|
||||||
|
|
||||||
graphics::present(ctx)
|
graphics::present(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn text_input_event(&mut self, _ctx: &mut Context, character: char) {
|
||||||
|
if !self.is_initialized && self.opts.enable_prompt_password {
|
||||||
|
if self.opts.password.is_none() {
|
||||||
|
let s = String::from(character);
|
||||||
|
self.opts.password = Some(s);
|
||||||
|
self.notice_text.add('*');
|
||||||
|
} else {
|
||||||
|
self.opts.password.as_mut().unwrap().push(character);
|
||||||
|
self.notice_text.add('*');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_down_event(
|
||||||
|
&mut self,
|
||||||
|
_ctx: &mut Context,
|
||||||
|
keycode: event::KeyCode,
|
||||||
|
_keymods: event::KeyMods,
|
||||||
|
_repeat: bool,
|
||||||
|
) {
|
||||||
|
if !self.is_initialized && self.opts.enable_prompt_password {
|
||||||
|
if keycode == event::KeyCode::Back {
|
||||||
|
let s: String = self.notice_text.contents();
|
||||||
|
|
||||||
|
if s.ends_with("*") {
|
||||||
|
self.notice_text = Text::new(TextFragment::new(s[0..(s.len() - 1)].to_owned()));
|
||||||
|
}
|
||||||
|
} else if keycode == event::KeyCode::Return {
|
||||||
|
self.password_entered = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
36
src/main.rs
36
src/main.rs
|
@ -3,10 +3,10 @@ mod display;
|
||||||
mod mpd_handler;
|
mod mpd_handler;
|
||||||
|
|
||||||
use ggez::conf::{WindowMode, WindowSetup};
|
use ggez::conf::{WindowMode, WindowSetup};
|
||||||
use ggez::event::winit_event::KeyboardInput;
|
use ggez::event::winit_event::{KeyboardInput, ModifiersState};
|
||||||
use ggez::event::{self, ControlFlow, EventHandler};
|
use ggez::event::{self, ControlFlow, EventHandler};
|
||||||
use ggez::graphics::{self, Rect};
|
use ggez::graphics::{self, Rect};
|
||||||
use ggez::ContextBuilder;
|
use ggez::{ContextBuilder, GameError};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
@ -50,6 +50,8 @@ fn main() -> Result<(), String> {
|
||||||
|
|
||||||
let mut display = display::MPDDisplay::new(&mut ctx, opt);
|
let mut display = display::MPDDisplay::new(&mut ctx, opt);
|
||||||
|
|
||||||
|
let mut modifiers_state: ModifiersState = ModifiersState::default();
|
||||||
|
|
||||||
event_loop.run(move |mut event, _window_target, control_flow| {
|
event_loop.run(move |mut event, _window_target, control_flow| {
|
||||||
if !ctx.continuing {
|
if !ctx.continuing {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
|
@ -64,6 +66,9 @@ fn main() -> Result<(), String> {
|
||||||
match event {
|
match event {
|
||||||
event::winit_event::Event::WindowEvent { event, .. } => match event {
|
event::winit_event::Event::WindowEvent { event, .. } => match event {
|
||||||
event::winit_event::WindowEvent::CloseRequested => event::quit(ctx),
|
event::winit_event::WindowEvent::CloseRequested => event::quit(ctx),
|
||||||
|
event::winit_event::WindowEvent::ModifiersChanged(state) => {
|
||||||
|
modifiers_state = state;
|
||||||
|
}
|
||||||
event::winit_event::WindowEvent::KeyboardInput {
|
event::winit_event::WindowEvent::KeyboardInput {
|
||||||
device_id: _,
|
device_id: _,
|
||||||
input:
|
input:
|
||||||
|
@ -72,12 +77,16 @@ fn main() -> Result<(), String> {
|
||||||
..
|
..
|
||||||
},
|
},
|
||||||
is_synthetic: _,
|
is_synthetic: _,
|
||||||
} => match keycode {
|
} => {
|
||||||
event::KeyCode::Escape | event::KeyCode::Q => {
|
match keycode {
|
||||||
|
event::KeyCode::Escape => {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
},
|
}
|
||||||
|
display.key_down_event(ctx, keycode, modifiers_state.into(), false);
|
||||||
|
}
|
||||||
event::winit_event::WindowEvent::Resized(phys_size) => {
|
event::winit_event::WindowEvent::Resized(phys_size) => {
|
||||||
graphics::set_screen_coordinates(
|
graphics::set_screen_coordinates(
|
||||||
ctx,
|
ctx,
|
||||||
|
@ -90,13 +99,26 @@ fn main() -> Result<(), String> {
|
||||||
)
|
)
|
||||||
.expect("Failed to handle resizing window");
|
.expect("Failed to handle resizing window");
|
||||||
}
|
}
|
||||||
|
event::winit_event::WindowEvent::ReceivedCharacter(ch) => {
|
||||||
|
display.text_input_event(ctx, ch);
|
||||||
|
}
|
||||||
x => log(format!("Other window event fired: {:?}", x)),
|
x => log(format!("Other window event fired: {:?}", x)),
|
||||||
},
|
},
|
||||||
event::winit_event::Event::MainEventsCleared => {
|
event::winit_event::Event::MainEventsCleared => {
|
||||||
ctx.timer_context.tick();
|
ctx.timer_context.tick();
|
||||||
|
|
||||||
display.update(ctx).expect("Update failed");
|
let mut game_result: Result<(), GameError> = display.update(ctx);
|
||||||
display.draw(ctx).expect("Draw failed");
|
if game_result.is_err() {
|
||||||
|
println!("ERROR update: {}", game_result.unwrap_err());
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
game_result = display.draw(ctx);
|
||||||
|
if game_result.is_err() {
|
||||||
|
println!("ERROR draw: {}", game_result.unwrap_err());
|
||||||
|
*control_flow = ControlFlow::Exit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ctx.mouse_context.reset_delta();
|
ctx.mouse_context.reset_delta();
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
use std::io::{Read, Write};
|
use crate::debug_log::log;
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, TcpStream};
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
@ -7,7 +8,7 @@ use std::thread;
|
||||||
use std::time::{Duration, Instant};
|
use std::time::{Duration, Instant};
|
||||||
|
|
||||||
const SLEEP_DURATION: Duration = Duration::from_millis(100);
|
const SLEEP_DURATION: Duration = Duration::from_millis(100);
|
||||||
const POLL_DURATION: Duration = Duration::from_secs(10);
|
const POLL_DURATION: Duration = Duration::from_secs(5);
|
||||||
const BUF_SIZE: usize = 1024 * 4;
|
const BUF_SIZE: usize = 1024 * 4;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Copy, Clone)]
|
#[derive(Debug, PartialEq, Copy, Clone)]
|
||||||
|
@ -22,12 +23,12 @@ enum PollState {
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct InfoFromShared {
|
pub struct InfoFromShared {
|
||||||
filename: String,
|
pub filename: String,
|
||||||
title: String,
|
pub title: String,
|
||||||
artist: String,
|
pub artist: String,
|
||||||
length: f64,
|
pub length: f64,
|
||||||
pos: f64,
|
pub pos: f64,
|
||||||
error_text: String,
|
pub error_text: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct MPDHandler {
|
pub struct MPDHandler {
|
||||||
|
@ -155,6 +156,13 @@ fn read_line(
|
||||||
let count = buf.len();
|
let count = buf.len();
|
||||||
let mut result = String::new();
|
let mut result = String::new();
|
||||||
|
|
||||||
|
if count == 0 {
|
||||||
|
return Err((
|
||||||
|
String::from("Empty string passed to read_line"),
|
||||||
|
String::new(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let mut buf_to_read: Vec<u8> = Vec::with_capacity(saved.len() + buf.len());
|
let mut buf_to_read: Vec<u8> = Vec::with_capacity(saved.len() + buf.len());
|
||||||
|
|
||||||
if !saved.is_empty() {
|
if !saved.is_empty() {
|
||||||
|
@ -274,15 +282,20 @@ impl MPDHandler {
|
||||||
let s_clone = s.clone();
|
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(|| Self::handler_loop(s_clone))));
|
||||||
|
|
||||||
s.write()
|
loop {
|
||||||
.map_err(|_| String::from("Failed to store thread handle in MPDHandler"))?
|
if let Ok(mut write_handle) = s.try_write() {
|
||||||
.self_thread = Some(thread);
|
write_handle.self_thread = Some(thread);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
thread::sleep(Duration::from_millis(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(s)
|
Ok(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_art_data(h: Arc<RwLock<Self>>) -> Result<Vec<u8>, ()> {
|
pub fn get_art_data(h: Arc<RwLock<Self>>) -> Result<Vec<u8>, ()> {
|
||||||
if let Ok(read_lock) = h.read() {
|
if let Ok(read_lock) = h.try_read() {
|
||||||
if read_lock.art_data.len() == read_lock.art_data_size {
|
if read_lock.art_data.len() == read_lock.art_data_size {
|
||||||
return Ok(read_lock.art_data.clone());
|
return Ok(read_lock.art_data.clone());
|
||||||
}
|
}
|
||||||
|
@ -292,7 +305,7 @@ impl MPDHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn can_get_art_data(h: Arc<RwLock<Self>>) -> bool {
|
pub fn can_get_art_data(h: Arc<RwLock<Self>>) -> bool {
|
||||||
if let Ok(read_lock) = h.read() {
|
if let Ok(read_lock) = h.try_read() {
|
||||||
return read_lock.can_get_album_art || read_lock.can_get_album_art_in_dir;
|
return read_lock.can_get_album_art || read_lock.can_get_album_art_in_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,7 +313,7 @@ impl MPDHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_current_song_info(h: Arc<RwLock<Self>>) -> Result<InfoFromShared, ()> {
|
pub fn get_current_song_info(h: Arc<RwLock<Self>>) -> Result<InfoFromShared, ()> {
|
||||||
if let Ok(read_lock) = h.read() {
|
if let Ok(read_lock) = h.try_read() {
|
||||||
return Ok(InfoFromShared {
|
return Ok(InfoFromShared {
|
||||||
filename: read_lock.current_song_filename.clone(),
|
filename: read_lock.current_song_filename.clone(),
|
||||||
title: read_lock.current_song_title.clone(),
|
title: read_lock.current_song_title.clone(),
|
||||||
|
@ -314,22 +327,54 @@ impl MPDHandler {
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn get_dirty_flag(h: Arc<RwLock<Self>>) -> Result<Arc<AtomicBool>, ()> {
|
||||||
|
if let Ok(read_lock) = h.try_read() {
|
||||||
|
return Ok(read_lock.dirty_flag.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
Err(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn is_dirty(h: Arc<RwLock<Self>>) -> Result<bool, ()> {
|
pub fn is_dirty(h: Arc<RwLock<Self>>) -> Result<bool, ()> {
|
||||||
if let Ok(write_lock) = h.write() {
|
if let Ok(write_lock) = h.try_write() {
|
||||||
return Ok(write_lock.dirty_flag.swap(false, Ordering::Relaxed));
|
return Ok(write_lock.dirty_flag.swap(false, Ordering::Relaxed));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(())
|
Err(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn force_get_current_song(h: Arc<RwLock<Self>>) -> () {
|
||||||
|
loop {
|
||||||
|
if let Ok(mut write_lock) = h.try_write() {
|
||||||
|
write_lock.force_get_current_song = true;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
thread::sleep(Duration::from_millis(10));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn handler_loop(h: Arc<RwLock<Self>>) -> Result<(), String> {
|
fn handler_loop(h: Arc<RwLock<Self>>) -> Result<(), String> {
|
||||||
let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
|
let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
|
||||||
let mut saved: Vec<u8> = Vec::new();
|
let mut saved: Vec<u8> = Vec::new();
|
||||||
let mut saved_str: String = String::new();
|
let mut saved_str: String = String::new();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Ok(write_handle) = h.try_write() {
|
||||||
|
write_handle
|
||||||
|
.stream
|
||||||
|
.set_nonblocking(true)
|
||||||
|
.map_err(|_| String::from("Failed to set non-blocking on TCP stream"))?;
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
thread::sleep(POLL_DURATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
'main: loop {
|
'main: loop {
|
||||||
if !Self::is_reading_picture(h.clone()) {
|
if !Self::is_reading_picture(h.clone()) {
|
||||||
thread::sleep(SLEEP_DURATION);
|
thread::sleep(SLEEP_DURATION);
|
||||||
if let Ok(write_handle) = h.write() {
|
if let Ok(write_handle) = h.try_write() {
|
||||||
if write_handle.self_thread.is_none() {
|
if write_handle.self_thread.is_none() {
|
||||||
// main thread failed to store handle to this thread
|
// main thread failed to store handle to this thread
|
||||||
println!("MPDHandle thread stopping due to failed handle storage");
|
println!("MPDHandle thread stopping due to failed handle storage");
|
||||||
|
@ -346,15 +391,18 @@ impl MPDHandler {
|
||||||
println!("WARNING: write_block error: {}", err_string);
|
println!("WARNING: write_block error: {}", err_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(read_handle) = h.read() {
|
if let Ok(read_handle) = h.try_read() {
|
||||||
if read_handle.stop_flag.load(Ordering::Relaxed) {
|
if read_handle.stop_flag.load(Ordering::Relaxed) {
|
||||||
break 'main;
|
break 'main;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
io::stdout().flush().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log("MPDHandler thread entering exit loop");
|
||||||
'exit: loop {
|
'exit: loop {
|
||||||
if let Ok(mut write_handle) = h.write() {
|
if let Ok(mut write_handle) = h.try_write() {
|
||||||
write_handle.self_thread = None;
|
write_handle.self_thread = None;
|
||||||
break 'exit;
|
break 'exit;
|
||||||
}
|
}
|
||||||
|
@ -371,29 +419,42 @@ impl MPDHandler {
|
||||||
saved_str: &mut String,
|
saved_str: &mut String,
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut write_handle = h
|
let mut write_handle = h
|
||||||
.write()
|
.try_write()
|
||||||
.map_err(|_| String::from("Failed to get MPDHandler write lock (read_block)"))?;
|
.map_err(|_| String::from("Failed to get MPDHandler write lock (read_block)"))?;
|
||||||
let read_result = write_handle
|
let mut read_amount: usize = 0;
|
||||||
.stream
|
let read_result = write_handle.stream.read(buf);
|
||||||
.read(buf)
|
if let Err(io_err) = read_result {
|
||||||
.map_err(|io_err| format!("Failed to read from TCP stream: {}", io_err))?;
|
if io_err.kind() != io::ErrorKind::WouldBlock {
|
||||||
if read_result == 0 {
|
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"));
|
return Err(String::from("Got zero bytes from TCP stream"));
|
||||||
}
|
}
|
||||||
let mut buf_vec: Vec<u8> = Vec::from(&buf[0..read_result]);
|
read_amount = read_amount_result;
|
||||||
|
}
|
||||||
|
let mut buf_vec: Vec<u8> = Vec::from(&buf[0..read_amount]);
|
||||||
|
|
||||||
'handle_buf: loop {
|
'handle_buf: loop {
|
||||||
if write_handle.current_binary_size > 0 {
|
if write_handle.current_binary_size > 0 {
|
||||||
if write_handle.current_binary_size <= buf_vec.len() {
|
if write_handle.current_binary_size < buf_vec.len() {
|
||||||
let count = write_handle.current_binary_size;
|
let count = write_handle.current_binary_size;
|
||||||
write_handle.art_data.extend_from_slice(&buf_vec[0..count]);
|
write_handle.art_data.extend_from_slice(&buf_vec[0..count]);
|
||||||
buf_vec = buf_vec.split_off(write_handle.current_binary_size + 1);
|
buf_vec = buf_vec.split_off(count + 1);
|
||||||
write_handle.current_binary_size = 0;
|
write_handle.current_binary_size = 0;
|
||||||
write_handle.poll_state = PollState::None;
|
write_handle.poll_state = PollState::None;
|
||||||
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
write_handle.dirty_flag.store(true, Ordering::Relaxed);
|
||||||
|
log("Got complete album art chunk");
|
||||||
} else {
|
} else {
|
||||||
write_handle.art_data.extend_from_slice(&buf_vec);
|
write_handle.art_data.extend_from_slice(&buf_vec);
|
||||||
write_handle.current_binary_size -= buf_vec.len();
|
write_handle.current_binary_size -= buf_vec.len();
|
||||||
|
log(format!(
|
||||||
|
"Album art recv progress: {}/{}",
|
||||||
|
write_handle.art_data.len(),
|
||||||
|
write_handle.art_data_size
|
||||||
|
));
|
||||||
break 'handle_buf;
|
break 'handle_buf;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -413,6 +474,10 @@ impl MPDHandler {
|
||||||
} // write_handle.is_init
|
} // write_handle.is_init
|
||||||
|
|
||||||
if line.starts_with("OK") {
|
if line.starts_with("OK") {
|
||||||
|
log(format!(
|
||||||
|
"Got OK when poll state is {:?}",
|
||||||
|
write_handle.poll_state
|
||||||
|
));
|
||||||
match write_handle.poll_state {
|
match write_handle.poll_state {
|
||||||
PollState::Password => write_handle.is_authenticated = true,
|
PollState::Password => write_handle.is_authenticated = true,
|
||||||
PollState::ReadPicture => {
|
PollState::ReadPicture => {
|
||||||
|
@ -518,10 +583,15 @@ impl MPDHandler {
|
||||||
} else if line.starts_with("Artist: ") {
|
} else if line.starts_with("Artist: ") {
|
||||||
write_handle.current_song_artist = line.split_off(8);
|
write_handle.current_song_artist = line.split_off(8);
|
||||||
} else {
|
} else {
|
||||||
println!("WARNING: Got unrecognized line: {}", line);
|
log(format!("WARNING: Got unrecognized/ignored line: {}", line));
|
||||||
}
|
}
|
||||||
} else if let Err((msg, read_line_in_progress)) = read_line_result {
|
} else if let Err((msg, read_line_in_progress)) = read_line_result {
|
||||||
println!("ERROR read_line: {}", msg);
|
log(format!(
|
||||||
|
"WARNING read_line: {}, saved size == {}, in_progress size == {}",
|
||||||
|
msg,
|
||||||
|
saved.len(),
|
||||||
|
read_line_in_progress.len()
|
||||||
|
));
|
||||||
*saved_str = read_line_in_progress;
|
*saved_str = read_line_in_progress;
|
||||||
break 'handle_buf;
|
break 'handle_buf;
|
||||||
} else {
|
} else {
|
||||||
|
@ -534,7 +604,7 @@ impl MPDHandler {
|
||||||
|
|
||||||
fn handler_write_block(h: Arc<RwLock<MPDHandler>>) -> Result<(), String> {
|
fn handler_write_block(h: Arc<RwLock<MPDHandler>>) -> Result<(), String> {
|
||||||
let mut write_handle = h
|
let mut write_handle = h
|
||||||
.write()
|
.try_write()
|
||||||
.map_err(|_| String::from("Failed to get MPDHandler write lock (write_block)"))?;
|
.map_err(|_| String::from("Failed to get MPDHandler write lock (write_block)"))?;
|
||||||
if write_handle.poll_state == PollState::None {
|
if write_handle.poll_state == PollState::None {
|
||||||
if !write_handle.did_check_overtime
|
if !write_handle.did_check_overtime
|
||||||
|
@ -615,11 +685,13 @@ impl MPDHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_reading_picture(h: Arc<RwLock<MPDHandler>>) -> bool {
|
fn is_reading_picture(h: Arc<RwLock<MPDHandler>>) -> bool {
|
||||||
if let Ok(read_handle) = h.read() {
|
loop {
|
||||||
read_handle.poll_state == PollState::ReadPicture
|
if let Ok(read_handle) = h.try_read() {
|
||||||
|| read_handle.poll_state == PollState::ReadPictureInDir
|
return read_handle.poll_state == PollState::ReadPicture
|
||||||
|
|| read_handle.poll_state == PollState::ReadPictureInDir;
|
||||||
} else {
|
} else {
|
||||||
false
|
thread::sleep(Duration::from_millis(5));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue