Skip to content

Commit

Permalink
Merge branch 'main' into barebones
Browse files Browse the repository at this point in the history
  • Loading branch information
CaspianA1 committed Jul 1, 2024
2 parents 07dbaaa + b72daf0 commit df2b58a
Show file tree
Hide file tree
Showing 19 changed files with 98 additions and 78 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ rand = "0.8.5"
regex = "1.10.3"
base64 = "0.21.7"
chrono = "0.4.35"
anyhow = {version = "1.0", features = ["backtrace"]}

# To make life easier:
lazy_static = "1.4.0"
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ Or with logging:
- Investigate the occasionally high CPU usage on the Pi (like 300%!)
- Could multiple update rates per window be useful?
- CD to Pi?
- Format all debug types with `<varname>:?` when possible

- Fun ideas:
- Run the dashboard on a PVM, or an original iMac, eventually?
Expand Down
4 changes: 2 additions & 2 deletions src/dashboard_defs/clock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ use crate::{

utility_types::{
vec2f::Vec2f,
generic_result::*,
update_rate::UpdateRate,
dynamic_optional::DynamicOptional,
generic_result::{GenericResult, MaybeError}
dynamic_optional::DynamicOptional
},

dashboard_defs::shared_window_state::SharedWindowState
Expand Down
2 changes: 1 addition & 1 deletion src/dashboard_defs/dashboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::{
utility_types::{
json_utils,
vec2f::Vec2f,
generic_result::*,
dynamic_optional::DynamicOptional,
generic_result::{GenericResult, MaybeError},
update_rate::{UpdateRate, UpdateRateCreator}
},

Expand Down
2 changes: 1 addition & 1 deletion src/dashboard_defs/spinitron.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ use crate::{

utility_types::{
vec2f::Vec2f,
generic_result::*,
update_rate::UpdateRate,
generic_result::MaybeError,
dynamic_optional::DynamicOptional
},

Expand Down
16 changes: 8 additions & 8 deletions src/dashboard_defs/surprise.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,20 @@ use crate::{
},

utility_types::{
generic_result::*,
dynamic_optional::DynamicOptional,
vec2f::{Vec2f, assert_in_unit_interval},
update_rate::{UpdateRateCreator, Seconds},
generic_result::{GenericResult, MaybeError}
update_rate::{Seconds, UpdateRateCreator}
},

texture::{TexturePool, TextureCreationInfo},
dashboard_defs::shared_window_state::SharedWindowState
};

/* Note: some surprises may take somewhat long to be
triggered if their update rates are relatively infrequent. */
triggered if their update rates are relatively infrequent.
TODO: make a separate updater for just getting the artificial
triggering going (this will be the socket-polling updater). */

type NumAppearanceSteps = u16;
type SurpriseAppearanceChance = f64; // 0 to 1
Expand Down Expand Up @@ -109,8 +111,6 @@ pub fn make_surprise_window(

////////// The core updater function that runs once every N milliseconds for each surprise

// TODO: make a separate updater for just getting the artificial triggering going (this will be the socket-polling updater)

fn updater_fn(params: WindowUpdaterParams) -> MaybeError {
let surprise_info = params.window.get_state_mut::<SurpriseInfo>();
let rand_generator = &mut params.shared_window_state.get_mut::<SharedWindowState>().rand_generator;
Expand Down Expand Up @@ -184,7 +184,7 @@ pub fn make_surprise_window(
let surprise_path_set: HashSet<SurprisePath> = surprise_paths.iter().map(Rc::clone).collect();

if surprise_path_set.len() != surprise_creation_info.len() {
return Err("There are duplicate paths in the set of surprises".into());
return error_msg!("There are duplicate paths in the set of surprises");
}

////////// Setting up the shared surprise info that can be triggered via signals
Expand All @@ -197,12 +197,12 @@ pub fn make_surprise_window(
Ok(listener) => listener,

Err(err) => {
return Err(format!(
return error_msg!(
"Could not create a surprise stream listener. \
Perhaps the socket at '{artificial_triggering_socket_path}' is already in use, or \
maybe it was still around from a crash? \
Official error: '{err}'."
).into());
);
}
};

Expand Down
7 changes: 4 additions & 3 deletions src/dashboard_defs/twilio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ use crate::{
request,

utility_types::{
vec2f::Vec2f,
generic_result::*,
update_rate::UpdateRate,
dynamic_optional::DynamicOptional,
update_rate::UpdateRate, vec2f::Vec2f,
generic_result::{GenericResult, MaybeError},
thread_task::{ContinuallyUpdated, Updatable}
},

Expand Down Expand Up @@ -652,7 +653,7 @@ pub fn make_twilio_window(

assert!(phone_numbers.len() == 1);

let number = phone_numbers[0]["phone_number"].as_str().ok_or("Expected the phone number to be a string!")?;
let number = phone_numbers[0]["phone_number"].as_str().context("Expected the phone number to be a string!")?;
let formatted_number = TwilioStateData::format_phone_number(number, "Messages to ", ":", "");

//////////
Expand Down
2 changes: 1 addition & 1 deletion src/dashboard_defs/updatable_text_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ use crate::{

utility_types::{
vec2f::Vec2f,
generic_result::*,
update_rate::UpdateRate,
generic_result::MaybeError,
dynamic_optional::DynamicOptional
},

Expand Down
2 changes: 1 addition & 1 deletion src/dashboard_defs/weather.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use crate::{

utility_types::{
vec2f::Vec2f,
generic_result::MaybeError,
generic_result::*,
dynamic_optional::DynamicOptional,
update_rate::{UpdateRateCreator, Seconds}
},
Expand Down
19 changes: 11 additions & 8 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ fn main() -> utility_types::generic_result::MaybeError {

//////////

let sdl_context = sdl2::init()?;
let sdl_video_subsystem = sdl_context.video()?;
let mut sdl_event_pump = sdl_context.event_pump()?;
use crate::utility_types::generic_result::ToGenericError;

let sdl_context = sdl2::init().to_generic()?;
let sdl_video_subsystem = sdl_context.video().to_generic()?;
let mut sdl_event_pump = sdl_context.event_pump().to_generic()?;

use sdl2::video::WindowBuilder;

Expand All @@ -94,7 +96,7 @@ fn main() -> utility_types::generic_result::MaybeError {
),

ScreenOption::Fullscreen => {
let mode = sdl_video_subsystem.display_mode(0, 0)?;
let mode = sdl_video_subsystem.display_mode(0, 0).to_generic()?;

build_window(
mode.w as u32, mode.h as u32,
Expand All @@ -113,7 +115,7 @@ fn main() -> utility_types::generic_result::MaybeError {
}

use sdl2::image::LoadSurface;
sdl_window.set_icon(sdl2::surface::Surface::from_file(app_config.icon_path)?);
sdl_window.set_icon(sdl2::surface::Surface::from_file(app_config.icon_path).to_generic()?);

//////////

Expand Down Expand Up @@ -141,13 +143,13 @@ fn main() -> utility_types::generic_result::MaybeError {

//////////

let mut sdl_timer = sdl_context.timer()?;
let mut sdl_timer = sdl_context.timer().to_generic()?;
let sdl_performance_frequency = sdl_timer.performance_frequency();
let sdl_ttf_context = sdl2::ttf::init()?;

let texture_creator = sdl_canvas.texture_creator();

let fps = sdl_video_subsystem.current_display_mode(0)?.refresh_rate as u32;
let fps = sdl_video_subsystem.current_display_mode(0).to_generic()?.refresh_rate as u32;

let sdl_renderer_info = sdl_canvas.info();
let max_texture_size = (sdl_renderer_info.max_texture_width, sdl_renderer_info.max_texture_height);
Expand Down Expand Up @@ -179,7 +181,8 @@ fn main() -> utility_types::generic_result::MaybeError {
let mut pausing_window = false;
// let mut initial_num_textures_in_pool = None;

log::info!("Finished setting up window. Canvas size: {:?}. Renderer info: {:?}.", rendering_params.sdl_canvas.output_size()?, sdl_renderer_info);
log::info!("Finished setting up window. Canvas size: {:?}. Renderer info: {:?}.",
rendering_params.sdl_canvas.output_size().to_generic()?, sdl_renderer_info);

'running: loop {
for sdl_event in sdl_event_pump.poll_iter() {
Expand Down
8 changes: 4 additions & 4 deletions src/request.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use std::borrow::Cow;
use crate::utility_types::generic_result::GenericResult;
use crate::utility_types::generic_result::*;

pub fn build_url(base_url: &str, path_params: &[Cow<str>],
query_params: &[(&str, Cow<str>)]) -> String {
Expand Down Expand Up @@ -37,10 +37,10 @@ pub fn get_with_maybe_header(url: &str, maybe_header: Option<(&str, &str)>) -> G
Ok(response)
}
else {
Err(format!(
error_msg!(
"Response status code for URL '{url}' was not '{EXPECTED_STATUS_CODE}', \
but '{}', with this reason: '{}'", response.status_code, response.reason_phrase
).into())
)
}
}

Expand All @@ -51,5 +51,5 @@ pub fn get(url: &str) -> GenericResult<minreq::Response> {
// This function is monadic!
pub fn as_type<T: for<'de> serde::Deserialize<'de>>(response: GenericResult<minreq::Response>) -> GenericResult<T> {
let unpacked_response = response?;
Ok(serde_json::from_str(unpacked_response.as_str()?)?)
serde_json::from_str(unpacked_response.as_str()?).to_generic()
}
16 changes: 8 additions & 8 deletions src/spinitron/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::borrow::Cow;

use crate::{
request,
utility_types::generic_result::GenericResult,
utility_types::generic_result::*,

spinitron::{
wrapper_types::MaybeSpinitronModelId,
Expand All @@ -24,27 +24,27 @@ fn get_json_from_spinitron_request<T: SpinitronModelWithProps>(
////////// Getting the API endpoint

let full_typename = std::any::type_name::<T>();
let last_colon_ind = full_typename.rfind(':').ok_or("Expected a colon in the model typename")?;
let last_colon_ind = full_typename.rfind(':').context("Expected a colon in the model typename")?;
let typename = &full_typename[last_colon_ind + 1..];

let mut typename_chars = typename.chars();
let first_char = typename_chars.next().ok_or("The typename has no chars in it, which is impossible")?;
let first_char = typename_chars.next().context("The typename has no chars in it, which is impossible")?;
let api_endpoint = format!("{}{}s", first_char.to_lowercase(), &typename[1..]);

////////// Checking endpoint validity

const VALID_ENDPOINTS: [&str; NUM_SPINITRON_MODEL_TYPES] = ["spins", "playlists", "personas", "shows"];

if !VALID_ENDPOINTS.contains(&api_endpoint.as_str()) {
return Err(format!("Invalid Spinitron API endpoint '{api_endpoint}'").into());
return error_msg!("Invalid Spinitron API endpoint '{api_endpoint}'");
}

////////// Limiting the requested fields by what exists within the given model type

let default_model_as_serde_value = serde_json::to_value(T::default())?;

let default_model_as_serde_obj = default_model_as_serde_value.as_object()
.ok_or("Expected JSON to be an object for the default Spinitron model")?;
.context("Expected JSON to be an object for the default Spinitron model")?;

// TODO: stop the `collect` allocation below
let fields: Vec<&str> = default_model_as_serde_obj.iter().map(|(key, _)| key.as_str()).collect();
Expand Down Expand Up @@ -77,8 +77,8 @@ fn get_json_from_spinitron_request<T: SpinitronModelWithProps>(
}

fn get_vec_from_spinitron_json<T: SpinitronModelWithProps>(json: &serde_json::Value) -> GenericResult<Vec<T>> {
let parsed_json_as_object = json.as_object().ok_or("Expected JSON to be an object")?;
Ok(serde_json::from_value(parsed_json_as_object["items"].clone())?)
let parsed_json_as_object = json.as_object().context("Expected JSON to be an object")?;
serde_json::from_value(parsed_json_as_object["items"].clone()).to_generic()
}

// This is a singular request
Expand All @@ -87,7 +87,7 @@ fn do_request<T: SpinitronModelWithProps>(api_key: &str, possible_model_id: Mayb

if possible_model_id.is_some() {
// If requesting a via model id, just a raw item will be returned
Ok(serde_json::from_value(response_json)?)
serde_json::from_value(response_json).to_generic()
}

else {
Expand Down
2 changes: 1 addition & 1 deletion src/spinitron/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use serde::{Serialize, Deserialize};

use crate::{
texture::TextureCreationInfo,
utility_types::generic_result::GenericResult,
utility_types::generic_result::*,

spinitron::{
wrapper_types::*,
Expand Down
4 changes: 2 additions & 2 deletions src/spinitron/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::{
texture::TextureCreationInfo,

utility_types::{
generic_result::{GenericResult, MaybeError},
generic_result::*,
thread_task::{Updatable, ContinuallyUpdated}
},

Expand Down Expand Up @@ -135,7 +135,7 @@ impl SpinitronStateData {
and precaching anything from disk in byte form as well. */
match info.as_ref() {
TextureCreationInfo::Path(path) =>
Ok(std::fs::read(path as &str)?),
std::fs::read(path as &str).to_generic(),

TextureCreationInfo::Url(url) =>
Ok(request::get(url)?.as_bytes().to_vec()),
Expand Down
Loading

0 comments on commit df2b58a

Please sign in to comment.