gamepads

package module
v0.9.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 7, 2025 License: MIT Imports: 12 Imported by: 0

README

🎮 go-gamepad-bus

A high-performance, event-driven gamepad/joystick bus written in pure Go.

This module uses the notify functionality from the golang.org/x/sys package to monitor device connections and disconnections in real-time. It operates through scalable, customizable event channels and a clean subscription interface, enabling responsive and modular input handling.

🧩 Built for Stream Integrations

Designed with stream-based communication in mind, it fits naturally into single-stream connections such as WebSockets, gRPC streams, or WebRTC data channels, making it ideal for webview and networked applications.

gamepadbus is ideal for:

  • WebSockets
  • gRPC streams
  • WebRTC data channels
  • UDP/TCP connections
  • or any (unary) stream connection where live gamepad data needs to flow.

🐧 Platform Support

Currently, this module is Linux-only.

I built it to scratch my own itch, generally i don't publish my own packages/applications but I felt like trying it out — existing packages lacked the hot-reloading and interface style I truly wanted. I don’t intend to add support for Windows or macOS, but the architecture was designed to allow easy extension to other platforms. I might intend to add some tests later on.

Feel free to contribute support for other operating systems.

🚀 Features

  • Real-time detection of device connect/disconnect
  • Non-blocking, channel-based event model
  • Simple subscription mechanism
  • Designed for seamless integration with streaming protocols
Example
package main

import (
	"fmt"
	"github.com/doingharm/go-gamepad-bus"
	"log"
)

func filterConnections(e *gamepads.Event) bool {

	if e.Type == gamepads.ControlEventType {
		data := e.Data.(gamepads.ControlEvent)

		if data.Type == gamepads.Button {
			return true
		}
	}

	return false
}

func main() {

	// initialize the bus
	b, errCh, err := gamepads.New()
	if err != nil {
		log.Fatalln(err.Error())
	}
	defer b.Close()

	// read error messages
	go func() {
		for err = range errCh {
			log.Println(err.Error())
		}
	}()

	// set up a new event channel to listen to all devices.
	if ch := b.NewEventChannel(); ch != nil {
		for event := range ch.Ch {
			// if event is ConnectEvent, subscribe to the gamepad to receive all ControlEvents
			if event.Type == gamepads.ConnectEventType {
				if err = b.Subscribe(event.Data.(gamepads.Gamepad).ID); err != nil {
					log.Println(err.Error())
				}
			}

			fmt.Println(*event)

		}
	}

}

Documentation

Index

Constants

View Source
const (
	ErrNotifierNotInitialized      = "notifier not initialized"
	ErrOsNotSupported              = "os is not supported (yet)"
	ErrJoystickAlreadySubscribed   = "joystick is already subscribed"
	ErrJoystickAlreadyUnsubscribed = "joystick is already unsubscribed"
	ErrJoystickNotFound            = "joystick with id '%s' was not found"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Bus

type Bus interface {
	// NewEventChannel creates a new event channel that filters the events based on the provided filter functions.
	NewEventChannel(filters ...FilterFunc) (dest *EventChannel)
	// Gamepads returns a list of all the available gamepads connected to the system.
	Gamepads() (gamepads []Gamepad)
	// Subscribe subscribes to the joystick events for a specific gamepad ID.
	Subscribe(id string) (err error)
	// Unsubscribe unsubscribes from the joystick events for a specific gamepad ID.
	Unsubscribe(id string) (err error)
	// Close stops the bus and closes all the event channels.
	Close()
}

Bus is the main interface for interacting with the joystick events.

func New

func New() (b Bus, errCh <-chan error, err error)

This function creates a new gamepad bus instance and returns it, along with an error channel for any errors that may occur during the initialization process.

type ControlEvent

type ControlEvent struct {
	Timestamp uint32
	Type      ControlType
	Index     int
	Value     int16
}

ControlEvent represents a single control event, such as a button press or axis movement.

type ControlType

type ControlType uint8

ControlType represents the different types of control events.

const (
	Button       ControlType = 0x01
	Axes         ControlType = 0x02
	InitialState ControlType = 0x08
)

type Event

type Event struct {
	Type EventType
	ID   string
	Data any
}

Event represents a single event that can be sent on the channel.

type EventChannel

type EventChannel struct {
	Ctx        context.Context
	Ch         chan *Event
	ErrCh      chan error
	CancelFunc context.CancelFunc
}

EventChannel represents an event channel that can be used to receive events from gamepads.

type EventType

type EventType uint8

EventType represents the different types of events that can occur.

const (
	ConnectEventType EventType = iota
	DisconnectEventType
	ControlEventType
)

type FilterFunc

type FilterFunc func(e *Event) bool

FilterFunc is a function type used to filter events before they are sent to the event channel.

type Gamepad

type Gamepad struct {
	ID        string
	Model     string
	Buttons   int
	ButtonMap []int
	Axes      int
	AxesMap   []int
}

Gamepad holds information of a gamepad

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL