mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 04:06:45 +01:00
wip: refactor pt.9, 403 errors
This commit is contained in:
parent
a784f7a6f2
commit
8aa1ba8d0f
29 changed files with 1008 additions and 902 deletions
|
|
@ -6,49 +6,39 @@ pub struct ArrangerView<E: Engine> {
|
|||
pub sequencer: SequencerView<E>,
|
||||
/// Contains all the sequencers.
|
||||
pub arrangement: ArrangementEditor<E>,
|
||||
/// Status bar
|
||||
pub status: ArrangerStatusBar,
|
||||
/// Height of arrangement
|
||||
pub split: u16,
|
||||
/// Width and height of app at last render
|
||||
pub size: Measure<E>,
|
||||
/// Menu bar
|
||||
pub menu: MenuBar<E, Self, ArrangerViewCommand>,
|
||||
/// Command history
|
||||
pub history: Vec<ArrangerViewCommand>,
|
||||
/// Which view is focused
|
||||
pub cursor: (usize, usize),
|
||||
/// Whether the focused view is entered
|
||||
pub entered: bool,
|
||||
}
|
||||
|
||||
impl<E: Engine> Audio for ArrangerView<E> {
|
||||
fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
if let Some(ref transport) = self.transport {
|
||||
transport.write().unwrap().process(client, scope);
|
||||
#[inline] fn process (&mut self, client: &Client, scope: &ProcessScope) -> Control {
|
||||
if self.sequencer.transport.process(client, scope) == Control::Quit {
|
||||
return Control::Quit
|
||||
}
|
||||
let Arrangement { scenes, ref mut tracks, selected, .. } = &mut self.arrangement;
|
||||
for track in tracks.iter_mut() {
|
||||
track.player.process(client, scope);
|
||||
if self.arrangement.process(client, scope) == Control::Quit {
|
||||
return Control::Quit
|
||||
}
|
||||
if let ArrangementEditorFocus::Clip(t, s) = selected {
|
||||
if let Some(Some(Some(phrase))) = scenes.get(*s).map(|scene|scene.clips.get(*t)) {
|
||||
if let Some(track) = tracks.get(*t) {
|
||||
if let ArrangementEditorFocus::Clip(t, s) = self.arrangement.selected {
|
||||
let phrase = self.arrangement.state.scenes.get(s).map(|scene|scene.clips.get(t));
|
||||
if let Some(Some(Some(phrase))) = phrase {
|
||||
if let Some(track) = self.arrangement.state.tracks.get(t) {
|
||||
if let Some((ref started_at, Some(ref playing))) = track.player.phrase {
|
||||
let phrase = phrase.read().unwrap();
|
||||
if *playing.read().unwrap() == *phrase {
|
||||
let pulse = self.clock.current.pulse.get();
|
||||
let start = started_at.pulse.get();
|
||||
let now = (pulse - start) % phrase.length as f64;
|
||||
self.editor.now.set(now);
|
||||
self.sequencer.editor.now.set(now);
|
||||
return Control::Continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.editor.now.set(0.);
|
||||
Control::Continue
|
||||
self.sequencer.editor.now.set(0.);
|
||||
self.state.process(client, scope)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -57,9 +47,9 @@ impl Content for ArrangerView<Tui> {
|
|||
type Engine = Tui;
|
||||
fn content (&self) -> impl Widget<Engine = Tui> {
|
||||
let focused = self.arrangement.focused;
|
||||
let border_bg = Arranger::<Tui>::border_bg();
|
||||
let border_fg = Arranger::<Tui>::border_fg(focused);
|
||||
let title_fg = Arranger::<Tui>::title_fg(focused);
|
||||
let border_bg = TuiTheme::border_bg();
|
||||
let border_fg = TuiTheme::border_fg(focused);
|
||||
let title_fg = TuiTheme::title_fg(focused);
|
||||
let border = Lozenge(Style::default().bg(border_bg).fg(border_fg));
|
||||
let entered = if self.arrangement.entered { "■" } else { " " };
|
||||
Split::down(
|
||||
|
|
@ -95,109 +85,14 @@ impl Content for ArrangerView<Tui> {
|
|||
/// General methods for arranger
|
||||
impl<E: Engine> ArrangerView<E> {
|
||||
pub fn new (
|
||||
jack: &Arc<RwLock<JackClient>>,
|
||||
transport: Option<Arc<RwLock<TransportToolbar<E>>>>,
|
||||
arrangement: Arrangement<E>,
|
||||
phrases: Arc<RwLock<PhrasePool<E>>>,
|
||||
sequencer: SequencerView<E>,
|
||||
arrangement: ArrangementEditor<E>,
|
||||
) -> Self {
|
||||
let mut app = Self {
|
||||
jack: jack.clone(),
|
||||
focus_cursor: (0, 1),
|
||||
entered: false,
|
||||
phrases_split: 20,
|
||||
arrangement_split: 15,
|
||||
editor: PhraseEditor::new(),
|
||||
status: ArrangerStatusBar::ArrangementClip,
|
||||
transport: transport.clone(),
|
||||
arrangement,
|
||||
phrases,
|
||||
history: vec![],
|
||||
size: Measure::new(),
|
||||
clock: if let Some(ref transport) = transport {
|
||||
transport.read().unwrap().clock.clone()
|
||||
} else {
|
||||
Arc::new(Clock::default())
|
||||
},
|
||||
menu: {
|
||||
use ArrangerViewCommand::*;
|
||||
MenuBar::new()
|
||||
.add({
|
||||
use ArrangementCommand::*;
|
||||
Menu::new("File")
|
||||
.cmd("n", "New project", Arrangement(New))
|
||||
.cmd("l", "Load project", Arrangement(Load))
|
||||
.cmd("s", "Save project", Arrangement(Save))
|
||||
})
|
||||
.add({
|
||||
use TransportViewCommand::*;
|
||||
Menu::new("Transport")
|
||||
.cmd("p", "Play", Transport(Play))
|
||||
.cmd("s", "Play from start", Transport(PlayFromStart))
|
||||
.cmd("a", "Pause", Transport(Pause))
|
||||
})
|
||||
.add({
|
||||
use ArrangementCommand::*;
|
||||
Menu::new("Track")
|
||||
.cmd("a", "Append new", Arrangement(AddTrack))
|
||||
.cmd("i", "Insert new", Arrangement(AddTrack))
|
||||
.cmd("n", "Rename", Arrangement(AddTrack))
|
||||
.cmd("d", "Delete", Arrangement(AddTrack))
|
||||
.cmd(">", "Move up", Arrangement(AddTrack))
|
||||
.cmd("<", "Move down", Arrangement(AddTrack))
|
||||
})
|
||||
.add({
|
||||
use ArrangementCommand::*;
|
||||
Menu::new("Scene")
|
||||
.cmd("a", "Append new", Arrangement(AddScene))
|
||||
.cmd("i", "Insert new", Arrangement(AddTrack))
|
||||
.cmd("n", "Rename", Arrangement(AddTrack))
|
||||
.cmd("d", "Delete", Arrangement(AddTrack))
|
||||
.cmd(">", "Move up", Arrangement(AddTrack))
|
||||
.cmd("<", "Move down", Arrangement(AddTrack))
|
||||
})
|
||||
.add({
|
||||
use PhrasePoolCommand::*;
|
||||
use PhraseRenameCommand as Rename;
|
||||
use PhraseLengthCommand as Length;
|
||||
Menu::new("Phrase")
|
||||
.cmd("a", "Append new", Phrases(Append))
|
||||
.cmd("i", "Insert new", Phrases(Insert))
|
||||
.cmd("n", "Rename", Phrases(Rename(Rename::Begin)))
|
||||
.cmd("t", "Set length", Phrases(Length(Length::Begin)))
|
||||
.cmd("d", "Delete", Phrases(Delete))
|
||||
.cmd("l", "Load from MIDI...", Phrases(Import))
|
||||
.cmd("s", "Save to MIDI...", Phrases(Export))
|
||||
.cmd(">", "Move up", Phrases(MoveUp))
|
||||
.cmd("<", "Move down", Phrases(MoveDown))
|
||||
})
|
||||
}
|
||||
};
|
||||
let mut app = Self { sequencer, arrangement, split: 15, size: Default::default() };
|
||||
app.update_focus();
|
||||
app
|
||||
}
|
||||
|
||||
//pub fn new (
|
||||
//jack: &Arc<RwLock<JackClient>>,
|
||||
//clock: &Arc<Clock>,
|
||||
//name: &str,
|
||||
//phrases: &Arc<RwLock<PhrasePool<E>>>
|
||||
//) -> Self {
|
||||
//Self {
|
||||
//jack: jack.clone(),
|
||||
//clock: clock.clone(),
|
||||
//name: Arc::new(RwLock::new(name.into())),
|
||||
//mode: ArrangementViewMode::Vertical(2),
|
||||
//selected: ArrangementEditorFocus::Clip(0, 0),
|
||||
//phrases: phrases.clone(),
|
||||
//scenes: vec![],
|
||||
//tracks: vec![],
|
||||
//focused: false,
|
||||
//color: Color::Rgb(28, 35, 25).into(),
|
||||
//size: Measure::new(),
|
||||
//entered: false,
|
||||
//}
|
||||
//}
|
||||
|
||||
/// Toggle global play/pause
|
||||
pub fn toggle_play (&mut self) -> Perhaps<bool> {
|
||||
match self.transport {
|
||||
|
|
@ -216,10 +111,12 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
}
|
||||
/// Focus the editor with the current phrase
|
||||
pub fn show_phrase (&mut self) { self.editor.show(self.arrangement.phrase().as_ref()); }
|
||||
pub fn show_phrase (&mut self) {
|
||||
self.editor.show(self.arrangement.state.phrase().as_ref());
|
||||
}
|
||||
/// Focus the editor with the current phrase
|
||||
pub fn edit_phrase (&mut self) {
|
||||
if self.arrangement.selected.is_clip() && self.arrangement.phrase().is_none() {
|
||||
if self.arrangement.selected.is_clip() && self.arrangement.state.phrase().is_none() {
|
||||
self.phrases.write().unwrap().append_new(None, Some(self.next_color().into()));
|
||||
self.arrangement.phrase_put();
|
||||
}
|
||||
|
|
@ -284,7 +181,7 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
}
|
||||
pub fn delete (&mut self) {
|
||||
match self.selected {
|
||||
match self.arrangement.selected {
|
||||
ArrangementEditorFocus::Track(_) => self.track_del(),
|
||||
ArrangementEditorFocus::Scene(_) => self.scene_del(),
|
||||
ArrangementEditorFocus::Clip(_, _) => self.phrase_del(),
|
||||
|
|
@ -292,7 +189,7 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
}
|
||||
pub fn increment (&mut self) {
|
||||
match self.selected {
|
||||
match self.arrangement.selected {
|
||||
ArrangementEditorFocus::Track(_) => self.track_width_inc(),
|
||||
ArrangementEditorFocus::Scene(_) => self.scene_next(),
|
||||
ArrangementEditorFocus::Clip(_, _) => self.phrase_next(),
|
||||
|
|
@ -300,7 +197,7 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
}
|
||||
pub fn decrement (&mut self) {
|
||||
match self.selected {
|
||||
match self.arrangement.selected {
|
||||
ArrangementEditorFocus::Track(_) => self.track_width_dec(),
|
||||
ArrangementEditorFocus::Scene(_) => self.scene_prev(),
|
||||
ArrangementEditorFocus::Clip(_, _) => self.phrase_prev(),
|
||||
|
|
@ -308,13 +205,13 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
}
|
||||
pub fn zoom_in (&mut self) {
|
||||
if let ArrangementViewMode::Vertical(factor) = self.mode {
|
||||
self.mode = ArrangementViewMode::Vertical(factor + 1)
|
||||
if let ArrangementEditorMode::Vertical(factor) = self.mode {
|
||||
self.mode = ArrangementEditorMode::Vertical(factor + 1)
|
||||
}
|
||||
}
|
||||
pub fn zoom_out (&mut self) {
|
||||
if let ArrangementViewMode::Vertical(factor) = self.mode {
|
||||
self.mode = ArrangementViewMode::Vertical(factor.saturating_sub(1))
|
||||
if let ArrangementEditorMode::Vertical(factor) = self.mode {
|
||||
self.mode = ArrangementEditorMode::Vertical(factor.saturating_sub(1))
|
||||
}
|
||||
}
|
||||
pub fn is_first_row (&self) -> bool {
|
||||
|
|
@ -336,25 +233,25 @@ impl<E: Engine> ArrangerView<E> {
|
|||
}
|
||||
pub fn go_up (&mut self) {
|
||||
match self.mode {
|
||||
ArrangementViewMode::Horizontal => self.track_prev(),
|
||||
ArrangementEditorMode::Horizontal => self.track_prev(),
|
||||
_ => self.scene_prev(),
|
||||
};
|
||||
}
|
||||
pub fn go_down (&mut self) {
|
||||
match self.mode {
|
||||
ArrangementViewMode::Horizontal => self.track_next(),
|
||||
ArrangementEditorMode::Horizontal => self.track_next(),
|
||||
_ => self.scene_next(),
|
||||
};
|
||||
}
|
||||
pub fn go_left (&mut self) {
|
||||
match self.mode {
|
||||
ArrangementViewMode::Horizontal => self.scene_prev(),
|
||||
ArrangementEditorMode::Horizontal => self.scene_prev(),
|
||||
_ => self.track_prev(),
|
||||
};
|
||||
}
|
||||
pub fn go_right (&mut self) {
|
||||
match self.mode {
|
||||
ArrangementViewMode::Horizontal => self.scene_next(),
|
||||
ArrangementEditorMode::Horizontal => self.scene_next(),
|
||||
_ => self.track_next(),
|
||||
};
|
||||
}
|
||||
|
|
@ -457,10 +354,10 @@ impl<E: Engine> Arrangement<E> {
|
|||
}
|
||||
/// Methods for scenes in arrangement
|
||||
impl<E: Engine> Arrangement<E> {
|
||||
pub fn scene (&self) -> Option<&Scene> {
|
||||
pub fn scene (&self) -> Option<&ArrangementScene> {
|
||||
self.selected.scene().map(|s|self.scenes.get(s)).flatten()
|
||||
}
|
||||
pub fn scene_mut (&mut self) -> Option<&mut Scene> {
|
||||
pub fn scene_mut (&mut self) -> Option<&mut ArrangementScene> {
|
||||
self.selected.scene().map(|s|self.scenes.get_mut(s)).flatten()
|
||||
}
|
||||
pub fn scene_next (&mut self) {
|
||||
|
|
@ -573,7 +470,7 @@ impl ArrangementTrack {
|
|||
}
|
||||
|
||||
/// Arranger display mode can be cycled
|
||||
impl ArrangementViewMode {
|
||||
impl ArrangementEditorMode {
|
||||
/// Cycle arranger display mode
|
||||
pub fn to_next (&mut self) {
|
||||
*self = match self {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue