mirror of
https://codeberg.org/unspeaker/tek.git
synced 2025-12-07 12:16:42 +01:00
wip: fix one batch of errors, unlock another
This commit is contained in:
parent
a54798994b
commit
10f191282e
14 changed files with 92 additions and 28 deletions
21
Cargo.lock
generated
21
Cargo.lock
generated
|
|
@ -448,6 +448,15 @@ version = "0.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "clojure-reader"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4fe72db90a90a91de4a9fbd79542538caa0445ebdebcd3112589cab4c1e0e10b"
|
||||||
|
dependencies = [
|
||||||
|
"ordered-float",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "colorchoice"
|
name = "colorchoice"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
|
|
@ -1653,6 +1662,15 @@ dependencies = [
|
||||||
"libredox",
|
"libredox",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "ordered-float"
|
||||||
|
version = "4.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "19ff2cf528c6c03d9ed653d6c4ce1dc0582dc4af309790ad92f07c1cd551b0be"
|
||||||
|
dependencies = [
|
||||||
|
"num-traits",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "owned_ttf_parser"
|
name = "owned_ttf_parser"
|
||||||
version = "0.24.0"
|
version = "0.24.0"
|
||||||
|
|
@ -2491,6 +2509,8 @@ checksum = "4873307b7c257eddcb50c9bedf158eb669578359fb28428bef438fec8e6ba7c2"
|
||||||
name = "tek"
|
name = "tek"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"clojure-reader",
|
||||||
|
"microxdg",
|
||||||
"tek_chain",
|
"tek_chain",
|
||||||
"tek_core",
|
"tek_core",
|
||||||
"tek_jack",
|
"tek_jack",
|
||||||
|
|
@ -2517,7 +2537,6 @@ dependencies = [
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"clap",
|
"clap",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
"microxdg",
|
|
||||||
"midly",
|
"midly",
|
||||||
"ratatui",
|
"ratatui",
|
||||||
"toml",
|
"toml",
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ edition = "2021"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
clap = { version = "4.5.4", features = [ "derive" ] }
|
|
||||||
clojure-reader = "0.1.0"
|
clojure-reader = "0.1.0"
|
||||||
microxdg = "0.1.2"
|
microxdg = "0.1.2"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -32,10 +32,12 @@ pub struct App {
|
||||||
impl App {
|
impl App {
|
||||||
pub fn new () -> Usually<Self> {
|
pub fn new () -> Usually<Self> {
|
||||||
let xdg = Arc::new(XdgApp::new("tek")?);
|
let xdg = Arc::new(XdgApp::new("tek")?);
|
||||||
let first_run = crate::config::AppPaths::new(&xdg)?.should_create();
|
let first_run = AppPaths::new(&xdg)?.should_create();
|
||||||
let jack = JackClient::Inactive(Client::new("tek", ClientOptions::NO_START_SERVER)?.0);
|
let jack = JackClient::Inactive(
|
||||||
|
Client::new("tek", ClientOptions::NO_START_SERVER)?.0
|
||||||
|
);
|
||||||
*MODAL.lock().unwrap() = first_run.then(||{
|
*MODAL.lock().unwrap() = first_run.then(||{
|
||||||
Exit::boxed(crate::devices::setup::SetupModal(Some(xdg.clone()), false))
|
Exit::boxed(SetupModal(Some(xdg.clone()), false))
|
||||||
});
|
});
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
entered: true,
|
entered: true,
|
||||||
|
|
@ -95,7 +97,7 @@ render!(App |self, buf, area| {
|
||||||
&self.transport,
|
&self.transport,
|
||||||
&self.arranger,
|
&self.arranger,
|
||||||
&If(self.arranger.selected.is_clip(), &Split::right([
|
&If(self.arranger.selected.is_clip(), &Split::right([
|
||||||
&ChainView::vertical(&self),
|
&tek_chain::ChainView::vertical(&self),
|
||||||
&self.sequencer,
|
&self.sequencer,
|
||||||
]))
|
]))
|
||||||
]).render(buf, area)?;
|
]).render(buf, area)?;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Command line option parser.
|
//! Command line option parser.
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use tek_core::clap::{self, Parser, Subcommand};
|
||||||
|
|
||||||
#[derive(Debug, Parser)]
|
#[derive(Debug, Parser)]
|
||||||
#[command(version, about, long_about = None)]
|
#[command(version, about, long_about = None)]
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,13 @@ submod! {
|
||||||
control
|
control
|
||||||
edn
|
edn
|
||||||
help
|
help
|
||||||
modal
|
|
||||||
setup
|
setup
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Global modal dialog
|
||||||
|
pub static MODAL: Lazy<Arc<Mutex<Option<Box<dyn Exit>>>>> =
|
||||||
|
Lazy::new(||Arc::new(Mutex::new(None)));
|
||||||
|
|
||||||
/// Application entrypoint.
|
/// Application entrypoint.
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
run(App::from_edn(include_str!("../../../demos/project.edn"))?
|
run(App::from_edn(include_str!("../../../demos/project.edn"))?
|
||||||
|
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
use crate::*;
|
|
||||||
|
|
||||||
/// Global modal dialog
|
|
||||||
pub static MODAL: Lazy<Arc<Mutex<Option<Box<dyn Exit>>>>> =
|
|
||||||
Lazy::new(||Arc::new(Mutex::new(None)));
|
|
||||||
|
|
@ -10,3 +10,4 @@ backtrace = "0.3.72"
|
||||||
toml = "0.8.12"
|
toml = "0.8.12"
|
||||||
better-panic = "0.3.0"
|
better-panic = "0.3.0"
|
||||||
midly = "0.5"
|
midly = "0.5"
|
||||||
|
clap = { version = "4.5.4", features = [ "derive" ] }
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
pub use ratatui;
|
pub use ratatui;
|
||||||
pub use crossterm;
|
pub use crossterm;
|
||||||
pub use midly;
|
pub use midly;
|
||||||
|
pub use clap;
|
||||||
pub use std::sync::{Arc, Mutex, RwLock};
|
pub use std::sync::{Arc, Mutex, RwLock};
|
||||||
pub use std::collections::BTreeMap;
|
pub use std::collections::BTreeMap;
|
||||||
pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
|
pub use crossterm::event::{Event, KeyEvent, KeyCode, KeyModifiers};
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ submod! {
|
||||||
midi
|
midi
|
||||||
phrase
|
phrase
|
||||||
sequencer
|
sequencer
|
||||||
|
sequencer_cli
|
||||||
sequencer_control
|
sequencer_control
|
||||||
sequencer_track
|
sequencer_track
|
||||||
arranger
|
arranger
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
//! Phrase editor.
|
//! Phrase editor.
|
||||||
include!("lib.rs");
|
include!("lib.rs");
|
||||||
pub fn main () -> Usually<()> {
|
pub fn main () -> Usually<()> {
|
||||||
tek_core::run(Arc::new(RwLock::new(crate::Sequencer::new())))?;
|
tek_core::run(Arc::new(RwLock::new(crate::Sequencer::from_args())))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
use tek_jack::jack::*;
|
|
||||||
|
|
||||||
/// MIDI message serialized to bytes
|
/// MIDI message serialized to bytes
|
||||||
pub type MIDIMessage = Vec<u8>;
|
pub type MIDIMessage = Vec<u8>;
|
||||||
|
|
|
||||||
|
|
@ -1,18 +1,5 @@
|
||||||
use crate::*;
|
use crate::*;
|
||||||
|
|
||||||
/// Define a MIDI phrase.
|
|
||||||
#[macro_export] macro_rules! phrase {
|
|
||||||
($($t:expr => $msg:expr),* $(,)?) => {{
|
|
||||||
#[allow(unused_mut)]
|
|
||||||
let mut phrase = BTreeMap::new();
|
|
||||||
$(phrase.insert($t, vec![]);)*
|
|
||||||
$(phrase.get_mut(&$t).unwrap().push($msg);)*
|
|
||||||
phrase
|
|
||||||
}}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PhraseData = Vec<Vec<MidiMessage>>;
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// A MIDI sequence.
|
/// A MIDI sequence.
|
||||||
pub struct Phrase {
|
pub struct Phrase {
|
||||||
|
|
@ -24,6 +11,8 @@ pub struct Phrase {
|
||||||
pub percussive: bool
|
pub percussive: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type PhraseData = Vec<Vec<MidiMessage>>;
|
||||||
|
|
||||||
impl Default for Phrase {
|
impl Default for Phrase {
|
||||||
fn default () -> Self {
|
fn default () -> Self {
|
||||||
Self::new("", 0, None)
|
Self::new("", 0, None)
|
||||||
|
|
@ -91,3 +80,14 @@ impl Phrase {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Define a MIDI phrase.
|
||||||
|
#[macro_export] macro_rules! phrase {
|
||||||
|
($($t:expr => $msg:expr),* $(,)?) => {{
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut phrase = BTreeMap::new();
|
||||||
|
$(phrase.insert($t, vec![]);)*
|
||||||
|
$(phrase.get_mut(&$t).unwrap().push($msg);)*
|
||||||
|
phrase
|
||||||
|
}}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,11 +2,13 @@ use crate::*;
|
||||||
|
|
||||||
/// Phrase editor.
|
/// Phrase editor.
|
||||||
pub struct Sequencer {
|
pub struct Sequencer {
|
||||||
|
pub name: String,
|
||||||
pub mode: bool,
|
pub mode: bool,
|
||||||
pub focused: bool,
|
pub focused: bool,
|
||||||
pub entered: bool,
|
pub entered: bool,
|
||||||
|
|
||||||
pub phrase: Option<Arc<RwLock<Phrase>>>,
|
pub phrase: Option<Arc<RwLock<Phrase>>>,
|
||||||
|
pub transport: Option<Arc<RwLock<TransportToolbar>>>,
|
||||||
pub buffer: BigBuffer,
|
pub buffer: BigBuffer,
|
||||||
pub keys: Buffer,
|
pub keys: Buffer,
|
||||||
/// Highlight input keys
|
/// Highlight input keys
|
||||||
|
|
@ -34,6 +36,7 @@ handle!(Sequencer |self, e| handle_keymap(self, e, KEYMAP_SEQUENCER));
|
||||||
impl Sequencer {
|
impl Sequencer {
|
||||||
pub fn new () -> Self {
|
pub fn new () -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
name: "".into(),
|
||||||
buffer: Default::default(),
|
buffer: Default::default(),
|
||||||
keys: keys_vert(),
|
keys: keys_vert(),
|
||||||
entered: false,
|
entered: false,
|
||||||
|
|
@ -44,6 +47,7 @@ impl Sequencer {
|
||||||
phrase: None,
|
phrase: None,
|
||||||
now: 0,
|
now: 0,
|
||||||
ppq: 96,
|
ppq: 96,
|
||||||
|
transport: None,
|
||||||
note_axis: FixedAxis {
|
note_axis: FixedAxis {
|
||||||
start: 12,
|
start: 12,
|
||||||
point: Some(36)
|
point: Some(36)
|
||||||
|
|
|
||||||
40
crates/tek_sequencer/src/sequencer_cli.rs
Normal file
40
crates/tek_sequencer/src/sequencer_cli.rs
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
//! Command line option parser.
|
||||||
|
|
||||||
|
use tek_core::clap::{self, Parser, Subcommand};
|
||||||
|
use tek_timer::TransportToolbar;
|
||||||
|
use crate::*;
|
||||||
|
|
||||||
|
#[derive(Debug, Parser)]
|
||||||
|
#[command(version, about, long_about = None)]
|
||||||
|
pub struct SequencerCli {
|
||||||
|
/// Name of JACK client
|
||||||
|
#[arg(short, long)] name: Option<String>,
|
||||||
|
/// Pulses per quarter note (sequencer resolution; default: 96)
|
||||||
|
#[arg(short, long)] ppq: Option<usize>,
|
||||||
|
/// Default phrase duration (in pulses; default: 4 * PPQ = 1 bar)
|
||||||
|
#[arg(short, long)] length: Option<usize>,
|
||||||
|
/// Whether to include a transport toolbar (default: true)
|
||||||
|
#[arg(short, long)] transport: Option<bool>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Sequencer {
|
||||||
|
pub fn from_args () -> Self {
|
||||||
|
let args = SequencerCli::parse();
|
||||||
|
let mut seq = Self::new();
|
||||||
|
if let Some(name) = args.name {
|
||||||
|
seq.name = name.clone();
|
||||||
|
}
|
||||||
|
if let Some(ppq) = args.ppq {
|
||||||
|
seq.ppq = ppq;
|
||||||
|
}
|
||||||
|
if let Some(length) = args.length {
|
||||||
|
if let Some(phrase) = seq.phrase.as_mut() {
|
||||||
|
phrase.write().unwrap().length = length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if args.transport == Some(true) {
|
||||||
|
seq.transport = Some(Arc::new(RwLock::new(TransportToolbar::new(None))));
|
||||||
|
}
|
||||||
|
seq
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue