beep_evdev/lib.rs
1use evdev::{Device, EventType, InputEvent, SoundType};
2use std::thread::sleep;
3use std::time::Duration;
4
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8pub const DEFAULT_DELAY: Duration = Duration::from_millis(100);
9pub const DEFAULT_FREQ: u16 = 440;
10pub const DEFAULT_LEN: Duration = Duration::from_millis(200);
11pub const DEFAULT_REPEATS: u16 = 1;
12const FILE: &str = "/dev/input/by-path/platform-pcspkr-event-spkr";
13
14/// A sequence of notes
15#[derive(Clone, Debug, Eq, PartialEq)]
16#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
17pub struct Melody(Vec<Note>);
18
19impl Melody {
20 #[must_use]
21 pub fn new(notes: Vec<Note>) -> Self {
22 Self(notes)
23 }
24
25 /// Plays the melody
26 ///
27 /// # Examples
28 /// ```
29 /// use beep_evdev::Melody;
30 ///
31 /// let melody: Melody = vec![
32 /// (659, 120).into(),
33 /// (622, 120).into(),
34 /// (659, 120).into(),
35 /// (622, 120).into(),
36 /// (659, 120).into(),
37 /// (94, 120).into(),
38 /// (587, 120).into(),
39 /// (523, 120).into(),
40 /// (440, 120).into(),
41 /// (262, 120).into(),
42 /// (330, 120).into(),
43 /// (440, 120).into(),
44 /// (494, 120).into(),
45 /// (330, 120).into(),
46 /// (415, 120).into(),
47 /// (494, 120).into(),
48 /// (523, 120).into(),
49 /// (330, 120).into(),
50 /// (659, 120).into(),
51 /// (622, 120).into(),
52 /// (659, 120).into(),
53 /// (622, 120).into(),
54 /// (659, 120).into(),
55 /// (494, 120).into(),
56 /// (587, 120).into(),
57 /// (523, 120).into(),
58 /// (440, 120).into(),
59 /// (262, 120).into(),
60 /// (330, 120).into(),
61 /// (440, 120).into(),
62 /// (494, 120).into(),
63 /// (330, 120).into(),
64 /// (523, 120).into(),
65 /// (494, 120).into(),
66 /// (440, 120).into(),
67 /// ]
68 /// .into();
69 /// melody.play().expect("could not play melody :-(");
70 /// ```
71 ///
72 /// # Errors
73 /// Returns an [`std::io::Error`] on I/O errors
74 pub fn play(&self) -> Result<(), std::io::Error> {
75 for note in &self.0 {
76 note.play()?;
77 }
78
79 Ok(())
80 }
81}
82
83impl Default for Melody {
84 fn default() -> Self {
85 Self::new(vec![Note::default()])
86 }
87}
88
89impl From<Vec<Note>> for Melody {
90 fn from(notes: Vec<Note>) -> Self {
91 Self::new(notes)
92 }
93}
94
95impl From<&[Note]> for Melody {
96 fn from(notes: &[Note]) -> Self {
97 Self::new(Vec::from(notes))
98 }
99}
100
101/// A note of a certain frequency and duration
102/// that may be repeated with a delay
103#[derive(Clone, Debug, Eq, PartialEq)]
104#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
105pub struct Note {
106 frequency: u16,
107 length: Duration,
108 repeats: u16,
109 delay: Duration,
110}
111
112impl Note {
113 /// Creates a new note
114 /// # Attributes
115 /// * frequency - The frequency in Hertz
116 /// * length - The length of the note
117 /// * repeats - The amount of repeats
118 /// * delay - The delay before each repeat
119 #[must_use]
120 pub const fn new(frequency: u16, length: Duration, repeats: u16, delay: Duration) -> Self {
121 Self {
122 frequency,
123 length,
124 repeats,
125 delay,
126 }
127 }
128
129 /// Plays the note
130 ///
131 /// # Examples
132 /// ```
133 /// use beep_evdev::Note;
134 ///
135 /// Note::default().play().expect("could not play melody :-(");
136 /// ```
137 ///
138 /// # Errors
139 /// Returns an [`std::io::Error`] on I/O errors
140 pub fn play(&self) -> Result<(), std::io::Error> {
141 if self.repeats > 0 {
142 beep(self.frequency)?;
143 sleep(self.length);
144 beep(0)?;
145 }
146
147 for _ in 1..self.repeats {
148 sleep(self.delay);
149 beep(self.frequency)?;
150 sleep(self.length);
151 beep(0)?;
152 }
153
154 Ok(())
155 }
156}
157
158impl Default for Note {
159 fn default() -> Self {
160 Self::new(DEFAULT_FREQ, DEFAULT_LEN, DEFAULT_REPEATS, DEFAULT_DELAY)
161 }
162}
163
164impl From<(u16, u64)> for Note {
165 /// Creates a note from a `(frequency, length)` tuple with default repeats and delay
166 fn from((frequency, length): (u16, u64)) -> Self {
167 Self::from((frequency, Duration::from_millis(length)))
168 }
169}
170
171impl From<(u16, Duration)> for Note {
172 /// Creates a note from a `(frequency, length)` tuple with default repeats and delay
173 fn from((frequency, length): (u16, Duration)) -> Self {
174 Self::new(frequency, length, DEFAULT_REPEATS, DEFAULT_DELAY)
175 }
176}
177
178/// Beeps the PC speaker at the given frequency
179///
180/// # Examples
181/// ```
182/// use beep_evdev::beep;
183/// use std::{thread, time};
184///
185/// beep(440).expect("could not beep");
186/// thread::sleep(time::Duration::from_millis(500));
187/// beep(880).expect("could not beep");
188/// thread::sleep(time::Duration::from_millis(500));
189/// beep(0).expect("could not beep");
190/// ```
191///
192/// # Errors
193/// Returns [`std::io::Error`] on I/O errors
194pub fn beep(hertz: u16) -> std::io::Result<()> {
195 Device::open(FILE)?.send_events(&[InputEvent::new(
196 EventType::SOUND,
197 SoundType::SND_TONE.0,
198 i32::from(hertz),
199 )])
200}