Metadata-Version: 2.4
Name: goxlrutil-api
Version: 0.0.1
Summary: Async Python library for communicating with the GoXLR Utility daemon
License: MIT
License-File: LICENSE
Keywords: goxlr,audio,streaming,api
Requires-Python: >=3.12,<4.0
Classifier: Development Status :: 3 - Alpha
Classifier: Framework :: AsyncIO
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio
Provides-Extra: webapp
Requires-Dist: fastapi (>=0.115) ; extra == "webapp"
Requires-Dist: httpx-ws (>=0.6)
Requires-Dist: httpx[http2] (>=0.27)
Requires-Dist: jinja2 (>=3.1) ; extra == "webapp"
Requires-Dist: jsonpatch (>=1.33)
Requires-Dist: python-multipart (>=0.0.9) ; extra == "webapp"
Requires-Dist: uvicorn[standard] (>=0.30) ; extra == "webapp"
Description-Content-Type: text/markdown

# goxlrutil-api

Async Python library for communicating with the
[GoXLR Utility daemon](https://github.com/GoXLR-on-Linux/goxlr-utility).

## Features

- **Three transports:** Unix socket, HTTP, WebSocket
- **Async-first** with optional sync wrappers
- **Live state cache:** incoming JSON Patch events are applied automatically
- **Typed API:** `dataclass`/`enum` models for all commands and responses

## Installation

```bash
pip install goxlrutil-api
# With demo webapp extras:
pip install "goxlrutil-api[webapp]"
```

## Quick start

```python
import asyncio
from goxlrutil_api import GoXLRClient
from goxlrutil_api.transport import UnixSocketTransport

async def main():
    transport = UnixSocketTransport()
    async with GoXLRClient(transport) as client:
        status = await client.get_status()
        for serial, mixer in status.mixers.items():
            print(serial, mixer.hardware.device_type)

asyncio.run(main())
```

## Transports

| Class | Usage |
|---|---|
| `UnixSocketTransport` | Local daemon via `/tmp/goxlr.socket` |
| `HttpTransport` | HTTP `POST /api/command` (local or remote) |
| `WebSocketTransport` | WebSocket `/api/websocket` – also receives live Patch events |

## Demo webapp

```bash
# With Poetry (development):
poetry install --all-extras
poetry run uvicorn apps.demo_webapp.main:app --reload

# Or with pip:
pip install "goxlrutil-api[webapp]"
uvicorn apps.demo_webapp.main:app --reload
```

Open http://localhost:8000

By default the webapp connects via **WebSocket** (`ws://localhost:14564/api/websocket`),
which enables live patch events – including button presses, volume changes, and fader updates.

To force Unix socket instead (no live events, request/response only):

```bash
GOXLR_USE_WS=0 poetry run uvicorn apps.demo_webapp.main:app --reload
```

The app starts even if the GoXLR daemon is not running – it will show a "not connected" status.

## Development

```bash
poetry install
poetry run pytest
poetry run ruff check src
poetry run pyright
```

## Protocol notes

- Unix socket uses a **4-byte big-endian** length-prefixed JSON frame.
- HTTP sends the same `DaemonRequest` JSON to `POST /api/command`.
- WebSocket wraps requests in `{"id": <uint>, "data": <DaemonRequest>}`.
- State updates from WebSocket are RFC 6902 JSON Patch operations.

