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