mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
browse phrases
This commit is contained in:
parent
625956766e
commit
83830d9cb3
9 changed files with 86 additions and 84 deletions
|
|
@ -56,7 +56,7 @@ pub fn process (_: &mut Chain, _: &Client, _: &ProcessScope) -> Control {
|
||||||
pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
|
pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
|
||||||
-> Usually<Rect>
|
-> Usually<Rect>
|
||||||
{
|
{
|
||||||
let Rect { mut x, mut y, width, height } = area;
|
let Rect { x, y, .. } = area;
|
||||||
let selected = Some(if state.focused {
|
let selected = Some(if state.focused {
|
||||||
Style::default().green().not_dim()
|
Style::default().green().not_dim()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -71,7 +71,7 @@ pub fn render (state: &Chain, buf: &mut Buffer, area: Rect)
|
||||||
},
|
},
|
||||||
ChainView::Row => {
|
ChainView::Row => {
|
||||||
draw_box_styled(buf, area, selected);
|
draw_box_styled(buf, area, selected);
|
||||||
let (area, areas) = Row::draw(buf, area, &state.items, 0)?;
|
let (area, _) = Row::draw(buf, area, &state.items, 0)?;
|
||||||
area
|
area
|
||||||
},
|
},
|
||||||
ChainView::Column => {
|
ChainView::Column => {
|
||||||
|
|
@ -172,10 +172,9 @@ pub fn draw_as_row (
|
||||||
pub fn draw_as_column (
|
pub fn draw_as_column (
|
||||||
state: &Chain, buf: &mut Buffer, area: Rect, selected: Option<Style>
|
state: &Chain, buf: &mut Buffer, area: Rect, selected: Option<Style>
|
||||||
) -> Usually<Rect> {
|
) -> Usually<Rect> {
|
||||||
let Rect { x, y, width, height } = area;
|
let Rect { x, mut y, width, height } = area;
|
||||||
//let (area, areas) = Column::draw(buf, area, &state.items, 0)?;
|
//let (area, areas) = Column::draw(buf, area, &state.items, 0)?;
|
||||||
let mut w = 0u16;
|
let mut w = 0u16;
|
||||||
let mut y = area.y;
|
|
||||||
let mut frames = vec![];
|
let mut frames = vec![];
|
||||||
for device in state.items.iter() {
|
for device in state.items.iter() {
|
||||||
let style_midi = Style::default().black().bold().on_green();
|
let style_midi = Style::default().black().bold().on_green();
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ impl<'a> LauncherGridView<'a> {
|
||||||
//self.separator_h(2, false);
|
//self.separator_h(2, false);
|
||||||
//self.separator_h((self.state.cursor.1 * 2) as u16, true);
|
//self.separator_h((self.state.cursor.1 * 2) as u16, true);
|
||||||
//self.separator_h(((self.state.cursor.1 + 1) * 2) as u16, true);
|
//self.separator_h(((self.state.cursor.1 + 1) * 2) as u16, true);
|
||||||
|
self.area.height = self.state.scenes.len() as u16 + 2;
|
||||||
let style = Some(Style::default().green().dim());
|
let style = Some(Style::default().green().dim());
|
||||||
if self.focused {
|
if self.focused {
|
||||||
let Rect { x, y, width, height } = self.area;
|
let Rect { x, y, width, height } = self.area;
|
||||||
|
|
@ -37,19 +38,19 @@ impl<'a> LauncherGridView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let (mut x, y) = (self.area.x, self.area.y);
|
let (mut x, y) = (self.area.x, self.area.y);
|
||||||
for (i, column) in columns.iter().enumerate() {
|
for (i, title) in columns.iter().enumerate() {
|
||||||
if x >= self.area.x + self.area.width {
|
if x >= self.area.x + self.area.width {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
column.blit(
|
title.blit(
|
||||||
self.buf, x + 2, y, Some(self.highlight(i == self.state.cursor.0).bold())
|
self.buf, x+1, y, Some(self.highlight(i == self.state.cursor.0).bold())
|
||||||
);
|
);
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
self.scenes(x + 2, y + 1);
|
self.scenes(x+1, y + 1);
|
||||||
} else if i < columns.len() {
|
} else if i < columns.len() {
|
||||||
self.clips(x + 2, y + 1, i - 1);
|
self.clips(x+1, y + 1, i - 1);
|
||||||
}
|
}
|
||||||
let w = (column.len() as u16).max(12) + 3;
|
let w = (title.len() as u16).max(10) + 3;
|
||||||
x = x + w;
|
x = x + w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -66,10 +67,10 @@ impl<'a> LauncherGridView<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn column_widths (&self) -> Vec<u16> {
|
fn column_widths (&self) -> Vec<u16> {
|
||||||
self.column_names().iter().map(|name|(name.len() as u16).max(12) + 3).collect()
|
self.column_names().iter().map(|name|(name.len() as u16).max(10) + 3).collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn scenes (&mut self, x: u16, y: u16) {
|
fn scenes (&mut self, x: u16, y: u16) -> u16 {
|
||||||
let mut index = 0usize;
|
let mut index = 0usize;
|
||||||
loop {
|
loop {
|
||||||
if index >= self.state.scenes.len() {
|
if index >= self.state.scenes.len() {
|
||||||
|
|
@ -79,12 +80,11 @@ impl<'a> LauncherGridView<'a> {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if let Some(scene) = self.state.scenes.get(index) {
|
if let Some(scene) = self.state.scenes.get(index) {
|
||||||
format!("⯈ {}", scene.name).blit(
|
let style = Some(self.highlight(
|
||||||
self.buf, x, y + index as u16,
|
|
||||||
Some(self.highlight(
|
|
||||||
(0 == self.state.cursor.0) && (index + 1 == self.state.cursor.1)
|
(0 == self.state.cursor.0) && (index + 1 == self.state.cursor.1)
|
||||||
).bold())
|
).bold());
|
||||||
)
|
"⯈".blit(self.buf, x, y + index as u16, style);
|
||||||
|
scene.name.blit(self.buf, x+1, y + index as u16, style);
|
||||||
}
|
}
|
||||||
index = index + 1;
|
index = index + 1;
|
||||||
}
|
}
|
||||||
|
|
@ -95,9 +95,10 @@ impl<'a> LauncherGridView<'a> {
|
||||||
} else {
|
} else {
|
||||||
Style::default().dim()
|
Style::default().dim()
|
||||||
}));
|
}));
|
||||||
|
index as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clips (&mut self, x: u16, y: u16, track: usize) {
|
fn clips (&mut self, x: u16, y: u16, track: usize) -> u16 {
|
||||||
let mut index = 0;
|
let mut index = 0;
|
||||||
loop {
|
loop {
|
||||||
if index >= self.state.scenes.len() {
|
if index >= self.state.scenes.len() {
|
||||||
|
|
@ -114,7 +115,7 @@ impl<'a> LauncherGridView<'a> {
|
||||||
let index = index as u16;
|
let index = index as u16;
|
||||||
let label = if let Some(Some(clip)) = clip {
|
let label = if let Some(Some(clip)) = clip {
|
||||||
let track = self.state.tracks[track].sequencer.state();
|
let track = self.state.tracks[track].sequencer.state();
|
||||||
let phrase = track.sequences.get(*clip);
|
let phrase = track.phrases.get(*clip);
|
||||||
if let Some(phrase) = phrase {
|
if let Some(phrase) = phrase {
|
||||||
format!("⯈{}", phrase.name)
|
format!("⯈{}", phrase.name)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -134,6 +135,7 @@ impl<'a> LauncherGridView<'a> {
|
||||||
} else {
|
} else {
|
||||||
Style::default().dim()
|
Style::default().dim()
|
||||||
}));
|
}));
|
||||||
|
index as u16
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight (&self, highlight: bool) -> Style {
|
fn highlight (&self, highlight: bool) -> Style {
|
||||||
|
|
|
||||||
|
|
@ -134,7 +134,7 @@ fn clip_next (state: &mut Launcher) -> Usually<bool> {
|
||||||
let scene = &mut state.scenes[scene_id];
|
let scene = &mut state.scenes[scene_id];
|
||||||
scene.clips[clip_id] = match scene.clips[clip_id] {
|
scene.clips[clip_id] = match scene.clips[clip_id] {
|
||||||
None => Some(0),
|
None => Some(0),
|
||||||
Some(i) => if i >= state.tracks[clip_id].sequencer.state().sequences.len().saturating_sub(1) {
|
Some(i) => if i >= state.tracks[clip_id].sequencer.state().phrases.len().saturating_sub(1) {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(i + 1)
|
Some(i + 1)
|
||||||
|
|
@ -149,7 +149,7 @@ fn clip_prev (state: &mut Launcher) -> Usually<bool> {
|
||||||
let clip_id = state.cursor.0 - 1;
|
let clip_id = state.cursor.0 - 1;
|
||||||
let scene = &mut state.scenes[scene_id];
|
let scene = &mut state.scenes[scene_id];
|
||||||
scene.clips[clip_id] = match scene.clips[clip_id] {
|
scene.clips[clip_id] = match scene.clips[clip_id] {
|
||||||
None => Some(state.tracks[clip_id].sequencer.state().sequences.len().saturating_sub(1)),
|
None => Some(state.tracks[clip_id].sequencer.state().phrases.len().saturating_sub(1)),
|
||||||
Some(i) => if i == 0 {
|
Some(i) => if i == 0 {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -117,18 +117,28 @@ impl Launcher {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_track (&self) -> Option<&Track> {
|
fn track <'a> (&'a self) -> Option<(usize, &'a Track)> {
|
||||||
if self.cursor.0 >= 1 {
|
match self.col() { 0 => None, _ => {
|
||||||
self.tracks.get(self.cursor.0 as usize - 1 as usize)
|
let id = self.col() as usize - 1;
|
||||||
} else {
|
self.tracks.get(id).map(|t|(id, t))
|
||||||
None
|
} }
|
||||||
}
|
}
|
||||||
|
fn scene <'a> (&'a self) -> Option<(usize, &'a Scene)> {
|
||||||
|
match self.row() { 0 => None, _ => {
|
||||||
|
let id = self.row() as usize - 1;
|
||||||
|
self.scenes.get(id).map(|t|(id, t))
|
||||||
|
} }
|
||||||
}
|
}
|
||||||
fn active_sequencer <'a> (&'a self) -> Option<std::sync::MutexGuard<Sequencer>> {
|
fn sequencer <'a> (&'a self) -> Option<MutexGuard<Sequencer>> {
|
||||||
self.active_track().map(|t|t.sequencer.state())
|
self.track().map(|t|t.1.sequencer.state())
|
||||||
}
|
}
|
||||||
fn active_chain <'a> (&'a self) -> Option<std::sync::MutexGuard<Chain>> {
|
fn chain <'a> (&'a self) -> Option<MutexGuard<Chain>> {
|
||||||
self.active_track().map(|t|t.chain.state())
|
self.track().map(|t|t.1.chain.state())
|
||||||
|
}
|
||||||
|
fn phrase_id (&self) -> Option<usize> {
|
||||||
|
let (track_id, _) = self.track()?;
|
||||||
|
let (_, scene) = self.scene()?;
|
||||||
|
*scene.clips.get(track_id)?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl DynamicDevice<Launcher> {
|
impl DynamicDevice<Launcher> {
|
||||||
|
|
@ -228,49 +238,41 @@ fn draw_section_sequencer (state: &Launcher, buf: &mut Buffer, area: Rect) -> Us
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
if let Some(track) = state.tracks.get(state.col().saturating_sub(1)) {
|
if let Some((_, track)) = state.track() {
|
||||||
let frame = state.position;
|
let frame = state.position;
|
||||||
let timebase = &state.timebase;
|
let timebase = &state.timebase;
|
||||||
let tick = (frame as f64 / timebase.frames_per_tick()) as usize;
|
let tick = (frame as f64 / timebase.frames_per_tick()) as usize;
|
||||||
let state = track.sequencer.state();
|
let sequencer = track.sequencer.state();
|
||||||
let zoom = state.resolution;
|
let zoom = sequencer.resolution;
|
||||||
|
|
||||||
|
let steps = if let Some(_phrase) = sequencer.phrase() { 0 } else { 0 } / 4; // TODO
|
||||||
|
|
||||||
let steps = if let Some(_phrase) = state.phrase() {
|
|
||||||
0
|
|
||||||
} else {
|
|
||||||
0
|
|
||||||
} / 4;
|
|
||||||
crate::device::sequencer::horizontal::timer(buf, x+5, y,
|
crate::device::sequencer::horizontal::timer(buf, x+5, y,
|
||||||
steps,
|
steps, sequencer.steps * zoom, sequencer.time_axis.0, sequencer.time_axis.1
|
||||||
state.steps * zoom,
|
|
||||||
state.time_axis.0,
|
|
||||||
state.time_axis.1
|
|
||||||
);
|
);
|
||||||
|
crate::device::sequencer::horizontal::keys(buf, Rect { x, y: y + 1, width, height },
|
||||||
let keys_area = Rect { x, y: y + 1, width, height };
|
sequencer.note_axis.1
|
||||||
crate::device::sequencer::horizontal::keys(buf, keys_area,
|
|
||||||
state.note_axis.1
|
|
||||||
)?;
|
)?;
|
||||||
|
if let Some(id) = state.phrase_id() {
|
||||||
if let Some(phrase) = state.phrase() {
|
if let Some(phrase) = sequencer.phrases.get(id) {
|
||||||
crate::device::sequencer::horizontal::lanes(buf, x, y + 1,
|
crate::device::sequencer::horizontal::lanes(buf, x, y + 1,
|
||||||
&phrase,
|
&phrase,
|
||||||
state.timebase.ppq() as u32,
|
sequencer.timebase.ppq() as u32,
|
||||||
state.resolution as u32,
|
sequencer.resolution as u32,
|
||||||
state.time_axis.0 as u32,
|
sequencer.time_axis.0 as u32,
|
||||||
state.time_axis.1 as u32,
|
sequencer.time_axis.1 as u32,
|
||||||
state.note_axis.0 as u32,
|
sequencer.note_axis.0 as u32,
|
||||||
state.note_axis.1 as u32,
|
sequencer.note_axis.1 as u32,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
let cursor_style = match view {
|
let cursor_style = match view {
|
||||||
LauncherView::Sequencer => Style::default().green().not_dim(),
|
LauncherView::Sequencer => Style::default().green().not_dim(),
|
||||||
_ => Style::default().green().dim(),
|
_ => Style::default().green().dim(),
|
||||||
};
|
};
|
||||||
crate::device::sequencer::horizontal::cursor(buf, x, y + 1, cursor_style,
|
crate::device::sequencer::horizontal::cursor(buf, x, y + 1, cursor_style,
|
||||||
state.time_cursor,
|
sequencer.time_cursor,
|
||||||
state.note_cursor
|
sequencer.note_cursor
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
Ok(area)
|
Ok(area)
|
||||||
|
|
@ -290,8 +292,8 @@ fn draw_section_chains (state: &Launcher, buf: &mut Buffer, area: Rect) -> Usual
|
||||||
},
|
},
|
||||||
_ => {},
|
_ => {},
|
||||||
};
|
};
|
||||||
let chain = state.active_chain();
|
let chain = state.chain();
|
||||||
let plugins = if let Some(chain) = &chain {
|
let _ = if let Some(chain) = &chain {
|
||||||
let (_, plugins) = crate::device::chain::draw_as_row(
|
let (_, plugins) = crate::device::chain::draw_as_row(
|
||||||
&*chain, buf, area, style
|
&*chain, buf, area, style
|
||||||
)?;
|
)?;
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ fn note_add (s: &mut Sequencer) -> Usually<bool> {
|
||||||
let key = u7::from_int_lossy((s.note_cursor + s.note_axis.0) as u8);
|
let key = u7::from_int_lossy((s.note_cursor + s.note_axis.0) as u8);
|
||||||
let note_on = MidiMessage::NoteOn { key, vel: 100.into() };
|
let note_on = MidiMessage::NoteOn { key, vel: 100.into() };
|
||||||
let note_off = MidiMessage::NoteOff { key, vel: 100.into() };
|
let note_off = MidiMessage::NoteOff { key, vel: 100.into() };
|
||||||
let sequence = &mut s.sequences[s.sequence].notes;
|
let sequence = &mut s.phrases[s.sequence].notes;
|
||||||
if sequence.contains_key(&start) {
|
if sequence.contains_key(&start) {
|
||||||
sequence.get_mut(&start).unwrap().push(note_on.clone());
|
sequence.get_mut(&start).unwrap().push(note_on.clone());
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ pub struct Sequencer {
|
||||||
/// Phrase selector
|
/// Phrase selector
|
||||||
pub sequence: usize,
|
pub sequence: usize,
|
||||||
/// Map: tick -> MIDI events at tick
|
/// Map: tick -> MIDI events at tick
|
||||||
pub sequences: Vec<Phrase>,
|
pub phrases: Vec<Phrase>,
|
||||||
/// Red keys on piano roll.
|
/// Red keys on piano roll.
|
||||||
pub notes_on: Vec<bool>,
|
pub notes_on: Vec<bool>,
|
||||||
/// Play sequence to output.
|
/// Play sequence to output.
|
||||||
|
|
@ -79,11 +79,10 @@ impl Sequencer {
|
||||||
pub fn new (
|
pub fn new (
|
||||||
name: &str,
|
name: &str,
|
||||||
timebase: &Arc<Timebase>,
|
timebase: &Arc<Timebase>,
|
||||||
sequences: Option<Vec<Phrase>>,
|
phrases: Option<Vec<Phrase>>,
|
||||||
) -> Usually<DynamicDevice<Self>> {
|
) -> Usually<DynamicDevice<Self>> {
|
||||||
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
let (client, _status) = Client::new(name, ClientOptions::NO_START_SERVER)?;
|
||||||
let transport = client.transport();
|
let transport = client.transport();
|
||||||
let ppq = timebase.ppq() as u32;
|
|
||||||
DynamicDevice::new(render, handle, process, Self {
|
DynamicDevice::new(render, handle, process, Self {
|
||||||
name: name.into(),
|
name: name.into(),
|
||||||
midi_in: client.register_port("in", MidiIn::default())?,
|
midi_in: client.register_port("in", MidiIn::default())?,
|
||||||
|
|
@ -93,7 +92,7 @@ impl Sequencer {
|
||||||
steps: 16,
|
steps: 16,
|
||||||
resolution: 4,
|
resolution: 4,
|
||||||
sequence: 0,
|
sequence: 0,
|
||||||
sequences: sequences.unwrap_or(vec![]),
|
phrases: phrases.unwrap_or(vec![]),
|
||||||
notes_on: vec![false;128],
|
notes_on: vec![false;128],
|
||||||
|
|
||||||
playing: TransportState::Starting,
|
playing: TransportState::Starting,
|
||||||
|
|
@ -111,7 +110,7 @@ impl Sequencer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn phrase <'a> (&'a self) -> Option<&'a Phrase> {
|
pub fn phrase <'a> (&'a self) -> Option<&'a Phrase> {
|
||||||
self.sequences.get(self.sequence)
|
self.phrases.get(self.sequence)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -219,7 +218,7 @@ pub fn draw_mon (buf: &mut Buffer, x: u16, y: u16, on: bool) {
|
||||||
fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
fn draw_clips (s: &Sequencer, buf: &mut Buffer, area: Rect) -> Usually<Rect> {
|
||||||
let Rect { x, y, .. } = area;
|
let Rect { x, y, .. } = area;
|
||||||
let style = Style::default().gray();
|
let style = Style::default().gray();
|
||||||
for (i, sequence) in s.sequences.iter().enumerate() {
|
for (i, sequence) in s.phrases.iter().enumerate() {
|
||||||
let label = format!("▶ {}", &sequence.name);
|
let label = format!("▶ {}", &sequence.name);
|
||||||
label.blit(buf, x + 2, y + 3 + (i as u16)*2, Some(if i == s.sequence {
|
label.blit(buf, x + 2, y + 3 + (i as u16)*2, Some(if i == s.sequence {
|
||||||
match s.playing {
|
match s.playing {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use super::*;
|
||||||
pub fn process (state: &mut Sequencer, _: &Client, scope: &ProcessScope) -> Control {
|
pub fn process (state: &mut Sequencer, _: &Client, scope: &ProcessScope) -> Control {
|
||||||
|
|
||||||
// Get currently playing sequence
|
// Get currently playing sequence
|
||||||
let sequence = state.sequences.get_mut(state.sequence);
|
let sequence = state.phrases.get_mut(state.sequence);
|
||||||
if sequence.is_none() {
|
if sequence.is_none() {
|
||||||
return Control::Continue
|
return Control::Continue
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,8 @@ pub fn steps (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
|
||||||
(step + 2) as u32 * ppq / s.resolution as u32,
|
(step + 2) as u32 * ppq / s.resolution as u32,
|
||||||
);
|
);
|
||||||
let (character, style) = match (
|
let (character, style) = match (
|
||||||
contains_note_on(&s.sequences[s.sequence], key, a, b),
|
contains_note_on(&s.phrases[s.sequence], key, a, b),
|
||||||
contains_note_on(&s.sequences[s.sequence], key, b, c),
|
contains_note_on(&s.phrases[s.sequence], key, b, c),
|
||||||
) {
|
) {
|
||||||
(true, true) => ("█", wh),
|
(true, true) => ("█", wh),
|
||||||
(true, false) => ("▀", wh),
|
(true, false) => ("▀", wh),
|
||||||
|
|
@ -87,7 +87,7 @@ pub fn playhead (s: &Sequencer, buf: &mut Buffer, x: u16, y: u16) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn keys (s: &Sequencer, buf: &mut Buffer, mut area: Rect, beat: usize) {
|
pub fn keys (s: &Sequencer, buf: &mut Buffer, area: Rect, beat: usize) {
|
||||||
let ppq = s.timebase.ppq() as u32;
|
let ppq = s.timebase.ppq() as u32;
|
||||||
let Rect { x, y, .. } = area;
|
let Rect { x, y, .. } = area;
|
||||||
let (note0, note1) = s.note_axis;
|
let (note0, note1) = s.note_axis;
|
||||||
|
|
@ -106,8 +106,8 @@ pub fn keys (s: &Sequencer, buf: &mut Buffer, mut area: Rect, beat: usize) {
|
||||||
(step + 2) as u32 * ppq / s.resolution as u32,
|
(step + 2) as u32 * ppq / s.resolution as u32,
|
||||||
);
|
);
|
||||||
let key = ::midly::num::u7::from(key as u8);
|
let key = ::midly::num::u7::from(key as u8);
|
||||||
is_on = is_on || contains_note_on(&s.sequences[s.sequence], key, a, b);
|
is_on = is_on || contains_note_on(&s.phrases[s.sequence], key, a, b);
|
||||||
is_on = is_on || contains_note_on(&s.sequences[s.sequence], key, b, c);
|
is_on = is_on || contains_note_on(&s.phrases[s.sequence], key, b, c);
|
||||||
if is_on {
|
if is_on {
|
||||||
color = Style::default().red();
|
color = Style::default().red();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ pub use std::time::Duration;
|
||||||
pub use std::collections::BTreeMap;
|
pub use std::collections::BTreeMap;
|
||||||
pub use std::sync::{
|
pub use std::sync::{
|
||||||
Arc,
|
Arc,
|
||||||
Mutex,
|
Mutex, MutexGuard,
|
||||||
atomic::{
|
atomic::{
|
||||||
Ordering,
|
Ordering,
|
||||||
AtomicBool,
|
AtomicBool,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue