#[cfg(target_os = "linux")]
extern crate libc;
#[cfg(target_os = "linux")]
extern crate libudev_sys;
#[cfg(target_os = "linux")]
#[macro_use]
extern crate nix;
#[cfg(target_os = "linux")]
extern crate vec_map;
#[cfg(target_os = "macos")]
#[macro_use(impl_TCFType)]
extern crate core_foundation;
#[cfg(target_os = "macos")]
extern crate io_kit_sys;
#[cfg(target_os = "macos")]
extern crate vec_map;
#[cfg(target_os = "windows")]
extern crate rusty_xinput;
#[cfg(target_os = "windows")]
extern crate winapi;
#[cfg(target_arch = "wasm32")]
extern crate stdweb;
extern crate uuid;
#[macro_use]
extern crate log;
use std::fmt;
use std::fmt::Display;
use std::fmt::Formatter;
use std::error;
use std::time::Duration;
use std::time::SystemTime;
mod platform;
mod utils;
pub const IS_Y_AXIS_REVERSED: bool = platform::IS_Y_AXIS_REVERSED;
#[derive(Debug)]
pub struct FfDevice {
inner: platform::FfDevice,
}
impl FfDevice {
pub fn set_ff_state(&mut self, strong: u16, weak: u16, min_duration: Duration) {
self.inner.set_ff_state(strong, weak, min_duration)
}
}
#[derive(Copy, Clone, PartialEq, Debug)]
pub struct Event {
pub id: usize,
pub event: EventType,
pub time: SystemTime,
}
impl Event {
pub fn new(id: usize, event: EventType) -> Self {
#[cfg(not(target_arch = "wasm32"))]
let time = SystemTime::now();
#[cfg(target_arch = "wasm32")]
let time = {
let epoch = SystemTime::UNIX_EPOCH;
let time = stdweb::web::Date::new().get_time();
let offset = Duration::from_millis(time as u64);
epoch + offset
};
Event { id, event, time }
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EventType {
ButtonPressed(EvCode),
ButtonReleased(EvCode),
AxisValueChanged(i32, EvCode),
Connected,
Disconnected,
}
#[derive(Copy, Clone, Debug)]
pub struct AxisInfo {
pub min: i32,
pub max: i32,
pub deadzone: Option<u32>,
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum PowerInfo {
Unknown,
Wired,
Discharging(u8),
Charging(u8),
Charged,
}
#[derive(Debug)]
pub struct Gilrs {
inner: platform::Gilrs,
}
impl Gilrs {
pub fn new() -> Result<Self, Error> {
let inner = platform::Gilrs::new().map_err(|e| match e {
PlatformError::NotImplemented(inner) => Error::NotImplemented(Gilrs { inner }),
PlatformError::Other(e) => Error::Other(e),
})?;
Ok(Gilrs { inner })
}
pub fn next_event(&mut self) -> Option<Event> {
self.inner.next_event()
}
pub fn gamepad(&self, id: usize) -> Option<&Gamepad> {
unsafe {
let gp: Option<&platform::Gamepad> = self.inner.gamepad(id);
gp.map(|gp| &*(gp as *const _ as *const Gamepad))
}
}
pub fn last_gamepad_hint(&self) -> usize {
self.inner.last_gamepad_hint()
}
}
#[derive(Debug)]
#[repr(transparent)]
pub struct Gamepad {
inner: platform::Gamepad,
}
impl Gamepad {
pub fn name(&self) -> &str {
self.inner.name()
}
pub fn is_connected(&self) -> bool {
self.inner.is_connected()
}
pub fn uuid(&self) -> [u8; 16] {
*self.inner.uuid().as_bytes()
}
pub fn power_info(&self) -> PowerInfo {
self.inner.power_info()
}
pub fn is_ff_supported(&self) -> bool {
self.inner.is_ff_supported()
}
pub fn ff_device(&self) -> Option<FfDevice> {
self.inner.ff_device().map(|inner| FfDevice { inner })
}
pub fn buttons(&self) -> &[EvCode] {
unsafe {
let bt: &[platform::EvCode] = self.inner.buttons();
&*(bt as *const _ as *const [EvCode])
}
}
pub fn axes(&self) -> &[EvCode] {
unsafe {
let ax: &[platform::EvCode] = self.inner.axes();
&*(ax as *const _ as *const [EvCode])
}
}
pub fn axis_info(&self, nec: EvCode) -> Option<&AxisInfo> {
self.inner.axis_info(nec.0)
}
}
#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
#[repr(transparent)]
pub struct EvCode(platform::EvCode);
impl EvCode {
pub fn into_u32(self) -> u32 {
self.0.into_u32()
}
}
impl Display for EvCode {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
self.0.fmt(f)
}
}
#[derive(Debug)]
enum PlatformError {
#[allow(dead_code)]
NotImplemented(platform::Gilrs),
#[allow(dead_code)]
Other(Box<dyn error::Error + Send + Sync>),
}
impl Display for PlatformError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
PlatformError::NotImplemented(_) => {
f.write_str("Gilrs does not support current platform.")
}
PlatformError::Other(ref e) => e.fmt(f),
}
}
}
impl error::Error for PlatformError {
fn description(&self) -> &str {
match *self {
PlatformError::NotImplemented(_) => "platform not supported",
PlatformError::Other(_) => "platform specific error",
}
}
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
PlatformError::NotImplemented(_) => None,
PlatformError::Other(ref e) => Some(&**e),
}
}
}
#[derive(Debug)]
pub enum Error {
#[allow(dead_code)]
NotImplemented(Gilrs),
#[allow(dead_code)]
Other(Box<dyn error::Error + Send + Sync>),
}
impl Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::NotImplemented(_) => f.write_str("Gilrs does not support current platform."),
Error::Other(ref e) => e.fmt(f),
}
}
}
impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::NotImplemented(_) => "platform not supported",
Error::Other(_) => "platform specific error",
}
}
fn cause(&self) -> Option<&dyn error::Error> {
match *self {
Error::NotImplemented(_) => None,
Error::Other(ref e) => Some(&**e),
}
}
}
pub mod native_ev_codes {
use super::EvCode;
use platform::native_ev_codes as nec;
pub const AXIS_LSTICKX: EvCode = EvCode(nec::AXIS_LSTICKX);
pub const AXIS_LSTICKY: EvCode = EvCode(nec::AXIS_LSTICKY);
pub const AXIS_LEFTZ: EvCode = EvCode(nec::AXIS_LEFTZ);
pub const AXIS_RSTICKX: EvCode = EvCode(nec::AXIS_RSTICKX);
pub const AXIS_RSTICKY: EvCode = EvCode(nec::AXIS_RSTICKY);
pub const AXIS_RIGHTZ: EvCode = EvCode(nec::AXIS_RIGHTZ);
pub const AXIS_DPADX: EvCode = EvCode(nec::AXIS_DPADX);
pub const AXIS_DPADY: EvCode = EvCode(nec::AXIS_DPADY);
pub const AXIS_RT: EvCode = EvCode(nec::AXIS_RT);
pub const AXIS_LT: EvCode = EvCode(nec::AXIS_LT);
pub const AXIS_RT2: EvCode = EvCode(nec::AXIS_RT2);
pub const AXIS_LT2: EvCode = EvCode(nec::AXIS_LT2);
pub const BTN_SOUTH: EvCode = EvCode(nec::BTN_SOUTH);
pub const BTN_EAST: EvCode = EvCode(nec::BTN_EAST);
pub const BTN_C: EvCode = EvCode(nec::BTN_C);
pub const BTN_NORTH: EvCode = EvCode(nec::BTN_NORTH);
pub const BTN_WEST: EvCode = EvCode(nec::BTN_WEST);
pub const BTN_Z: EvCode = EvCode(nec::BTN_Z);
pub const BTN_LT: EvCode = EvCode(nec::BTN_LT);
pub const BTN_RT: EvCode = EvCode(nec::BTN_RT);
pub const BTN_LT2: EvCode = EvCode(nec::BTN_LT2);
pub const BTN_RT2: EvCode = EvCode(nec::BTN_RT2);
pub const BTN_SELECT: EvCode = EvCode(nec::BTN_SELECT);
pub const BTN_START: EvCode = EvCode(nec::BTN_START);
pub const BTN_MODE: EvCode = EvCode(nec::BTN_MODE);
pub const BTN_LTHUMB: EvCode = EvCode(nec::BTN_LTHUMB);
pub const BTN_RTHUMB: EvCode = EvCode(nec::BTN_RTHUMB);
pub const BTN_DPAD_UP: EvCode = EvCode(nec::BTN_DPAD_UP);
pub const BTN_DPAD_DOWN: EvCode = EvCode(nec::BTN_DPAD_DOWN);
pub const BTN_DPAD_LEFT: EvCode = EvCode(nec::BTN_DPAD_LEFT);
pub const BTN_DPAD_RIGHT: EvCode = EvCode(nec::BTN_DPAD_RIGHT);
}