gilrs/
gamepad.rs

1// Copyright 2016-2018 Mateusz Sieczko and other GilRs Developers
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// http://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8use crate::{
9    ev::{
10        state::{AxisData, ButtonData, GamepadState},
11        Axis, AxisOrBtn, Button, Code, Event, EventType,
12    },
13    ff::{
14        server::{self, FfMessage, Message},
15        Error as FfError,
16    },
17    mapping::{Mapping, MappingData, MappingDb},
18    utils, MappingError,
19};
20
21use gilrs_core::{
22    self, AxisInfo, Error as PlatformError, Event as RawEvent, EventType as RawEventType,
23};
24
25use uuid::Uuid;
26
27use std::cmp::Ordering;
28use std::{
29    collections::VecDeque,
30    error,
31    fmt::{self, Display},
32    sync::mpsc::{Receiver, Sender},
33    time::Duration,
34};
35
36pub use gilrs_core::PowerInfo;
37
38#[cfg(feature = "serde-serialize")]
39use serde::{Deserialize, Serialize};
40
41const DEFAULT_DEADZONE: f32 = 0.1;
42
43/// Main object responsible of managing gamepads.
44///
45/// In order to get gamepad handle, use `gamepad()`, or `connected_gamepad()`. The main difference
46/// between these two is that `gamepad()` will also return handle to gamepad that is currently
47/// disconnected. However, both functions will return `None` if gamepad with given id has never
48/// existed.
49///
50/// # Event loop
51///
52/// All interesting actions like button was pressed or new controller was connected are represented
53/// by struct [`Event`](struct.Event.html). Use `next_event()` function to retrieve event from
54/// queue.
55///
56/// ```
57/// use gilrs::{Gilrs, Event, EventType, Button};
58///
59/// let mut gilrs = Gilrs::new().unwrap();
60///
61/// // Event loop
62/// loop {
63///     while let Some(event) = gilrs.next_event() {
64///         match event {
65///             Event { id, event: EventType::ButtonPressed(Button::South, _), .. } => {
66///                 println!("Player {}: jump!", id)
67///             }
68///             Event { id, event: EventType::Disconnected, .. } => {
69///                 println!("We lost player {}", id)
70///             }
71///             _ => (),
72///         };
73///     }
74///     # break;
75/// }
76/// ```
77///
78/// # Cached gamepad state
79///
80/// `Gilrs` also menage cached gamepad state. Updating state is done automatically, unless it's
81///  disabled by `GilrsBuilder::set_update_state(false)`. However, if you are using custom filters,
82/// you still have to update state manually – to do this call `update()` method.
83///
84/// To access state you can use `Gamepad::state()` function. Gamepad also implement some state
85/// related functions directly, see [`Gamepad`](struct.Gamepad.html) for more.
86///
87/// ## Counter
88///
89/// `Gilrs` has additional functionality, referred here as *counter*. The idea behind it is simple,
90/// each time you end iteration of update loop, you call `Gilrs::inc()` which will increase
91/// internal counter by one. When state of one if elements changes, value of counter is saved. When
92/// checking state of one of elements you can tell exactly when this event happened. Timestamps are
93/// not good solution here because they can tell you when *system* observed event, not when you
94/// processed it. On the other hand, they are good when you want to implement key repeat or software
95/// debouncing.
96///
97/// ```
98/// use gilrs::{Gilrs, Button};
99///
100/// let mut gilrs = Gilrs::new().unwrap();
101/// let mut player_one = None;
102///
103/// loop {
104///     while let Some(ev) = gilrs.next_event() {
105///         if player_one.is_none() {
106///             player_one = Some(ev.id);
107///         }
108///
109///         // Do other things with event
110///     }
111///
112///     if let Some(id) = player_one {
113///         let gamepad = gilrs.gamepad(id);
114///
115///         if gamepad.is_pressed(Button::DPadLeft) {
116///             // go left
117///         }
118///
119///         match gamepad.button_data(Button::South) {
120///             Some(d) if d.is_pressed() && d.counter() == gilrs.counter() => {
121///                 // jump only if button was observed to be pressed in this iteration
122///             }
123///             _ => ()
124///         }
125///     }
126///
127///     // Increase counter
128///     gilrs.inc();
129/// #   break;
130/// }
131///
132#[derive(Debug)]
133pub struct Gilrs {
134    inner: gilrs_core::Gilrs,
135    next_id: usize,
136    tx: Sender<Message>,
137    rx: Receiver<FfMessage>,
138    counter: u64,
139    mappings: MappingDb,
140    default_filters: bool,
141    events: VecDeque<Event>,
142    axis_to_btn_pressed: f32,
143    axis_to_btn_released: f32,
144    pub(crate) update_state: bool,
145    pub(crate) gamepads_data: Vec<GamepadData>,
146}
147
148impl Gilrs {
149    /// Creates new `Gilrs` with default settings. See [`GilrsBuilder`](struct.GilrsBuilder.html)
150    /// for more details.
151    pub fn new() -> Result<Self, Error> {
152        GilrsBuilder::new().build()
153    }
154
155    /// Returns next pending event. If there is no pending event, `None` is
156    /// returned. This function will not block current thread and should be safe
157    /// to call in async context. Doesn't block the thread it is run in
158    pub fn next_event(&mut self) -> Option<Event> {
159        self.next_event_inner(false, None)
160    }
161
162    /// Same as [Gilrs::next_event], but blocks the thread it is run in. Useful
163    /// for apps that aren't run inside a loop and just react to the user's input,
164    /// like GUI apps.
165    ///
166    /// ## Platform support
167    ///
168    /// This function is not supported on web and will always panic.
169    pub fn next_event_blocking(&mut self, timeout: Option<Duration>) -> Option<Event> {
170        self.next_event_inner(true, timeout)
171    }
172
173    fn next_event_inner(
174        &mut self,
175        is_blocking: bool,
176        blocking_timeout: Option<Duration>,
177    ) -> Option<Event> {
178        use crate::ev::filter::{axis_dpad_to_button, deadzone, Filter, Jitter};
179
180        let ev = if self.default_filters {
181            let jitter_filter = Jitter::new();
182            loop {
183                let ev = self
184                    .next_event_priv(is_blocking, blocking_timeout)
185                    .filter_ev(&axis_dpad_to_button, self)
186                    .filter_ev(&jitter_filter, self)
187                    .filter_ev(&deadzone, self);
188
189                // Skip all dropped events, there is no reason to return them
190                match ev {
191                    Some(ev) if ev.is_dropped() => (),
192                    _ => break ev,
193                }
194            }
195        } else {
196            self.next_event_priv(is_blocking, blocking_timeout)
197        };
198
199        if self.update_state {
200            if let Some(ref ev) = ev {
201                self.update(ev);
202            }
203        }
204
205        ev
206    }
207
208    /// Returns next pending event.
209    fn next_event_priv(
210        &mut self,
211        is_blocking: bool,
212        blocking_timeout: Option<Duration>,
213    ) -> Option<Event> {
214        if let Some(msg) = self.rx.try_recv().ok() {
215            match msg {
216                FfMessage::EffectCompleted { event } => return Some(event),
217            }
218        }
219        if let Some(ev) = self.events.pop_front() {
220            Some(ev)
221        } else {
222            let event = if is_blocking {
223                self.inner.next_event_blocking(blocking_timeout)
224            } else {
225                self.inner.next_event()
226            };
227
228            match event {
229                Some(RawEvent {
230                    id,
231                    event: event_type,
232                    time,
233                    ..
234                }) => {
235                    trace!("Original event: {:?}", event);
236                    let id = GamepadId(id);
237
238                    let event = match event_type {
239                        RawEventType::ButtonPressed(nec) => {
240                            let nec = Code(nec);
241                            match self.gamepad(id).axis_or_btn_name(nec) {
242                                Some(AxisOrBtn::Btn(b)) => {
243                                    self.events.push_back(Event {
244                                        id,
245                                        time,
246                                        event: EventType::ButtonChanged(b, 1.0, nec),
247                                    });
248
249                                    EventType::ButtonPressed(b, nec)
250                                }
251                                Some(AxisOrBtn::Axis(a)) => EventType::AxisChanged(a, 1.0, nec),
252                                None => {
253                                    self.events.push_back(Event {
254                                        id,
255                                        time,
256                                        event: EventType::ButtonChanged(Button::Unknown, 1.0, nec),
257                                    });
258
259                                    EventType::ButtonPressed(Button::Unknown, nec)
260                                }
261                            }
262                        }
263                        RawEventType::ButtonReleased(nec) => {
264                            let nec = Code(nec);
265                            match self.gamepad(id).axis_or_btn_name(nec) {
266                                Some(AxisOrBtn::Btn(b)) => {
267                                    self.events.push_back(Event {
268                                        id,
269                                        time,
270                                        event: EventType::ButtonChanged(b, 0.0, nec),
271                                    });
272
273                                    EventType::ButtonReleased(b, nec)
274                                }
275                                Some(AxisOrBtn::Axis(a)) => EventType::AxisChanged(a, 0.0, nec),
276                                None => {
277                                    self.events.push_back(Event {
278                                        id,
279                                        time,
280                                        event: EventType::ButtonChanged(Button::Unknown, 0.0, nec),
281                                    });
282
283                                    EventType::ButtonReleased(Button::Unknown, nec)
284                                }
285                            }
286                        }
287                        RawEventType::AxisValueChanged(val, nec) => {
288                            // Let's trust at least our backend code
289                            let axis_info = *self.gamepad(id).inner.axis_info(nec).unwrap();
290                            let nec = Code(nec);
291
292                            match self.gamepad(id).axis_or_btn_name(nec) {
293                                Some(AxisOrBtn::Btn(b)) => {
294                                    let val = btn_value(&axis_info, val);
295
296                                    if val >= self.axis_to_btn_pressed
297                                        && !self.gamepad(id).state().is_pressed(nec)
298                                    {
299                                        self.events.push_back(Event {
300                                            id,
301                                            time,
302                                            event: EventType::ButtonChanged(b, val, nec),
303                                        });
304
305                                        EventType::ButtonPressed(b, nec)
306                                    } else if val <= self.axis_to_btn_released
307                                        && self.gamepad(id).state().is_pressed(nec)
308                                    {
309                                        self.events.push_back(Event {
310                                            id,
311                                            time,
312                                            event: EventType::ButtonChanged(b, val, nec),
313                                        });
314
315                                        EventType::ButtonReleased(b, nec)
316                                    } else {
317                                        EventType::ButtonChanged(b, val, nec)
318                                    }
319                                }
320                                Some(AxisOrBtn::Axis(a)) => {
321                                    EventType::AxisChanged(a, axis_value(&axis_info, val, a), nec)
322                                }
323                                None => EventType::AxisChanged(
324                                    Axis::Unknown,
325                                    axis_value(&axis_info, val, Axis::Unknown),
326                                    nec,
327                                ),
328                            }
329                        }
330                        RawEventType::Connected => {
331                            match id.0.cmp(&self.gamepads_data.len()) {
332                                Ordering::Equal => {
333                                    self.gamepads_data.push(GamepadData::new(
334                                        id,
335                                        self.tx.clone(),
336                                        self.inner.gamepad(id.0).unwrap(),
337                                        &self.mappings,
338                                    ));
339                                }
340                                Ordering::Less => {
341                                    self.gamepads_data[id.0] = GamepadData::new(
342                                        id,
343                                        self.tx.clone(),
344                                        self.inner.gamepad(id.0).unwrap(),
345                                        &self.mappings,
346                                    );
347                                }
348                                Ordering::Greater => {
349                                    error!(
350                                        "Platform implementation error: got Connected event with \
351                                         id {}, when expected id {}",
352                                        id.0,
353                                        self.gamepads_data.len()
354                                    );
355                                }
356                            }
357
358                            EventType::Connected
359                        }
360                        RawEventType::Disconnected => {
361                            let _ = self.tx.send(Message::Close { id: id.0 });
362
363                            EventType::Disconnected
364                        }
365                        _ => {
366                            unimplemented!()
367                        }
368                    };
369
370                    Some(Event { id, event, time })
371                }
372                None => None,
373            }
374        }
375    }
376
377    /// Updates internal state according to `event`.
378    ///
379    /// Please note, that it's not necessary to call this function unless you modify events by using
380    /// additional filters and disabled automatic updates when creating `Gilrs`.
381    pub fn update(&mut self, event: &Event) {
382        use crate::EventType::*;
383
384        let counter = self.counter;
385
386        let data = match self.gamepads_data.get_mut(event.id.0) {
387            Some(d) => d,
388            None => return,
389        };
390
391        match event.event {
392            ButtonPressed(_, nec) => {
393                data.state.set_btn_pressed(nec, true, counter, event.time);
394            }
395            ButtonReleased(_, nec) => {
396                data.state.set_btn_pressed(nec, false, counter, event.time);
397            }
398            ButtonRepeated(_, nec) => {
399                data.state.set_btn_repeating(nec, counter, event.time);
400            }
401            ButtonChanged(_, value, nec) => {
402                data.state.set_btn_value(nec, value, counter, event.time);
403            }
404            AxisChanged(_, value, nec) => {
405                data.state
406                    .update_axis(nec, AxisData::new(value, counter, event.time));
407            }
408            Disconnected | Connected | Dropped | ForceFeedbackEffectCompleted => (),
409        }
410    }
411
412    /// Increases internal counter by one. Counter data is stored with state and can be used to
413    /// determine when last event happened. You probably want to use this function in your update
414    /// loop after processing events.
415    pub fn inc(&mut self) {
416        // Counter is 62bit. See `ButtonData`.
417        if self.counter == 0x3FFF_FFFF_FFFF_FFFF {
418            self.counter = 0;
419        } else {
420            self.counter += 1;
421        }
422    }
423
424    /// Returns counter. Counter data is stored with state and can be used to determine when last
425    /// event happened.
426    pub fn counter(&self) -> u64 {
427        self.counter
428    }
429
430    /// Sets counter to 0.
431    pub fn reset_counter(&mut self) {
432        self.counter = 0;
433    }
434
435    fn finish_gamepads_creation(&mut self) {
436        let tx = self.tx.clone();
437        for id in 0..self.inner.last_gamepad_hint() {
438            let gamepad = self.inner.gamepad(id).unwrap();
439            self.gamepads_data.push(GamepadData::new(
440                GamepadId(id),
441                tx.clone(),
442                gamepad,
443                &self.mappings,
444            ))
445        }
446    }
447
448    /// Returns handle to gamepad with given ID. Unlike `connected_gamepad()`, this function will
449    /// also return handle to gamepad that is currently disconnected.
450    ///
451    /// ```
452    /// # let mut gilrs = gilrs::Gilrs::new().unwrap();
453    /// use gilrs::{Button, EventType};
454    ///
455    /// loop {
456    ///     while let Some(ev) = gilrs.next_event() {
457    ///         // unwrap() should never panic because we use id from event
458    ///         let is_up_pressed = gilrs.gamepad(ev.id).is_pressed(Button::DPadUp);
459    ///
460    ///         match ev.event {
461    ///             EventType::ButtonPressed(Button::South, _) if is_up_pressed => {
462    ///                 // do something…
463    ///             }
464    ///             _ => (),
465    ///         }
466    ///     }
467    ///     # break;
468    /// }
469    /// ```
470    pub fn gamepad(&self, id: GamepadId) -> Gamepad {
471        Gamepad {
472            inner: self.inner.gamepad(id.0).unwrap(),
473            data: &self.gamepads_data[id.0],
474        }
475    }
476
477    /// Returns a reference to connected gamepad or `None`.
478    pub fn connected_gamepad(&self, id: GamepadId) -> Option<Gamepad<'_>> {
479        // Make sure that it will not panic even with invalid GamepadId, so ConnectedGamepadIterator
480        // will always work.
481        if let Some(data) = self.gamepads_data.get(id.0) {
482            let inner = self.inner.gamepad(id.0)?;
483
484            if inner.is_connected() {
485                Some(Gamepad { inner, data })
486            } else {
487                None
488            }
489        } else {
490            None
491        }
492    }
493
494    /// Returns iterator over all connected gamepads and their ids.
495    ///
496    /// ```
497    /// # let gilrs = gilrs::Gilrs::new().unwrap();
498    /// for (id, gamepad) in gilrs.gamepads() {
499    ///     assert!(gamepad.is_connected());
500    ///     println!("Gamepad with id {} and name {} is connected",
501    ///              id, gamepad.name());
502    /// }
503    /// ```
504    pub fn gamepads(&self) -> ConnectedGamepadsIterator<'_> {
505        ConnectedGamepadsIterator(self, 0)
506    }
507
508    /// Adds `ev` at the end of internal event queue. It can later be retrieved with `next_event()`.
509    pub fn insert_event(&mut self, ev: Event) {
510        self.events.push_back(ev);
511    }
512
513    pub(crate) fn ff_sender(&self) -> &Sender<Message> {
514        &self.tx
515    }
516
517    /// Sets gamepad's mapping and returns SDL2 representation of them. Returned mappings may not be
518    /// compatible with SDL2 - if it is important, use
519    /// [`set_mapping_strict()`](#method.set_mapping_strict).
520    ///
521    /// The `name` argument can be a string slice with custom gamepad name or `None`. If `None`,
522    /// gamepad name reported by driver will be used.
523    ///
524    /// # Errors
525    ///
526    /// This function return error if `name` contains comma, `mapping` have axis and button entry
527    /// for same element (for example `Axis::LetfTrigger` and `Button::LeftTrigger`) or gamepad does
528    /// not have any element with `EvCode` used in mapping. `Button::Unknown` and
529    /// `Axis::Unknown` are not allowd as keys to `mapping` – in this case,
530    /// `MappingError::UnknownElement` is returned.
531    ///
532    /// Error is also returned if this function is not implemented or gamepad is not connected.
533    ///
534    /// # Example
535    ///
536    /// ```
537    /// use gilrs::{Mapping, Button};
538    ///
539    /// # let mut gilrs = gilrs::Gilrs::new().unwrap();
540    /// let mut data = Mapping::new();
541    /// // …
542    ///
543    /// // or `match gilrs.set_mapping(0, &data, None) {`
544    /// match gilrs.set_mapping(0, &data, "Custom name") {
545    ///     Ok(sdl) => println!("SDL2 mapping: {}", sdl),
546    ///     Err(e) => println!("Failed to set mapping: {}", e),
547    /// };
548    /// ```
549    ///
550    /// See also `examples/mapping.rs`.
551    pub fn set_mapping<'b, O: Into<Option<&'b str>>>(
552        &mut self,
553        gamepad_id: usize,
554        mapping: &MappingData,
555        name: O,
556    ) -> Result<String, MappingError> {
557        if let Some(gamepad) = self.inner.gamepad(gamepad_id) {
558            if !gamepad.is_connected() {
559                return Err(MappingError::NotConnected);
560            }
561
562            let name = match name.into() {
563                Some(s) => s,
564                None => gamepad.name(),
565            };
566
567            let (mapping, s) = Mapping::from_data(
568                mapping,
569                gamepad.buttons(),
570                gamepad.axes(),
571                name,
572                Uuid::from_bytes(gamepad.uuid()),
573            )?;
574
575            // We checked if gamepad is connected, so it should never panic
576            let data = &mut self.gamepads_data[gamepad_id];
577            data.mapping = mapping;
578
579            Ok(s)
580        } else {
581            Err(MappingError::NotConnected)
582        }
583    }
584
585    /// Similar to [`set_mapping()`](#method.set_mapping) but returned string should be compatible
586    /// with SDL2.
587    ///
588    /// # Errors
589    ///
590    /// Returns `MappingError::NotSdl2Compatible` if `mapping` have an entry for `Button::{C, Z}`
591    /// or `Axis::{LeftZ, RightZ}`.
592    pub fn set_mapping_strict<'b, O: Into<Option<&'b str>>>(
593        &mut self,
594        gamepad_id: usize,
595        mapping: &MappingData,
596        name: O,
597    ) -> Result<String, MappingError> {
598        if mapping.button(Button::C).is_some()
599            || mapping.button(Button::Z).is_some()
600            || mapping.axis(Axis::LeftZ).is_some()
601            || mapping.axis(Axis::RightZ).is_some()
602        {
603            Err(MappingError::NotSdl2Compatible)
604        } else {
605            self.set_mapping(gamepad_id, mapping, name)
606        }
607    }
608
609    pub(crate) fn next_ff_id(&mut self) -> usize {
610        // TODO: reuse free ids
611        let id = self.next_id;
612        self.next_id = match self.next_id.checked_add(1) {
613            Some(x) => x,
614            None => panic!("Failed to assign ID to new effect"),
615        };
616        id
617    }
618}
619
620/// Allow to create `Gilrs ` with customized behaviour.
621pub struct GilrsBuilder {
622    mappings: MappingDb,
623    default_filters: bool,
624    axis_to_btn_pressed: f32,
625    axis_to_btn_released: f32,
626    update_state: bool,
627    env_mappings: bool,
628    included_mappings: bool,
629}
630
631impl GilrsBuilder {
632    /// Create builder with default settings. Use `build()` to create `Gilrs`.
633    pub fn new() -> Self {
634        GilrsBuilder {
635            mappings: MappingDb::new(),
636            default_filters: true,
637            axis_to_btn_pressed: 0.75,
638            axis_to_btn_released: 0.65,
639            update_state: true,
640            env_mappings: true,
641            included_mappings: true,
642        }
643    }
644
645    /// If `true`, use [`axis_dpad_to_button`](ev/filter/fn.axis_dpad_to_button.html),
646    /// [`Jitter`](ev/filter/struct.Jitter.html) and [`deadzone`](ev/filter/fn.deadzone.html)
647    /// filters with default parameters. Defaults to `true`.
648    pub fn with_default_filters(mut self, default_filters: bool) -> Self {
649        self.default_filters = default_filters;
650
651        self
652    }
653
654    /// Adds SDL mappings.
655    pub fn add_mappings(mut self, mappings: &str) -> Self {
656        self.mappings.insert(mappings);
657
658        self
659    }
660
661    /// If true, will add SDL mappings from `SDL_GAMECONTROLLERCONFIG` environment variable.
662    /// Defaults to true.
663    pub fn add_env_mappings(mut self, env_mappings: bool) -> Self {
664        self.env_mappings = env_mappings;
665
666        self
667    }
668
669    /// If true, will add SDL mappings included from
670    /// https://github.com/gabomdq/SDL_GameControllerDB. Defaults to true.
671    pub fn add_included_mappings(mut self, included_mappings: bool) -> Self {
672        self.included_mappings = included_mappings;
673
674        self
675    }
676
677    /// Sets values on which `ButtonPressed` and `ButtonReleased` events will be emitted. `build()`
678    /// will return error if `pressed ≤ released` or if one of values is outside [0.0, 1.0].
679    ///
680    /// Defaults to 0.75 for `pressed` and 0.65 for `released`.
681    pub fn set_axis_to_btn(mut self, pressed: f32, released: f32) -> Self {
682        self.axis_to_btn_pressed = pressed;
683        self.axis_to_btn_released = released;
684
685        self
686    }
687
688    /// Disable or enable automatic state updates. You should use this if you use custom filters;
689    /// in this case you have to update state manually anyway.
690    pub fn set_update_state(mut self, enabled: bool) -> Self {
691        self.update_state = enabled;
692
693        self
694    }
695
696    /// Creates `Gilrs`.
697    pub fn build(mut self) -> Result<Gilrs, Error> {
698        if self.included_mappings {
699            self.mappings.add_included_mappings();
700        }
701
702        if self.env_mappings {
703            self.mappings.add_env_mappings();
704        }
705
706        debug!("Loaded {} mappings.", self.mappings.len());
707
708        if self.axis_to_btn_pressed <= self.axis_to_btn_released
709            || self.axis_to_btn_pressed < 0.0
710            || self.axis_to_btn_pressed > 1.0
711            || self.axis_to_btn_released < 0.0
712            || self.axis_to_btn_released > 1.0
713        {
714            return Err(Error::InvalidAxisToBtn);
715        }
716
717        let mut is_dummy = false;
718        let inner = match gilrs_core::Gilrs::new() {
719            Ok(g) => g,
720            Err(PlatformError::NotImplemented(g)) => {
721                is_dummy = true;
722
723                g
724            }
725            Err(PlatformError::Other(e)) => return Err(Error::Other(e)),
726            Err(_) => unimplemented!(),
727        };
728
729        let (tx, rx) = server::init();
730
731        let mut gilrs = Gilrs {
732            inner,
733            next_id: 0,
734            tx,
735            rx,
736            counter: 0,
737            mappings: self.mappings,
738            default_filters: self.default_filters,
739            events: VecDeque::new(),
740            axis_to_btn_pressed: self.axis_to_btn_pressed,
741            axis_to_btn_released: self.axis_to_btn_released,
742            update_state: self.update_state,
743            gamepads_data: Vec::new(),
744        };
745        gilrs.finish_gamepads_creation();
746
747        if is_dummy {
748            Err(Error::NotImplemented(gilrs))
749        } else {
750            Ok(gilrs)
751        }
752    }
753}
754
755impl Default for GilrsBuilder {
756    fn default() -> Self {
757        Self::new()
758    }
759}
760
761/// Iterator over all connected gamepads.
762pub struct ConnectedGamepadsIterator<'a>(&'a Gilrs, usize);
763
764impl<'a> Iterator for ConnectedGamepadsIterator<'a> {
765    type Item = (GamepadId, Gamepad<'a>);
766
767    fn next(&mut self) -> Option<(GamepadId, Gamepad<'a>)> {
768        loop {
769            if self.1 == self.0.inner.last_gamepad_hint() {
770                return None;
771            }
772
773            if let Some(gp) = self.0.connected_gamepad(GamepadId(self.1)) {
774                let idx = self.1;
775                self.1 += 1;
776                return Some((GamepadId(idx), gp));
777            }
778
779            self.1 += 1;
780        }
781    }
782}
783
784/// Represents handle to game controller.
785///
786/// Using this struct you can access cached gamepad state, information about gamepad such as name
787/// or UUID and manage force feedback effects.
788#[derive(Debug, Copy, Clone)]
789pub struct Gamepad<'a> {
790    data: &'a GamepadData,
791    inner: &'a gilrs_core::Gamepad,
792}
793
794impl<'a> Gamepad<'a> {
795    /// Returns the mapping name if it exists otherwise returns the os provided name.
796    pub fn name(&self) -> &str {
797        if let Some(map_name) = self.map_name() {
798            map_name
799        } else {
800            self.os_name()
801        }
802    }
803
804    /// if `mapping_source()` is `SdlMappings` returns the name of the mapping used by the gamepad.
805    /// Otherwise returns `None`.
806    pub fn map_name(&self) -> Option<&str> {
807        self.data.map_name()
808    }
809
810    /// Returns the name of the gamepad supplied by the OS.
811    pub fn os_name(&self) -> &str {
812        self.inner.name()
813    }
814
815    /// Returns gamepad's UUID.
816    ///
817    /// It is recommended to process with the [UUID crate](https://crates.io/crates/uuid).
818    /// Use `Uuid::from_bytes` method to create a `Uuid` from the returned bytes.
819    pub fn uuid(&self) -> [u8; 16] {
820        self.inner.uuid()
821    }
822
823    /// Returns the vendor ID, as assigned by the USB-IF, when available.
824    pub fn vendor_id(&self) -> Option<u16> {
825        self.inner.vendor_id()
826    }
827
828    /// Returns the product ID, as assigned by the vendor, when available.
829    pub fn product_id(&self) -> Option<u16> {
830        self.inner.product_id()
831    }
832
833    /// Returns cached gamepad state.
834    pub fn state(&self) -> &GamepadState {
835        &self.data.state
836    }
837
838    /// Returns true if gamepad is connected.
839    pub fn is_connected(&self) -> bool {
840        self.inner.is_connected()
841    }
842
843    /// Examines cached gamepad state to check if given button is pressed. Panics if `btn` is
844    /// `Unknown`.
845    ///
846    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
847    /// directly on `State`, because this version have to check which `Code` is mapped to element of
848    /// gamepad.
849    pub fn is_pressed(&self, btn: Button) -> bool {
850        self.data.is_pressed(btn)
851    }
852
853    /// Examines cached gamepad state to check axis's value. Panics if `axis` is `Unknown`.
854    ///
855    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
856    /// directly on `State`, because this version have to check which `Code` is mapped to element of
857    /// gamepad.
858    pub fn value(&self, axis: Axis) -> f32 {
859        self.data.value(axis)
860    }
861
862    /// Returns button state and when it changed.
863    ///
864    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
865    /// directly on `State`, because this version have to check which `Code` is mapped to element of
866    /// gamepad.
867    pub fn button_data(&self, btn: Button) -> Option<&ButtonData> {
868        self.data.button_data(btn)
869    }
870
871    /// Returns axis state and when it changed.
872    ///
873    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
874    /// directly on `State`, because this version have to check which `Code` is mapped to element of
875    /// gamepad.
876    pub fn axis_data(&self, axis: Axis) -> Option<&AxisData> {
877        self.data.axis_data(axis)
878    }
879
880    /// Returns device's power supply state. See [`PowerInfo`](enum.PowerInfo.html) for details.
881    pub fn power_info(&self) -> PowerInfo {
882        self.inner.power_info()
883    }
884
885    /// Returns source of gamepad mapping. Can be used to filter gamepads which do not provide
886    /// unified controller layout.
887    ///
888    /// ```
889    /// use gilrs::MappingSource;
890    /// # let mut gilrs = gilrs::Gilrs::new().unwrap();
891    ///
892    /// for (_, gamepad) in gilrs.gamepads().filter(
893    ///     |gp| gp.1.mapping_source() != MappingSource::None)
894    /// {
895    ///     println!("{} is ready to use!", gamepad.name());
896    /// }
897    /// ```
898    pub fn mapping_source(&self) -> MappingSource {
899        if self.data.mapping.is_default() {
900            // TODO: check if it's Driver or None
901            MappingSource::Driver
902        } else {
903            MappingSource::SdlMappings
904        }
905    }
906
907    /// Returns true if force feedback is supported by device.
908    pub fn is_ff_supported(&self) -> bool {
909        self.inner.is_ff_supported()
910    }
911
912    /// Change gamepad position used by force feedback effects.
913    pub fn set_listener_position<Vec3: Into<[f32; 3]>>(
914        &self,
915        position: Vec3,
916    ) -> Result<(), FfError> {
917        if !self.is_connected() {
918            Err(FfError::Disconnected(self.id()))
919        } else if !self.is_ff_supported() {
920            Err(FfError::FfNotSupported(self.id()))
921        } else {
922            self.data.tx.send(Message::SetListenerPosition {
923                id: self.data.id.0,
924                position: position.into(),
925            })?;
926            Ok(())
927        }
928    }
929
930    /// Returns `AxisOrBtn` mapped to `Code`.
931    pub fn axis_or_btn_name(&self, ec: Code) -> Option<AxisOrBtn> {
932        self.data.axis_or_btn_name(ec)
933    }
934
935    /// Returns `Code` associated with `btn`.
936    pub fn button_code(&self, btn: Button) -> Option<Code> {
937        self.data.button_code(btn)
938    }
939
940    /// Returns `Code` associated with `axis`.
941    pub fn axis_code(&self, axis: Axis) -> Option<Code> {
942        self.data.axis_code(axis)
943    }
944
945    /// Returns area in which axis events should be ignored.
946    pub fn deadzone(&self, axis: Code) -> Option<f32> {
947        self.inner.axis_info(axis.0).map(|i| {
948            let range = i.max as f32 - i.min as f32;
949
950            if range == 0.0 {
951                0.0
952            } else {
953                i.deadzone
954                    .map(|d| d as f32 / range * 2.0)
955                    .unwrap_or(DEFAULT_DEADZONE)
956            }
957        })
958    }
959
960    /// Returns ID of gamepad.
961    pub fn id(&self) -> GamepadId {
962        self.data.id
963    }
964
965    pub(crate) fn mapping(&self) -> &Mapping {
966        &self.data.mapping
967    }
968}
969
970#[derive(Debug)]
971pub(crate) struct GamepadData {
972    state: GamepadState,
973    mapping: Mapping,
974    tx: Sender<Message>,
975    id: GamepadId,
976    // Flags used by the deadzone filter.
977    pub(crate) have_sent_nonzero_for_axis: [bool; 6],
978}
979
980impl GamepadData {
981    fn new(
982        id: GamepadId,
983        tx: Sender<Message>,
984        gamepad: &gilrs_core::Gamepad,
985        db: &MappingDb,
986    ) -> Self {
987        let mapping = db
988            .get(Uuid::from_bytes(gamepad.uuid()))
989            .map(
990                |s| match Mapping::parse_sdl_mapping(s, gamepad.buttons(), gamepad.axes()) {
991                    Ok(result) => result,
992                    Err(e) => {
993                        warn!(
994                            "Unable to parse SDL mapping for UUID {}\n\t{:?}\n\tDefault mapping \
995                             will be used.",
996                            Uuid::from_bytes(gamepad.uuid()),
997                            e
998                        );
999                        Mapping::default(gamepad)
1000                    }
1001                },
1002            )
1003            .unwrap_or_else(|| Mapping::default(gamepad));
1004
1005        if gamepad.is_ff_supported() && gamepad.is_connected() {
1006            if let Some(device) = gamepad.ff_device() {
1007                let _ = tx.send(Message::Open { id: id.0, device });
1008            }
1009        }
1010
1011        GamepadData {
1012            state: GamepadState::new(),
1013            mapping,
1014            tx,
1015            id,
1016            have_sent_nonzero_for_axis: Default::default(),
1017        }
1018    }
1019
1020    /// if `mapping_source()` is `SdlMappings` returns the name of the mapping used by the gamepad.
1021    /// Otherwise returns `None`.
1022    ///
1023    /// Warning: Mappings are set after event `Connected` is processed therefore this function will
1024    /// always return `None` before first calls to `Gilrs::next_event()`.
1025    pub fn map_name(&self) -> Option<&str> {
1026        if self.mapping.is_default() {
1027            None
1028        } else {
1029            Some(self.mapping.name())
1030        }
1031    }
1032
1033    /// Examines cached gamepad state to check if given button is pressed. Panics if `btn` is
1034    /// `Unknown`.
1035    ///
1036    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
1037    /// directly on `State`, because this version have to check which `Code` is mapped to element of
1038    /// gamepad.
1039    pub fn is_pressed(&self, btn: Button) -> bool {
1040        assert_ne!(btn, Button::Unknown);
1041
1042        self.button_code(btn)
1043            .or_else(|| btn.to_nec())
1044            .map(|nec| self.state.is_pressed(nec))
1045            .unwrap_or(false)
1046    }
1047
1048    /// Examines cached gamepad state to check axis's value. Panics if `axis` is `Unknown`.
1049    ///
1050    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
1051    /// directly on `State`, because this version have to check which `Code` is mapped to element of
1052    /// gamepad.
1053    pub fn value(&self, axis: Axis) -> f32 {
1054        assert_ne!(axis, Axis::Unknown);
1055
1056        self.axis_code(axis)
1057            .map(|nec| self.state.value(nec))
1058            .unwrap_or(0.0)
1059    }
1060
1061    /// Returns button state and when it changed.
1062    ///
1063    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
1064    /// directly on `State`, because this version have to check which `Code` is mapped to element of
1065    /// gamepad.
1066    pub fn button_data(&self, btn: Button) -> Option<&ButtonData> {
1067        self.button_code(btn)
1068            .and_then(|nec| self.state.button_data(nec))
1069    }
1070
1071    /// Returns axis state and when it changed.
1072    ///
1073    /// If you know `Code` of the element that you want to examine, it's recommended to use methods
1074    /// directly on `State`, because this version have to check which `Code` is mapped to element of
1075    /// gamepad.
1076    pub fn axis_data(&self, axis: Axis) -> Option<&AxisData> {
1077        self.axis_code(axis)
1078            .and_then(|nec| self.state.axis_data(nec))
1079    }
1080
1081    /// Returns `AxisOrBtn` mapped to `Code`.
1082    pub fn axis_or_btn_name(&self, ec: Code) -> Option<AxisOrBtn> {
1083        self.mapping.map(&ec.0)
1084    }
1085
1086    /// Returns `Code` associated with `btn`.
1087    pub fn button_code(&self, btn: Button) -> Option<Code> {
1088        self.mapping.map_rev(&AxisOrBtn::Btn(btn)).map(Code)
1089    }
1090
1091    /// Returns `Code` associated with `axis`.
1092    pub fn axis_code(&self, axis: Axis) -> Option<Code> {
1093        self.mapping.map_rev(&AxisOrBtn::Axis(axis)).map(Code)
1094    }
1095}
1096
1097/// Source of gamepad mappings.
1098#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1099pub enum MappingSource {
1100    /// Gamepad uses SDL mappings.
1101    SdlMappings,
1102    /// Gamepad does not use any mappings but driver should provide unified controller layout.
1103    Driver,
1104    /// Gamepad does not use any mappings and most gamepad events will probably be `Button::Unknown`
1105    /// or `Axis::Unknown`
1106    None,
1107}
1108
1109/// Gamepad ID.
1110///
1111/// It's not possible to create instance of this type directly, but you can obtain one from Gamepad
1112/// handle or any event. ID is valid for entire lifetime of `Gilrs` context.
1113#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash)]
1114#[cfg_attr(feature = "serde-serialize", derive(Serialize, Deserialize))]
1115pub struct GamepadId(pub(crate) usize);
1116
1117impl From<GamepadId> for usize {
1118    fn from(x: GamepadId) -> usize {
1119        x.0
1120    }
1121}
1122
1123impl Display for GamepadId {
1124    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1125        self.0.fmt(f)
1126    }
1127}
1128
1129fn axis_value(info: &AxisInfo, val: i32, axis: Axis) -> f32 {
1130    let mut range = info.max as f32 - info.min as f32;
1131    let mut val = val as f32 - info.min as f32;
1132
1133    if let Some(i_range) = info.max.checked_sub(info.min) {
1134        // Only consider adjusting range & val if calculating the range doesn't cause overflow.  If
1135        // the range is so large overflow occurs, adjusting values by 1.0 would be insignificant.
1136        if i_range % 2 == 1 {
1137            // Add one to range and val, so value at center (like 127/255) will be mapped 0.0
1138            range += 1.0;
1139            val += 1.0;
1140        }
1141    }
1142
1143    val = val / range * 2.0 - 1.0;
1144
1145    if gilrs_core::IS_Y_AXIS_REVERSED
1146        && (axis == Axis::LeftStickY || axis == Axis::RightStickY || axis == Axis::DPadY)
1147        && val != 0.0
1148    {
1149        val = -val;
1150    }
1151
1152    utils::clamp(val, -1.0, 1.0)
1153}
1154
1155fn btn_value(info: &AxisInfo, val: i32) -> f32 {
1156    let range = info.max as f32 - info.min as f32;
1157    let mut val = val as f32 - info.min as f32;
1158    val /= range;
1159
1160    utils::clamp(val, 0.0, 1.0)
1161}
1162
1163/// Error type which can be returned when creating `Gilrs`.
1164#[non_exhaustive]
1165#[derive(Debug)]
1166pub enum Error {
1167    /// Gilrs does not support current platform, but you can use dummy context from this error if
1168    /// gamepad input is not essential.
1169    NotImplemented(Gilrs),
1170    /// Either `pressed ≤ released` or one of values is outside [0.0, 1.0] range.
1171    InvalidAxisToBtn,
1172    /// Platform specific error.
1173    Other(Box<dyn error::Error + Send + Sync + 'static>),
1174}
1175
1176impl Display for Error {
1177    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1178        match self {
1179            Error::NotImplemented(_) => f.write_str("Gilrs does not support current platform."),
1180            Error::InvalidAxisToBtn => f.write_str(
1181                "Either `pressed ≤ released` or one of values is outside [0.0, 1.0] range.",
1182            ),
1183            Error::Other(ref e) => e.fmt(f),
1184        }
1185    }
1186}
1187
1188impl error::Error for Error {
1189    fn source(&self) -> Option<&(dyn error::Error + 'static)> {
1190        match self {
1191            Error::Other(e) => Some(e.as_ref()),
1192            _ => None,
1193        }
1194    }
1195}
1196
1197const _: () = {
1198    const fn assert_send<T: Send>() {}
1199
1200    #[cfg(not(target_arch = "wasm32"))]
1201    assert_send::<Gilrs>();
1202};
1203
1204#[cfg(test)]
1205mod tests {
1206    use super::{axis_value, btn_value, Axis, AxisInfo};
1207
1208    #[test]
1209    fn axis_value_documented_case() {
1210        let info = AxisInfo {
1211            min: 0,
1212            max: 255,
1213            deadzone: None,
1214        };
1215        let axis = Axis::LeftStickY;
1216        assert_eq!(0., axis_value(&info, 127, axis));
1217    }
1218
1219    #[test]
1220    fn axis_value_overflow() {
1221        let info = AxisInfo {
1222            min: std::i32::MIN,
1223            max: std::i32::MAX,
1224            deadzone: None,
1225        };
1226        let axis = Axis::LeftStickY;
1227
1228        assert_eq!(0., axis_value(&info, -1, axis));
1229        assert_eq!(0., axis_value(&info, 0, axis));
1230        assert_eq!(0., axis_value(&info, 1, axis));
1231
1232        assert_eq!(1.0, axis_value(&info, i32::MIN, axis));
1233        assert_eq!(-1.0, axis_value(&info, i32::MAX, axis));
1234    }
1235
1236    #[test]
1237    fn btn_value_overflow() {
1238        let info = AxisInfo {
1239            min: std::i32::MIN,
1240            max: std::i32::MAX,
1241            deadzone: None,
1242        };
1243
1244        assert_eq!(0.5, btn_value(&info, -1));
1245        assert_eq!(0.5, btn_value(&info, 0));
1246        assert_eq!(0.5, btn_value(&info, 1));
1247
1248        assert_eq!(0.0, btn_value(&info, i32::MIN));
1249        assert_eq!(1.0, btn_value(&info, i32::MAX));
1250    }
1251}