1pub mod messages;
4
5use std::time::Duration;
6
7use num_derive::{FromPrimitive, ToPrimitive};
8use num_traits::{FromPrimitive, ToPrimitive};
9use server::{AsScalar, CheckedConn, CheckedPermissions, FromScalar, MessageAllowed};
10
11use crate::messages::*;
12
13#[macro_export]
14macro_rules! use_api {
15 () => {
16 mod haptics_permissions {
17 use haptics::messages::*;
18 #[derive(Clone, Default, server::Permissions)]
19 #[server_name = "os/haptics"]
20 pub struct HapticsPermissions;
21 }
22 type HapticsApi = haptics::HapticsApi<haptics_permissions::HapticsPermissions>;
23 };
24}
25
26#[derive(Debug, Copy, Clone, ToPrimitive, FromPrimitive)]
27pub enum HapticPattern {
28 Click,
29 StrongClick,
30 DoubleClick,
31 StrongClick100,
32 StrongClick60,
33 StrongClick30,
34 SharpClick100,
35 SharpClick60,
36 SharpClick30,
37 SoftBump100,
38 SoftBump60,
39 SoftBump30,
40 DoubleClick100,
41 DoubleClick60,
42 TripleClick100,
43 SoftFuzz60,
44 StrongBuzz100,
45 Alert750ms,
46 Alert1000ms,
47 StrongClickOne100,
48 StrongClickTwo80,
49 StrongClickThree60,
50 StrongClickFour30,
51 MediumClickOne100,
52 MediumClickTwo80,
53 MediumClickThree60,
54 SharpTickOne100,
55 SharpTickTwo80,
56 SharpTickThree60,
57 ShortDoubleClickStrongOne100,
58 ShortDoubleClickStrongTwo80,
59 ShortDoubleClickStrongThree60,
60 ShortDoubleClickStrongFour30,
61 ShortDoubleClickMediumOne100,
62 ShortDoubleClickMediumTwo80,
63 ShortDoubleClickMediumThree60,
64 ShortDoubleSharpTickOne100,
65 ShortDoubleSharpTickTwo80,
66 ShortDoubleSharpTickThree60,
67 LongDoubleSharpClickStrongOne100,
68 LongDoubleSharpClickStrongTwo80,
69 LongDoubleSharpClickStrongThree60,
70 LongDoubleSharpClickStrongFour30,
71 LongDoubleSharpClickMediumOne100,
72 LongDoubleSharpClickMediumTwo80,
73 LongDoubleSharpClickMediumThree60,
74 LongDoubleSharpTickOne100,
75 LongDoubleSharpTickTwo80,
76 LongDoubleSharpTickThree60,
77 BuzzOne100,
78 BuzzTwo80,
79 BuzzThree60,
80 BuzzFour40,
81 BuzzFive20,
82 PulsingStrongOne100,
83 PulsingStrongTwo60,
84 PulsingMediumOne100,
85 PulsingMediumTwo60,
86 PulsingSharpOne100,
87 PulsingSharpTwo60,
88 TransitionClickOne100,
89 TransitionClickTwo80,
90 TransitionClickThree60,
91 TransitionClickFour40,
92 TransitionClickFive20,
93 TransitionClickSix10,
94 TransitionHumOne100,
95 TransitionHumTwo80,
96 TransitionHumThree60,
97 TransitionHumFour40,
98 TransitionHumFive20,
99 TransitionHumSix10,
100 TransitionRampDownLongSmoothOne100to0,
101 TransitionRampDownLongSmoothTwo100to0,
102 TransitionRampDownMediumSmoothOne100to0,
103 TransitionRampDownMediumSmoothTwo100to0,
104 TransitionRampDownShortSmoothOne100to0,
105 TransitionRampDownShortSmoothTwo100to0,
106 TransitionRampDownLongSharpOne100to0,
107 TransitionRampDownLongSharpTwo100to0,
108 TransitionRampDownMediumSharpOne100to0,
109 TransitionRampDownMediumSharpTwo100to0,
110 TransitionRampDownShortSharpOne100to0,
111 TransitionRampDownShortSharpTwo100to0,
112 TransitionRampUpLongSmoothOne0to100,
113 TransitionRampUpLongSmoothTwo0to100,
114 TransitionRampUpMediumSmoothOne0to100,
115 TransitionRampUpMediumSmoothTwo0to100,
116 TransitionRampUpShortSmoothOne0to100,
117 TransitionRampUpShortSmoothTwo0to100,
118 TransitionRampUpLongSharpOne0to100,
119 TransitionRampUpLongSharpTwo0to100,
120 TransitionRampUpMediumSharpOne0to100,
121 TransitionRampUpMediumSharpTwo0to100,
122 TransitionRampUpShortSharpOne0to100,
123 TransitionRampUpShortSharpTwo0to100,
124 TransitionRampDownLongSmoothOne50to0,
125 TransitionRampDownLongSmoothTwo50to0,
126 TransitionRampDownMediumSmoothOne50to0,
127 TransitionRampDownMediumSmoothTwo50to0,
128 TransitionRampDownShortSmoothOne50to0,
129 TransitionRampDownShortSmoothTwo50to0,
130 TransitionRampDownLongSharpOne50to0,
131 TransitionRampDownLongSharpTwo50to0,
132 TransitionRampDownMediumSharpOne50to0,
133 TransitionRampDownMediumSharpTwo50to0,
134 TransitionRampDownShortSharpOne50to0,
135 TransitionRampDownShortSharpTwo50to0,
136 TransitionRampUpLongSmoothOne0to50,
137 TransitionRampUpLongSmoothTwo0to50,
138 TransitionRampUpMediumSmoothOne0to50,
139 TransitionRampUpMediumSmoothTwo0to50,
140 TransitionRampUpShortSmoothOne0to50,
141 TransitionRampUpShortSmoothTwo0to50,
142 TransitionRampUpLongSharpOne0to50,
143 TransitionRampUpLongSharpTwo0to50,
144 TransitionRampUpMediumSharpOne0to50,
145 TransitionRampUpMediumSharpTwo0to50,
146 TransitionRampUpShortSharpOne0to50,
147 TransitionRampUpShortSharpTwo0to50,
148 LongBuzzForProgrammaticStopping100,
149 SmoothHumOne50,
150 SmoothHumTwo40,
151 SmoothHumThree30,
152 SmoothHumFour20,
153 SmoothHumFive10,
154}
155
156impl HapticPattern {
157 pub fn from_string(s: &str) -> Option<HapticPattern> {
158 match s {
159 "Click" => Some(HapticPattern::Click),
160 "StrongClick" => Some(HapticPattern::StrongClick),
161 "DoubleClick" => Some(HapticPattern::DoubleClick),
162 "StrongClick100" => Some(HapticPattern::StrongClick100),
163 "StrongClick60" => Some(HapticPattern::StrongClick60),
164 "StrongClick30" => Some(HapticPattern::StrongClick30),
165 "SharpClick100" => Some(HapticPattern::SharpClick100),
166 "SharpClick60" => Some(HapticPattern::SharpClick60),
167 "SharpClick30" => Some(HapticPattern::SharpClick30),
168 "SoftBump100" => Some(HapticPattern::SoftBump100),
169 "SoftBump60" => Some(HapticPattern::SoftBump60),
170 "SoftBump30" => Some(HapticPattern::SoftBump30),
171 "DoubleClick100" => Some(HapticPattern::DoubleClick100),
172 "DoubleClick60" => Some(HapticPattern::DoubleClick60),
173 "TripleClick100" => Some(HapticPattern::TripleClick100),
174 "SoftFuzz60" => Some(HapticPattern::SoftFuzz60),
175 "StrongBuzz100" => Some(HapticPattern::StrongBuzz100),
176 "Alert750ms" => Some(HapticPattern::Alert750ms),
177 "Alert1000ms" => Some(HapticPattern::Alert1000ms),
178 "StrongClickOne100" => Some(HapticPattern::StrongClickOne100),
179 "StrongClickTwo80" => Some(HapticPattern::StrongClickTwo80),
180 "StrongClickThree60" => Some(HapticPattern::StrongClickThree60),
181 "StrongClickFour30" => Some(HapticPattern::StrongClickFour30),
182 "MediumClickOne100" => Some(HapticPattern::MediumClickOne100),
183 "MediumClickTwo80" => Some(HapticPattern::MediumClickTwo80),
184 "MediumClickThree60" => Some(HapticPattern::MediumClickThree60),
185 "SharpTickOne100" => Some(HapticPattern::SharpTickOne100),
186 "SharpTickTwo80" => Some(HapticPattern::SharpTickTwo80),
187 "SharpTickThree60" => Some(HapticPattern::SharpTickThree60),
188 "ShortDoubleClickStrongOne100" => Some(HapticPattern::ShortDoubleClickStrongOne100),
189 "ShortDoubleClickStrongTwo80" => Some(HapticPattern::ShortDoubleClickStrongTwo80),
190 "ShortDoubleClickStrongThree60" => Some(HapticPattern::ShortDoubleClickStrongThree60),
191 "ShortDoubleClickStrongFour30" => Some(HapticPattern::ShortDoubleClickStrongFour30),
192 "ShortDoubleClickMediumOne100" => Some(HapticPattern::ShortDoubleClickMediumOne100),
193 "ShortDoubleClickMediumTwo80" => Some(HapticPattern::ShortDoubleClickMediumTwo80),
194 "ShortDoubleClickMediumThree60" => Some(HapticPattern::ShortDoubleClickMediumThree60),
195 "ShortDoubleSharpTickOne100" => Some(HapticPattern::ShortDoubleSharpTickOne100),
196 "ShortDoubleSharpTickTwo80" => Some(HapticPattern::ShortDoubleSharpTickTwo80),
197 "ShortDoubleSharpTickThree60" => Some(HapticPattern::ShortDoubleSharpTickThree60),
198 "LongDoubleSharpClickStrongOne100" => Some(HapticPattern::LongDoubleSharpClickStrongOne100),
199 "LongDoubleSharpClickStrongTwo80" => Some(HapticPattern::LongDoubleSharpClickStrongTwo80),
200 "LongDoubleSharpClickStrongThree60" => Some(HapticPattern::LongDoubleSharpClickStrongThree60),
201 "LongDoubleSharpClickStrongFour30" => Some(HapticPattern::LongDoubleSharpClickStrongFour30),
202 "LongDoubleSharpClickMediumOne100" => Some(HapticPattern::LongDoubleSharpClickMediumOne100),
203 "LongDoubleSharpClickMediumTwo80" => Some(HapticPattern::LongDoubleSharpClickMediumTwo80),
204 "LongDoubleSharpClickMediumThree60" => Some(HapticPattern::LongDoubleSharpClickMediumThree60),
205 "LongDoubleSharpTickOne100" => Some(HapticPattern::LongDoubleSharpTickOne100),
206 "LongDoubleSharpTickTwo80" => Some(HapticPattern::LongDoubleSharpTickTwo80),
207 "LongDoubleSharpTickThree60" => Some(HapticPattern::LongDoubleSharpTickThree60),
208 "BuzzOne100" => Some(HapticPattern::BuzzOne100),
209 "BuzzTwo80" => Some(HapticPattern::BuzzTwo80),
210 "BuzzThree60" => Some(HapticPattern::BuzzThree60),
211 "BuzzFour40" => Some(HapticPattern::BuzzFour40),
212 "BuzzFive20" => Some(HapticPattern::BuzzFive20),
213 "PulsingStrongOne100" => Some(HapticPattern::PulsingStrongOne100),
214 "PulsingStrongTwo60" => Some(HapticPattern::PulsingStrongTwo60),
215 "PulsingMediumOne100" => Some(HapticPattern::PulsingMediumOne100),
216 "PulsingMediumTwo60" => Some(HapticPattern::PulsingMediumTwo60),
217 "PulsingSharpOne100" => Some(HapticPattern::PulsingSharpOne100),
218 "PulsingSharpTwo60" => Some(HapticPattern::PulsingSharpTwo60),
219 "TransitionClickOne100" => Some(HapticPattern::TransitionClickOne100),
220 "TransitionClickTwo80" => Some(HapticPattern::TransitionClickTwo80),
221 "TransitionClickThree60" => Some(HapticPattern::TransitionClickThree60),
222 "TransitionClickFour40" => Some(HapticPattern::TransitionClickFour40),
223 "TransitionClickFive20" => Some(HapticPattern::TransitionClickFive20),
224 "TransitionClickSix10" => Some(HapticPattern::TransitionClickSix10),
225 "TransitionHumOne100" => Some(HapticPattern::TransitionHumOne100),
226 "TransitionHumTwo80" => Some(HapticPattern::TransitionHumTwo80),
227 "TransitionHumThree60" => Some(HapticPattern::TransitionHumThree60),
228 "TransitionHumFour40" => Some(HapticPattern::TransitionHumFour40),
229 "TransitionHumFive20" => Some(HapticPattern::TransitionHumFive20),
230 "TransitionHumSix10" => Some(HapticPattern::TransitionHumSix10),
231 "TransitionRampDownLongSmoothOne100to0" => {
232 Some(HapticPattern::TransitionRampDownLongSmoothOne100to0)
233 }
234 "TransitionRampDownLongSmoothTwo100to0" => {
235 Some(HapticPattern::TransitionRampDownLongSmoothTwo100to0)
236 }
237 "TransitionRampDownMediumSmoothOne100to0" => {
238 Some(HapticPattern::TransitionRampDownMediumSmoothOne100to0)
239 }
240 "TransitionRampDownMediumSmoothTwo100to0" => {
241 Some(HapticPattern::TransitionRampDownMediumSmoothTwo100to0)
242 }
243 "TransitionRampDownShortSmoothOne100to0" => {
244 Some(HapticPattern::TransitionRampDownShortSmoothOne100to0)
245 }
246 "TransitionRampDownShortSmoothTwo100to0" => {
247 Some(HapticPattern::TransitionRampDownShortSmoothTwo100to0)
248 }
249 "TransitionRampDownLongSharpOne100to0" => {
250 Some(HapticPattern::TransitionRampDownLongSharpOne100to0)
251 }
252 "TransitionRampDownLongSharpTwo100to0" => {
253 Some(HapticPattern::TransitionRampDownLongSharpTwo100to0)
254 }
255 "TransitionRampDownMediumSharpOne100to0" => {
256 Some(HapticPattern::TransitionRampDownMediumSharpOne100to0)
257 }
258 "TransitionRampDownMediumSharpTwo100to0" => {
259 Some(HapticPattern::TransitionRampDownMediumSharpTwo100to0)
260 }
261 "TransitionRampDownShortSharpOne100to0" => {
262 Some(HapticPattern::TransitionRampDownShortSharpOne100to0)
263 }
264 "TransitionRampDownShortSharpTwo100to0" => {
265 Some(HapticPattern::TransitionRampDownShortSharpTwo100to0)
266 }
267 "TransitionRampUpLongSmoothOne0to100" => Some(HapticPattern::TransitionRampUpLongSmoothOne0to100),
268 "TransitionRampUpLongSmoothTwo0to100" => Some(HapticPattern::TransitionRampUpLongSmoothTwo0to100),
269 "TransitionRampUpMediumSmoothOne0to100" => {
270 Some(HapticPattern::TransitionRampUpMediumSmoothOne0to100)
271 }
272 "TransitionRampUpMediumSmoothTwo0to100" => {
273 Some(HapticPattern::TransitionRampUpMediumSmoothTwo0to100)
274 }
275 "TransitionRampUpShortSmoothOne0to100" => {
276 Some(HapticPattern::TransitionRampUpShortSmoothOne0to100)
277 }
278 "TransitionRampUpShortSmoothTwo0to100" => {
279 Some(HapticPattern::TransitionRampUpShortSmoothTwo0to100)
280 }
281 "TransitionRampUpLongSharpOne0to100" => Some(HapticPattern::TransitionRampUpLongSharpOne0to100),
282 "TransitionRampUpLongSharpTwo0to100" => Some(HapticPattern::TransitionRampUpLongSharpTwo0to100),
283 "TransitionRampUpMediumSharpOne0to100" => {
284 Some(HapticPattern::TransitionRampUpMediumSharpOne0to100)
285 }
286 "TransitionRampUpMediumSharpTwo0to100" => {
287 Some(HapticPattern::TransitionRampUpMediumSharpTwo0to100)
288 }
289 "TransitionRampUpShortSharpOne0to100" => Some(HapticPattern::TransitionRampUpShortSharpOne0to100),
290 "TransitionRampUpShortSharpTwo0to100" => Some(HapticPattern::TransitionRampUpShortSharpTwo0to100),
291 "TransitionRampDownLongSmoothOne50to0" => {
292 Some(HapticPattern::TransitionRampDownLongSmoothOne50to0)
293 }
294 "TransitionRampDownLongSmoothTwo50to0" => {
295 Some(HapticPattern::TransitionRampDownLongSmoothTwo50to0)
296 }
297 "TransitionRampDownMediumSmoothOne50to0" => {
298 Some(HapticPattern::TransitionRampDownMediumSmoothOne50to0)
299 }
300 "TransitionRampDownMediumSmoothTwo50to0" => {
301 Some(HapticPattern::TransitionRampDownMediumSmoothTwo50to0)
302 }
303 "TransitionRampDownShortSmoothOne50to0" => {
304 Some(HapticPattern::TransitionRampDownShortSmoothOne50to0)
305 }
306 "TransitionRampDownShortSmoothTwo50to0" => {
307 Some(HapticPattern::TransitionRampDownShortSmoothTwo50to0)
308 }
309 "TransitionRampDownLongSharpOne50to0" => Some(HapticPattern::TransitionRampDownLongSharpOne50to0),
310 "TransitionRampDownLongSharpTwo50to0" => Some(HapticPattern::TransitionRampDownLongSharpTwo50to0),
311 "TransitionRampDownMediumSharpOne50to0" => {
312 Some(HapticPattern::TransitionRampDownMediumSharpOne50to0)
313 }
314 "TransitionRampDownMediumSharpTwo50to0" => {
315 Some(HapticPattern::TransitionRampDownMediumSharpTwo50to0)
316 }
317 "TransitionRampDownShortSharpOne50to0" => {
318 Some(HapticPattern::TransitionRampDownShortSharpOne50to0)
319 }
320 "TransitionRampDownShortSharpTwo50to0" => {
321 Some(HapticPattern::TransitionRampDownShortSharpTwo50to0)
322 }
323 "TransitionRampUpLongSmoothOne0to50" => Some(HapticPattern::TransitionRampUpLongSmoothOne0to50),
324 "TransitionRampUpLongSmoothTwo0to50" => Some(HapticPattern::TransitionRampUpLongSmoothTwo0to50),
325 "TransitionRampUpMediumSmoothOne0to50" => {
326 Some(HapticPattern::TransitionRampUpMediumSmoothOne0to50)
327 }
328 "TransitionRampUpMediumSmoothTwo0to50" => {
329 Some(HapticPattern::TransitionRampUpMediumSmoothTwo0to50)
330 }
331 "TransitionRampUpShortSmoothOne0to50" => Some(HapticPattern::TransitionRampUpShortSmoothOne0to50),
332 "TransitionRampUpShortSmoothTwo0to50" => Some(HapticPattern::TransitionRampUpShortSmoothTwo0to50),
333 "TransitionRampUpLongSharpOne0to50" => Some(HapticPattern::TransitionRampUpLongSharpOne0to50),
334 "TransitionRampUpLongSharpTwo0to50" => Some(HapticPattern::TransitionRampUpLongSharpTwo0to50),
335 "TransitionRampUpMediumSharpOne0to50" => Some(HapticPattern::TransitionRampUpMediumSharpOne0to50),
336 "TransitionRampUpMediumSharpTwo0to50" => Some(HapticPattern::TransitionRampUpMediumSharpTwo0to50),
337 "TransitionRampUpShortSharpOne0to50" => Some(HapticPattern::TransitionRampUpShortSharpOne0to50),
338 "TransitionRampUpShortSharpTwo0to50" => Some(HapticPattern::TransitionRampUpShortSharpTwo0to50),
339 "LongBuzzForProgrammaticStopping100" => Some(HapticPattern::LongBuzzForProgrammaticStopping100),
340 "SmoothHumOne50" => Some(HapticPattern::SmoothHumOne50),
341 "SmoothHumTwo40" => Some(HapticPattern::SmoothHumTwo40),
342 "SmoothHumThree30" => Some(HapticPattern::SmoothHumThree30),
343 "SmoothHumFour20" => Some(HapticPattern::SmoothHumFour20),
344 "SmoothHumFive10" => Some(HapticPattern::SmoothHumFive10),
345 _ => None, }
347 }
348}
349
350#[derive(Default)]
351pub struct HapticsApi<P: CheckedPermissions> {
352 conn: CheckedConn<P>,
353}
354
355impl<P: CheckedPermissions> HapticsApi<P> {
356 pub fn try_new_with_timeout(timeout: Duration) -> Option<Self> {
357 Some(Self { conn: CheckedConn::try_connect_with_timeout(timeout)? })
358 }
359
360 pub fn click(&self)
361 where
362 P: MessageAllowed<Vibrate>,
363 {
364 self.vibrate(HapticPattern::Click);
365 }
366
367 pub fn triple_click(&self)
368 where
369 P: MessageAllowed<Vibrate>,
370 {
371 self.vibrate(HapticPattern::TripleClick100);
372 }
373
374 pub fn strong_click(&self)
375 where
376 P: MessageAllowed<Vibrate>,
377 {
378 self.vibrate(HapticPattern::StrongClick);
379 }
380
381 pub fn double_click(&self)
382 where
383 P: MessageAllowed<Vibrate>,
384 {
385 self.vibrate(HapticPattern::DoubleClick);
386 }
387
388 pub fn vibrate(&self, haptic_pattern: HapticPattern)
389 where
390 P: MessageAllowed<Vibrate>,
391 {
392 self.conn.try_send_scalar(Vibrate(haptic_pattern)).ok();
393 }
394}
395
396impl AsScalar<1> for HapticPattern {
397 fn as_scalar(&self) -> [u32; 1] { [self.to_u32().unwrap()] }
398}
399
400impl FromScalar<1> for HapticPattern {
401 fn from_scalar([value]: [u32; 1]) -> Self { Self::from_u32(value).unwrap_or(HapticPattern::Click) }
402}