# Changelog

## [Unreleased]

### Added

- `Gamepad.start_link/1`: starts a reader that sends each controller event to a `:sink`, either a pid (sent `{:gamepad, event}`) or a one-argument function. `:source` overrides the detected reader: `{:helper, path}` runs any program that writes `Gamepad.Wire` lines, and `{:linux, glob}` reads the joystick device files matching `glob`. Returns `:ignore` when the machine has no reader.
- `Gamepad.available?/0` and `Gamepad.source/0`: whether a reader exists and which one (`:linux`, `{:helper, path}` or `nil`).
- `Gamepad.Wire`: the line protocol (`device`, `gone`, `button`, `axis`) and `parse/1`, which turns a line into an event map — `:connected`, `:disconnected`, `:button` with `pressed`, `:axis` with `value` — or `nil`. Buttons and axes use Xbox layout names, listed by `buttons/0` and `axes/0`. Sticks run `-1.0..1.0`, triggers `0.0..1.0`.
- Linux reader: `/dev/input/js*` read directly and decoded by `Gamepad.Linux` (`devices/0,1`, which takes the glob to list, and `decode/2`); new device files are picked up every two seconds. The device files must be readable by the user.
- macOS reader: `priv/gamepad_helper`, built from `c_src/gamepad_helper.swift` on GameController.framework by `mix compile` when `swiftc` is on `PATH`. Without `swiftc` the build skips it and `start_link/1` returns `:ignore`.
- Windows reader: `priv/gamepad_helper.exe`, built from `c_src/gamepad_helper_win.c` on XInput by `mix compile` through `Makefile.win`. Requires the Visual Studio Build Tools (`cl` and `nmake`).
- Browser reader: `priv/static/gamepad.js`, whose `Gamepad.watch(sink, options)` polls a page's Gamepad API and calls `sink` with one `Gamepad.Wire` line per change. `options.every` polls on a millisecond timer instead of every animation frame, `stop()` on the returned handle ends it, and `Gamepad.available()` reports whether the page has the API. `Gamepad.browser_script/0` returns the file's path for serving.

### Fixed

- The macOS and Windows helpers exit when the program reading them closes their
  input, as it does on exiting or crashing. They kept running, one more for every
  run of the program.
- On Linux the device readers run inside the VM and end with it.
