git ssb

0+

dinoworm 🐛 / metronome



Commit 4ba4ca13e7973216b4183f63e28393f41614ba18

checkpoint

Michael Williams committed on 5/13/2018, 6:11:30 AM
Parent: 9b8912a81188690277f8add60b236015174da8c9

Files changed

src/main.rschanged
src/clock.rsadded
src/control.rsadded
src/main.rsView
@@ -46,66 +46,83 @@
4646 // extern crate ctrlc;
4747
4848 use std::char;
4949 use ncurses::{WchResult};
50-// use std::sync::atomic::{AtomicBool, Ordering};
51-// use std::sync::Arc;
50 +use std::thread::{sleep,spawn};
51 +use std::time::{Duration};
5252
53 +mod clock;
5354
5455 // https://unicode.org/charts/PDF/U0000.pdf
5556 static CHAR_SPACE: u32 = 0x0020;
5657 static CHAR_RETURN: u32 = 0x000D;
5758 static CHAR_NEWLINE: u32 = 0x000A;
5859
59-fn main() {
60- // let locale_conf = LcCategory::all;
61- // setlocale(locale_conf, "en_US.UTF-8");
60 +fn main () {
61 + clock();
62 + // terminal_interface();
63 +
64 + loop {
65 + sleep(Duration::new(10, 0));
66 + }
67 +}
6268
63- /* Setup ncurses. */
64- ncurses::initscr();
69 +fn clock () {
70 + spawn(move|| {
71 + let time_signature = clock::TimeSignature {
72 + nanos_per_beat: BEATS_PER_MINUTE / SECONDS_PER_MINUTE * NANOS_PER_SECOND,
73 + ticks_per_beat: DEFAULT_TICKS_PER_BEAT,
74 + beats_per_measure: DEFAULT_BEATS_PER_MEASURE
75 + };
76 + let mut clock = clock::Clock::new(time_signature);
77 + loop {
78 + clock.tick();
79 + println!("{:?}", clock.get_time());
80 + }
81 + });
82 +}
6583
66- /* Enable mouse events. */
67- ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None);
84 +fn terminal_interface () {
85 + spawn(move|| {
86 + let locale_conf = ncurses::LcCategory::all;
87 + ncurses::setlocale(locale_conf, "en_US.UTF-8");
6888
69- /* Allow for extended keyboard (like F1). */
70- ncurses::keypad(ncurses::stdscr(), true);
71- ncurses::noecho();
89 + /* Setup ncurses. */
90 + ncurses::initscr();
7291
92 + /* Enable mouse events. */
93 + ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None);
7394
74- /*
75- let running = Arc::new(AtomicBool::new(true));
76- let r = running.clone();
77- ctrlc::set_handler(move || {
78- r.store(false, Ordering::SeqCst);
79- }).expect("Error setting Ctrl-C handler");
95 + /* Allow for extended keyboard (like F1). */
96 + ncurses::keypad(ncurses::stdscr(), true);
97 + ncurses::noecho();
8098
81- while running.load(Ordering::SeqCst) {
82- */
83- loop {
84- let ch = ncurses::wget_wch(ncurses::stdscr());
99 + loop {
100 + let ch = ncurses::wget_wch(ncurses::stdscr());
85101
86- match ch {
87- Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => {
88- tap();
89- }
102 + match ch {
103 + Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => {
104 + tap();
105 + }
90106
91- // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs
92- Some(WchResult::KeyCode(_)) => {}
107 + // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs
108 + Some(WchResult::KeyCode(_)) => {}
93109
94- // Some(WchResult::KeyCode(KEY_ENTER)) => beat(),
95- Some(WchResult::Char(ch)) => {
96- if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) {
97- tap();
110 + // Some(WchResult::KeyCode(KEY_ENTER)) => beat(),
111 + Some(WchResult::Char(ch)) => {
112 + if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) {
113 + tap();
114 + }
98115 }
116 +
117 + None => {}
99118 }
100119
101- None => {}
120 + ncurses::refresh();
102121 }
103122
104- ncurses::refresh();
105- }
106-
107- ncurses::endwin();
123 + ncurses::endwin();
124 + });
108125 }
109126
110127 fn tap () {
111128 ncurses::attron(ncurses::A_BOLD());
src/clock.rsView
@@ -1,0 +1,87 @@
1 +// inspired by https://github.com/mmckegg/rust-loop-drop/blob/master/src/midi_time.rs
2 +// http://www.deluge.co/?q=midi-tempo-bpm
3 +
4 +use std::time::{Duration, Instant};
5 +use std::thread::{sleep};
6 +
7 +pub type Time = Instant;
8 +
9 +pub type Nanos = u64;
10 +pub type Ticks = u64;
11 +pub type Beats = u64;
12 +pub type Measures = u64;
13 +
14 +static SECONDS_PER_MINUTE: u64 = 60;
15 +static NANOS_PER_SECOND: u64 = 1_000_000;
16 +static BEATS_PER_MINUTE: u64 = 60;
17 +static DEFAULT_TICKS_PER_BEAT: u64 = 1;
18 +static DEFAULT_BEATS_PER_MEASURE: u64 = 4;
19 +
20 +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
21 +pub struct TimeSignature {
22 + nanos_per_beat: u64, // tempo
23 + clicks_per_beat: u64, // meter: notes per beat
24 + beats_per_bar: u64 // meter
25 +}
26 +
27 +impl TimeSignature {
28 + pub fn new (beats_per_minute: f64) {
29 + let beats_per_nano = ticks_per_minute
30 + }
31 +
32 + pub fn nanos_per_tick (&self) -> u64 {
33 + (self.nanos_per_beat / self.ticks_per_beat) as u64
34 + }
35 +
36 + pub fn ticks_since (&self, diff_duration: Duration) -> u64 {
37 + let total_nanos = diff_duration.as_secs() * 1_000_000_000 + diff_duration.subsec_nanos() as u64;
38 + self.nanos_per_tick() - total_nanos
39 + }
40 +}
41 +
42 +#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
43 +pub struct Clock {
44 + time: Time,
45 + time_signature: TimeSignature
46 +}
47 +
48 +pub struct ClockMessage {
49 +}
50 +
51 +impl Clock {
52 + pub fn new (time_signature: TimeSignature) -> Self {
53 + Self {
54 + time: Instant::now(),
55 + time_signature
56 + }
57 + }
58 +
59 + pub fn get_time (&self) -> Time {
60 + self.time
61 + }
62 +
63 + // https://github.com/BookOwl/fps_clock/blob/master/src/lib.rs
64 + pub fn tick (&mut self) -> u64 {
65 + let diff_duration = self.time.elapsed();
66 + let diff_nanos = self.time_signature.nanos_since(diff_duration);
67 + if diff_nanos > 0 {
68 + sleep(Duration::new(0, diff_nanos as u32))
69 + };
70 + self.time = Instant::now();
71 + diff_nanos
72 + }
73 +}
74 +
75 +/*
76 +pub fn nanos_from_ticks (ticks: Ticks, time_signature: TimeSignature) -> Nanos {
77 + ticks * time_signature.nanos_per_beat
78 +}
79 +
80 +pub fn ticks_from_beats (beats: Beats, time_signature: TimeSignature) -> Ticks {
81 + beats * time_signature.ticks_per_beat
82 +}
83 +
84 +pub fn ticks_from_measure (measures: Measures, time_signature: TimeSignature) -> Ticks {
85 + measures * time_signature.beats_per_measure * time_signature.ticks_per_beat
86 +}
87 +*/
src/control.rsView
@@ -1,0 +1,40 @@
1 +use std::thread;
2 +use std::sync::mpsc::{channel, Sender, Receiver};
3 +
4 +pub type Time = f32;
5 +
6 +pub enum ChangeMode {
7 + Start,
8 + Continue,
9 + Stop
10 +}
11 +
12 +pub
13 +
14 +
15 +pub enum Control {
16 + Time(Time),
17 + ChangeMode(ChangeMode),
18 + TapTempo,
19 + SetTempo(),
20 + Nudge(
21 + Configure(ChangeMode)
22 +}
23 +
24 +pub fn create_control_channel() -> (Sender<Control>, Receiver<Control>) {
25 + return channel();
26 +}
27 +
28 +pub fn connect_clock(fps: u32, control_tx: Sender<Control>) {
29 + thread::spawn(move|| {
30 + let mut fps_clock = fps_clock::FpsClock::new(fps);
31 + let mut nanosecs_since_start = 0.0;
32 + let mut nanosecs_since_last_tick;
33 + loop {
34 + nanosecs_since_last_tick = fps_clock.tick();
35 + nanosecs_since_start += nanosecs_since_last_tick;
36 + let clock_time = Control::Time(nanosecs_since_start);
37 + control_tx.send(clock_time).unwrap();
38 + }
39 + });
40 +}

Built with git-ssb-web