From 562be7f64ba699f851e3183d5a9f3278fdd79e42 Mon Sep 17 00:00:00 2001 From: Huck Boles Date: Sun, 11 Jun 2023 21:17:30 -0500 Subject: [PATCH] reset: getting async setup --- Cargo.lock | 298 +++++++++++++++++---------------------- Cargo.toml | 2 +- src/cells.rs | 79 +++++------ src/graphics.rs | 174 +++++++++++++---------- src/graphics/actions.rs | 107 -------------- src/graphics/area.rs | 93 ------------ src/graphics/keys.rs | 70 --------- src/graphics/layout.rs | 44 ------ src/graphics/map.rs | 90 ------------ src/graphics/point.rs | 69 --------- src/graphics/render.rs | 135 ------------------ src/graphics/selector.rs | 66 --------- src/lib.rs | 19 +-- src/main.rs | 22 +-- src/music.rs | 85 ----------- src/music/scale.rs | 83 ----------- src/music/transport.rs | 13 -- src/state.rs | 63 --------- src/state/transport.rs | 53 ------- src/tests.rs | 39 +++++ src/transport.rs | 19 --- 21 files changed, 314 insertions(+), 1309 deletions(-) delete mode 100644 src/graphics/actions.rs delete mode 100644 src/graphics/area.rs delete mode 100644 src/graphics/keys.rs delete mode 100644 src/graphics/layout.rs delete mode 100644 src/graphics/map.rs delete mode 100644 src/graphics/point.rs delete mode 100644 src/graphics/render.rs delete mode 100644 src/graphics/selector.rs delete mode 100644 src/music.rs delete mode 100644 src/music/scale.rs delete mode 100644 src/music/transport.rs delete mode 100644 src/state.rs delete mode 100644 src/state/transport.rs create mode 100644 src/tests.rs delete mode 100644 src/transport.rs diff --git a/Cargo.lock b/Cargo.lock index e52137c..7cdf62e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,15 +14,21 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + [[package]] name = "cellseq" version = "0.1.0" dependencies = [ - "crossbeam", "crossterm", "eyre", "ndarray", "rand", + "tokio", ] [[package]] @@ -31,73 +37,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "crossbeam" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c" -dependencies = [ - "cfg-if", - "crossbeam-channel", - "crossbeam-deque", - "crossbeam-epoch", - "crossbeam-queue", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-channel" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-deque" -version = "0.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" -dependencies = [ - "cfg-if", - "crossbeam-epoch", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.9.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" -dependencies = [ - "autocfg", - "cfg-if", - "crossbeam-utils", - "memoffset", - "scopeguard", -] - -[[package]] -name = "crossbeam-queue" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1cfb3ea8a53f37c40dea2c7bedcbd88bdfae54f5e2175d6ecaff1c988353add" -dependencies = [ - "cfg-if", - "crossbeam-utils", -] - -[[package]] -name = "crossbeam-utils" -version = "0.8.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" -dependencies = [ - "cfg-if", -] - [[package]] name = "crossterm" version = "0.26.1" @@ -135,15 +74,24 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", "wasi", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + [[package]] name = "indenter" version = "0.3.3" @@ -152,15 +100,15 @@ checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" [[package]] name = "libc" -version = "0.2.144" +version = "0.2.146" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b00cc1c228a6782d0f076e7b232802e0c5689d41bb5df366f2a6b6621cfdfe1" +checksum = "f92be4933c13fd498862a9e02a3055f8a8d9c039ce33db97306fd5a6caa7f29b" [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" dependencies = [ "autocfg", "scopeguard", @@ -168,9 +116,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.18" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "518ef76f2f87365916b142844c16d8fefd85039bc5699050210a7778ee1cd1de" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "matrixmultiply" @@ -182,15 +130,6 @@ dependencies = [ "rawpointer", ] -[[package]] -name = "memoffset" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" -dependencies = [ - "autocfg", -] - [[package]] name = "mio" version = "0.8.8" @@ -200,7 +139,7 @@ dependencies = [ "libc", "log", "wasi", - "windows-sys 0.48.0", + "windows-sys", ] [[package]] @@ -244,11 +183,21 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_cpus" +version = "1.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +dependencies = [ + "hermit-abi", + "libc", +] + [[package]] name = "once_cell" -version = "1.17.2" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9670a07f94779e00908f3e686eab508878ebb390ba6e604d3a284c00e8d0487b" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "parking_lot" @@ -262,23 +211,47 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" +checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" dependencies = [ "cfg-if", "libc", "redox_syscall", "smallvec", - "windows-sys 0.45.0", + "windows-targets", ] +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + [[package]] name = "ppv-lite86" version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +[[package]] +name = "proc-macro2" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ab9c7eadfd8df19006f1cf1a4aed13540ed5cbc047010ece5826e10825488" +dependencies = [ + "proc-macro2", +] + [[package]] name = "rand" version = "0.8.5" @@ -317,9 +290,9 @@ checksum = "60a357793950651c4ed0f3f52338f53b2f809f32d83a07f72909fa13e4c6c1e3" [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -366,6 +339,63 @@ version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "syn" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32d41677bcbe24c20c52e7c70b0d8db04134c5d1066bf98662e2871ad200ea3e" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "tokio" +version = "1.28.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94d7b1cfd2aa4011f2de74c2c4c63665e27a71006b0a192dcd2710272e73dfa2" +dependencies = [ + "autocfg", + "bytes", + "libc", + "mio", + "num_cpus", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -394,37 +424,13 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets", ] [[package]] @@ -433,93 +439,51 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.48.0" diff --git a/Cargo.toml b/Cargo.toml index 6dc1a49..317d0c8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,4 +10,4 @@ ndarray = "0.15" rand = "0.8" crossterm = "0.26" eyre = "0.6" -crossbeam = "0.8.2" +tokio = { version = "1", features = ["full"] } diff --git a/src/cells.rs b/src/cells.rs index f04e9b3..f2ee6b0 100644 --- a/src/cells.rs +++ b/src/cells.rs @@ -1,12 +1,15 @@ -use crate::{Map, Point}; -use crossterm::style::{ - Attribute, Attributes, - Color::{Black, Green, Grey}, - Colors, +use crossterm::{ + cursor::MoveTo, + queue, + style::{ + Attribute::{Bold, Reset}, + Color::{Black, Green, Grey}, + ContentStyle, Print, SetStyle, + }, }; use ndarray::Array2; use rand::{thread_rng, Rng}; -use std::{cell::Cell, ops::Deref}; +use std::{cell::Cell, io::stdout, ops::Deref}; use super::*; @@ -19,12 +22,13 @@ pub enum State { #[derive(Debug, Clone)] pub struct World { pub map: Array2>, + pub area: Area, } impl World { pub fn new(area: Area) -> Self { let map = Array2::from_elem((area.width(), area.height()), Cell::new(State::Dead)); - Self { map } + Self { map, area } } pub fn randomize(&mut self, val: f64) { @@ -47,15 +51,13 @@ impl World { }; } - wrap!(self.column(0), self.column(self.x_size() - 2)); - wrap!(self.column(self.x_size() - 1), self.column(1)); - wrap!(self.row(0), self.row(self.y_size() - 2)); - wrap!(self.row(self.y_size() - 1), self.row(1)); + wrap!(self.column(0), self.column(self.area.width() - 2)); + wrap!(self.column(self.area.width() - 1), self.column(1)); + wrap!(self.row(0), self.row(self.area.height() - 2)); + wrap!(self.row(self.area.height() - 1), self.row(1)); } -} -impl Map> for World { - fn update(&mut self) { + pub fn update(&mut self) { let mut previous = self.clone(); previous.wrap_walls(); for (next, prev) in self @@ -82,36 +84,33 @@ impl Map> for World { } } - fn x_size(&self) -> usize { - self.ncols() - } - - fn y_size(&self) -> usize { - self.nrows() - } - - fn characters(&self) -> (char, char) { - ('●', '◌') - } - - fn colors(&self) -> (Colors, Colors) { - (Colors::new(Green, Black), Colors::new(Grey, Black)) - } - - fn styles(&self) -> (Attributes, Attributes) { - (Attribute::Bold.into(), Attribute::Reset.into()) - } - - fn draw_point(&self, point: Point) -> Option { - if let Some(cell) = self.get((point.y, point.x)) { + fn draw_point(&self, point: Point, offset: Point) -> Result<()> { + let mut style = ContentStyle { + foreground_color: None, + background_color: Some(Black), + underline_color: None, + attributes: Reset.into(), + }; + let char = if let Some(cell) = self.get::<(usize, usize)>(point.into()) { if cell.get() == State::Alive { - return Some('●'); + style.foreground_color = Some(Green); + style.attributes = Bold.into(); + '●' } else { - return Some('◌'); + style.background_color = Some(Grey); + '◌' } } else { - return None; - } + ' ' + }; + + queue!( + stdout(), + MoveTo(offset.x, offset.y), + SetStyle(style), + Print(char) + )?; + Ok(()) } } diff --git a/src/graphics.rs b/src/graphics.rs index 5415c8c..d224b4b 100644 --- a/src/graphics.rs +++ b/src/graphics.rs @@ -1,88 +1,110 @@ -mod actions; -mod area; -mod keys; -mod layout; -mod map; -mod point; -mod render; -mod selector; - -pub use actions::*; -pub use area::*; -pub use keys::*; -pub use layout::*; -pub use map::*; -pub use point::*; -pub use render::*; -pub use selector::*; - use super::*; -use crossterm::{ - cursor::MoveTo, - event::{read, Event}, - execute, queue, - style::{Print, SetAttributes, SetColors}, - terminal, -}; -use eyre::Result; -use std::{ - io::{stdout, Write}, - sync::{Arc, Mutex}, - thread, - time::Duration, -}; - -pub fn draw_map(map: &impl Map, area: &Area) -> Result<()> { - let ((x_zero, y_zero), (x_max, y_max)) = area.to_u16()?; - - let origin = Point::new(x_zero.into(), y_zero.into()); - - let (char_on, char_off) = map.characters(); - let (on_colors, off_colors) = map.colors(); - let (style_on, style_off) = map.styles(); - - for x in 0..=(map.x_size()) { - for y in 0..=(map.y_size()) { - let point = Point::new(x, y); - let char = map.draw_point(point).unwrap_or(' '); - let (x_off, y_off) = origin.u16_offset(point)?; - - if x_off <= x_zero || x_off >= x_max || y_off <= y_zero || y_off >= y_max - 1 { - continue; - } - - queue!( - stdout(), - MoveTo(x_off, y_off), - SetAttributes(style_on), - SetColors(on_colors), - Print(char) - )?; +use std::ops::{Add, Sub}; + +#[derive(Clone, Debug, Copy, PartialEq, Eq)] +pub struct Point { + pub x: u16, + pub y: u16, +} + +impl Point { + pub fn new(x: u16, y: u16) -> Self { + Self { x, y } + } +} + +impl Add for Point { + type Output = Self; + fn add(self, rhs: Self) -> Self::Output { + Self { + x: self.x + rhs.x, + y: self.y + rhs.y, + } + } +} + +impl Sub for Point { + type Output = Self; + fn sub(self, rhs: Self) -> Self::Output { + Self { + x: if rhs.x < self.x { self.x - rhs.x } else { 0 }, + y: if rhs.y < self.y { self.y - rhs.y } else { 0 }, } } +} + +impl From<(usize, usize)> for Point { + fn from(value: (usize, usize)) -> Self { + Self { + x: value.0.try_into().unwrap_or(0), + y: value.1.try_into().unwrap_or(0), + } + } +} + +impl Into<(usize, usize)> for Point { + fn into(self) -> (usize, usize) { + ( + self.x.try_into().unwrap_or(0), + self.y.try_into().unwrap_or(0), + ) + } +} - area.outline_area()?; +#[derive(Clone, Debug, Copy, PartialEq, Eq)] +pub struct Area { + pub origin: Point, + pub max: Point, +} - stdout().flush()?; +impl Area { + pub fn new(origin: Point, max: Point) -> Self { + Self { origin, max } + } + + pub fn contains(&self, point: Point) -> bool { + point.x >= self.origin.x + && point.y >= self.origin.y + && point.x <= self.max.x + && point.y <= self.max.y + } + + pub fn height(&self) -> usize { + (self.max.y - self.origin.y).try_into().unwrap_or(0) + } + + pub fn width(&self) -> usize { + (self.max.x - self.origin.x).try_into().unwrap_or(0) + } +} - Ok(()) +impl From<(Point, Point)> for Area { + fn from(value: (Point, Point)) -> Self { + Self { + origin: value.0, + max: value.1, + } + } } -pub fn loop_map( - map: &(impl Map + Clone), - area: &Area, - time: Duration, - steps: usize, -) -> Result<()> { - loop { - let mut tmp = map.clone(); - for _ in 0..steps { - execute!(stdout(), terminal::Clear(terminal::ClearType::All))?; - draw_map(&tmp, area)?; - stdout().flush()?; - tmp.update(); - thread::sleep(time); +impl From<(u16, u16, u16, u16)> for Area { + fn from(value: (u16, u16, u16, u16)) -> Self { + Self { + origin: Point::new(value.0, value.1), + max: Point::new(value.2, value.3), } } } + +impl Into<(Point, Point)> for Area { + fn into(self) -> (Point, Point) { + (self.origin, self.max) + } +} + +impl Into<(u16, u16, u16, u16)> for Area { + fn into(self) -> (u16, u16, u16, u16) { + (self.origin.x, self.origin.y, self.max.x, self.max.y) + } +} diff --git a/src/graphics/actions.rs b/src/graphics/actions.rs deleted file mode 100644 index 15f734c..0000000 --- a/src/graphics/actions.rs +++ /dev/null @@ -1,107 +0,0 @@ -use super::*; - -#[derive(Debug)] -pub enum Action { - None, - Move(Direction), - Clock(Clock), - Channel(usize), - Select, - SelectArea, - SwitchPanel, - Reload, - Randomize, - Exit, - Help, - Edit, -} - -#[derive(Debug)] -pub enum Clock { - Stop, - Start, - Pause, - Faster(usize), - Slower(usize), -} - -#[derive(Debug)] -pub enum Direction { - Up, - Down, - Left, - Right, -} - -pub fn action(action: Action, state: ArcState) -> Result<()> { - match action { - Action::None => Ok(()), - Action::Exit => exit(), - Action::Move(direction) => move_cursor(direction, state), - Action::Clock(clock) => transport_action(clock, state), - Action::Channel(n) => change_channel(n, state), - Action::Select => Ok(()), - Action::SelectArea => Ok(()), - Action::Reload => Ok(()), - Action::Randomize => Ok(()), - Action::Help => Ok(()), - Action::Edit => Ok(()), - Action::SwitchPanel => switch_panel(state), - } -} - -fn transport_action(clock: Clock, state: ArcState) -> Result<()> { - let mut state = state.lock().unwrap(); - match clock { - Clock::Stop => state.transport.running = false, - Clock::Start => state.transport.running = true, - Clock::Pause => state.transport.running = !state.transport.running, - Clock::Faster(n) => state.transport.bpm += n, - Clock::Slower(n) => state.transport.bpm -= n, - }; - Ok(()) -} - -fn move_cursor(direction: Direction, state: ArcState) -> Result<()> { - let mut state = state.lock().unwrap(); - match direction { - Direction::Up => { - if state.cursor.position.y > 1 { - state.cursor.position.y -= 1 - } - } - Direction::Down => { - if state.cursor.position.y < state.cursor.area.height() { - state.cursor.position.y += 1 - } - } - Direction::Left => { - if state.cursor.position.x > 1 { - state.cursor.position.x -= 1 - } - } - Direction::Right => { - if state.cursor.position.x < state.cursor.area.width() { - state.cursor.position.x += 1 - } - } - } - Ok(()) -} - -fn switch_panel(state: ArcState) -> Result<()> { - let mut mutex = state.lock().unwrap(); - mutex.cursor.area = if mutex.cursor.area == mutex.layout.mask { - mutex.layout.cells - } else { - mutex.layout.mask - }; - Ok(()) -} - -fn change_channel(channel: usize, state: ArcState) -> Result<()> { - let mut mutex = state.lock().unwrap(); - mutex.channels.0 = channel; - draw_map(&mutex.mask[channel], &mutex.layout.mask)?; - Ok(()) -} diff --git a/src/graphics/area.rs b/src/graphics/area.rs deleted file mode 100644 index b9b12f0..0000000 --- a/src/graphics/area.rs +++ /dev/null @@ -1,93 +0,0 @@ -use crossterm::{ - cursor::MoveTo, - queue, - style::{ - Color::{Black, White}, - Colors, SetColors, - }, -}; -use eyre::Result; - -use super::*; - -#[derive(Clone, Debug, PartialEq, Eq, Copy)] -pub struct Area { - pub origin: Point, - pub max: Point, -} - -impl From<(Point, Point)> for Area { - fn from(value: (Point, Point)) -> Self { - Self { - origin: value.0, - max: value.1, - } - } -} - -impl Area { - pub fn new(x_zero: usize, y_zero: usize, x_max: usize, y_max: usize) -> Self { - Self { - origin: Point::new(x_zero, y_zero), - max: Point::new(x_max, y_max), - } - } - - pub fn to_u16(&self) -> Result<((u16, u16), (u16, u16))> { - Ok(( - (self.origin.x.try_into()?, self.origin.y.try_into()?), - (self.max.x.try_into()?, self.max.y.try_into()?), - )) - } - - pub fn width(&self) -> usize { - self.max.y - self.origin.y - } - - pub fn height(&self) -> usize { - self.max.x - self.origin.x - } - - pub fn outline_area(&self) -> Result<()> { - let colors = Colors::new(White, Black); - let ((x_zero, y_zero), (x_max, y_max)) = self.to_u16()?; - - for y in y_zero + 1..y_max - 1 { - queue!( - stdout(), - MoveTo(x_zero, y), - SetColors(colors), - Print("┃"), - MoveTo(x_max, y), - SetColors(colors), - Print("┃") - )?; - } - - for x in x_zero + 1..x_max { - queue!( - stdout(), - MoveTo(x, y_zero), - SetColors(colors), - Print("━"), - MoveTo(x, y_max - 1), - SetColors(colors), - Print("━") - )?; - } - - for ((x, y), c) in [ - (x_zero, y_zero), - (x_max, y_zero), - (x_zero, y_max - 1), - (x_max, y_max - 1), - ] - .iter() - .zip(['┏', '┓', '┗', '┛'].iter()) - { - queue!(stdout(), MoveTo(*x, *y), SetColors(colors), Print(c))?; - } - - Ok(()) - } -} diff --git a/src/graphics/keys.rs b/src/graphics/keys.rs deleted file mode 100644 index b91ee0f..0000000 --- a/src/graphics/keys.rs +++ /dev/null @@ -1,70 +0,0 @@ -use crossterm::event::{KeyCode, KeyEvent, KeyModifiers}; - -use super::*; -use crate::Clock; - -pub fn key_event(event: KeyEvent) -> Action { - match event.modifiers { - KeyModifiers::NONE => match_normal_key(event.code), - KeyModifiers::CONTROL => match_ctl_key(event.code), - KeyModifiers::SHIFT => match_shift_key(event.code), - _ => Action::None, - } -} - -pub fn match_normal_key(key: KeyCode) -> Action { - match key { - KeyCode::Enter => Action::Clock(Clock::Pause), - KeyCode::Esc => Action::Exit, - KeyCode::Tab => Action::SwitchPanel, - KeyCode::Up => Action::Move(Direction::Up), - KeyCode::Down => Action::Move(Direction::Down), - KeyCode::Right => Action::Move(Direction::Right), - KeyCode::Left => Action::Move(Direction::Left), - KeyCode::Char(c) => match c { - '?' => Action::Help, - ' ' => Action::Select, - '[' => Action::Clock(Clock::Slower(1)), - ']' => Action::Clock(Clock::Faster(1)), - '{' => Action::Clock(Clock::Slower(5)), - '}' => Action::Clock(Clock::Faster(5)), - 'q' => Action::Exit, - 'r' => Action::Reload, - 'j' => Action::Move(Direction::Down), - 'k' => Action::Move(Direction::Up), - 'h' => Action::Move(Direction::Left), - 'l' => Action::Move(Direction::Right), - '1' => Action::Channel(1), - '2' => Action::Channel(2), - '3' => Action::Channel(3), - '4' => Action::Channel(4), - '5' => Action::Channel(5), - '6' => Action::Channel(6), - '7' => Action::Channel(7), - '8' => Action::Channel(8), - '9' => Action::Channel(9), - '0' => Action::Channel(10), - _ => Action::None, - }, - _ => Action::None, - } -} - -pub fn match_ctl_key(key: KeyCode) -> Action { - match key { - KeyCode::Char('c') => Action::Exit, - _ => Action::None, - } -} - -pub fn match_shift_key(key: KeyCode) -> Action { - match key { - KeyCode::Enter => Action::Clock(Clock::Stop), - KeyCode::Char(c) => match c { - ' ' => Action::SelectArea, - 'r' => Action::Randomize, - _ => Action::None, - }, - _ => Action::None, - } -} diff --git a/src/graphics/layout.rs b/src/graphics/layout.rs deleted file mode 100644 index 2f5fc7d..0000000 --- a/src/graphics/layout.rs +++ /dev/null @@ -1,44 +0,0 @@ -use crossterm::terminal; -use eyre::Result; - -use super::*; - -#[derive(Clone, Debug)] -pub struct Layout { - pub screen: Area, - pub cells: Area, - pub mask: Area, - pub channels: Area, - pub transport: Area, -} - -impl Layout { - pub fn build() -> Result { - let (col, row) = terminal::size()?; - - let col: usize = col.into(); - let row: usize = row.into(); - - let screen = Area::new(0, 0, col, row); - let cells = Area::new(1, 0, col / 2 - 6, row / 2 - 1); - let mask = Area::new(col / 2 + 6, 0, col - 2, row / 2 - 1); - let channels = Area::new(1, row / 2 + 1, col - 2, row - 1); - let transport = Area::new(col / 2 - 5, 4, col / 2 + 5, 9); - - Ok(Self { - screen, - cells, - mask, - channels, - transport, - }) - } - - pub fn draw_outlines(&self) -> Result<()> { - self.cells.outline_area()?; - self.mask.outline_area()?; - self.channels.outline_area()?; - self.transport.outline_area()?; - Ok(()) - } -} diff --git a/src/graphics/map.rs b/src/graphics/map.rs deleted file mode 100644 index 61db0d8..0000000 --- a/src/graphics/map.rs +++ /dev/null @@ -1,90 +0,0 @@ -use crate::Point; -use crossterm::style::{ - Attribute, Attributes, - Color::{Black, White}, - Colors, -}; -use ndarray::Array2; -use rand::{thread_rng, Rng}; -use std::ops::{Deref, DerefMut}; - -use super::*; - -pub trait Map { - fn draw_point(&self, point: Point) -> Option; - fn x_size(&self) -> usize; - fn y_size(&self) -> usize; - fn characters(&self) -> (char, char); - fn colors(&self) -> (Colors, Colors); - fn styles(&self) -> (Attributes, Attributes); - fn update(&mut self); -} - -#[derive(Debug, Clone)] -pub struct Mask { - pub mask: Array2, - pub colors: (Colors, Colors), -} - -impl Mask { - pub fn new(area: Area) -> Self { - let mask = Array2::from_elem((area.width(), area.height()), Note::Off); - Self { - mask, - colors: (Colors::new(White, Black), Colors::new(Black, Black)), - } - } - - pub fn randomize(&mut self, val: f64, scale: Scale) { - let mut rng = thread_rng(); - for f in self.iter_mut() { - if rng.gen::() > val { - let notes = scale.to_notes(); - *f = notes[rng.gen::() % notes.len()]; - } - } - } -} - -impl Deref for Mask { - type Target = Array2; - fn deref(&self) -> &Self::Target { - &self.mask - } -} - -impl DerefMut for Mask { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.mask - } -} - -impl Map for Mask { - fn x_size(&self) -> usize { - self.ncols() - } - - fn y_size(&self) -> usize { - self.nrows() - } - - fn draw_point(&self, point: Point) -> Option { - self.get((point.y, point.x)).map(|n| n.to_char()) - } - - fn characters(&self) -> (char, char) { - ('■', '□') - } - - fn colors(&self) -> (Colors, Colors) { - self.colors - } - - fn styles(&self) -> (Attributes, Attributes) { - let on = Attributes::from(Attribute::Bold); - let off = Attributes::from(Attribute::Reset); - (on, off) - } - - fn update(&mut self) {} -} diff --git a/src/graphics/point.rs b/src/graphics/point.rs deleted file mode 100644 index dcb78fd..0000000 --- a/src/graphics/point.rs +++ /dev/null @@ -1,69 +0,0 @@ -use crossterm::style::{Attribute, Color}; -use eyre::Result; -use std::ops::{Add, Div, Mul, Sub}; - -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Pixel { - pub location: Point, - pub value: char, - pub fg: Color, - pub bg: Color, - pub style: Attribute, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] -pub struct Point { - pub x: usize, - pub y: usize, -} - -impl Point { - pub fn new(x: usize, y: usize) -> Self { - Self { x, y } - } - - pub fn u16_offset(&self, offset: Point) -> Result<(u16, u16)> { - let output = *self + offset; - Ok((output.x.try_into()?, output.y.try_into()?)) - } -} - -impl Add for Point { - type Output = Self; - fn add(self, rhs: Self) -> Self::Output { - Self { - x: self.x + rhs.x, - y: self.y + rhs.y, - } - } -} - -impl Sub for Point { - type Output = Self; - fn sub(self, rhs: Self) -> Self::Output { - Self { - x: self.x - rhs.x, - y: self.y - rhs.y, - } - } -} - -impl Mul for Point { - type Output = Self; - fn mul(self, rhs: Self) -> Self::Output { - Self { - x: self.x * rhs.x, - y: self.y * rhs.y, - } - } -} - -impl Div for Point { - type Output = Self; - fn div(self, rhs: Self) -> Self::Output { - Self { - x: self.x / rhs.x, - y: self.y / rhs.y, - } - } -} diff --git a/src/graphics/render.rs b/src/graphics/render.rs deleted file mode 100644 index b911bc5..0000000 --- a/src/graphics/render.rs +++ /dev/null @@ -1,135 +0,0 @@ -use super::*; - -use crossbeam::channel::{bounded, Receiver, Sender}; - -pub type ArcState = Arc>; - -pub fn main_loop(state: GlobalState) -> Result<()> { - execute!(stdout(), terminal::Clear(terminal::ClearType::All))?; - - state.layout.draw_outlines()?; - - let (clock, sync) = bounded::<()>(0); - let state = Arc::new(Mutex::new(state)); - - let timer_state = Arc::clone(&state); - let world_state = Arc::clone(&state); - let action_state = Arc::clone(&state); - // let cursor_state = Arc::clone(&state); - - let timer = std::thread::spawn(move || timer_loop(timer_state, clock)); - let world = std::thread::spawn(move || world_loop(world_state, sync)); - let action = std::thread::spawn(move || action_loop(action_state)); - // let cursor = std::thread::spawn(move || cursor_loop(cursor_state)); - - timer.join().unwrap()?; - world.join().unwrap()?; - action.join().unwrap()?; - // cursor.join().unwrap()?; - - Ok(()) -} - -fn timer_loop(state: ArcState, clock: Sender<()>) -> Result<()> { - loop { - let tick = state.lock().unwrap().tick(); - thread::sleep(tick); - clock.send(())?; - } -} - -pub fn world_loop(state: ArcState, sync: Receiver<()>) -> Result<()> { - loop { - let mutex = state.lock().unwrap(); - if mutex.transport.running { - let mut world = mutex.world.clone(); - let mask = mutex.mask[mutex.channels.0].clone(); - let world_layout = mutex.layout.cells; - let mask_layout = mutex.layout.mask; - drop(mutex); - - world.update(); - draw_map(&world, &world_layout)?; - draw_map(&mask, &mask_layout)?; - sync.recv()?; - state.lock().as_mut().unwrap().world = world; - } else { - drop(mutex); - sync.recv()?; - } - } -} - -pub fn action_loop(state: ArcState) -> Result<()> { - while let Ok(event) = read() { - match event { - Event::Key(key) => action(key_event(key), state.clone())?, - Event::Resize(_, _) => state.lock().unwrap().layout = Layout::build()?, - _ => (), - } - } - Ok(()) -} - -pub fn cursor_loop(state: ArcState) -> Result<()> { - loop { - state.lock().unwrap().cursor.render()?; - std::thread::sleep(Duration::from_millis(100)) - } -} - -// pub fn render_loop(state: &mut GlobalState) -> Result<()> { -// execute!(stdout(), terminal::Clear(terminal::ClearType::All))?; - -// state.layout.draw_outlines()?; - -// let world = Arc::new(Mutex::new(state.world.clone())); -// let state_arc = Arc::new(Mutex::new(state)); - -// loop { -// let arc = Arc::clone(&state_arc); -// let tick = arc.lock().unwrap().tick(); -// let timer = std::thread::spawn(move || thread::sleep(tick)); - -// let event = std::thread::spawn(move || { -// if poll(tick).unwrap() { -// match read().unwrap() { -// Event::Key(key) => key_event(key), -// _ => Action::None, -// } -// } else { -// Action::None -// } -// }); - -// let mut maps = std::thread::spawn(|| {}); -// if arc.lock().unwrap().transport.running { -// let map = world.clone(); -// let mut mask = arc.lock().unwrap().mask.clone(); -// let cell_area = arc.lock().unwrap().layout.cells; -// let mask_area = arc.lock().unwrap().layout.mask; - -// maps = std::thread::spawn(move || { -// let mut map = map.lock().unwrap(); -// map.update(); -// let tmp = map.clone(); -// draw_map(&tmp, &cell_area).unwrap(); -// mask[0].update(); -// let tmp = mask[0].clone(); -// draw_map(&tmp, &mask_area).unwrap(); -// }); -// } - -// let area = arc.lock().unwrap().layout.transport; - -// arc.lock().unwrap().transport.render(area)?; - -// action(event.join().unwrap(), arc.clone())?; -// maps.join().unwrap(); - -// arc.lock().unwrap().cursor.render()?; - -// timer.join().unwrap(); -// stdout().flush()?; -// } -// } diff --git a/src/graphics/selector.rs b/src/graphics/selector.rs deleted file mode 100644 index becfb27..0000000 --- a/src/graphics/selector.rs +++ /dev/null @@ -1,66 +0,0 @@ -use crate::Point; -use crossterm::{ - cursor, queue, - style::{self, Attribute, Attributes, Color, Colors}, -}; -use eyre::Result; -use std::{ - io::stdout, - ops::{Deref, DerefMut}, -}; - -use super::*; - -#[derive(Debug, Clone, Copy)] -pub struct Cursor { - pub position: Point, - pub color: Colors, - pub style: Attributes, - pub char: char, - pub area: Area, -} - -impl Deref for Cursor { - type Target = Point; - fn deref(&self) -> &Self::Target { - &self.position - } -} - -impl DerefMut for Cursor { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.position - } -} - -impl Default for Cursor { - fn default() -> Self { - Self::new(Area::new(0, 0, 0, 0)) - } -} - -impl Cursor { - pub fn new(area: Area) -> Self { - Self { - position: Point::new(1, 1), - color: Colors::new(Color::White, Color::Black), - char: '█', - style: Attributes::from(Attribute::Bold), - area, - } - } - - pub fn render(&self) -> Result<()> { - let offset = self.area.origin + self.position; - queue!( - stdout(), - cursor::Hide, - cursor::MoveTo(offset.x.try_into().unwrap(), offset.y.try_into().unwrap()), - style::SetAttributes(self.style), - style::SetColors(self.color), - cursor::Show, - style::Print(self.char.to_string()) - )?; - Ok(()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 97a4a32..20d18d0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,23 +1,10 @@ mod cells; mod graphics; -mod music; -mod state; pub use cells::*; pub use graphics::*; -pub use music::*; -pub use state::*; -use eyre::Result; -use std::time::Duration; - -pub fn exit() -> Result<()> { - crossterm::terminal::disable_raw_mode()?; - crossterm::execute!(std::io::stdout(), crossterm::cursor::Show)?; - std::process::exit(0); -} +#[cfg(test)] +mod tests; -pub fn bpm_to_ms(bpm: usize) -> Duration { - let ms = 60000 / bpm; - Duration::from_millis(ms.try_into().unwrap()) -} +use eyre::Result; diff --git a/src/main.rs b/src/main.rs index c53dab3..a3a92f4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,22 +1,6 @@ -use cellseq::*; -use crossterm::{cursor::Hide, execute, terminal}; use eyre::Result; -use std::io::stdout; -fn main() -> Result<()> { - terminal::enable_raw_mode()?; - execute!(stdout(), Hide)?; - - let mut state = GlobalState::build()?; - - state.world.randomize(0.75); - state.mask[0].randomize(0.75, Scale::Aeolian); - - match main_loop(state) { - Ok(_) => exit(), - Err(e) => { - eprintln!("{}", e); - exit() - } - } +#[tokio::main] +async fn main() -> Result<()> { + todo!() } diff --git a/src/music.rs b/src/music.rs deleted file mode 100644 index 409a579..0000000 --- a/src/music.rs +++ /dev/null @@ -1,85 +0,0 @@ -mod scale; -mod transport; - -pub use scale::*; -pub use transport::*; - -use std::{fmt::Display, ops::Deref}; - -#[derive(Clone, Copy, Debug)] -pub struct TimeSignature { - pub top: usize, - pub bottom: usize, -} - -impl From<(usize, usize)> for TimeSignature { - fn from(value: (usize, usize)) -> Self { - Self { - top: value.0, - bottom: value.1, - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Note { - Off, - A(Acc), - B(Acc), - C(Acc), - D(Acc), - E(Acc), - F(Acc), - G(Acc), -} - -impl Display for Note { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let str = match self { - Note::Off => "".to_string(), - Note::A(a) => format!("A{a}"), - Note::B(a) => format!("B{a}"), - Note::C(a) => format!("C{a}"), - Note::D(a) => format!("D{a}"), - Note::E(a) => format!("E{a}"), - Note::F(a) => format!("F{a}"), - Note::G(a) => format!("G{a}"), - }; - - write!(f, "{str}") - } -} - -impl Note { - pub fn to_char(&self) -> char { - match self { - Note::Off => ' ', - Note::A(_) => 'a', - Note::B(_) => 'b', - Note::C(_) => 'c', - Note::D(_) => 'd', - Note::E(_) => 'e', - Note::F(_) => 'f', - Note::G(_) => 'g', - } - } -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] -pub enum Acc { - Flt, - Nat, - Shp, -} - -impl Display for Acc { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let str = match self { - Acc::Flt => "b", - Acc::Nat => "", - Acc::Shp => "#", - }; - - write!(f, "{str}") - } -} diff --git a/src/music/scale.rs b/src/music/scale.rs deleted file mode 100644 index 486bfbd..0000000 --- a/src/music/scale.rs +++ /dev/null @@ -1,83 +0,0 @@ -use super::*; - -use super::{ - Acc::{Nat, Shp}, - Note::{A, B, C, D, E, F, G}, -}; - -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum Scale { - Ionian, - Dorian, - Phrygian, - Lydian, - Mixolydian, - Aeolian, - Locrian, - MajPent, - SusEgypt, - BlueMajPent, - BlueMinPen, - MinPent, - WholeTone, - Chromatic, -} - -impl Scale { - pub fn to_notes(&self) -> Vec { - let octave = [ - C(Nat), - C(Shp), - D(Nat), - D(Shp), - E(Nat), - F(Nat), - F(Shp), - G(Nat), - G(Shp), - A(Nat), - A(Shp), - B(Nat), - ]; - - let diatonic = [1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1]; - let pentatonic = [1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0]; - let whole_tone = [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; - - fn mask_scale(notes: &[Note; 12], mask: [u8; 12]) -> Vec { - notes - .iter() - .zip(mask.iter()) - .filter_map(|(note, mask)| if *mask == 1 { Some(*note) } else { None }) - .collect() - } - - macro_rules! rotate { - ($s:expr,r,$n:expr) => {{ - $s.rotate_right($n); - $s - }}; - ($s:expr,l,$n:expr) => {{ - $s.rotate_left($n); - $s - }}; - } - - match self { - Scale::Ionian => mask_scale(&octave, diatonic), - Scale::Dorian => rotate!(mask_scale(&octave, diatonic), l, 2), - Scale::Phrygian => rotate!(mask_scale(&octave, diatonic), l, 4), - Scale::Lydian => rotate!(mask_scale(&octave, diatonic), l, 5), - Scale::Mixolydian => rotate!(mask_scale(&octave, diatonic), r, 5), - Scale::Aeolian => rotate!(mask_scale(&octave, diatonic), r, 3), - Scale::Locrian => rotate!(mask_scale(&octave, diatonic), r, 1), - Scale::MajPent => mask_scale(&octave, pentatonic), - Scale::SusEgypt => rotate!(mask_scale(&octave, pentatonic), l, 2), - Scale::BlueMinPen => rotate!(mask_scale(&octave, pentatonic), l, 4), - Scale::BlueMajPent => rotate!(mask_scale(&octave, pentatonic), r, 5), - Scale::MinPent => rotate!(mask_scale(&octave, pentatonic), r, 3), - Scale::WholeTone => mask_scale(&octave, whole_tone), - Scale::Chromatic => octave.to_vec(), - } - } -} diff --git a/src/music/transport.rs b/src/music/transport.rs deleted file mode 100644 index 415f2e2..0000000 --- a/src/music/transport.rs +++ /dev/null @@ -1,13 +0,0 @@ -use super::*; - -#[derive(Clone, Copy, Debug)] -pub struct Song { - pub key: Option, - pub scale: Option, -} - -impl Song { - pub fn new(key: Option, scale: Option) -> Self { - Self { key, scale } - } -} diff --git a/src/state.rs b/src/state.rs deleted file mode 100644 index 159c265..0000000 --- a/src/state.rs +++ /dev/null @@ -1,63 +0,0 @@ -mod transport; - -pub use transport::*; - -use crossbeam::channel::{bounded, Receiver, Sender}; - -use super::*; - -#[derive(Debug, Clone)] -pub struct GlobalState { - pub world: World, - pub layout: Layout, - pub transport: Transport, - pub song: Song, - pub mask: Vec, - pub channels: (usize, Vec), - pub cursor: Cursor, - pub update_mask: (Sender, Receiver), -} - -impl GlobalState { - pub fn build() -> Result { - let layout = Layout::build()?; - - let world = World::new(layout.cells); - - let channels = Vec::with_capacity(10); - let mut mask: Vec = Vec::with_capacity(10); - - for _ in 0..10 { - mask.push(Mask::new(layout.mask)); - } - - let transport = Transport::new(4, 4, 120); - - let cursor = Cursor::new(layout.mask); - - let song = Song::new(None, None); - - let update_mask = bounded::(0); - - Ok(Self { - world, - layout, - transport, - song, - mask, - channels: (0, channels), - cursor, - update_mask, - }) - } - - pub fn tick(&self) -> Duration { - bpm_to_ms(self.transport.bpm) - } -} - -#[derive(Clone, Copy, Debug)] -pub struct MidiChannel { - pub num: usize, - pub poly_num: usize, -} diff --git a/src/state/transport.rs b/src/state/transport.rs deleted file mode 100644 index b230928..0000000 --- a/src/state/transport.rs +++ /dev/null @@ -1,53 +0,0 @@ -use super::*; - -use crossterm::{ - cursor::MoveTo, - queue, - style::{Attribute, Color, Colors, Print, SetAttributes, SetColors}, -}; -use std::io::stdout; - -#[derive(Debug, Clone, Copy)] -pub struct Transport { - pub running: bool, - pub bpm: usize, - pub sig: TimeSignature, - pub repeat: usize, -} - -impl Transport { - pub fn new(top: usize, bottom: usize, bpm: usize) -> Self { - Self { - sig: TimeSignature { top, bottom }, - bpm, - running: true, - repeat: 0, - } - } - - pub fn render(&self, area: Area) -> Result<()> { - let ((x_zero, y_zero), (_, _)) = area.to_u16()?; - - let bpm = format!("bpm: {}", self.bpm); - let sig = format!("sig: {}/{}", self.sig.top, self.sig.bottom); - let rep = format!("rep: {}", self.repeat); - - queue!( - stdout(), - MoveTo(x_zero + 1, y_zero + 1), - SetAttributes(Attribute::Bold.into()), - SetColors(Colors::new(Color::White, Color::Black)), - Print(bpm), - MoveTo(x_zero + 1, y_zero + 2), - SetAttributes(Attribute::Bold.into()), - SetColors(Colors::new(Color::White, Color::Black)), - Print(sig), - MoveTo(x_zero + 1, y_zero + 3), - SetAttributes(Attribute::Bold.into()), - SetColors(Colors::new(Color::White, Color::Black)), - Print(rep), - )?; - - Ok(()) - } -} diff --git a/src/tests.rs b/src/tests.rs new file mode 100644 index 0000000..b4351ab --- /dev/null +++ b/src/tests.rs @@ -0,0 +1,39 @@ +use super::*; + +#[test] +fn area_tests() -> Result<()> { + let origin = Point::new(5, 5); + let max = Point::new(35, 25); + let area = Area::new(origin, max); + + assert_eq!(area.height(), 20); + assert_eq!(area.width(), 30); + + assert!(area.contains(Point::new(20, 20))); + assert!(area.contains(Point::new(5, 10))); + assert!(area.contains(Point::new(24, 25))); + assert!(area.contains(Point::new(35, 25))); + assert!(area.contains(Point::new(5, 5))); + + assert!(!area.contains(Point::new(0, 10))); + assert!(!area.contains(Point::new(15, 0))); + assert!(!area.contains(Point::new(55, 24))); + assert!(!area.contains(Point::new(15, 60))); + + assert_eq!(area, Area::from((Point::new(5, 5), Point::new(35, 25)))); + assert_eq!(area, Area::from((5, 5, 35, 25))); + assert_ne!(area, Area::from((5, 55, 35, 25))); + Ok(()) +} + +#[test] +fn point_tests() -> Result<()> { + let p1 = Point::new(10, 10); + let p2 = Point::new(15, 30); + + assert_eq!(p2 - p1, Point::new(5, 20)); + assert_eq!(p1 - p2, Point::new(0, 0)); + + assert_eq!(Point::new(5, 5), Point::from((5, 5))); + Ok(()) +} diff --git a/src/transport.rs b/src/transport.rs deleted file mode 100644 index a9c46cb..0000000 --- a/src/transport.rs +++ /dev/null @@ -1,19 +0,0 @@ -use super::*; - -pub struct Transport { - pub running: bool, - pub bpm: usize, - pub sig: TimeSignature, - pub repeat: usize, -} - -impl Transport { - pub fn new(top: usize, bottom: usize, bpm: usize) -> Self { - Self { - sig: TimeSignature { top, bottom }, - bpm, - running: true, - repeat: 0, - } - } -} -- 2.45.2