diff --git a/.forgejo/workflows/build.yaml b/.forgejo/workflows/build.yaml index dd99c340..5dfe682e 100644 --- a/.forgejo/workflows/build.yaml +++ b/.forgejo/workflows/build.yaml @@ -5,9 +5,7 @@ jobs: image: nixos/nix:latest steps: - run: nix-channel --list && nix-channel --update - - run: nix-shell -p git --command 'git clone $GITHUB_SERVER_URL/$GITHUB_REPOSITORY .' - - run: nix-shell -p git --command 'cd rust-jack && git remote set-url origin https://codeberg.org/unspeaker/rust-jack' - - run: nix-shell -p git --command 'git submodule update --init --recursive' + - run: nix-shell -p git --command 'git clone --recursive $GITHUB_SERVER_URL/$GITHUB_REPOSITORY .' - run: whoami && pwd && ls -al - run: nix-shell --command 'cargo version -vv && cargo test && cargo build --release && cloc crates/tek/src' .forgejo/workflows/build.nix - run: "docker run --security-opt seccomp=unconfined -v $PWD:/volume xd009642/tarpaulin cargo tarpaulin --out Html --all-features" diff --git a/.gitmodules b/.gitmodules index c32def4c..3c5a123f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +1,4 @@ [submodule "rust-jack"] path = rust-jack - url = git@codeberg.org:unspeaker/rust-jack.git + url = https://codeberg.org/unspeaker/rust-jack branch = timebase diff --git a/README.md b/README.md index ef493af3..76bdd870 100644 --- a/README.md +++ b/README.md @@ -32,9 +32,7 @@ the project roadmap is at https://codeberg.org/unspeaker/tek/milestones * **requirements:** linux; jack or pipewire; 24-bit terminal (i use `kitty`) * **recommended:** midi controller; samples in wav format; lv2 plugins. -### installation - -#### arch linux +### arch linux [tek](https://codeberg.org/unspeaker/tek) is available as a package in the AUR. you can install it using an AUR helper (e.g. `paru`): diff --git a/engine/src/tui.rs b/engine/src/tui.rs index 56abbe5d..5fae7615 100644 --- a/engine/src/tui.rs +++ b/engine/src/tui.rs @@ -19,6 +19,7 @@ pub(crate) use ratatui::{ prelude::{Color, Style, Buffer}, style::Modifier, backend::{Backend, CrosstermBackend, ClearType}, + layout::{Size, Rect}, buffer::Cell }; @@ -64,11 +65,11 @@ impl Tui { /// Construct a new TUI engine and wrap it for shared ownership. pub fn new () -> Usually<Arc<RwLock<Self>>> { let backend = CrosstermBackend::new(stdout()); - let area = backend.size()?; + let Size { width, height } = backend.size()?; Ok(Arc::new(RwLock::new(Self { exited: Arc::new(AtomicBool::new(false)), - buffer: Buffer::empty(area), - area: [area.x, area.y, area.width, area.height], + buffer: Buffer::empty(Rect { x: 0, y: 0, width, height }), + area: [0, 0, width, height], backend, }))) } @@ -133,25 +134,23 @@ impl<T: Render<Tui> + Handle<Tui> + Sized + 'static> TuiRun<T> for Arc<RwLock<Tu let exited = self.read().unwrap().exited.clone(); let engine = self.clone(); let state = state.clone(); - let size = engine.read().unwrap().backend.size().expect("get size failed"); - let mut buffer = Buffer::empty(size); + let Size { width, height } = engine.read().unwrap().backend.size().expect("get size failed"); + let mut buffer = Buffer::empty(Rect { x: 0, y: 0, width, height }); spawn(move || loop { if exited.fetch_and(true, Relaxed) { break } - let size = engine.read().unwrap().backend.size() + let Size { width, height } = engine.read().unwrap().backend.size() .expect("get size failed"); if let Ok(state) = state.try_read() { + let size = Rect { x: 0, y: 0, width, height }; if buffer.area != size { engine.write().unwrap().backend.clear_region(ClearType::All) .expect("clear failed"); buffer.resize(size); buffer.reset(); } - let mut output = TuiOutput { - buffer, - area: [size.x, size.y, size.width, size.height] - }; + let mut output = TuiOutput { buffer, area: [0, 0, width, height] }; state.render(&mut output).expect("render failed"); buffer = engine.write().unwrap().flip(output.buffer, size); } diff --git a/layout/src/transform.rs b/layout/src/transform.rs index 731f2a16..cda8f91a 100644 --- a/layout/src/transform.rs +++ b/layout/src/transform.rs @@ -136,21 +136,12 @@ transform_xy_unit!(Fixed }); transform_xy_unit!(Shrink - |self, to|Ok( - self.content().min_size(to)?.map(|to|match *self { - Self::X(w, _) => [ - if to.w() > w { to.w() - w } else { 0.into() }, - to.h() - ], - Self::Y(h, _) => [ - to.w(), - if to.h() > h { to.h() - h } else { 0.into() } - ], - Self::XY(w, h, _) => [ - if to.w() > w { to.w() - w } else { 0.into() }, - if to.h() > h { to.h() - h } else { 0.into() } - ], - }.into())), + |self, to|Ok(self.content().min_size(to)? + .map(|wh|wh.wh()) + .map(|[w, h]|[ + w.minus(self.dx()).into(), + h.minus(self.dy()).into() + ].into())), |self, to|Ok(self.min_size(to.area().wh().into())? .map(|size|to.render_in(to.area().clip(size).into(), &self.content())) .transpose()?.unwrap_or(()))); diff --git a/src/transport.rs b/src/transport.rs index 5ff9b647..f9314b02 100644 --- a/src/transport.rs +++ b/src/transport.rs @@ -10,21 +10,23 @@ pub struct TransportTui { pub size: Measure<Tui>, pub cursor: (usize, usize), pub focus: TransportFocus, + pub color: ItemPalette, } from_jack!(|jack|TransportTui Self { jack: jack.clone(), clock: ClockModel::from(jack), size: Measure::new(), cursor: (0, 0), - focus: TransportFocus::PlayPause + focus: TransportFocus::PlayPause, + color: ItemPalette::random(), }); has_clock!(|self: TransportTui|&self.clock); audio!(|self: TransportTui, client, scope|ClockAudio(self).process(client, scope)); handle!(<Tui>|self: TransportTui, from|TransportCommand::execute_with_state(self, from)); -render!(<Tui>|self: TransportTui|row!([ - Fixed::xy(5, 3, PlayPause(false)), - Fixed::y(3, TransportView::new(self, None, true)) -])); +render!(<Tui>|self: TransportTui|Fixed::y(3, row!([ + " ", Fixed::x(5, PlayPause(false)), + " ", Shrink::x(1, TransportView::new(self, Some(self.color), true)), +]))); impl std::fmt::Debug for TransportTui { fn fmt (&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { f.debug_struct("TransportTui") @@ -88,7 +90,6 @@ impl TransportView { render!(<Tui>|self: TransportView|{ let color = self.color; Fixed::y(3, Tui::bg(color.base.rgb, Fill::x(row!([ - //PlayPause(self.started), " ", col!([ TransportField(" Beat", self.beat.as_str(), &color), TransportField(" Time", format!("{:.1}s", self.current_second).as_str(), &color),