Update to latest ggez (0.8.1)
A lot of ".expect(...)" or ".unwrap(...)" lines were added, so these need to be refactored out. For now, just got it to work with the latest ggez. Currently noticed bugs: - Album art is brighter than original. - Fullscreen doesn't work.
This commit is contained in:
parent
34d3e47863
commit
7f6a24545c
4 changed files with 1263 additions and 1026 deletions
1969
Cargo.lock
generated
1969
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
|
@ -1,18 +1,20 @@
|
||||||
[package]
|
[package]
|
||||||
name = "mpd_info_screen"
|
name = "mpd_info_screen"
|
||||||
version = "0.3.7"
|
version = "0.3.8"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
description = "Displays info on currently playing music from an MPD daemon"
|
description = "Displays info on currently playing music from an MPD daemon"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
repository = "https://github.com/Stephen-Seo/mpd_info_screen"
|
repository = "https://github.com/Stephen-Seo/mpd_info_screen"
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
structopt = "0.3"
|
structopt = "0.3"
|
||||||
image = "0.24"
|
image = "0.24"
|
||||||
ggez = "0.7"
|
ggez = "0.8.1"
|
||||||
freetype = { version = "0.7", optional = true }
|
freetype = { version = "0.7", optional = true }
|
||||||
|
wgpu = "0.14"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
bindgen = { version = "0.53", optional = true }
|
bindgen = { version = "0.53", optional = true }
|
||||||
|
|
246
src/display.rs
246
src/display.rs
|
@ -1,12 +1,14 @@
|
||||||
use crate::debug_log::{self, log};
|
use crate::debug_log::{self, log};
|
||||||
use crate::mpd_handler::{InfoFromShared, MPDHandler, MPDHandlerState, MPDPlayState};
|
use crate::mpd_handler::{InfoFromShared, MPDHandler, MPDHandlerState, MPDPlayState};
|
||||||
use crate::Opt;
|
use crate::Opt;
|
||||||
use ggez::event::{self, EventHandler};
|
use ggez::event::EventHandler;
|
||||||
use ggez::graphics::{
|
use ggez::graphics::{
|
||||||
self, Color, DrawMode, DrawParam, Drawable, Font, Image, Mesh, MeshBuilder, PxScale, Rect,
|
self, Color, DrawMode, DrawParam, Drawable, FontData, Image, Mesh, MeshBuilder, PxScale, Rect,
|
||||||
Text, TextFragment, Transform,
|
Text, TextFragment, Transform,
|
||||||
};
|
};
|
||||||
use ggez::{timer, Context, GameError, GameResult};
|
use ggez::input::keyboard::{self, KeyInput};
|
||||||
|
use ggez::mint::Vector2;
|
||||||
|
use ggez::{Context, GameError, GameResult};
|
||||||
use image::io::Reader as ImageReader;
|
use image::io::Reader as ImageReader;
|
||||||
use image::DynamicImage;
|
use image::DynamicImage;
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
@ -56,7 +58,7 @@ fn seconds_to_time(seconds: f64) -> String {
|
||||||
#[allow(clippy::ptr_arg)]
|
#[allow(clippy::ptr_arg)]
|
||||||
fn string_to_text(
|
fn string_to_text(
|
||||||
string: String,
|
string: String,
|
||||||
_loaded_fonts: &mut Vec<(PathBuf, Font)>,
|
_loaded_fonts: &mut Vec<(PathBuf, String)>,
|
||||||
_ctx: &mut Context,
|
_ctx: &mut Context,
|
||||||
) -> Text {
|
) -> Text {
|
||||||
Text::new(TextFragment::from(string))
|
Text::new(TextFragment::from(string))
|
||||||
|
@ -65,7 +67,7 @@ fn string_to_text(
|
||||||
#[cfg(feature = "unicode_support")]
|
#[cfg(feature = "unicode_support")]
|
||||||
fn string_to_text(
|
fn string_to_text(
|
||||||
string: String,
|
string: String,
|
||||||
loaded_fonts: &mut Vec<(PathBuf, Font)>,
|
loaded_fonts: &mut Vec<(PathBuf, String)>,
|
||||||
ctx: &mut Context,
|
ctx: &mut Context,
|
||||||
) -> Text {
|
) -> Text {
|
||||||
use super::unicode_support;
|
use super::unicode_support;
|
||||||
|
@ -80,7 +82,7 @@ fn string_to_text(
|
||||||
}
|
}
|
||||||
|
|
||||||
let find_font =
|
let find_font =
|
||||||
|c: char, loaded_fonts: &mut Vec<(PathBuf, Font)>, ctx: &mut Context| -> Option<usize> {
|
|c: char, loaded_fonts: &mut Vec<(PathBuf, String)>, ctx: &mut Context| -> Option<usize> {
|
||||||
for (idx, (path, _)) in loaded_fonts.iter().enumerate() {
|
for (idx, (path, _)) in loaded_fonts.iter().enumerate() {
|
||||||
let result = unicode_support::font_has_char(c, path);
|
let result = unicode_support::font_has_char(c, path);
|
||||||
if result.is_ok() && result.unwrap() {
|
if result.is_ok() && result.unwrap() {
|
||||||
|
@ -90,9 +92,16 @@ fn string_to_text(
|
||||||
|
|
||||||
let find_result = unicode_support::get_matching_font_from_char(c);
|
let find_result = unicode_support::get_matching_font_from_char(c);
|
||||||
if let Ok(path) = find_result {
|
if let Ok(path) = find_result {
|
||||||
let new_font = Font::new(ctx, &path);
|
let new_font = FontData::from_path(ctx, &path);
|
||||||
if let Ok(font) = new_font {
|
if let Ok(font) = new_font {
|
||||||
loaded_fonts.push((path, font));
|
let font_name: String = path
|
||||||
|
.file_name()
|
||||||
|
.expect("Should be valid filename at end of Font path.")
|
||||||
|
.to_str()
|
||||||
|
.expect("Font filename should be valid unicode.")
|
||||||
|
.to_owned();
|
||||||
|
ctx.gfx.add_font(&font_name, font);
|
||||||
|
loaded_fonts.push((path, font_name));
|
||||||
return Some(loaded_fonts.len() - 1);
|
return Some(loaded_fonts.len() - 1);
|
||||||
} else {
|
} else {
|
||||||
log(
|
log(
|
||||||
|
@ -133,13 +142,13 @@ fn string_to_text(
|
||||||
text.add(current_fragment);
|
text.add(current_fragment);
|
||||||
current_fragment = Default::default();
|
current_fragment = Default::default();
|
||||||
}
|
}
|
||||||
let (_, font) = loaded_fonts[idx];
|
let (_, font) = &loaded_fonts[idx];
|
||||||
current_fragment.font = Some(font);
|
current_fragment.font = Some(font.clone());
|
||||||
}
|
}
|
||||||
current_fragment.text.push(c);
|
current_fragment.text.push(c);
|
||||||
} else if let Some(idx) = idx_opt {
|
} else if let Some(idx) = idx_opt {
|
||||||
let font = loaded_fonts[idx].1;
|
let font = &loaded_fonts[idx].1;
|
||||||
if let Some(current_font) = current_fragment.font {
|
if let Some(current_font) = current_fragment.font.as_ref() {
|
||||||
if current_font == font {
|
if current_font == font {
|
||||||
current_fragment.text.push(c);
|
current_fragment.text.push(c);
|
||||||
} else {
|
} else {
|
||||||
|
@ -148,17 +157,17 @@ fn string_to_text(
|
||||||
current_fragment = Default::default();
|
current_fragment = Default::default();
|
||||||
}
|
}
|
||||||
current_fragment.text.push(c);
|
current_fragment.text.push(c);
|
||||||
current_fragment.font = Some(font);
|
current_fragment.font = Some(font.clone());
|
||||||
}
|
}
|
||||||
} else if current_fragment.text.is_empty() {
|
} else if current_fragment.text.is_empty() {
|
||||||
current_fragment.text.push(c);
|
current_fragment.text.push(c);
|
||||||
current_fragment.font = Some(font);
|
current_fragment.font = Some(font.clone());
|
||||||
} else {
|
} else {
|
||||||
text.add(current_fragment);
|
text.add(current_fragment);
|
||||||
current_fragment = Default::default();
|
current_fragment = Default::default();
|
||||||
|
|
||||||
current_fragment.text.push(c);
|
current_fragment.text.push(c);
|
||||||
current_fragment.font = Some(font);
|
current_fragment.font = Some(font.clone());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if !current_fragment.text.is_empty() && current_fragment.font.is_some() {
|
if !current_fragment.text.is_empty() && current_fragment.font.is_some() {
|
||||||
|
@ -213,7 +222,7 @@ pub struct MPDDisplay {
|
||||||
hide_text: bool,
|
hide_text: bool,
|
||||||
tried_album_art_in_dir: bool,
|
tried_album_art_in_dir: bool,
|
||||||
mpd_play_state: MPDPlayState,
|
mpd_play_state: MPDPlayState,
|
||||||
loaded_fonts: Vec<(PathBuf, Font)>,
|
loaded_fonts: Vec<(PathBuf, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MPDDisplay {
|
impl MPDDisplay {
|
||||||
|
@ -292,24 +301,24 @@ impl MPDDisplay {
|
||||||
fn get_album_art_transform(&mut self, ctx: &mut Context, fill_scaled: bool) {
|
fn get_album_art_transform(&mut self, ctx: &mut Context, fill_scaled: bool) {
|
||||||
if fill_scaled {
|
if fill_scaled {
|
||||||
if let Some(image) = &self.album_art {
|
if let Some(image) = &self.album_art {
|
||||||
let screen_coords: Rect = graphics::screen_coordinates(ctx);
|
let drawable_size = ctx.gfx.drawable_size();
|
||||||
let art_rect: Rect = image.dimensions();
|
let art_rect: Rect = image.dimensions(ctx).expect("Image should have dimensions");
|
||||||
|
|
||||||
// try to fit to width first
|
// try to fit to width first
|
||||||
let mut x_scale = screen_coords.w / art_rect.w;
|
let mut x_scale = drawable_size.0 / art_rect.w;
|
||||||
let mut y_scale = x_scale;
|
let mut y_scale = x_scale;
|
||||||
let mut new_width = art_rect.w * x_scale;
|
let mut new_width = art_rect.w * x_scale;
|
||||||
let mut new_height = art_rect.h * y_scale;
|
let mut new_height = art_rect.h * y_scale;
|
||||||
if new_height > screen_coords.h.abs() {
|
if new_height > drawable_size.1.abs() {
|
||||||
// fit to height instead
|
// fit to height instead
|
||||||
y_scale = screen_coords.h.abs() / art_rect.h;
|
y_scale = drawable_size.1.abs() / art_rect.h;
|
||||||
x_scale = y_scale;
|
x_scale = y_scale;
|
||||||
new_width = art_rect.w * x_scale;
|
new_width = art_rect.w * x_scale;
|
||||||
new_height = art_rect.h * y_scale;
|
new_height = art_rect.h * y_scale;
|
||||||
}
|
}
|
||||||
|
|
||||||
let offset_x: f32 = (screen_coords.w.abs() - new_width) / 2.0f32;
|
let offset_x: f32 = (drawable_size.0.abs() - new_width) / 2.0f32;
|
||||||
let offset_y: f32 = (screen_coords.h.abs() - new_height) / 2.0f32;
|
let offset_y: f32 = (drawable_size.1.abs() - new_height) / 2.0f32;
|
||||||
|
|
||||||
self.album_art_draw_transform = Some(Transform::Values {
|
self.album_art_draw_transform = Some(Transform::Values {
|
||||||
dest: [offset_x, offset_y].into(),
|
dest: [offset_x, offset_y].into(),
|
||||||
|
@ -321,10 +330,10 @@ impl MPDDisplay {
|
||||||
self.album_art_draw_transform = None;
|
self.album_art_draw_transform = None;
|
||||||
}
|
}
|
||||||
} else if let Some(image) = &self.album_art {
|
} else if let Some(image) = &self.album_art {
|
||||||
let screen_coords: Rect = graphics::screen_coordinates(ctx);
|
let drawable_size = ctx.gfx.drawable_size();
|
||||||
let art_rect: Rect = image.dimensions();
|
let art_rect: Rect = image.dimensions(ctx).expect("Image should have dimensions");
|
||||||
let offset_x: f32 = (screen_coords.w.abs() - art_rect.w.abs()) / 2.0f32;
|
let offset_x: f32 = (drawable_size.0.abs() - art_rect.w.abs()) / 2.0f32;
|
||||||
let offset_y: f32 = (screen_coords.h.abs() - art_rect.h.abs()) / 2.0f32;
|
let offset_y: f32 = (drawable_size.1.abs() - art_rect.h.abs()) / 2.0f32;
|
||||||
self.album_art_draw_transform = Some(Transform::Values {
|
self.album_art_draw_transform = Some(Transform::Values {
|
||||||
dest: [offset_x, offset_y].into(),
|
dest: [offset_x, offset_y].into(),
|
||||||
rotation: 0.0f32,
|
rotation: 0.0f32,
|
||||||
|
@ -430,13 +439,13 @@ impl MPDDisplay {
|
||||||
}
|
}
|
||||||
let img = img_result?;
|
let img = img_result?;
|
||||||
let rgba8 = img.to_rgba8();
|
let rgba8 = img.to_rgba8();
|
||||||
let ggez_img = Image::from_rgba8(
|
let ggez_img = Image::from_pixels(
|
||||||
ctx,
|
ctx,
|
||||||
rgba8.width() as u16,
|
|
||||||
rgba8.height() as u16,
|
|
||||||
rgba8.as_raw(),
|
rgba8.as_raw(),
|
||||||
)
|
wgpu::TextureFormat::Rgba8Unorm,
|
||||||
.map_err(|e| format!("Error: Failed to load album art image in ggez Image: {}", e))?;
|
rgba8.width(),
|
||||||
|
rgba8.height(),
|
||||||
|
);
|
||||||
|
|
||||||
self.album_art = Some(ggez_img);
|
self.album_art = Some(ggez_img);
|
||||||
|
|
||||||
|
@ -444,14 +453,14 @@ impl MPDDisplay {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn refresh_text_transforms(&mut self, ctx: &mut Context) -> GameResult<()> {
|
fn refresh_text_transforms(&mut self, ctx: &mut Context) -> GameResult<()> {
|
||||||
let screen_coords: Rect = graphics::screen_coordinates(ctx);
|
let drawable_size = ctx.gfx.drawable_size();
|
||||||
|
|
||||||
let text_height_limit = TEXT_HEIGHT_SCALE * screen_coords.h.abs();
|
let text_height_limit = TEXT_HEIGHT_SCALE * drawable_size.1.abs();
|
||||||
let album_height_limit = ALBUM_HEIGHT_SCALE * screen_coords.h.abs();
|
let album_height_limit = ALBUM_HEIGHT_SCALE * drawable_size.1.abs();
|
||||||
let artist_height_limit = ARTIST_HEIGHT_SCALE * screen_coords.h.abs();
|
let artist_height_limit = ARTIST_HEIGHT_SCALE * drawable_size.1.abs();
|
||||||
let timer_height = TIMER_HEIGHT_SCALE * screen_coords.h.abs();
|
let timer_height = TIMER_HEIGHT_SCALE * drawable_size.1.abs();
|
||||||
|
|
||||||
let mut offset_y: f32 = screen_coords.h;
|
let mut offset_y: f32 = drawable_size.1;
|
||||||
|
|
||||||
let mut filename_y: f32 = 0.0;
|
let mut filename_y: f32 = 0.0;
|
||||||
let mut album_y: f32 = 0.0;
|
let mut album_y: f32 = 0.0;
|
||||||
|
@ -470,8 +479,7 @@ impl MPDDisplay {
|
||||||
timer_y: &mut f32| {
|
timer_y: &mut f32| {
|
||||||
let mut current_x = INIT_FONT_SIZE_X;
|
let mut current_x = INIT_FONT_SIZE_X;
|
||||||
let mut current_y = INIT_FONT_SIZE_Y;
|
let mut current_y = INIT_FONT_SIZE_Y;
|
||||||
let mut width: f32;
|
let mut width_height: Vector2<f32> = Vector2 { x: 0.0, y: 0.0 };
|
||||||
let mut height: f32 = 0.0;
|
|
||||||
let mut iteration_count: u8 = 0;
|
let mut iteration_count: u8 = 0;
|
||||||
loop {
|
loop {
|
||||||
iteration_count += 1;
|
iteration_count += 1;
|
||||||
|
@ -485,12 +493,13 @@ impl MPDDisplay {
|
||||||
y: current_y,
|
y: current_y,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
width = text.width(ctx);
|
width_height = text
|
||||||
height = text.height(ctx);
|
.measure(ctx)
|
||||||
|
.expect("Should be able to get width/height of text.");
|
||||||
|
|
||||||
if is_string {
|
if is_string {
|
||||||
if screen_coords.w < width
|
if drawable_size.0 < width_height.x
|
||||||
|| height
|
|| width_height.y
|
||||||
>= (if is_artist {
|
>= (if is_artist {
|
||||||
artist_height_limit
|
artist_height_limit
|
||||||
} else if is_album {
|
} else if is_album {
|
||||||
|
@ -502,7 +511,7 @@ impl MPDDisplay {
|
||||||
current_x *= DECREASE_AMT;
|
current_x *= DECREASE_AMT;
|
||||||
current_y *= DECREASE_AMT;
|
current_y *= DECREASE_AMT;
|
||||||
continue;
|
continue;
|
||||||
} else if screen_coords.w * MIN_WIDTH_RATIO > width {
|
} else if drawable_size.0 * MIN_WIDTH_RATIO > width_height.x {
|
||||||
current_x *= INCREASE_AMT;
|
current_x *= INCREASE_AMT;
|
||||||
current_y *= INCREASE_AMT;
|
current_y *= INCREASE_AMT;
|
||||||
continue;
|
continue;
|
||||||
|
@ -510,7 +519,7 @@ impl MPDDisplay {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let diff_scale_y = current_y / height * timer_height;
|
let diff_scale_y = current_y / width_height.y * timer_height;
|
||||||
let current_x = current_x * diff_scale_y / current_y;
|
let current_x = current_x * diff_scale_y / current_y;
|
||||||
for fragment in text.fragments_mut() {
|
for fragment in text.fragments_mut() {
|
||||||
fragment.scale = Some(PxScale {
|
fragment.scale = Some(PxScale {
|
||||||
|
@ -521,20 +530,23 @@ impl MPDDisplay {
|
||||||
*timer_x = current_x;
|
*timer_x = current_x;
|
||||||
*timer_y = diff_scale_y;
|
*timer_y = diff_scale_y;
|
||||||
// width = text.width(ctx); // not really used after this
|
// width = text.width(ctx); // not really used after this
|
||||||
height = text.height(ctx);
|
width_height.y = text
|
||||||
|
.measure(ctx)
|
||||||
|
.expect("Should be able to get width/height of text.")
|
||||||
|
.y;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*y = *offset_y - height;
|
*y = *offset_y - width_height.y;
|
||||||
*transform = Transform::Values {
|
*transform = Transform::Values {
|
||||||
dest: [TEXT_X_OFFSET, *offset_y - height].into(),
|
dest: [TEXT_X_OFFSET, *offset_y - width_height.y].into(),
|
||||||
rotation: 0.0,
|
rotation: 0.0,
|
||||||
scale: [1.0, 1.0].into(),
|
scale: [1.0, 1.0].into(),
|
||||||
offset: [0.0, 0.0].into(),
|
offset: [0.0, 0.0].into(),
|
||||||
};
|
};
|
||||||
|
|
||||||
*offset_y -= height + TEXT_OFFSET_Y_SPACING;
|
*offset_y -= width_height.y + TEXT_OFFSET_Y_SPACING;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !self.filename_text.contents().is_empty() && !self.opts.disable_show_filename {
|
if !self.filename_text.contents().is_empty() && !self.opts.disable_show_filename {
|
||||||
|
@ -623,11 +635,26 @@ impl MPDDisplay {
|
||||||
&mut self.timer_y,
|
&mut self.timer_y,
|
||||||
);
|
);
|
||||||
|
|
||||||
let filename_dimensions = self.filename_text.dimensions(ctx);
|
let filename_dimensions = self
|
||||||
let album_dimensions = self.album_text.dimensions(ctx);
|
.filename_text
|
||||||
let artist_dimensions = self.artist_text.dimensions(ctx);
|
.dimensions(ctx)
|
||||||
let title_dimensions = self.title_text.dimensions(ctx);
|
.expect("Should be able to get dimensions of Text.");
|
||||||
let timer_dimensions = self.timer_text.dimensions(ctx);
|
let album_dimensions = self
|
||||||
|
.album_text
|
||||||
|
.dimensions(ctx)
|
||||||
|
.expect("Should be able to get dimensions of Text.");
|
||||||
|
let artist_dimensions = self
|
||||||
|
.artist_text
|
||||||
|
.dimensions(ctx)
|
||||||
|
.expect("Should be able to get dimensions of Text.");
|
||||||
|
let title_dimensions = self
|
||||||
|
.title_text
|
||||||
|
.dimensions(ctx)
|
||||||
|
.expect("Should be able to get dimensions of Text.");
|
||||||
|
let timer_dimensions = self
|
||||||
|
.timer_text
|
||||||
|
.dimensions(ctx)
|
||||||
|
.expect("Should be able to get dimensions of Text.");
|
||||||
|
|
||||||
let mut mesh_builder: MeshBuilder = MeshBuilder::new();
|
let mut mesh_builder: MeshBuilder = MeshBuilder::new();
|
||||||
if !self.opts.disable_show_filename {
|
if !self.opts.disable_show_filename {
|
||||||
|
@ -678,7 +705,9 @@ impl MPDDisplay {
|
||||||
Color::from_rgba(0, 0, 0, self.opts.text_bg_opacity),
|
Color::from_rgba(0, 0, 0, self.opts.text_bg_opacity),
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
let mesh: Mesh = mesh_builder
|
let mesh: Mesh = Mesh::from_data(
|
||||||
|
ctx,
|
||||||
|
mesh_builder
|
||||||
.rectangle(
|
.rectangle(
|
||||||
DrawMode::fill(),
|
DrawMode::fill(),
|
||||||
Rect {
|
Rect {
|
||||||
|
@ -689,7 +718,8 @@ impl MPDDisplay {
|
||||||
},
|
},
|
||||||
Color::from_rgba(0, 0, 0, self.opts.text_bg_opacity),
|
Color::from_rgba(0, 0, 0, self.opts.text_bg_opacity),
|
||||||
)?
|
)?
|
||||||
.build(ctx)?;
|
.build(),
|
||||||
|
);
|
||||||
|
|
||||||
self.text_bg_mesh = Some(mesh);
|
self.text_bg_mesh = Some(mesh);
|
||||||
|
|
||||||
|
@ -889,102 +919,99 @@ impl EventHandler for MPDDisplay {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let delta = timer::delta(ctx);
|
let delta = ctx.time.delta();
|
||||||
self.timer += delta.as_secs_f64();
|
self.timer += delta.as_secs_f64();
|
||||||
let timer_diff = seconds_to_time(self.length - self.timer);
|
let timer_diff = seconds_to_time(self.length - self.timer);
|
||||||
self.timer_text = Text::new(timer_diff);
|
self.timer_text = Text::new(timer_diff);
|
||||||
self.timer_text.set_font(
|
self.timer_text.set_scale(PxScale {
|
||||||
Font::default(),
|
|
||||||
PxScale {
|
|
||||||
x: self.timer_x,
|
x: self.timer_x,
|
||||||
y: self.timer_y,
|
y: self.timer_y,
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> {
|
fn draw(&mut self, ctx: &mut ggez::Context) -> Result<(), GameError> {
|
||||||
graphics::clear(ctx, Color::BLACK);
|
let mut canvas = graphics::Canvas::from_frame(ctx, Color::BLACK);
|
||||||
|
|
||||||
if self.mpd_play_state != MPDPlayState::Stopped
|
if self.mpd_play_state != MPDPlayState::Stopped
|
||||||
&& self.album_art.is_some()
|
&& self.album_art.is_some()
|
||||||
&& self.album_art_draw_transform.is_some()
|
&& self.album_art_draw_transform.is_some()
|
||||||
{
|
{
|
||||||
self.album_art.as_ref().unwrap().draw(
|
canvas.draw(
|
||||||
ctx,
|
self.album_art.as_ref().unwrap(),
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.album_art_draw_transform.unwrap(),
|
transform: self.album_art_draw_transform.unwrap(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.hide_text {
|
if !self.hide_text {
|
||||||
self.notice_text.draw(ctx, DrawParam::default())?;
|
canvas.draw(&self.notice_text, DrawParam::default());
|
||||||
|
|
||||||
if self.mpd_play_state != MPDPlayState::Stopped && self.is_valid && self.is_initialized
|
if self.mpd_play_state != MPDPlayState::Stopped && self.is_valid && self.is_initialized
|
||||||
{
|
{
|
||||||
if let Some(mesh) = &self.text_bg_mesh {
|
if let Some(mesh) = &self.text_bg_mesh {
|
||||||
mesh.draw(ctx, DrawParam::default())?;
|
canvas.draw(mesh, DrawParam::default());
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.opts.disable_show_filename {
|
if !self.opts.disable_show_filename {
|
||||||
self.filename_text.draw(
|
canvas.draw(
|
||||||
ctx,
|
&self.filename_text,
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.filename_transform,
|
transform: self.filename_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.opts.disable_show_album {
|
if !self.opts.disable_show_album {
|
||||||
self.album_text.draw(
|
canvas.draw(
|
||||||
ctx,
|
&self.album_text,
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.album_transform,
|
transform: self.album_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.opts.disable_show_artist {
|
if !self.opts.disable_show_artist {
|
||||||
self.artist_text.draw(
|
canvas.draw(
|
||||||
ctx,
|
&self.artist_text,
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.artist_transform,
|
transform: self.artist_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !self.opts.disable_show_title {
|
if !self.opts.disable_show_title {
|
||||||
self.title_text.draw(
|
canvas.draw(
|
||||||
ctx,
|
&self.title_text,
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.title_transform,
|
transform: self.title_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.mpd_play_state == MPDPlayState::Playing {
|
if self.mpd_play_state == MPDPlayState::Playing {
|
||||||
self.timer_text.draw(
|
canvas.draw(
|
||||||
ctx,
|
&self.timer_text,
|
||||||
DrawParam {
|
DrawParam {
|
||||||
trans: self.timer_transform,
|
transform: self.timer_transform,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
},
|
||||||
)?;
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
graphics::present(ctx)
|
canvas.finish(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn text_input_event(&mut self, _ctx: &mut Context, character: char) {
|
fn text_input_event(&mut self, _ctx: &mut Context, character: char) -> Result<(), GameError> {
|
||||||
if !self.is_initialized && self.opts.enable_prompt_password && !character.is_control() {
|
if !self.is_initialized && self.opts.enable_prompt_password && !character.is_control() {
|
||||||
if self.opts.password.is_none() {
|
if self.opts.password.is_none() {
|
||||||
let s = String::from(character);
|
let s = String::from(character);
|
||||||
|
@ -995,17 +1022,18 @@ impl EventHandler for MPDDisplay {
|
||||||
self.notice_text.add('*');
|
self.notice_text.add('*');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_down_event(
|
fn key_down_event(
|
||||||
&mut self,
|
&mut self,
|
||||||
_ctx: &mut Context,
|
_ctx: &mut Context,
|
||||||
keycode: event::KeyCode,
|
input: KeyInput,
|
||||||
_keymods: event::KeyMods,
|
|
||||||
_repeat: bool,
|
_repeat: bool,
|
||||||
) {
|
) -> Result<(), GameError> {
|
||||||
if !self.is_initialized && self.opts.enable_prompt_password {
|
if !self.is_initialized && self.opts.enable_prompt_password {
|
||||||
if keycode == event::KeyCode::Back {
|
if input.keycode == Some(keyboard::KeyCode::Back) {
|
||||||
let s: String = self.notice_text.contents();
|
let s: String = self.notice_text.contents();
|
||||||
|
|
||||||
if s.ends_with('*') {
|
if s.ends_with('*') {
|
||||||
|
@ -1015,28 +1043,34 @@ impl EventHandler for MPDDisplay {
|
||||||
if let Some(input_p) = &mut self.opts.password {
|
if let Some(input_p) = &mut self.opts.password {
|
||||||
input_p.pop();
|
input_p.pop();
|
||||||
}
|
}
|
||||||
} else if keycode == event::KeyCode::Return {
|
} else if input.keycode == Some(keyboard::KeyCode::Return) {
|
||||||
self.password_entered = true;
|
self.password_entered = true;
|
||||||
}
|
}
|
||||||
} else if keycode == event::KeyCode::H {
|
} else if input.keycode == Some(keyboard::KeyCode::H) {
|
||||||
self.hide_text = true;
|
self.hide_text = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn key_up_event(
|
fn key_up_event(&mut self, _ctx: &mut Context, input: KeyInput) -> Result<(), GameError> {
|
||||||
&mut self,
|
if input.keycode == Some(keyboard::KeyCode::H) {
|
||||||
_ctx: &mut Context,
|
|
||||||
keycode: event::KeyCode,
|
|
||||||
_keymods: event::KeyMods,
|
|
||||||
) {
|
|
||||||
if keycode == event::KeyCode::H {
|
|
||||||
self.hide_text = false;
|
self.hide_text = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize_event(&mut self, ctx: &mut Context, _width: f32, _height: f32) {
|
fn resize_event(
|
||||||
|
&mut self,
|
||||||
|
ctx: &mut Context,
|
||||||
|
_width: f32,
|
||||||
|
_height: f32,
|
||||||
|
) -> Result<(), GameError> {
|
||||||
self.get_album_art_transform(ctx, !self.opts.do_not_fill_scale_album_art);
|
self.get_album_art_transform(ctx, !self.opts.do_not_fill_scale_album_art);
|
||||||
self.refresh_text_transforms(ctx)
|
self.refresh_text_transforms(ctx)
|
||||||
.expect("Failed to set text transforms");
|
.expect("Failed to set text transforms");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
44
src/main.rs
44
src/main.rs
|
@ -7,8 +7,7 @@ mod unicode_support;
|
||||||
use ggez::conf::{WindowMode, WindowSetup};
|
use ggez::conf::{WindowMode, WindowSetup};
|
||||||
use ggez::event::winit_event::{ElementState, KeyboardInput, ModifiersState};
|
use ggez::event::winit_event::{ElementState, KeyboardInput, ModifiersState};
|
||||||
use ggez::event::{self, ControlFlow, EventHandler};
|
use ggez::event::{self, ControlFlow, EventHandler};
|
||||||
use ggez::filesystem::mount;
|
use ggez::input::keyboard::{self, KeyInput};
|
||||||
use ggez::graphics::{self, Rect};
|
|
||||||
use ggez::{ContextBuilder, GameError};
|
use ggez::{ContextBuilder, GameError};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -75,7 +74,7 @@ fn main() -> Result<(), String> {
|
||||||
.expect("Failed to create ggez context");
|
.expect("Failed to create ggez context");
|
||||||
|
|
||||||
// mount "/" read-only so that fonts can be loaded via absolute paths
|
// mount "/" read-only so that fonts can be loaded via absolute paths
|
||||||
mount(&mut ctx, &PathBuf::from("/"), true);
|
ctx.fs.mount(&PathBuf::from("/"), true);
|
||||||
|
|
||||||
let mut display = display::MPDDisplay::new(&mut ctx, opt.clone());
|
let mut display = display::MPDDisplay::new(&mut ctx, opt.clone());
|
||||||
|
|
||||||
|
@ -94,7 +93,7 @@ fn main() -> Result<(), String> {
|
||||||
event::process_event(ctx, &mut event);
|
event::process_event(ctx, &mut event);
|
||||||
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 => ctx.request_quit(),
|
||||||
event::winit_event::WindowEvent::ModifiersChanged(state) => {
|
event::winit_event::WindowEvent::ModifiersChanged(state) => {
|
||||||
modifiers_state = state;
|
modifiers_state = state;
|
||||||
}
|
}
|
||||||
|
@ -108,31 +107,31 @@ fn main() -> Result<(), String> {
|
||||||
},
|
},
|
||||||
is_synthetic: _,
|
is_synthetic: _,
|
||||||
} => {
|
} => {
|
||||||
if keycode == event::KeyCode::Escape {
|
if keycode == keyboard::KeyCode::Escape {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
let ki = KeyInput {
|
||||||
|
scancode: 0,
|
||||||
|
keycode: Some(keycode),
|
||||||
|
mods: From::from(modifiers_state),
|
||||||
|
};
|
||||||
if state == ElementState::Pressed {
|
if state == ElementState::Pressed {
|
||||||
display.key_down_event(ctx, keycode, modifiers_state.into(), false);
|
display.key_down_event(ctx, ki, false).ok();
|
||||||
} else {
|
} else {
|
||||||
display.key_up_event(ctx, keycode, modifiers_state.into());
|
display.key_up_event(ctx, ki).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event::winit_event::WindowEvent::Resized(phys_size) => {
|
event::winit_event::WindowEvent::Resized(phys_size) => {
|
||||||
graphics::set_screen_coordinates(
|
ctx.gfx
|
||||||
ctx,
|
.set_drawable_size(phys_size.width as f32, phys_size.height as f32)
|
||||||
Rect {
|
.ok();
|
||||||
x: 0.0,
|
display
|
||||||
y: 0.0,
|
.resize_event(ctx, phys_size.width as f32, phys_size.height as f32)
|
||||||
w: phys_size.width as f32,
|
.ok();
|
||||||
h: phys_size.height as f32,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.expect("Failed to handle resizing window");
|
|
||||||
display.resize_event(ctx, phys_size.width as f32, phys_size.height as f32);
|
|
||||||
}
|
}
|
||||||
event::winit_event::WindowEvent::ReceivedCharacter(ch) => {
|
event::winit_event::WindowEvent::ReceivedCharacter(ch) => {
|
||||||
display.text_input_event(ctx, ch);
|
display.text_input_event(ctx, ch).ok();
|
||||||
}
|
}
|
||||||
x => log(
|
x => log(
|
||||||
format!("Other window event fired: {:?}", x),
|
format!("Other window event fired: {:?}", x),
|
||||||
|
@ -141,7 +140,7 @@ fn main() -> Result<(), String> {
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
event::winit_event::Event::MainEventsCleared => {
|
event::winit_event::Event::MainEventsCleared => {
|
||||||
ctx.timer_context.tick();
|
ctx.time.tick();
|
||||||
|
|
||||||
let mut game_result: Result<(), GameError> = display.update(ctx);
|
let mut game_result: Result<(), GameError> = display.update(ctx);
|
||||||
if game_result.is_err() {
|
if game_result.is_err() {
|
||||||
|
@ -149,14 +148,17 @@ fn main() -> Result<(), String> {
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctx.gfx.begin_frame().unwrap();
|
||||||
game_result = display.draw(ctx);
|
game_result = display.draw(ctx);
|
||||||
if game_result.is_err() {
|
if game_result.is_err() {
|
||||||
println!("Error draw: {}", game_result.unwrap_err());
|
println!("Error draw: {}", game_result.unwrap_err());
|
||||||
*control_flow = ControlFlow::Exit;
|
*control_flow = ControlFlow::Exit;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ctx.gfx.end_frame().unwrap();
|
||||||
|
|
||||||
ctx.mouse_context.reset_delta();
|
ctx.mouse.reset_delta();
|
||||||
|
|
||||||
// sleep to force ~5 fps
|
// sleep to force ~5 fps
|
||||||
thread::sleep(Duration::from_millis(200));
|
thread::sleep(Duration::from_millis(200));
|
||||||
|
|
Loading…
Reference in a new issue