# `Gamepad`
[🔗](https://github.com/jaman/gamepad/blob/v0.1.0/lib/gamepad.ex#L1)

Reads the game controllers attached to this machine and hands their events to a
process or a function.

    {:ok, _pid} = Gamepad.start_link(sink: self())
    receive do
      {:gamepad, %{type: :button, button: :a, pressed: true}} -> :jump
    end

Events are the maps `Gamepad.Wire` describes: a controller connecting or going away,
a button pressed or released, an axis moving, with buttons and axes named in the
Xbox layout whatever the hardware. A pid sink receives each as `{:gamepad, event}`;
a function sink is called with the event.

What reads the hardware depends on the operating system:

  * Linux — `/dev/input/js*` is read inside the VM, one `Gamepad.Linux.Reader`
    process per device file, linked to the reader and decoded by `Gamepad.Linux`.
    New device files are looked for every two seconds. The files must be readable
    by the user; distributions usually grant that to the `input` group or to
    everyone
  * macOS — `priv/gamepad_helper`, a Swift program on GameController.framework that
    `mix compile` builds when `swiftc` is present; it names every controller macOS
    itself supports over Bluetooth or USB
  * Windows — `priv/gamepad_helper.exe`, a C program on XInput that `mix compile`
    builds through `Makefile.win` with the Visual Studio Build Tools

A helper is a port the reader owns; it exits once the port closes, which happens
when the reader stops, crashes, or its VM goes.

With no reader on the machine — a Linux box with no device files, a macOS build
without the helper — `start_link/1` returns `:ignore`. `available?/0` says
beforehand whether one exists.

A browser is read the same way by `priv/static/gamepad.js` (`browser_script/0`
gives the path to serve it from): `Gamepad.watch(sink, options)` polls the page's
Gamepad API and calls `sink` with one `Gamepad.Wire` line per change, buttons and
axes in the standard mapping named as the wire names them, triggers as axes;
`options.every` polls every that many milliseconds instead of every animation
frame; the handle's `stop()` ends it, sending `gone` for every controller.
`Gamepad.available()` says whether the page has the API at all. A server given
those lines reads them with `Gamepad.Wire.parse/1`.

# `sink`

```elixir
@type sink() :: pid() | (Gamepad.Wire.event() -&gt; any())
```

Where events go: a process, sent `{:gamepad, event}`, or a function of the event.

# `available?`

```elixir
@spec available?() :: boolean()
```

Whether this machine has a way to read controllers at all.

# `browser_script`

```elixir
@spec browser_script() :: Path.t()
```

The path of `gamepad.js`, the reader a browser page runs.

# `child_spec`

Returns a specification to start this module under a supervisor.

See `Supervisor`.

# `source`

```elixir
@spec source() :: :linux | {:linux, String.t()} | {:helper, Path.t()} | nil
```

The reader this machine would use: `:linux`, `{:helper, path}`, or `nil`.

`:linux` is answered on Linux whether or not a controller is plugged in, since one
may be plugged in later.

# `start_link`

```elixir
@spec start_link(keyword()) :: GenServer.on_start() | :ignore
```

Starts the reader.

## Options

  * `:sink` — required; a pid, sent `{:gamepad, event}` for each event, or a
    one-argument function called with each event
  * `:source` — a reader in place of the detected one, as `source/0` returns it; a
    `{:helper, path}` runs any program speaking the `Gamepad.Wire` protocol, and a
    `{:linux, glob}` reads the joystick device files matching `glob`

Returns `:ignore` when there is no reader.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
