mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-06 19:56:42 +01:00
tons more lint fixes
This commit is contained in:
parent
e96faeb6d3
commit
96f360791b
23 changed files with 121 additions and 122 deletions
|
|
@ -6,7 +6,7 @@ pub use clojure_reader::edn::Edn;
|
|||
|
||||
pub trait FromEdn<C>: Sized {
|
||||
const ID: &'static str;
|
||||
fn from_edn <'e> (context: C, expr: &[Edn<'e>]) -> Usually<Self>;
|
||||
fn from_edn (context: C, expr: &[Edn<'_>]) -> Usually<Self>;
|
||||
}
|
||||
|
||||
/// Implements the [FromEdn] trait.
|
||||
|
|
@ -46,7 +46,7 @@ from_edn!(|jack = &Arc<RwLock<JackClient>>, "sampler", args| -> crate::Sampler {
|
|||
dir = String::from(*n);
|
||||
}
|
||||
},
|
||||
Edn::List(args) => match args.get(0) {
|
||||
Edn::List(args) => match args.first() {
|
||||
Some(Edn::Symbol("sample")) => {
|
||||
let (midi, sample) = MidiSample::from_edn((jack, &dir), &args[1..])?;
|
||||
if let Some(midi) = midi {
|
||||
|
|
@ -62,7 +62,6 @@ from_edn!(|jack = &Arc<RwLock<JackClient>>, "sampler", args| -> crate::Sampler {
|
|||
let midi_in = jack.read().unwrap().client().register_port("in", MidiIn::default())?;
|
||||
Ok(Self {
|
||||
jack: jack.clone(),
|
||||
name: name.into(),
|
||||
mapped: samples,
|
||||
unmapped: Default::default(),
|
||||
voices: Default::default(),
|
||||
|
|
@ -70,6 +69,7 @@ from_edn!(|jack = &Arc<RwLock<JackClient>>, "sampler", args| -> crate::Sampler {
|
|||
audio_outs: vec![],
|
||||
output_gain: 0.,
|
||||
midi_in,
|
||||
name,
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ pub trait MidiView<E: Engine>: MidiRange + MidiPoint + HasSize<E> {
|
|||
fn autozoom (&self) {
|
||||
let time_len = self.time_len().get();
|
||||
let time_axis = self.time_axis().get();
|
||||
let mut time_zoom = self.time_zoom().get();
|
||||
let time_zoom = self.time_zoom().get();
|
||||
//while time_len.div_ceil(time_zoom) > time_axis {
|
||||
//println!("\r{time_len} {time_zoom} {time_axis}");
|
||||
//time_zoom = Note::next(time_zoom);
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ pub trait MidiPlaybackApi: HasPlayPhrase + HasClock + HasMidiOuts {
|
|||
// If it's time to switch to the next phrase:
|
||||
if start <= sample0.saturating_sub(sample) {
|
||||
// Samples elapsed since phrase was supposed to start
|
||||
let skipped = sample0 - start;
|
||||
let _skipped = sample0 - start;
|
||||
// Switch over to enqueued phrase
|
||||
let started = Moment::from_sample(self.clock().timebase(), start as f64);
|
||||
// Launch enqueued phrase
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ pub trait MidiRecordApi: HasClock + HasPlayPhrase + HasMidiIns {
|
|||
}
|
||||
}
|
||||
}
|
||||
if let Some((start_at, phrase)) = &self.next_phrase() {
|
||||
if let Some((start_at, _clip)) = &self.next_phrase() {
|
||||
// TODO switch to next phrase and record into it
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ mod piano_h; pub(crate) use self::piano_h::*;
|
|||
////////////////////////////////////////////////////////
|
||||
|
||||
pub fn render <F: Fn(&mut TuiOutput)->Usually<()>+Send+Sync> (render: F) -> impl Render<Tui> {
|
||||
Widget::new(|_|Ok(Some([0u16,0u16].into())), render)
|
||||
Widget::new(|_|Ok(Some([0u16,0u16])), render)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////
|
||||
|
|
|
|||
|
|
@ -37,13 +37,11 @@ pub enum GrooveboxCommand {
|
|||
Sampler(SamplerCommand),
|
||||
}
|
||||
handle!(<Tui>|self:GrooveboxTui,input|GrooveboxCommand::execute_with_state(self, input));
|
||||
input_to_command!(GrooveboxCommand: <Tui>|state:GrooveboxTui,input|match input.event() {
|
||||
_ => match state.focus {
|
||||
input_to_command!(GrooveboxCommand: <Tui>|state:GrooveboxTui,input|match state.focus {
|
||||
GrooveboxFocus::Sequencer => GrooveboxCommand::Sequencer(
|
||||
SequencerCommand::input_to_command(&state.sequencer, input)?),
|
||||
GrooveboxFocus::Sampler => GrooveboxCommand::Sampler(
|
||||
SamplerCommand::input_to_command(&state.sampler, input)?),
|
||||
}
|
||||
});
|
||||
command!(|self:GrooveboxCommand,state:GrooveboxTui|match self {
|
||||
GrooveboxCommand::Sequencer(command) =>
|
||||
|
|
|
|||
|
|
@ -2,12 +2,17 @@ use crate::*;
|
|||
use super::*;
|
||||
use KeyCode::Char;
|
||||
use std::fs::File;
|
||||
use symphonia::core::codecs::CODEC_TYPE_NULL;
|
||||
use symphonia::core::errors::Error;
|
||||
use symphonia::core::io::MediaSourceStream;
|
||||
use symphonia::core::probe::Hint;
|
||||
use symphonia::core::audio::SampleBuffer;
|
||||
use symphonia::default::get_codecs;
|
||||
use symphonia::{
|
||||
core::{
|
||||
formats::Packet,
|
||||
codecs::{Decoder, CODEC_TYPE_NULL},
|
||||
errors::Error,
|
||||
io::MediaSourceStream,
|
||||
probe::Hint,
|
||||
audio::SampleBuffer,
|
||||
},
|
||||
default::get_codecs,
|
||||
};
|
||||
|
||||
pub struct SamplerTui {
|
||||
pub state: Sampler,
|
||||
|
|
@ -305,8 +310,8 @@ fn scan (dir: &PathBuf) -> Usually<(Vec<OsString>, Vec<OsString>)> {
|
|||
|
||||
impl Sample {
|
||||
fn from_file (path: &PathBuf) -> Usually<Self> {
|
||||
let mut sample = Self::default();
|
||||
sample.name = path.file_name().unwrap().to_string_lossy().into();
|
||||
let name = path.file_name().unwrap().to_string_lossy().into();
|
||||
let mut sample = Self { name, ..Default::default() };
|
||||
// Use file extension if present
|
||||
let mut hint = Hint::new();
|
||||
if let Some(ext) = path.extension() {
|
||||
|
|
@ -322,33 +327,40 @@ impl Sample {
|
|||
&Default::default()
|
||||
)?;
|
||||
let mut format = probed.format;
|
||||
let mut decoder = get_codecs().make(
|
||||
&format.tracks().iter()
|
||||
let params = &format.tracks().iter()
|
||||
.find(|t| t.codec_params.codec != CODEC_TYPE_NULL)
|
||||
.expect("no tracks found")
|
||||
.codec_params,
|
||||
&Default::default()
|
||||
)?;
|
||||
.codec_params;
|
||||
let mut decoder = get_codecs().make(params, &Default::default())?;
|
||||
loop {
|
||||
match format.next_packet() {
|
||||
Ok(packet) => {
|
||||
// Decode a packet
|
||||
let decoded = match decoder.decode(&packet) {
|
||||
Ok(decoded) => decoded,
|
||||
Err(err) => { return Err(err.into()); }
|
||||
Ok(packet) => sample.decode_packet(&mut decoder, packet)?,
|
||||
Err(Error::IoError(_)) => break decoder.last_decoded(),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
};
|
||||
sample.end = sample.channels.iter().fold(0, |l, c|l + c.len());
|
||||
Ok(sample)
|
||||
}
|
||||
fn decode_packet (
|
||||
&mut self, decoder: &mut Box<dyn Decoder>, packet: Packet
|
||||
) -> Usually<()> {
|
||||
// Decode a packet
|
||||
let decoded = decoder
|
||||
.decode(&packet)
|
||||
.map_err(|e|Box::<dyn crate::Error>::from(e))?;
|
||||
// Determine sample rate
|
||||
let spec = *decoded.spec();
|
||||
if let Some(rate) = sample.rate {
|
||||
if let Some(rate) = self.rate {
|
||||
if rate != spec.rate as usize {
|
||||
panic!("sample rate changed");
|
||||
}
|
||||
} else {
|
||||
sample.rate = Some(spec.rate as usize);
|
||||
self.rate = Some(spec.rate as usize);
|
||||
}
|
||||
// Determine channel count
|
||||
while sample.channels.len() < spec.channels.count() {
|
||||
sample.channels.push(vec![]);
|
||||
while self.channels.len() < spec.channels.count() {
|
||||
self.channels.push(vec![]);
|
||||
}
|
||||
// Load sample
|
||||
let mut samples = SampleBuffer::new(
|
||||
|
|
@ -359,17 +371,11 @@ impl Sample {
|
|||
samples.copy_interleaved_ref(decoded);
|
||||
for frame in samples.samples().chunks(spec.channels.count()) {
|
||||
for (chan, frame) in frame.iter().enumerate() {
|
||||
sample.channels[chan].push(*frame)
|
||||
self.channels[chan].push(*frame)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(Error::IoError(_)) => break decoder.last_decoded(),
|
||||
Err(err) => return Err(err.into()),
|
||||
};
|
||||
};
|
||||
sample.end = sample.channels.iter().fold(0, |l, c|l + c.len());
|
||||
Ok(sample)
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -206,7 +206,7 @@ fn to_arrangement_command (state: &ArrangerTui, input: &TuiInput) -> Option<Arra
|
|||
key_pat!(Down) => Some(
|
||||
Cmd::Select(Selected::Scene((s + 1).min(s_len.saturating_sub(1))))),
|
||||
key_pat!(Left) =>
|
||||
return None,
|
||||
None,
|
||||
key_pat!(Right) => Some(
|
||||
Cmd::Select(Selected::Clip(0, s))),
|
||||
|
||||
|
|
@ -221,7 +221,7 @@ fn to_arrangement_command (state: &ArrangerTui, input: &TuiInput) -> Option<Arra
|
|||
key_pat!(Char('c')) => Some(Cmd::Track(Track::SetColor(t, ItemPalette::random()))),
|
||||
|
||||
key_pat!(Up) =>
|
||||
return None,
|
||||
None,
|
||||
key_pat!(Down) => Some(
|
||||
Cmd::Select(Selected::Clip(t, 0))),
|
||||
key_pat!(Left) => Some(
|
||||
|
|
@ -237,11 +237,11 @@ fn to_arrangement_command (state: &ArrangerTui, input: &TuiInput) -> Option<Arra
|
|||
key_pat!(Char('c')) => Some(Cmd::Color(ItemPalette::random())),
|
||||
|
||||
key_pat!(Up) =>
|
||||
return None,
|
||||
None,
|
||||
key_pat!(Down) => Some(
|
||||
Cmd::Select(Selected::Scene(0))),
|
||||
key_pat!(Left) =>
|
||||
return None,
|
||||
None,
|
||||
key_pat!(Right) => Some(
|
||||
Cmd::Select(Selected::Track(0))),
|
||||
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ render!(<Tui>|self: ArrangerMode|{});
|
|||
/// Arranger display mode can be cycled
|
||||
impl ArrangerMode {
|
||||
/// Cycle arranger display mode
|
||||
pub fn to_next (&mut self) {
|
||||
pub fn next (&mut self) {
|
||||
*self = match self {
|
||||
Self::H => Self::V(1),
|
||||
Self::V(1) => Self::V(2),
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ impl ArrangerTui {
|
|||
let scene = ArrangerScene {
|
||||
name: Arc::new(name.into()),
|
||||
clips: vec![None;self.tracks.len()],
|
||||
color: color.unwrap_or_else(||ItemPalette::random()),
|
||||
color: color.unwrap_or_else(ItemPalette::random),
|
||||
};
|
||||
self.scenes.push(scene);
|
||||
let index = self.scenes.len() - 1;
|
||||
|
|
@ -20,10 +20,10 @@ impl ArrangerTui {
|
|||
format!("S{:3>}", self.scenes.len() + 1)
|
||||
}
|
||||
pub fn selected_scene (&self) -> Option<&ArrangerScene> {
|
||||
self.selected.scene().map(|s|self.scenes.get(s)).flatten()
|
||||
self.selected.scene().and_then(|s|self.scenes.get(s))
|
||||
}
|
||||
pub fn selected_scene_mut (&mut self) -> Option<&mut ArrangerScene> {
|
||||
self.selected.scene().map(|s|self.scenes.get_mut(s)).flatten()
|
||||
self.selected.scene().and_then(|s|self.scenes.get_mut(s))
|
||||
}
|
||||
}
|
||||
#[derive(Default, Debug, Clone)] pub struct ArrangerScene {
|
||||
|
|
@ -49,7 +49,7 @@ impl ArrangerScene {
|
|||
if factor == 0 {
|
||||
scenes.iter().map(|scene|{
|
||||
let pulses = scene.pulses().max(PPQ);
|
||||
total = total + pulses;
|
||||
total += pulses;
|
||||
(pulses, total - pulses)
|
||||
}).collect()
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -13,13 +13,17 @@ pub enum ArrangerSelection {
|
|||
}
|
||||
/// Focus identification methods
|
||||
impl ArrangerSelection {
|
||||
pub fn description <E: Engine> (
|
||||
pub fn is_mix (&self) -> bool { matches!(self, Self::Mix) }
|
||||
pub fn is_track (&self) -> bool { matches!(self, Self::Track(_)) }
|
||||
pub fn is_scene (&self) -> bool { matches!(self, Self::Scene(_)) }
|
||||
pub fn is_clip (&self) -> bool { matches!(self, Self::Clip(_, _)) }
|
||||
pub fn description (
|
||||
&self,
|
||||
tracks: &Vec<ArrangerTrack>,
|
||||
scenes: &Vec<ArrangerScene>,
|
||||
tracks: &[ArrangerTrack],
|
||||
scenes: &[ArrangerScene],
|
||||
) -> String {
|
||||
format!("Selected: {}", match self {
|
||||
Self::Mix => format!("Everything"),
|
||||
Self::Mix => "Everything".to_string(),
|
||||
Self::Track(t) => match tracks.get(*t) {
|
||||
Some(track) => format!("T{t}: {}", &track.name.read().unwrap()),
|
||||
None => "T??".into(),
|
||||
|
|
@ -37,18 +41,6 @@ impl ArrangerSelection {
|
|||
}
|
||||
})
|
||||
}
|
||||
pub fn is_mix (&self) -> bool {
|
||||
match self { Self::Mix => true, _ => false }
|
||||
}
|
||||
pub fn is_track (&self) -> bool {
|
||||
match self { Self::Track(_) => true, _ => false }
|
||||
}
|
||||
pub fn is_scene (&self) -> bool {
|
||||
match self { Self::Scene(_) => true, _ => false }
|
||||
}
|
||||
pub fn is_clip (&self) -> bool {
|
||||
match self { Self::Clip(_, _) => true, _ => false }
|
||||
}
|
||||
pub fn track (&self) -> Option<usize> {
|
||||
use ArrangerSelection::*;
|
||||
match self {
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ impl ArrangerTui {
|
|||
let track = ArrangerTrack {
|
||||
width: name.len() + 2,
|
||||
name: Arc::new(name.into()),
|
||||
color: color.unwrap_or_else(||ItemPalette::random()),
|
||||
color: color.unwrap_or_else(ItemPalette::random),
|
||||
player: MidiPlayer::from(&self.clock),
|
||||
};
|
||||
self.tracks.push(track);
|
||||
|
|
@ -96,7 +96,7 @@ pub struct TracksAudio<'a>(
|
|||
/// Note chunk buffer
|
||||
pub &'a mut Vec<Vec<Vec<u8>>>,
|
||||
);
|
||||
impl<'a> Audio for TracksAudio<'a> {
|
||||
impl Audio for TracksAudio<'_> {
|
||||
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
let model = &mut self.0;
|
||||
let note_buffer = &mut self.1;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ from!(<'a>|args:(&'a ArrangerTui, usize)|ArrangerVClips<'a> = Self {
|
|||
|
||||
render!(<Tui>|self: ArrangerVClips<'a>|Fill::wh(
|
||||
col!((scene, pulses) in self.scenes.iter().zip(self.rows.iter().map(|row|row.0)) => {
|
||||
Self::format_scene(&self.tracks, scene, pulses)
|
||||
Self::format_scene(self.tracks, scene, pulses)
|
||||
})
|
||||
));
|
||||
|
||||
|
|
@ -28,8 +28,10 @@ impl<'a> ArrangerVClips<'a> {
|
|||
let height = 1.max((pulses / PPQ) as u16);
|
||||
let playing = scene.is_playing(tracks);
|
||||
Fixed::h(height, row!([
|
||||
Tui::bg(scene.color.base.rgb, if playing { "▶ " } else { " " }),
|
||||
Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb, Tui::grow_x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))),
|
||||
Tui::bg(scene.color.base.rgb,
|
||||
if playing { "▶ " } else { " " }),
|
||||
Tui::fg_bg(scene.color.lightest.rgb, scene.color.base.rgb,
|
||||
Tui::grow_x(1, Tui::bold(true, scene.name.read().unwrap().as_str()))),
|
||||
row!((index, track, x1, x2) in ArrangerTrack::with_widths(tracks) => {
|
||||
Self::format_clip(scene, index, track, (x2 - x1) as u16, height)
|
||||
})])
|
||||
|
|
@ -41,8 +43,7 @@ impl<'a> ArrangerVClips<'a> {
|
|||
Fixed::wh(w, h, Layers::new(move |add|{
|
||||
if let Some(Some(phrase)) = scene.clips.get(index) {
|
||||
let mut bg = TuiTheme::border_bg();
|
||||
let name = &(phrase as &Arc<RwLock<MidiClip>>).read().unwrap().name;
|
||||
let name = format!("{}", name);
|
||||
let name = &(phrase as &Arc<RwLock<MidiClip>>).read().unwrap().name.to_string();
|
||||
let max_w = name.len().min((w as usize).saturating_sub(2));
|
||||
let color = phrase.read().unwrap().color;
|
||||
bg = color.dark.rgb;
|
||||
|
|
@ -52,7 +53,7 @@ impl<'a> ArrangerVClips<'a> {
|
|||
}
|
||||
};
|
||||
add(&Tui::bg(bg,
|
||||
Tui::push_x(1, Fixed::w(w as u16, &name.as_str()[0..max_w])))
|
||||
Tui::push_x(1, Fixed::w(w, &name.as_str()[0..max_w])))
|
||||
)?;
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -29,13 +29,13 @@ render!(<Tui>|self: ArrangerVHead<'a>|Tui::push_x(self.scenes_w, row!(
|
|||
row(color, &Self::format_name(track, w)),
|
||||
row(color, &Self::format_input(track)?),
|
||||
row(color, &Self::format_output(track)?),
|
||||
row(color, &Self::format_elapsed(track, &self.timebase)),
|
||||
row(color, &Self::format_until_next(track, &self.current)),
|
||||
row(color, &Self::format_elapsed(track, self.timebase)),
|
||||
row(color, &Self::format_until_next(track, self.current)),
|
||||
]))))
|
||||
}
|
||||
)));
|
||||
|
||||
impl<'a> ArrangerVHead<'a> {
|
||||
impl ArrangerVHead<'_> {
|
||||
/// name and width of track
|
||||
fn format_name (track: &ArrangerTrack, _w: usize) -> impl Render<Tui> {
|
||||
let name = track.name().read().unwrap().clone();
|
||||
|
|
@ -43,12 +43,12 @@ impl<'a> ArrangerVHead<'a> {
|
|||
}
|
||||
/// input port
|
||||
fn format_input (track: &ArrangerTrack) -> Usually<impl Render<Tui>> {
|
||||
Ok(format!(">{}", track.player.midi_ins().get(0).map(|port|port.short_name())
|
||||
Ok(format!(">{}", track.player.midi_ins().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
/// output port
|
||||
fn format_output (track: &ArrangerTrack) -> Usually<impl Render<Tui>> {
|
||||
Ok(format!("<{}", track.player.midi_outs().get(0).map(|port|port.short_name())
|
||||
Ok(format!("<{}", track.player.midi_outs().first().map(|port|port.short_name())
|
||||
.transpose()?.unwrap_or("?".into())))
|
||||
}
|
||||
/// beats elapsed
|
||||
|
|
|
|||
|
|
@ -28,10 +28,10 @@ pub enum PhraseCommand {
|
|||
SetTimeLock(bool),
|
||||
Show(Option<Arc<RwLock<MidiClip>>>),
|
||||
}
|
||||
event_map_input_to_command!(Tui: MidiEditorModel: PhraseCommand: MidiEditorModel::KEYS);
|
||||
|
||||
event_map_input_to_command!(Tui: MidiEditorModel: PhraseCommand: MidiEditorModel::KEYS);
|
||||
impl MidiEditorModel {
|
||||
const KEYS: [(TuiEvent, &'static dyn Fn(&Self)->PhraseCommand);31] = [
|
||||
const KEYS: KeyMapping<31, Self> = [
|
||||
(kexp!(Ctrl-Alt-Up), &|s: &Self|SetNoteScroll(s.note_point() + 3)),
|
||||
(kexp!(Ctrl-Alt-Down), &|s: &Self|SetNoteScroll(s.note_point().saturating_sub(3))),
|
||||
(kexp!(Ctrl-Alt-Left), &|s: &Self|SetTimeScroll(s.time_point().saturating_sub(s.time_zoom().get()))),
|
||||
|
|
@ -120,7 +120,7 @@ pub trait PhraseViewMode: Render<Tui> + HasSize<Tui> + MidiRange + MidiPoint + D
|
|||
fn phrase (&self) -> &Option<Arc<RwLock<MidiClip>>>;
|
||||
fn phrase_mut (&mut self) -> &mut Option<Arc<RwLock<MidiClip>>>;
|
||||
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<MidiClip>>>) {
|
||||
*self.phrase_mut() = phrase.map(|p|p.clone());
|
||||
*self.phrase_mut() = phrase.cloned();
|
||||
self.redraw();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,19 +37,19 @@ impl PianoHorizontal {
|
|||
Self {
|
||||
buffer: Default::default(),
|
||||
point: MidiPointModel::default(),
|
||||
phrase: phrase.cloned(),
|
||||
size,
|
||||
range,
|
||||
phrase: phrase.map(|p|p.clone()),
|
||||
color
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
render!(<Tui>|self: PianoHorizontal|{
|
||||
let keys = move||PianoHorizontalKeys(&self);
|
||||
let timeline = move||PianoHorizontalTimeline(&self);
|
||||
let notes = move||PianoHorizontalNotes(&self);
|
||||
let cursor = move||PianoHorizontalCursor(&self);
|
||||
let keys = move||PianoHorizontalKeys(self);
|
||||
let timeline = move||PianoHorizontalTimeline(self);
|
||||
let notes = move||PianoHorizontalNotes(self);
|
||||
let cursor = move||PianoHorizontalCursor(self);
|
||||
let keys_width = 5;
|
||||
let border = Fill::wh(Outer(Style::default().fg(self.color.dark.rgb).bg(self.color.darkest.rgb)));
|
||||
let with_border = |x|lay!([border, Tui::inset_xy(1, 1, &x)]);
|
||||
|
|
@ -169,8 +169,8 @@ impl PhraseViewMode for PianoHorizontal {
|
|||
self.buffer = buffer
|
||||
}
|
||||
fn set_phrase (&mut self, phrase: Option<&Arc<RwLock<MidiClip>>>) {
|
||||
*self.phrase_mut() = phrase.map(|p|p.clone());
|
||||
self.color = phrase.map(|p|p.read().unwrap().color.clone())
|
||||
*self.phrase_mut() = phrase.cloned();
|
||||
self.color = phrase.map(|p|p.read().unwrap().color)
|
||||
.unwrap_or(ItemPalette::from(ItemColor::from(TuiTheme::g(64))));
|
||||
self.redraw();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ render!(<Tui>|self: PianoHorizontalCursor<'a>|render(|to|Ok({
|
|||
for (area_y, screen_y, note) in note_y_iter(note_lo, note_hi, y0) {
|
||||
if note == note_point {
|
||||
for x in 0..w {
|
||||
let screen_x = x0 + x as u16;
|
||||
let screen_x = x0 + x;
|
||||
let time_1 = time_start + x as usize * time_zoom;
|
||||
let time_2 = time_1 + time_zoom;
|
||||
if time_1 <= time_point && time_point < time_2 {
|
||||
|
|
|
|||
|
|
@ -297,7 +297,7 @@ impl PhraseSelector {
|
|||
} else if let Some((_, Some(phrase))) = state.play_phrase() {
|
||||
let phrase = phrase.read().unwrap();
|
||||
if phrase.looped {
|
||||
(" ".into(), phrase.name.clone(), phrase.color.clone())
|
||||
(" ".into(), phrase.name.clone(), phrase.color)
|
||||
} else {
|
||||
(" ".into(), " ".into(), TuiTheme::g(64).into())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ impl Command<PoolModel> for PhraseRenameCommand {
|
|||
match state.phrases_mode_mut().clone() {
|
||||
Some(PoolMode::Rename(phrase, ref mut old_name)) => match self {
|
||||
Set(s) => {
|
||||
state.phrases()[phrase].write().unwrap().name = s.into();
|
||||
state.phrases()[phrase].write().unwrap().name = s;
|
||||
return Ok(Some(Self::Set(old_name.clone())))
|
||||
},
|
||||
Confirm => {
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub struct ArrangerStatus {
|
|||
}
|
||||
from!(|state:&ArrangerTui|ArrangerStatus = {
|
||||
let samples = state.clock.chunk.load(Relaxed);
|
||||
let rate = state.clock.timebase.sr.get() as f64;
|
||||
let rate = state.clock.timebase.sr.get();
|
||||
let buffer = samples as f64 / rate;
|
||||
let width = state.size.w();
|
||||
Self {
|
||||
|
|
@ -48,7 +48,7 @@ impl ArrangerStatus {
|
|||
double(("[]", "phrase"), ("{}", "order"),),
|
||||
]))
|
||||
}
|
||||
fn stats <'a> (&'a self) -> impl Render<Tui> + use<'a> {
|
||||
fn stats (&self) -> impl Render<Tui> + use<'_> {
|
||||
row!([&self.cpu, &self.res, &self.size])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -16,9 +16,9 @@ render!(<Tui>|self:MidiEditStatus<'a>|{
|
|||
]);
|
||||
Fill::w(Tui::fg_bg(fg, bg, row!([
|
||||
Fixed::wh(26, 3, col!(![
|
||||
field(" Edit", format!("{name}")),
|
||||
field(" Length", format!("{length}")),
|
||||
field(" Loop", format!("{looped}"))])),
|
||||
field(" Edit", name.to_string()),
|
||||
field(" Length", length.to_string()),
|
||||
field(" Loop", looped.to_string())])),
|
||||
Fixed::wh(30, 3, col!(![
|
||||
field(" Time", format!("{}/{}-{} ({}*{}) {}",
|
||||
self.0.time_point(), self.0.time_start().get(), self.0.time_end(),
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ pub struct SequencerStatus {
|
|||
}
|
||||
from!(|state:&SequencerTui|SequencerStatus = {
|
||||
let samples = state.clock.chunk.load(Relaxed);
|
||||
let rate = state.clock.timebase.sr.get() as f64;
|
||||
let rate = state.clock.timebase.sr.get();
|
||||
let buffer = samples as f64 / rate;
|
||||
let width = state.size.w();
|
||||
Self {
|
||||
|
|
@ -46,7 +46,7 @@ impl SequencerStatus {
|
|||
double(("c", "color"), ("", ""),),
|
||||
]))
|
||||
}
|
||||
fn stats <'a> (&'a self) -> impl Render<Tui> + use<'a> {
|
||||
fn stats (&self) -> impl Render<Tui> + use<'_> {
|
||||
row!([&self.cpu, &self.res, &self.size])
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,6 +92,8 @@ impl<'a, const N: usize, E: PartialEq, T, U> EventMap<'a, N, E, T, U> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) type KeyMapping<const N: usize, T> = [(TuiEvent, &'static dyn Fn(&T)->PhraseCommand);N];
|
||||
|
||||
#[macro_export] macro_rules! kexp {
|
||||
(Ctrl-Alt-$code:ident) => { key_event_expr!($code, KeyModifiers::from_bits(0b0000_0110).unwrap()) };
|
||||
(Ctrl-$code:ident) => { key_event_expr!($code, KeyModifiers::CONTROL) };
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue