1use clap::{Parser, Subcommand};
2use ratatui::style::Color;
3
4use crate::music::Note;
5
6const HELP_TEMPLATE: &str = "{before-help}\
8{name} {version} -- by {author}
9{about}
10
11{usage-heading} {usage}
12
13{all-args}{after-help}
14";
15
16#[derive(Parser, Debug)]
18#[command(author, version, about, long_about = None, help_template = HELP_TEMPLATE)]
19pub struct ScopeArgs {
20 #[clap(subcommand)]
21 pub source: ScopeSource,
22
23 #[command(flatten)]
24 pub opts: SourceOptions,
25
26 #[command(flatten)]
27 pub ui: UiOptions,
28}
29
30#[derive(Debug, Clone, Parser)]
31pub struct UiOptions {
32 #[arg(short, long, value_name = "x", default_value_t = 1.0)]
34 pub scale: f32,
35
36 #[arg(long, default_value_t = false)]
38 pub scatter: bool,
39
40 #[arg(long, default_value_t = false)]
42 pub no_reference: bool,
43
44 #[arg(long, default_value_t = false)]
46 pub no_ui: bool,
47
48 #[arg(long, default_value_t = false)]
50 pub no_braille: bool,
51
52 #[arg(long, value_name = "color1,color2", value_delimiter = ',', default_value = "red,yellow,cyan,magenta")]
54 pub palette_color: Vec<Color>,
55
56 #[arg(long, value_name = "color", default_value_t = Color::Cyan)]
58 pub labels_color: Color,
59
60 #[arg(long, value_name = "color", default_value_t = Color::DarkGray)]
62 pub axis_color: Color,
63}
64
65#[derive(Debug, Clone, Subcommand)]
66pub enum ScopeSource {
67 #[cfg(feature = "pulseaudio")]
68 Pulse {
70 device: Option<String>,
72
73 #[arg(long, value_name = "N", default_value_t = 32)]
75 server_buffer: u32,
76 },
77
78 #[cfg(feature = "file")]
79 File {
81 path: String,
83
84 #[arg(short, long, default_value_t = false)]
86 limit_rate: bool,
87 },
88
89 #[cfg(feature = "cpal")]
90 Audio {
92 device: Option<String>,
94
95 #[arg(long, default_value_t = 5)]
97 timeout: u64,
98
99 #[arg(long, default_value_t = false)]
101 list: bool,
102 },
103}
104
105#[derive(Debug, Clone, Parser)]
106pub struct SourceOptions {
107 #[arg(short, long, value_name = "N", default_value_t = 2)]
109 pub channels: usize,
110
111 #[arg(short, long, value_name = "SIZE", default_value_t = 2048)]
113 pub buffer: u32,
114
115 #[arg(short = 'r', long, value_name = "HZ", default_value_t = 48000)]
117 pub sample_rate: u32,
118
119 #[arg(short, long, value_name = "NOTE")]
121 pub tune: Option<String>,
122}
123
124impl SourceOptions {
126 pub fn tune(&mut self) {
127 if let Some(txt) = &self.tune {
128 if let Ok(note) = txt.parse::<Note>() {
130 self.buffer = note.tune_buffer_size(self.sample_rate);
131 while self.buffer.is_multiple_of(self.channels as u32 * 2) {
132 self.buffer += 1; }
135 } else {
136 eprintln!("[!] Unrecognized note '{}', ignoring option", txt);
137 }
138 }
139 }
140}