Commit de37e989827890621e4dbd2d5a5493b416130606
working interface
Michael Williams committed on 5/13/2018, 9:33:58 AMParent: 229b9f1cfc11b985c177c23edce4f274862be578
Files changed
src/clock.rs | changed |
src/control.rs | changed |
src/main.rs | changed |
src/interface.rs | added |
src/clock.rs | ||
---|---|---|
@@ -39,8 +39,16 @@ | ||
39 | 39 … | beats_per_bar: DEFAULT_BEATS_PER_BAR |
40 | 40 … | } |
41 | 41 … | } |
42 | 42 … | |
43 … | + pub fn to_beats_per_minute (&self) -> f64 { | |
44 … | + let nanos_per_beat = self.nanos_per_beat; | |
45 … | + let beats_per_nano = 1_f64 / self.nanos_per_beat as f64; | |
46 … | + let beats_per_second = beats_per_nano * NANOS_PER_SECOND as f64; | |
47 … | + let beats_per_minute = beats_per_second * SECONDS_PER_MINUTE as f64; | |
48 … | + beats_per_minute | |
49 … | + } | |
50 … | + | |
43 | 51 … | pub fn nanos_per_tick (&self) -> u64 { |
44 | 52 … | (self.nanos_per_beat / self.ticks_per_beat) as u64 |
45 | 53 … | } |
46 | 54 … | |
@@ -85,58 +93,59 @@ | ||
85 | 93 … | } |
86 | 94 … | |
87 | 95 … | |
88 | 96 … | pub struct Clock { |
89 | - control_tx: Sender<control::ControlMessage>, | |
90 | - start_instant: Instant, | |
91 | - tick_instant: Instant, | |
97 … | + start: Time, | |
98 … | + tick: Time, | |
92 | 99 … | signature: ClockSignature |
93 | 100 … | } |
94 | 101 … | |
95 | 102 … | pub enum ClockMessage { |
96 | 103 … | Time(ClockTime) |
97 | 104 … | } |
98 | 105 … | |
99 | 106 … | impl Clock { |
100 | - pub fn new (signature: ClockSignature, control: &control::Control) -> Self { | |
101 | - let start_instant = Instant::now(); | |
107 … | + pub fn new (signature: ClockSignature) -> Self { | |
108 … | + let start = Time::now(); | |
102 | 109 … | |
103 | 110 … | Self { |
104 | - start_instant, | |
105 | - tick_instant: start_instant, | |
106 | - signature, | |
107 | - control_tx: control.tx.clone() | |
111 … | + start, | |
112 … | + tick: start, | |
113 … | + signature | |
108 | 114 … | } |
109 | 115 … | } |
110 | 116 … | |
117 … | + pub fn start (signature: ClockSignature, control_tx: Sender<control::ControlMessage>) { | |
118 … | + let mut clock = Self::new(signature); | |
119 … | + | |
120 … | + spawn(move|| { | |
121 … | + loop { | |
122 … | + clock.tick(); | |
123 … | + | |
124 … | + control_tx.send(control::ControlMessage::Time(clock.time())).unwrap(); | |
125 … | + } | |
126 … | + }); | |
127 … | + } | |
128 … | + | |
111 | 129 … | pub fn time (&self) -> ClockTime { |
112 | 130 … | ClockTime::new(self.nanos_since_start(), self.signature) |
113 | 131 … | } |
114 | 132 … | |
115 | 133 … | pub fn diff (&self) -> ClockTime { |
116 | - ClockTime::new(self.nanos_since_tick(), self.signature) | |
134 … | + let nanos_since_tick = self.nanos_since_tick(); | |
135 … | + let nanos_per_tick = self.signature.nanos_per_tick(); | |
136 … | + let diff = nanos_per_tick - nanos_since_tick; | |
137 … | + ClockTime::new(diff, self.signature) | |
117 | 138 … | } |
118 | 139 … | |
119 | 140 … | pub fn nanos_since_start (&self) -> Nanos { |
120 | - duration_to_nanos(self.start_instant.elapsed()) | |
141 … | + duration_to_nanos(self.start.elapsed()) | |
121 | 142 … | } |
122 | 143 … | |
123 | 144 … | pub fn nanos_since_tick (&self) -> Nanos { |
124 | - duration_to_nanos(self.tick_instant.elapsed()) | |
145 … | + duration_to_nanos(self.tick.elapsed()) | |
125 | 146 … | } |
126 | 147 … | |
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 | - | |
139 | 148 … | // https://github.com/BookOwl/fps_clock/blob/master/src/lib.rs |
140 | 149 … | pub fn tick (&mut self) -> ClockTime { |
141 | 150 … | let diff = self.diff(); |
142 | 151 … | |
@@ -144,9 +153,9 @@ | ||
144 | 153 … | sleep(Duration::new(0, diff.nanos as u32)) |
145 | 154 … | }; |
146 | 155 … | |
147 | 156 … | |
148 | - self.tick_instant = Instant::now(); | |
157 … | + self.tick = Time::now(); | |
149 | 158 … | |
150 | 159 … | diff |
151 | 160 … | } |
152 | 161 … | } |
src/control.rs | ||
---|---|---|
@@ -21,8 +21,9 @@ | ||
21 | 21 … | |
22 | 22 … | |
23 | 23 … | pub enum ControlMessage { |
24 | 24 … | Time(clock::ClockTime), |
25 … | + Signature(clock::ClockSignature), | |
25 | 26 … | Start, |
26 | 27 … | Stop, |
27 | 28 … | TapTempo, |
28 | 29 … | SetTempo, |
src/main.rs | ||
---|---|---|
@@ -1,125 +1,40 @@ | ||
1 | 1 … | extern crate ncurses; |
2 | 2 … | |
3 | -use ncurses::{WchResult}; | |
4 | -use std::char; | |
5 | -use std::sync::mpsc::{channel, Sender, Receiver}; | |
6 | -use std::thread::{sleep, spawn}; | |
7 | -use std::time::{Duration}; | |
8 | - | |
9 | 3 … | mod clock; |
10 | 4 … | mod control; |
5 … | +mod interface; | |
11 | 6 … | |
12 | -// https://unicode.org/charts/PDF/U0000.pdf | |
13 | -static CHAR_SPACE: u32 = 0x0020; | |
14 | -static CHAR_RETURN: u32 = 0x000D; | |
15 | -static CHAR_NEWLINE: u32 = 0x000A; | |
16 | - | |
17 | 7 … | fn main () { |
18 | - let control = control::Control::new(); | |
8 … | + Metronome::run(60_f64); | |
9 … | +} | |
19 | 10 … | |
20 | - let clock_signature = clock::ClockSignature::new(60_f64); | |
21 | - let mut clock = clock::Clock::new(clock_signature, &control); | |
22 | 11 … | |
23 | - clock.start(); | |
12 … | +pub type Bpm = f64; | |
24 | 13 … | |
25 | - let terminal_interface = TerminalInterface::new(&control); | |
26 | - | |
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 | - } | |
35 | - } | |
14 … | +struct Metronome { | |
15 … | + pub bpm: Bpm | |
36 | 16 … | } |
37 | 17 … | |
38 | - | |
39 | -pub struct TerminalInterface { | |
40 | - control_tx: Sender<control::ControlMessage>, | |
41 | - tx: Sender<InterfaceMessage>, | |
42 | - rx: Receiver<InterfaceMessage> | |
43 | -} | |
18 … | +impl Metronome { | |
19 … | + pub fn run (bpm: Bpm) { | |
20 … | + let control = control::Control::new(); | |
44 | 21 … | |
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 | - } | |
22 … | + let clock_signature = clock::ClockSignature::new(bpm); | |
55 | 23 … | |
56 | - pub fn start (&self) { | |
57 | - let control_tx = self.control_tx.clone(); | |
24 … | + let clock = clock::Clock::start(clock_signature, control.tx.clone()); | |
25 … | + let terminal_interface = interface::TerminalInterface::start(clock_signature, control.tx.clone()); | |
58 | 26 … | |
59 | - spawn(move|| { | |
60 | - /* Setup ncurses. */ | |
61 | - ncurses::initscr(); | |
62 | - | |
63 | - let locale_conf = ncurses::LcCategory::all; | |
64 | - ncurses::setlocale(locale_conf, "en_US.UTF-8"); | |
65 | - | |
66 | - /* Enable mouse events. */ | |
67 | - ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None); | |
68 | - | |
69 | - /* Allow for extended keyboard (like F1). */ | |
70 | - ncurses::keypad(ncurses::stdscr(), true); | |
71 | - ncurses::noecho(); | |
72 | - | |
73 | - loop { | |
74 | - let ch = ncurses::wget_wch(ncurses::stdscr()); | |
75 | - | |
76 | - match ch { | |
77 | - Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => { | |
78 | - control_tx.send(control::ControlMessage::TapTempo).unwrap(); | |
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 => {} | |
92 | - } | |
93 | - | |
94 | - ncurses::refresh(); | |
27 … | + for control_message in control.rx { | |
28 … | + match control_message { | |
29 … | + control::ControlMessage::Signature(signature) => { | |
30 … | + terminal_interface.tx.send(interface::InterfaceMessage::Signature(signature)).unwrap(); | |
31 … | + }, | |
32 … | + control::ControlMessage::Time(time) => { | |
33 … | + terminal_interface.tx.send(interface::InterfaceMessage::Time(time)).unwrap(); | |
34 … | + }, | |
35 … | + _ => {} | |
95 | 36 … | } |
96 | - | |
97 | - ncurses::endwin(); | |
98 | - }); | |
99 | - | |
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 | - }); | |
37 … | + } | |
110 | 38 … | } |
111 | 39 … | } |
112 | 40 … | |
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()); | |
120 | -} | |
121 | - | |
122 | - | |
123 | -pub enum InterfaceMessage { | |
124 | - Time(clock::ClockTime) | |
125 | -} |
src/interface.rs | ||
---|---|---|
@@ -1,0 +1,114 @@ | ||
1 … | +extern crate ncurses; | |
2 … | + | |
3 … | +use ncurses::{WchResult}; | |
4 … | +use std::sync::mpsc::{channel, Sender, Receiver}; | |
5 … | +use std::thread::{sleep, spawn}; | |
6 … | + | |
7 … | +use clock; | |
8 … | +use control; | |
9 … | + | |
10 … | +// https://unicode.org/charts/PDF/U0000.pdf | |
11 … | +static CHAR_SPACE: u32 = 0x0020; | |
12 … | +static CHAR_RETURN: u32 = 0x000D; | |
13 … | +static CHAR_NEWLINE: u32 = 0x000A; | |
14 … | + | |
15 … | + | |
16 … | +pub struct TerminalInterface { | |
17 … | + pub tx: Sender<InterfaceMessage> | |
18 … | +} | |
19 … | + | |
20 … | +impl TerminalInterface { | |
21 … | + pub fn start (signature: clock::ClockSignature, control_tx: Sender<control::ControlMessage>) -> Self { | |
22 … | + let (tx, rx) = channel(); | |
23 … | + | |
24 … | + let interface = Self { | |
25 … | + tx | |
26 … | + }; | |
27 … | + | |
28 … | + spawn(move|| { | |
29 … | + /* Setup ncurses. */ | |
30 … | + ncurses::initscr(); | |
31 … | + | |
32 … | + let locale_conf = ncurses::LcCategory::all; | |
33 … | + ncurses::setlocale(locale_conf, "en_US.UTF-8"); | |
34 … | + | |
35 … | + /* Enable mouse events. */ | |
36 … | + ncurses::mousemask(ncurses::ALL_MOUSE_EVENTS as ncurses::mmask_t, None); | |
37 … | + | |
38 … | + /* Allow for extended keyboard (like F1). */ | |
39 … | + ncurses::keypad(ncurses::stdscr(), true); | |
40 … | + ncurses::noecho(); | |
41 … | + | |
42 … | + loop { | |
43 … | + let ch = ncurses::wget_wch(ncurses::stdscr()); | |
44 … | + | |
45 … | + match ch { | |
46 … | + Some(WchResult::KeyCode(ncurses::KEY_MOUSE)) => { | |
47 … | + control_tx.send(control::ControlMessage::TapTempo).unwrap(); | |
48 … | + } | |
49 … | + | |
50 … | + // https://github.com/jeaye/ncurses-rs/blob/master/src/constants.rs | |
51 … | + Some(WchResult::KeyCode(_)) => {} | |
52 … | + | |
53 … | + // Some(WchResult::KeyCode(KEY_ENTER)) => beat(), | |
54 … | + Some(WchResult::Char(ch)) => { | |
55 … | + if (ch == CHAR_SPACE || ch == CHAR_NEWLINE) { | |
56 … | + control_tx.send(control::ControlMessage::TapTempo).unwrap(); | |
57 … | + } | |
58 … | + } | |
59 … | + | |
60 … | + None => {} | |
61 … | + } | |
62 … | + | |
63 … | + ncurses::refresh(); | |
64 … | + } | |
65 … | + | |
66 … | + ncurses::endwin(); | |
67 … | + }); | |
68 … | + | |
69 … | + spawn(move|| { | |
70 … | + for interface_message in rx { | |
71 … | + match interface_message { | |
72 … | + InterfaceMessage::Time(time) => { | |
73 … | + ncurses::clear(); | |
74 … | + ncurses::mv(0, 0); | |
75 … | + print_time(time); | |
76 … | + print_signature(signature); | |
77 … | + } | |
78 … | + InterfaceMessage::Signature(signature) => { | |
79 … | + } | |
80 … | + } | |
81 … | + | |
82 … | + ncurses::refresh(); | |
83 … | + } | |
84 … | + }); | |
85 … | + | |
86 … | + interface | |
87 … | + } | |
88 … | +} | |
89 … | + | |
90 … | +pub fn print_time (time: clock::ClockTime) { | |
91 … | + ncurses::printw("nanos: "); | |
92 … | + ncurses::printw(format!("{}\n", time.nanos).as_ref()); | |
93 … | + ncurses::printw("ticks: "); | |
94 … | + ncurses::printw(format!("{}\n", time.ticks).as_ref()); | |
95 … | + ncurses::printw("beats: "); | |
96 … | + ncurses::printw(format!("{}\n", time.beats).as_ref()); | |
97 … | + ncurses::printw("bars: "); | |
98 … | + ncurses::printw(format!("{}\n", time.bars).as_ref()); | |
99 … | +} | |
100 … | + | |
101 … | +pub fn print_signature (signature: clock::ClockSignature) { | |
102 … | + ncurses::printw("beats per minute: "); | |
103 … | + ncurses::printw(format!("{}\n", signature.to_beats_per_minute()).as_ref()); | |
104 … | + ncurses::printw("ticks per beat: "); | |
105 … | + ncurses::printw(format!("{}\n", signature.ticks_per_beat).as_ref()); | |
106 … | + ncurses::printw("beats per bar: "); | |
107 … | + ncurses::printw(format!("{}\n", signature.beats_per_bar).as_ref()); | |
108 … | +} | |
109 … | + | |
110 … | + | |
111 … | +pub enum InterfaceMessage { | |
112 … | + Time(clock::ClockTime), | |
113 … | + Signature(clock::ClockSignature), | |
114 … | +} |
Built with git-ssb-web