diff --git a/.scratch.rs b/.scratch.rs new file mode 100644 index 00000000..e6eede87 --- /dev/null +++ b/.scratch.rs @@ -0,0 +1,357 @@ +/// Just a scratchpad + +/// From sequencer: + + //pub fn footer ( + //buf: &mut Buffer, + //area: Rect, + //note0: usize, + //note: usize, + //time0: usize, + //time: usize, + //time_z: usize, + //) { + //let Rect { mut x, y, width, height } = area; + //buf.set_string(x, y + height, format!("├{}┤", "-".repeat((width - 2).into())), + //Style::default().dim()); + //buf.set_string(x, y + height + 2, format!("├{}┤", "-".repeat((width - 2).into())), + //Style::default().dim()); + //x = x + 2; + //{ + //for (_, [letter, title, value]) in [ + //["S", &format!("ync"), &format!("<4/4>")], + //["Q", &format!("uant"), &format!("<1/{}>", 4 * time_z)], + //["N", &format!("ote"), &format!("{} ({}-{})", note0 + note, note0, "X")], + //["T", &format!("ime"), &format!("{} ({}-{})", time0 + time, time0 + 1, "X")], + //].iter().enumerate() { + //buf.set_string(x, y + height + 1, letter, Style::default().bold().yellow().dim()); + //x = x + 1; + //buf.set_string(x, y + height + 1, &title, Style::default().bold().dim()); + //x = x + title.len() as u16 + 1; + //buf.set_string(x, y + height + 1, &value, Style::default().not_dim()); + //x = x + value.len() as u16; + //buf.set_string(x, y + height + 1, " ", Style::default().dim()); + //x = x + 2; + //} + //} + //} + +//mod vertical { + //use super::*; + + //pub fn draw ( + //s: &Sequencer, + //buf: &mut Buffer, + //mut area: Rect, + //) -> Usually { + //area.x = area.x + 13; + //keys(s, buf, area, 0); + //steps(s, buf, area, 0); + //playhead(s, buf, area.x, area.y); + //Ok(area) + //} + + //pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { + //if s.sequence.is_none() { + //return + //} + //let ppq = s.timebase.ppq() as usize; + //let bg = Style::default(); + //let bw = bg.dim(); + //let wh = bg.white(); + //let Rect { x, y, .. } = area; + //for step in s.time_start..s.time_start+area.height as usize { + //let y = y - (s.time_start + step / 2) as u16; + //let step = step as usize; + ////buf.set_string(x + 5, y, &" ".repeat(32.max(note1-s.note_start)as usize), bg); + //if step % s.time_zoom == 0 { + //buf.set_string(x + 2, y, &format!("{:2} ", step + 1), Style::default()); + //} + //for k in s.note_start..s.note_start+area.width as usize { + //let key = ::midly::num::u7::from_int_lossy(k as u8); + //if step % 2 == 0 { + //let (a, b, c) = ( + //(step + 0) as usize * ppq / s.time_zoom as usize, + //(step + 1) as usize * ppq / s.time_zoom as usize, + //(step + 2) as usize * ppq / s.time_zoom as usize, + //); + //let phrase = &s.phrases[s.sequence.unwrap()]; + //let (character, style) = match ( + //phrase.contains_note_on(key, a, b), + //phrase.contains_note_on(key, b, c), + //) { + //(true, true) => ("█", wh), + //(true, false) => ("▀", wh), + //(false, true) => ("▄", wh), + //(false, false) => ("·", bw), + //}; + //character.blit(buf, x + (5 + k - s.note_start) as u16, y, Some(style)); + //} + //} + //if beat == step as usize { + //buf.set_string(x + 4, y, if beat % 2 == 0 { "▀" } else { "▄" }, Style::default().yellow()); + //for key in s.note_start..s.note_start+area.width as usize { + //let _color = if s.notes_on[key as usize] { + //Style::default().red() + //} else { + //KEY_STYLE[key as usize % 12] + //}; + //} + //} + //} + //} + + //pub fn playhead (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16) { + //let x = x + 5 + s.note_cursor as u16; + //let y = y + s.time_cursor as u16 / 2; + //let c = if s.time_cursor % 2 == 0 { "▀" } else { "▄" }; + //buf.set_string(x, y, c, Style::default()); + //} + +//pub const KEY_WHITE: Style = Style { + //fg: Some(Color::Gray), + //bg: None, + //underline_color: None, + //add_modifier: ::ratatui::style::Modifier::empty(), + //sub_modifier: ::ratatui::style::Modifier::empty(), +//}; + +//pub const KEY_BLACK: Style = Style { + //fg: Some(Color::Black), + //bg: None, + //underline_color: None, + //add_modifier: ::ratatui::style::Modifier::empty(), + //sub_modifier: ::ratatui::style::Modifier::empty(), +//}; + +//pub const KEY_STYLE: [Style;12] = [ + //KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, + //KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, +//]; + + //pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { + //let ppq = s.timebase.ppq() as usize; + //let Rect { x, y, .. } = area; + //for key in s.note_start..s.note_start+area.width as usize { + //let x = x + (5 + key - s.note_start) as u16; + //if key % 12 == 0 { + //let octave = format!("C{}", (key / 12) as i8 - 4); + //buf.set_string(x, y, &octave, Style::default()); + //} + //let mut color = KEY_STYLE[key as usize % 12]; + //let mut is_on = s.notes_on[key as usize]; + //let step = beat; + //let (a, b, c) = ( + //(step + 0) as usize * ppq / s.time_zoom as usize, + //(step + 1) as usize * ppq / s.time_zoom as usize, + //(step + 2) as usize * ppq / s.time_zoom as usize, + //); + //let key = ::midly::num::u7::from(key as u8); + //let phrase = &s.phrases[s.sequence.unwrap()]; + //is_on = is_on || phrase.contains_note_on(key, a, b); + //is_on = is_on || phrase.contains_note_on(key, b, c); + //if is_on { + //color = Style::default().red(); + //} + //buf.set_string(x, y - 1, &format!("▄"), color); + //} + //} + +////pub fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { + ////let Rect { x, y, width, height } = area; + ////let header = draw_header(s, buf, area)?; + ////let piano = match s.view { + ////SequencerMode::Tiny => Rect { x, y, width, height: 0 }, + ////SequencerMode::Compact => Rect { x, y, width, height: 0 }, + ////SequencerMode::Vertical => self::vertical::draw(s, buf, Rect { + ////x, y: y + header.height, width, height, + ////})?, + ////SequencerMode::Horizontal => self::horizontal::draw( + ////buf, + ////Rect { x, y: y + header.height, width, height, }, + ////s.phrase(), + ////s.timebase.ppq() as usize, + ////s.time_cursor, + ////s.time_start, + ////s.time_zoom, + ////s.note_cursor, + ////s.note_start, + ////None + ////)?, + ////}; + ////Ok(draw_box(buf, Rect { + ////x, y, + ////width: header.width.max(piano.width), + ////height: header.height + piano.height + ////})) +////} + +////pub fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { + ////let Rect { x, y, width, .. } = area; + ////let style = Style::default().gray(); + ////crate::view::TransportView { + ////timebase: &s.timebase, + ////playing: s.playing, + ////record: s.recording, + ////overdub: s.overdub, + ////monitor: s.monitoring, + ////frame: 0 + ////}.render(buf, area)?; + ////let separator = format!("├{}┤", "-".repeat((width - 2).into())); + ////separator.blit(buf, x, y + 2, Some(style.dim())); + ////let _ = draw_clips(s, buf, area)?; + ////Ok(Rect { x, y, width, height: 3 }) +////} + +////pub fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { + ////let Rect { x, y, .. } = area; + ////let style = Style::default().gray(); + ////for (i, sequence) in s.phrases.iter().enumerate() { + ////let label = format!("▶ {}", &sequence.name); + ////label.blit(buf, x + 2, y + 3 + (i as u16)*2, Some(if Some(i) == s.sequence { + ////match s.playing { + ////TransportState::Rolling => style.white().bold(), + ////_ => style.not_dim().bold() + ////} + ////} else { + ////style.dim() + ////})); + ////} + ////Ok(Rect { x, y, width: 14, height: 14 }) +////} +//} + +/// From arranger: + +//use crate::core::*; +//use crate::view::*; +//use crate::model::*; + +//pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) + //-> Usually +//{ + //if area.height < 2 { + //return Ok(area) + //} + //area.x = area.width.saturating_sub(80) / 2; + //area.width = area.width.min(80); + //area.height = state.tracks.len() as u16 + 2; + //draw_box(buf, area); + //let x = area.x + 1; + //let y = area.y + 1; + //let _h = area.height - 2; + //for (i, track) in state.tracks.iter().enumerate() { + ////buf.set_string( + ////x, y + index as u16, + ////&track.name, Style::default().bold().not_dim() + ////); + //for (j, (column, field)) in [ + //(0, format!(" {:10} ", track.name)), + //(12, format!(" {:.1}dB ", track.gain)), + //(22, format!(" [ ] ")), + //(30, format!(" C ")), + //(35, format!(" {:.1}dB ", track.level)), + //(45, format!(" [ ] ")), + //(51, format!(" {:7} ", track.route)), + //].into_iter().enumerate() { + //buf.set_string( + //x + column as u16, + //y + i as u16, + //field, + //if state.selected_track == i && state.selected_column == j { + //Style::default().white().bold().not_dim() + //} else { + //Style::default().not_dim() + //} + //); + ////stdout.queue(move_to(column, row))?; + ////if state.selected_track == i && state.selected_column == j { + ////stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?; + ////} else { + ////stdout.queue(PrintStyledContent(field.to_string().bold()))?; + ////} + ////fn render_meters ( + ////state: &mut Mixer, + ////stdout: &mut Stdout, + ////offset: Rect + ////) -> Result<(), Box> { + ////let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); + ////for (i, track) in state.tracks.iter().enumerate() { + ////let row = (i + 1) as u16; + ////stdout + ////.queue(move_to(10, row))?.queue(PrintStyledContent("▁".green()))? + ////.queue(move_to(20, row))?.queue(PrintStyledContent("▁".green()))? + ////.queue(move_to(28, row))?.queue(PrintStyledContent("▁".green()))? + ////.queue(move_to(43, row))?.queue(PrintStyledContent("▁".green()))?; + ////} + ////Ok(()) + ////} + //} + //} + //Ok(area) +//} + + +/// From transport: + + // Record button/indicator + //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ + //"⏺ REC".blit(buf, x, y, Some(if self.record { red } else { dim })) + //}, + + //// Overdub button/indicator + //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ + //"⏺ DUB".blit(buf, x, y, Some(if self.overdub { yellow } else { dim })) + //}, + + //// Monitor button/indicator + //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ + //"⏺ MON".blit(buf, x, y, Some(if self.monitor { green } else { dim })) + //}, + // + +// From sampler: +//fn render_table ( + //self: &mut Sampler, + //stdout: &mut Stdout, + //offset: (u16, u16), +//) -> Result<(), Box> { + //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); + //stdout.queue(move_to(0, 3))?.queue( + //Print(" Name Rate Trigger Route") + //)?; + //for (i, sample) in self.samples.lock().unwrap().iter().enumerate() { + //let row = 4 + i as u16; + //for (j, (column, field)) in [ + //(0, format!(" {:7} ", sample.name)), + //(9, format!(" {:.1}Hz ", sample.rate)), + //(18, format!(" MIDI C{} {} ", sample.trigger.0, sample.trigger.1)), + //(33, format!(" {:.1}dB -> Output ", sample.gain)), + //(50, format!(" {} ", sample.playing.unwrap_or(0))), + //].into_iter().enumerate() { + //stdout.queue(move_to(column, row))?; + //if self.selected_sample == i && self.selected_column == j { + //stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?; + //} else { + //stdout.queue(PrintStyledContent(field.to_string().bold()))?; + //} + //} + //} + //Ok(()) +//} + +//fn render_meters ( + //self: &mut Sampler, + //stdout: &mut Stdout, + //offset: (u16, u16), +//) -> Result<(), Box> { + //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); + //for (i, sample) in self.samples.lock().iter().enumerate() { + //let row = 4 + i as u16; + //stdout.queue(move_to(32, row))?.queue( + //PrintStyledContent("▁".green()) + //)?; + //} + //Ok(()) +//} + diff --git a/src/cli.rs b/src/cli.rs index 52d2702c..845ba389 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,3 +1,5 @@ +//! Command line option parser. + use clap::{Parser, Subcommand}; #[derive(Debug, Parser)] diff --git a/src/config.rs b/src/config.rs index 51eaa12a..3a9b062a 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,3 +1,5 @@ +//! Global settings. + use crate::core::*; use std::path::{Path, PathBuf}; use std::fs::{File, create_dir_all}; diff --git a/src/control.rs b/src/control.rs index 08d56b75..54ca57d2 100644 --- a/src/control.rs +++ b/src/control.rs @@ -1,3 +1,5 @@ +//! Handling of input events. + use crate::{core::*, handle, App, AppFocus}; pubmod!{ arranger chain focus mixer plugin sampler sequencer transport } diff --git a/src/core.rs b/src/core.rs index 78b5c3de..d23f8834 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,3 +1,5 @@ +//! Prelude. + // Stdlib dependencies: pub(crate) use std::error::Error; pub(crate) use std::io::{stdout}; diff --git a/src/edn.rs b/src/edn.rs index e56210c7..87230f87 100644 --- a/src/edn.rs +++ b/src/edn.rs @@ -1,3 +1,5 @@ +//! Project file format. + use crate::{core::*, model::*, App}; use clojure_reader::{edn::{read, Edn}, error::Error as EdnError}; diff --git a/src/jack.rs b/src/jack.rs index 688a84f4..135698ca 100644 --- a/src/jack.rs +++ b/src/jack.rs @@ -1,3 +1,5 @@ +//! Audio engine. + use crate::core::*; submod!( device event factory ports ); diff --git a/src/main.rs b/src/main.rs index 240630d3..19d20b99 100644 --- a/src/main.rs +++ b/src/main.rs @@ -9,7 +9,7 @@ extern crate clap; extern crate jack as _jack; extern crate crossterm; -mod core; crate::core::submod! { cli config control model view jack edn } +mod core; crate::core::pubmod! { cli config control model view jack edn } use crate::{core::*, model::*}; diff --git a/src/model.rs b/src/model.rs index e7f63bb9..967a4d0a 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,3 +1,5 @@ +//! Application state. + pub mod looper; pub mod mixer; pub mod phrase; diff --git a/src/model/sampler.rs b/src/model/sampler.rs index e73ba723..57a3b8e9 100644 --- a/src/model/sampler.rs +++ b/src/model/sampler.rs @@ -83,6 +83,7 @@ impl Sampler { Control::Continue } + /// Create [Voice]s from [Sample]s in response to MIDI input. fn process_midi_in (&mut self, scope: &ProcessScope) { for RawMidi { time, bytes } in self.ports.midi_ins.get("midi").unwrap().iter(scope) { if let LiveEvent::Midi { message, .. } = LiveEvent::parse(bytes).unwrap() { @@ -95,22 +96,26 @@ impl Sampler { } } + /// Zero the output buffer. fn clear_output_buffer (&mut self) { for buffer in self.buffer.iter_mut() { buffer.fill(0.0); } } + /// Mix all currently playing samples into the output. fn process_audio_out (&mut self, scope: &ProcessScope) { let channel_count = self.buffer.len(); self.voices.retain_mut(|voice|{ for index in 0..scope.n_frames() as usize { if let Some(frame) = voice.next() { for (channel, sample) in frame.iter().enumerate() { + // Averaging mixer: //self.buffer[channel % channel_count][index] = ( //(self.buffer[channel % channel_count][index] + sample * self.output_gain) / 2.0 //); - self.buffer[channel % channel_count][index] += sample * self.output_gain; + self.buffer[channel % channel_count][index] += + sample * self.output_gain; } } else { return false @@ -142,6 +147,7 @@ impl Sampler { }}; } +/// Read WAV from file pub fn read_sample_data (src: &str) -> Usually<(usize, Vec>)> { let mut channels: Vec> = vec![]; for channel in wavers::Wav::from_path(src)?.channels() { @@ -157,6 +163,7 @@ pub fn read_sample_data (src: &str) -> Usually<(usize, Vec>)> { Ok((end, data)) } +/// A sound sample. pub struct Sample { pub name: String, pub start: usize, @@ -178,6 +185,7 @@ impl Sample { } } +/// A currently playing instance of a sample. pub struct Voice { pub sample: Arc, pub after: usize, @@ -203,48 +211,3 @@ impl Iterator for Voice { None } } - -//fn render_table ( - //self: &mut Sampler, - //stdout: &mut Stdout, - //offset: (u16, u16), -//) -> Result<(), Box> { - //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); - //stdout.queue(move_to(0, 3))?.queue( - //Print(" Name Rate Trigger Route") - //)?; - //for (i, sample) in self.samples.lock().unwrap().iter().enumerate() { - //let row = 4 + i as u16; - //for (j, (column, field)) in [ - //(0, format!(" {:7} ", sample.name)), - //(9, format!(" {:.1}Hz ", sample.rate)), - //(18, format!(" MIDI C{} {} ", sample.trigger.0, sample.trigger.1)), - //(33, format!(" {:.1}dB -> Output ", sample.gain)), - //(50, format!(" {} ", sample.playing.unwrap_or(0))), - //].into_iter().enumerate() { - //stdout.queue(move_to(column, row))?; - //if self.selected_sample == i && self.selected_column == j { - //stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?; - //} else { - //stdout.queue(PrintStyledContent(field.to_string().bold()))?; - //} - //} - //} - //Ok(()) -//} - -//fn render_meters ( - //self: &mut Sampler, - //stdout: &mut Stdout, - //offset: (u16, u16), -//) -> Result<(), Box> { - //let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); - //for (i, sample) in self.samples.lock().iter().enumerate() { - //let row = 4 + i as u16; - //stdout.queue(move_to(32, row))?.queue( - //PrintStyledContent("▁".green()) - //)?; - //} - //Ok(()) -//} - diff --git a/src/view.rs b/src/view.rs index 0477345b..6e1017ec 100644 --- a/src/view.rs +++ b/src/view.rs @@ -1,3 +1,5 @@ +//! Rendering of application to display. + pub mod arranger; pub mod border; pub mod chain; diff --git a/src/view/arranger.rs b/src/view/arranger.rs index 8a07d158..3e1b4ee3 100644 --- a/src/view/arranger.rs +++ b/src/view/arranger.rs @@ -305,72 +305,3 @@ impl<'a> ArrangerView<'a> { ]).render(buf, area) } } - -//use crate::core::*; -//use crate::view::*; -//use crate::model::*; - -//pub fn render (state: &Mixer, buf: &mut Buffer, mut area: Rect) - //-> Usually -//{ - //if area.height < 2 { - //return Ok(area) - //} - //area.x = area.width.saturating_sub(80) / 2; - //area.width = area.width.min(80); - //area.height = state.tracks.len() as u16 + 2; - //draw_box(buf, area); - //let x = area.x + 1; - //let y = area.y + 1; - //let _h = area.height - 2; - //for (i, track) in state.tracks.iter().enumerate() { - ////buf.set_string( - ////x, y + index as u16, - ////&track.name, Style::default().bold().not_dim() - ////); - //for (j, (column, field)) in [ - //(0, format!(" {:10} ", track.name)), - //(12, format!(" {:.1}dB ", track.gain)), - //(22, format!(" [ ] ")), - //(30, format!(" C ")), - //(35, format!(" {:.1}dB ", track.level)), - //(45, format!(" [ ] ")), - //(51, format!(" {:7} ", track.route)), - //].into_iter().enumerate() { - //buf.set_string( - //x + column as u16, - //y + i as u16, - //field, - //if state.selected_track == i && state.selected_column == j { - //Style::default().white().bold().not_dim() - //} else { - //Style::default().not_dim() - //} - //); - ////stdout.queue(move_to(column, row))?; - ////if state.selected_track == i && state.selected_column == j { - ////stdout.queue(PrintStyledContent(field.to_string().bold().reverse()))?; - ////} else { - ////stdout.queue(PrintStyledContent(field.to_string().bold()))?; - ////} - ////fn render_meters ( - ////state: &mut Mixer, - ////stdout: &mut Stdout, - ////offset: Rect - ////) -> Result<(), Box> { - ////let move_to = |col, row| crossterm::cursor::MoveTo(offset.0 + col, offset.1 + row); - ////for (i, track) in state.tracks.iter().enumerate() { - ////let row = (i + 1) as u16; - ////stdout - ////.queue(move_to(10, row))?.queue(PrintStyledContent("▁".green()))? - ////.queue(move_to(20, row))?.queue(PrintStyledContent("▁".green()))? - ////.queue(move_to(28, row))?.queue(PrintStyledContent("▁".green()))? - ////.queue(move_to(43, row))?.queue(PrintStyledContent("▁".green()))?; - ////} - ////Ok(()) - ////} - //} - //} - //Ok(area) -//} - diff --git a/src/view/sequencer.rs b/src/view/sequencer.rs index 46cd3675..3310eedb 100644 --- a/src/view/sequencer.rs +++ b/src/view/sequencer.rs @@ -328,222 +328,3 @@ fn half_block (lower: bool, upper: bool) -> Option { _ => None } } - - //pub fn footer ( - //buf: &mut Buffer, - //area: Rect, - //note0: usize, - //note: usize, - //time0: usize, - //time: usize, - //time_z: usize, - //) { - //let Rect { mut x, y, width, height } = area; - //buf.set_string(x, y + height, format!("├{}┤", "-".repeat((width - 2).into())), - //Style::default().dim()); - //buf.set_string(x, y + height + 2, format!("├{}┤", "-".repeat((width - 2).into())), - //Style::default().dim()); - //x = x + 2; - //{ - //for (_, [letter, title, value]) in [ - //["S", &format!("ync"), &format!("<4/4>")], - //["Q", &format!("uant"), &format!("<1/{}>", 4 * time_z)], - //["N", &format!("ote"), &format!("{} ({}-{})", note0 + note, note0, "X")], - //["T", &format!("ime"), &format!("{} ({}-{})", time0 + time, time0 + 1, "X")], - //].iter().enumerate() { - //buf.set_string(x, y + height + 1, letter, Style::default().bold().yellow().dim()); - //x = x + 1; - //buf.set_string(x, y + height + 1, &title, Style::default().bold().dim()); - //x = x + title.len() as u16 + 1; - //buf.set_string(x, y + height + 1, &value, Style::default().not_dim()); - //x = x + value.len() as u16; - //buf.set_string(x, y + height + 1, " ", Style::default().dim()); - //x = x + 2; - //} - //} - //} - -//mod vertical { - //use super::*; - - //pub fn draw ( - //s: &Sequencer, - //buf: &mut Buffer, - //mut area: Rect, - //) -> Usually { - //area.x = area.x + 13; - //keys(s, buf, area, 0); - //steps(s, buf, area, 0); - //playhead(s, buf, area.x, area.y); - //Ok(area) - //} - - //pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { - //if s.sequence.is_none() { - //return - //} - //let ppq = s.timebase.ppq() as usize; - //let bg = Style::default(); - //let bw = bg.dim(); - //let wh = bg.white(); - //let Rect { x, y, .. } = area; - //for step in s.time_start..s.time_start+area.height as usize { - //let y = y - (s.time_start + step / 2) as u16; - //let step = step as usize; - ////buf.set_string(x + 5, y, &" ".repeat(32.max(note1-s.note_start)as usize), bg); - //if step % s.time_zoom == 0 { - //buf.set_string(x + 2, y, &format!("{:2} ", step + 1), Style::default()); - //} - //for k in s.note_start..s.note_start+area.width as usize { - //let key = ::midly::num::u7::from_int_lossy(k as u8); - //if step % 2 == 0 { - //let (a, b, c) = ( - //(step + 0) as usize * ppq / s.time_zoom as usize, - //(step + 1) as usize * ppq / s.time_zoom as usize, - //(step + 2) as usize * ppq / s.time_zoom as usize, - //); - //let phrase = &s.phrases[s.sequence.unwrap()]; - //let (character, style) = match ( - //phrase.contains_note_on(key, a, b), - //phrase.contains_note_on(key, b, c), - //) { - //(true, true) => ("█", wh), - //(true, false) => ("▀", wh), - //(false, true) => ("▄", wh), - //(false, false) => ("·", bw), - //}; - //character.blit(buf, x + (5 + k - s.note_start) as u16, y, Some(style)); - //} - //} - //if beat == step as usize { - //buf.set_string(x + 4, y, if beat % 2 == 0 { "▀" } else { "▄" }, Style::default().yellow()); - //for key in s.note_start..s.note_start+area.width as usize { - //let _color = if s.notes_on[key as usize] { - //Style::default().red() - //} else { - //KEY_STYLE[key as usize % 12] - //}; - //} - //} - //} - //} - - //pub fn playhead (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16) { - //let x = x + 5 + s.note_cursor as u16; - //let y = y + s.time_cursor as u16 / 2; - //let c = if s.time_cursor % 2 == 0 { "▀" } else { "▄" }; - //buf.set_string(x, y, c, Style::default()); - //} - -//pub const KEY_WHITE: Style = Style { - //fg: Some(Color::Gray), - //bg: None, - //underline_color: None, - //add_modifier: ::ratatui::style::Modifier::empty(), - //sub_modifier: ::ratatui::style::Modifier::empty(), -//}; - -//pub const KEY_BLACK: Style = Style { - //fg: Some(Color::Black), - //bg: None, - //underline_color: None, - //add_modifier: ::ratatui::style::Modifier::empty(), - //sub_modifier: ::ratatui::style::Modifier::empty(), -//}; - -//pub const KEY_STYLE: [Style;12] = [ - //KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, - //KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, KEY_BLACK, KEY_WHITE, -//]; - - //pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) { - //let ppq = s.timebase.ppq() as usize; - //let Rect { x, y, .. } = area; - //for key in s.note_start..s.note_start+area.width as usize { - //let x = x + (5 + key - s.note_start) as u16; - //if key % 12 == 0 { - //let octave = format!("C{}", (key / 12) as i8 - 4); - //buf.set_string(x, y, &octave, Style::default()); - //} - //let mut color = KEY_STYLE[key as usize % 12]; - //let mut is_on = s.notes_on[key as usize]; - //let step = beat; - //let (a, b, c) = ( - //(step + 0) as usize * ppq / s.time_zoom as usize, - //(step + 1) as usize * ppq / s.time_zoom as usize, - //(step + 2) as usize * ppq / s.time_zoom as usize, - //); - //let key = ::midly::num::u7::from(key as u8); - //let phrase = &s.phrases[s.sequence.unwrap()]; - //is_on = is_on || phrase.contains_note_on(key, a, b); - //is_on = is_on || phrase.contains_note_on(key, b, c); - //if is_on { - //color = Style::default().red(); - //} - //buf.set_string(x, y - 1, &format!("▄"), color); - //} - //} - -////pub fn render (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { - ////let Rect { x, y, width, height } = area; - ////let header = draw_header(s, buf, area)?; - ////let piano = match s.view { - ////SequencerMode::Tiny => Rect { x, y, width, height: 0 }, - ////SequencerMode::Compact => Rect { x, y, width, height: 0 }, - ////SequencerMode::Vertical => self::vertical::draw(s, buf, Rect { - ////x, y: y + header.height, width, height, - ////})?, - ////SequencerMode::Horizontal => self::horizontal::draw( - ////buf, - ////Rect { x, y: y + header.height, width, height, }, - ////s.phrase(), - ////s.timebase.ppq() as usize, - ////s.time_cursor, - ////s.time_start, - ////s.time_zoom, - ////s.note_cursor, - ////s.note_start, - ////None - ////)?, - ////}; - ////Ok(draw_box(buf, Rect { - ////x, y, - ////width: header.width.max(piano.width), - ////height: header.height + piano.height - ////})) -////} - -////pub fn draw_header (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { - ////let Rect { x, y, width, .. } = area; - ////let style = Style::default().gray(); - ////crate::view::TransportView { - ////timebase: &s.timebase, - ////playing: s.playing, - ////record: s.recording, - ////overdub: s.overdub, - ////monitor: s.monitoring, - ////frame: 0 - ////}.render(buf, area)?; - ////let separator = format!("├{}┤", "-".repeat((width - 2).into())); - ////separator.blit(buf, x, y + 2, Some(style.dim())); - ////let _ = draw_clips(s, buf, area)?; - ////Ok(Rect { x, y, width, height: 3 }) -////} - -////pub fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually { - ////let Rect { x, y, .. } = area; - ////let style = Style::default().gray(); - ////for (i, sequence) in s.phrases.iter().enumerate() { - ////let label = format!("▶ {}", &sequence.name); - ////label.blit(buf, x + 2, y + 3 + (i as u16)*2, Some(if Some(i) == s.sequence { - ////match s.playing { - ////TransportState::Rolling => style.white().bold(), - ////_ => style.not_dim().bold() - ////} - ////} else { - ////style.dim() - ////})); - ////} - ////Ok(Rect { x, y, width: 14, height: 14 }) -////} -//} diff --git a/src/view/transport.rs b/src/view/transport.rs index 502a329b..785558f4 100644 --- a/src/view/transport.rs +++ b/src/view/transport.rs @@ -79,18 +79,3 @@ render!(TransportToolbar |self, buf, area| { ]).render(buf, area) }); - - // Record button/indicator - //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ - //"⏺ REC".blit(buf, x, y, Some(if self.record { red } else { dim })) - //}, - - //// Overdub button/indicator - //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ - //"⏺ DUB".blit(buf, x, y, Some(if self.overdub { yellow } else { dim })) - //}, - - //// Monitor button/indicator - //&|buf: &mut Buffer, Rect { x, y, .. }: Rect|{ - //"⏺ MON".blit(buf, x, y, Some(if self.monitor { green } else { dim })) - //},