Commit 229b9f1cfc11b985c177c23edce4f274862be578
close but no
Michael Williams committed on 5/13/2018, 8:15:18 AMParent: 9cf1052d129942a85af116c81a7f960330143ad6
Files changed
src/clock.rs | changed |
src/control.rs | changed |
src/main.rs | changed |
src/clock.rs | ||
---|---|---|
@@ -1,10 +1,13 @@ | ||
1 | 1 … | // inspired by https://github.com/mmckegg/rust-loop-drop/blob/master/src/midi_time.rs |
2 | 2 … | // http://www.deluge.co/?q=midi-tempo-bpm |
3 | 3 … | |
4 | 4 … | use std::time::{Duration, Instant}; |
5 | -use std::thread::{sleep}; | |
5 … | +use std::thread::{sleep, spawn}; | |
6 … | +use std::sync::mpsc::{channel, Sender, Receiver}; | |
6 | 7 … | |
8 … | +use control; | |
9 … | + | |
7 | 10 … | pub type Time = Instant; |
8 | 11 … | |
9 | 12 … | pub type Nanos = u64; |
10 | 13 … | pub type Ticks = u64; |
@@ -18,11 +21,11 @@ | ||
18 | 21 … | static DEFAULT_BEATS_PER_BAR: u64 = 4; |
19 | 22 … | |
20 | 23 … | |
21 | 24 … | pub struct ClockSignature { |
22 | - nanos_per_beat: u64, // tempo | |
23 | - ticks_per_beat: u64, // meter | |
24 | - beats_per_bar: u64 // meter | |
25 … | + pub nanos_per_beat: u64, // tempo | |
26 … | + pub ticks_per_beat: u64, // meter | |
27 … | + pub beats_per_bar: u64 // meter | |
25 | 28 … | } |
26 | 29 … | |
27 | 30 … | impl ClockSignature { |
28 | 31 … | pub fn new (beats_per_minute: f64) -> Self { |
@@ -63,12 +66,12 @@ | ||
63 | 66 … | } |
64 | 67 … | |
65 | 68 … | |
66 | 69 … | pub struct ClockTime { |
67 | - nanos: Nanos, | |
68 | - ticks: Ticks, | |
69 | - beats: Beats, | |
70 | - bars: Bars | |
70 … | + pub nanos: Nanos, | |
71 … | + pub ticks: Ticks, | |
72 … | + pub beats: Beats, | |
73 … | + pub bars: Bars | |
71 | 74 … | } |
72 | 75 … | |
73 | 76 … | impl ClockTime { |
74 | 77 … | pub fn new (nanos: Nanos, signature: ClockSignature) -> Self { |
@@ -80,26 +83,29 @@ | ||
80 | 83 … | } |
81 | 84 … | } |
82 | 85 … | } |
83 | 86 … | |
84 | - | |
87 … | + | |
85 | 88 … | pub struct Clock { |
89 … | + control_tx: Sender<control::ControlMessage>, | |
86 | 90 … | start_instant: Instant, |
87 | 91 … | tick_instant: Instant, |
88 | 92 … | signature: ClockSignature |
89 | 93 … | } |
90 | 94 … | |
91 | -pub struct ClockMessage { | |
95 … | +pub enum ClockMessage { | |
96 … | + Time(ClockTime) | |
92 | 97 … | } |
93 | 98 … | |
94 | 99 … | impl Clock { |
95 | - pub fn new (signature: ClockSignature) -> Self { | |
100 … | + pub fn new (signature: ClockSignature, control: &control::Control) -> Self { | |
96 | 101 … | let start_instant = Instant::now(); |
97 | 102 … | |
98 | 103 … | Self { |
99 | 104 … | start_instant, |
100 | 105 … | tick_instant: start_instant, |
101 | - signature | |
106 … | + signature, | |
107 … | + control_tx: control.tx.clone() | |
102 | 108 … | } |
103 | 109 … | } |
104 | 110 … | |
105 | 111 … | pub fn time (&self) -> ClockTime { |
@@ -117,8 +123,20 @@ | ||
117 | 123 … | pub fn nanos_since_tick (&self) -> Nanos { |
118 | 124 … | duration_to_nanos(self.tick_instant.elapsed()) |
119 | 125 … | } |
120 | 126 … | |
127 … | + pub fn start (&self) { | |
128 … | + let control_tx = self.control_tx.clone(); | |
129 … | + | |
130 … | + spawn(move|| { | |
131 … | + loop { | |
132 … | + self.tick(); | |
133 … | + | |
134 … | + control_tx.send(control::ControlMessage::Time(self.time())); | |
135 … | + } | |
136 … | + }); | |
137 … | + } | |
138 … | + | |
121 | 139 … | // https://github.com/BookOwl/fps_clock/blob/master/src/lib.rs |
122 | 140 … | pub fn tick (&mut self) -> ClockTime { |
123 | 141 … | let diff = self.diff(); |
124 | 142 … |
src/control.rs | ||
---|---|---|
@@ -1,40 +1,32 @@ | ||
1 | -use std::thread; | |
2 | 1 … | use std::sync::mpsc::{channel, Sender, Receiver}; |
3 | 2 … | |
4 | -pub type Time = f32; | |
3 … | +use clock; | |
5 | 4 … | |
6 | -pub enum ChangeMode { | |
7 | - Start, | |
8 | - Continue, | |
9 | - Stop | |
5 … | + | |
6 … | +pub struct Control { | |
7 … | + pub tx: Sender<ControlMessage>, | |
8 … | + pub rx: Receiver<ControlMessage> | |
10 | 9 … | } |
11 | 10 … | |
12 | -pub | |
11 … | +impl Control { | |
12 … | + pub fn new() -> Self { | |
13 … | + let (tx, rx) = channel(); | |
14 … | + | |
15 … | + Self { | |
16 … | + tx, | |
17 … | + rx | |
18 … | + } | |
19 … | + } | |
20 … | +} | |
13 | 21 … | |
14 | - | |
15 | -pub enum Control { | |
16 | - Time(Time), | |
17 | - ChangeMode(ChangeMode), | |
22 … | + | |
23 … | +pub enum ControlMessage { | |
24 … | + Time(clock::ClockTime), | |
25 … | + Start, | |
26 … | + Stop, | |
18 | 27 … | TapTempo, |
19 | - SetTempo(), | |
20 | - Nudge( | |
21 | - Configure(ChangeMode) | |
28 … | + SetTempo, | |
29 … | + NudgeClock, | |
30 … | + Configure | |
22 | 31 … | } |
23 | 32 … | |
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 | -} |
src/main.rs | ||
---|---|---|
@@ -1,127 +1,125 @@ | ||
1 | -/* | |
2 | -use std::io; | |
3 | -use std::io::prelude::*; | |
4 | - | |
5 | -use std::sync::mpsc; | |
6 | -use std::thread::sleep; | |
7 | -use std::time::{Duration}; | |
8 | - | |
9 | -fn main () { | |
10 | - let metronome = Metronone::new(); | |
11 | - metronome().unwrap(); | |
12 | -} | |
13 | - | |
14 | -pub struct Metronone {} | |
15 | - | |
16 | -impl Metronome () { | |
17 | - pub fn new () -> <()> { | |
18 | - let stdin = io::stdin(); | |
19 | - let mut buffer = vec![0_u8; 2_usize.pow(8)]; | |
20 | - | |
21 | - loop { | |
22 | - let mut handle = stdin.lock(); | |
23 | - match handle.read(&mut buffer) { | |
24 | - Ok(num_bytes) => { | |
25 | - println!("{} bytes read", num_bytes); | |
26 | - let string = String::from_utf8(buffer.clone()).unwrap(); | |
27 | - }, | |
28 | - Err(error) => println!("error: {}", error), | |
29 | - } | |
30 | - | |
31 | - sleep(Duration::new(0, 30 * 1000 * 1000)); | |
32 | - } | |
33 | - } | |
34 | -*/ | |
35 | - | |
36 | -/* | |
37 | - Copyright © 2013 Free Software Foundation, Inc | |
38 | - See licensing in LICENSE file | |
39 | - File: examples/ex_7.rs | |
40 | - Author: Jesse 'Jeaye' Wilkerson | |
41 | - Description: | |
42 | - Basic input and attribute example, using the Unicode-aware get_wch functions. | |
43 | -*/ | |
44 | - | |
45 | 1 … | extern crate ncurses; |
46 | -// extern crate ctrlc; | |
47 | 2 … | |
3 … | +use ncurses::{WchResult}; | |
48 | 4 … | use std::char; |
49 | -use ncurses::{WchResult}; | |
50 | -use std::thread::{sleep,spawn}; | |
5 … | +use std::sync::mpsc::{channel, Sender, Receiver}; | |
6 … | +use std::thread::{sleep, spawn}; | |
51 | 7 … | use std::time::{Duration}; |
52 | 8 … | |
53 | 9 … | mod clock; |
10 … | +mod control; | |
54 | 11 … | |
55 | 12 … | // https://unicode.org/charts/PDF/U0000.pdf |
56 | 13 … | static CHAR_SPACE: u32 = 0x0020; |
57 | 14 … | static CHAR_RETURN: u32 = 0x000D; |
58 | 15 … | static CHAR_NEWLINE: u32 = 0x000A; |
59 | 16 … | |
60 | 17 … | fn main () { |
61 | - clock(); | |
62 | - // terminal_interface(); | |
18 … | + let control = control::Control::new(); | |
19 … | + | |
20 … | + let clock_signature = clock::ClockSignature::new(60_f64); | |
21 … | + let mut clock = clock::Clock::new(clock_signature, &control); | |
22 … | + | |
23 … | + clock.start(); | |
24 … | + | |
25 … | + let terminal_interface = TerminalInterface::new(&control); | |
63 | 26 … | |
64 | - loop { | |
65 | - sleep(Duration::new(10, 0)); | |
27 … | + terminal_interface.start(); | |
28 … | + | |
29 … | + for control_message in control.rx { | |
30 … | + match control_message { | |
31 … | + control::ControlMessage::Time(time) => { | |
32 … | + terminal_interface.tx.send(InterfaceMessage::Time(time)); | |
33 … | + } | |
34 … | + } | |
66 | 35 … | } |
67 | 36 … | } |
68 | 37 … | |
69 | -fn clock () { | |
70 | - spawn(move|| { | |
71 | - let signature = clock::ClockSignature::new(60_f64); | |
72 | - let mut clock = clock::Clock::new(signature); | |
73 | - loop { | |
74 | - clock.tick(); | |
75 | - println!("{:?}", clock.time()); | |
76 | - } | |
77 | - }); | |
38 … | + | |
39 … | +pub struct TerminalInterface { | |
40 … | + control_tx: Sender<control::ControlMessage>, | |
41 … | + tx: Sender<InterfaceMessage>, | |
42 … | + rx: Receiver<InterfaceMessage> | |
78 | 43 … | } |
79 | 44 … | |
80 | -fn terminal_interface () { | |
81 | - spawn(move|| { | |
82 | - let locale_conf = ncurses::LcCategory::all; | |
83 | - ncurses::setlocale(locale_conf, "en_US.UTF-8"); | |
45 … | +impl TerminalInterface { | |
46 … | + pub fn new (control: &control::Control) -> Self { | |
47 … | + let (tx, rx) = channel(); | |
48 … | + | |
49 … | + Self { | |
50 … | + control_tx: control.tx.clone(), | |
51 … | + tx, | |
52 … | + rx | |
53 … | + } | |
54 … | + } | |
84 | 55 … | |
85 | - /* Setup ncurses. */ | |
86 | - ncurses::initscr(); | |
56 … | + pub fn start (&self) { | |
57 … | + let control_tx = self.control_tx.clone(); | |
87 | 58 … | |
88 | - /* Enable mouse events. */ | |
89 | - ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None); | |
59 … | + spawn(move|| { | |
60 … | + /* Setup ncurses. */ | |
61 … | + ncurses::initscr(); | |
90 | 62 … | |
91 | - /* Allow for extended keyboard (like F1). */ | |
92 | - ncurses::keypad(ncurses::stdscr(), true); | |
93 | - ncurses::noecho(); | |
63 … | + let locale_conf = ncurses::LcCategory::all; | |
64 … | + ncurses::setlocale(locale_conf, "en_US.UTF-8"); | |
94 | 65 … | |
95 | - loop { | |
96 | - let ch = ncurses::wget_wch(ncurses::stdscr()); | |
66 … | + /* Enable mouse events. */ | |
67 … | + ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None); | |
97 | 68 … | |
98 | - match ch { | |
99 | - Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => { | |
100 | - tap(); | |
101 | - } | |
69 … | + /* Allow for extended keyboard (like F1). */ | |
70 … | + ncurses::keypad(ncurses::stdscr(), true); | |
71 … | + ncurses::noecho(); | |
102 | 72 … | |
103 | - // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs | |
104 | - Some(WchResult::KeyCode(_)) => {} | |
73 … | + loop { | |
74 … | + let ch = ncurses::wget_wch(ncurses::stdscr()); | |
105 | 75 … | |
106 | - // Some(WchResult::KeyCode(KEY_ENTER)) => beat(), | |
107 | - Some(WchResult::Char(ch)) => { | |
108 | - if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) { | |
109 | - tap(); | |
76 … | + match ch { | |
77 … | + Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => { | |
78 … | + control_tx.send(control::ControlMessage::TapTempo).unwrap(); | |
110 | 79 … | } |
80 … | + | |
81 … | + // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs | |
82 … | + Some(WchResult::KeyCode(_)) => {} | |
83 … | + | |
84 … | + // Some(WchResult::KeyCode(KEY_ENTER)) => beat(), | |
85 … | + Some(WchResult::Char(ch)) => { | |
86 … | + if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) { | |
87 … | + control_tx.send(control::ControlMessage::TapTempo).unwrap(); | |
88 … | + } | |
89 … | + } | |
90 … | + | |
91 … | + None => {} | |
111 | 92 … | } |
112 | 93 … | |
113 | - None => {} | |
94 … | + ncurses::refresh(); | |
114 | 95 … | } |
115 | 96 … | |
116 | - ncurses::refresh(); | |
117 | - } | |
97 … | + ncurses::endwin(); | |
98 … | + }); | |
118 | 99 … | |
119 | - ncurses::endwin(); | |
120 | - }); | |
100 … | + spawn(move|| { | |
101 … | + for interface_message in self.rx { | |
102 … | + match interface_message { | |
103 … | + InterfaceMessage::Time(time) => { | |
104 … | + print_time(time); | |
105 … | + } | |
106 … | + } | |
107 … | + | |
108 … | + } | |
109 … | + }); | |
110 … | + } | |
121 | 111 … | } |
122 | 112 … | |
123 | -fn tap () { | |
124 | - ncurses::attron(ncurses::A_BOLD()); | |
125 | - ncurses::printw("\nBeat"); | |
126 | - ncurses::attroff(ncurses::A_BOLD()); | |
113 … | +pub fn print_time (time: clock::ClockTime) { | |
114 … | + ncurses::clear(); | |
115 … | + ncurses::mv(0, 0); | |
116 … | + ncurses::printw("nanos: "); | |
117 … | + ncurses::printw(format!("{}\n", time.nanos).as_ref()); | |
118 … | + ncurses::printw("\nticks: "); | |
119 … | + ncurses::printw(format!("{}\n", time.ticks).as_ref()); | |
127 | 120 … | } |
121 … | + | |
122 … | + | |
123 … | +pub enum InterfaceMessage { | |
124 … | + Time(clock::ClockTime) | |
125 … | +} |
Built with git-ssb-web