1use std::env;
2
3use boppo_core::color;
4use boppo_websocket::{
5 Button, ButtonEvent, ButtonEvents,
6 audio::{SoundBuilder, play, play_with_controller, stop_all_sounds},
7 commands::execute_command,
8 connect_and_setup_globals,
9};
10
11#[tokio::main]
12async fn main() {
13 if env::args().len() != 3 {
14 panic!("usage: features <hostname> <password>");
15 }
16 let url = env::args().nth(1).unwrap();
17 let password = env::args().nth(2).unwrap();
18 println!("Connecting to {url:?} ...");
19 connect_and_setup_globals(&url, &password)
20 .await
21 .expect("failed to connect");
22 println!("Connected!");
23
24 const FLASH_BUTTON: Button = Button::B0;
25 const PRESS_LIGHT_BUTTON: Button = Button::B1;
26 const SFX_SIMPLE_BUTTON: Button = Button::B5;
27 const SFX_WAIT_BUTTON: Button = Button::B6;
28 const SFX_ERROR_BUTTON: Button = Button::B7;
29 const STOP_ALL_SOUNDS_BUTTON: Button = Button::B8;
30 const SLEEP_BUTTON: Button = Button::B9;
31
32 const PAUSE_BUTTON: Button = Button::B2;
33 const SPEED_CHANGE_BUTTON: Button = Button::B3;
34 const VOLUME_CHANGE_BUTTON: Button = Button::B4;
35
36 SFX_SIMPLE_BUTTON.set_color(color::ORANGE);
37 SFX_WAIT_BUTTON.set_color(color::ORANGE);
38 SFX_ERROR_BUTTON.set_color(color::RED);
39 PAUSE_BUTTON.set_color(color::GREEN);
40 SPEED_CHANGE_BUTTON.set_color(color::PURPLE);
41 VOLUME_CHANGE_BUTTON.set_color(color::YELLOW);
42 STOP_ALL_SOUNDS_BUTTON.set_color(color::WHITE);
43 SLEEP_BUTTON.set_color(color::GREY);
44
45 tokio::spawn(async move {
46 let mut button_events = ButtonEvents::subscribe();
47 let music_controller =
48 play_with_controller(SoundBuilder::file("music/Being_Me.mp3").repeat_forever())
49 .await
50 .unwrap();
51
52 music_controller.set_paused(true);
53
54 let mut paused = true;
55 let mut volume = 1.0;
56 let mut speed = 1.0;
57
58 loop {
59 let event = button_events.next().await;
60 print_event(event);
61 let button = event.button();
62 if event.is_released() && button != PRESS_LIGHT_BUTTON {
63 continue;
64 }
65 match button {
66 PRESS_LIGHT_BUTTON => {
67 let color = if event.is_pressed() {
68 color::RED
69 } else {
70 color::OFF
71 };
72 PRESS_LIGHT_BUTTON.set_color(color);
73 }
74 SFX_SIMPLE_BUTTON => {
75 play("/effects/success.qoa").await.ok();
76 }
77 SFX_ERROR_BUTTON => {
78 play("/effects/MISSING_SOUND_FOR_ERROR.qoa").await.ok();
79 }
80 SFX_WAIT_BUTTON => {
81 let controller = play_with_controller("music/add_music_instructions.mp3")
82 .await
83 .unwrap();
84 SFX_WAIT_BUTTON.set_color(color::BLUE);
85 tokio::spawn(async move {
86 controller.wait_until_finished().await;
87 SFX_WAIT_BUTTON.set_color(color::ORANGE);
88 });
89 }
90 PAUSE_BUTTON => {
91 paused = !paused;
92 let color = if paused { color::GREEN } else { color::RED };
93 PAUSE_BUTTON.set_color(color);
94 music_controller.set_paused(paused);
95 }
96 VOLUME_CHANGE_BUTTON => {
97 volume = match volume {
98 1.0 => 0.5,
99 _ => 1.0,
100 };
101 music_controller.set_volume(volume);
102 }
103 SPEED_CHANGE_BUTTON => {
104 speed = match speed {
105 1.0 => 2.0,
106 2.0 => 0.5,
107 _ => 1.0,
108 };
109 music_controller.set_speed(speed);
110 }
111 STOP_ALL_SOUNDS_BUTTON => {
112 stop_all_sounds().await.ok();
113 }
114 SLEEP_BUTTON => {
115 execute_command("sleep").await.ok();
116 }
117 _ => {}
118 }
119 }
120 });
121
122 loop {
123 FLASH_BUTTON.set_color(color::RED);
124 tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
125 FLASH_BUTTON.set_color(color::OFF);
126 tokio::time::sleep(tokio::time::Duration::from_millis(500)).await;
127 }
128}
129
130fn print_event(event: ButtonEvent) {
131 let action = if event.is_pressed() {
132 "pressed"
133 } else {
134 "released"
135 };
136 println!("tablet event: button {} {action}", event.button().index());
137}