# SoundTouch Web UI

A modern single-page web application (SPA) for controlling Bose SoundTouch devices. Built with a JSON API backend and client-side JavaScript rendering for superior performance and maintainability.

## Architecture

```
Browser → Static HTML → JavaScript → JSON API → Go Server
                     ↓
               Client-Side Rendering
```

### Key Benefits
- **Better Performance**: No server-side template processing overhead
- **Improved Maintainability**: Clear separation between frontend (JavaScript) and backend (Go)
- **Real-time Experience**: Smooth client-side updates without page reloads
- **Mobile Ready**: The JSON API can power both this web interface and mobile applications

## Features

Based on captured WebSocket interactions and device API capabilities, this web UI provides:

### Device Management
- **Auto-discovery** of SoundTouch devices on the network
- **Real-time status monitoring** via WebSocket connections
- **Multi-device support** with centralized control
- **Connection status** indicators and health monitoring

### Playback Control
- **Play/Pause/Stop/Next/Previous** controls
- **Now playing information** with artwork, track details, and progress
- **Real-time updates** of playback state changes
- **Source selection** from available inputs (Spotify, TuneIn, Bluetooth, AUX, etc.)

### Audio Controls
- **Volume control** with real-time slider updates
- **Mute/Unmute** functionality
- **Bass adjustment** (on supported models)
- **Audio level monitoring** and statistics

### Preset Management
- **6 preset buttons** with visual feedback
- **Preset content display** showing station/playlist names
- **One-click preset selection**

### Advanced Features
- **WebSocket real-time updates** for instant state synchronization
- **Responsive design** optimized for desktop and mobile
- **Dark mode support** (auto-detects system preference)
- **Accessibility features** (keyboard navigation, screen reader support)
- **Network statistics** and device health monitoring

## Screenshots

### Main Device Overview
The main page shows all discovered devices with their current status, now-playing information, and quick controls.

### Detailed Device Control
Individual device pages provide full control over:
- Detailed now-playing information with artwork
- Comprehensive audio controls (volume, bass)
- Full preset and source selection
- Real-time status updates

## Installation

### Prerequisites
- Go 1.21 or later
- Access to SoundTouch devices on the same network
- Modern web browser with WebSocket support

### Building
```bash
# From project root
make build

# Or manually
cd cmd/soundtouch-player
go build -o soundtouch-player
```

### Running
```bash
# Run with default settings (port 8080)
./soundtouch-player

# Specify custom port
./soundtouch-player -port 8888

# Connect to specific device
./soundtouch-player -host 192.0.2.100
```

### Command Line Options
```
--port, -p string    HTTP port to listen on (default "8080", env PORT)
--bind string        Address for the HTTP listener: host, IP, or interface name (env BIND_ADDR)
--interface string   Network interface name for mDNS/UPnP discovery (env DISCOVERY_INTERFACE)
--devices strings    SoundTouch device IP(s) to add manually, repeatable (env SOUNDTOUCH_DEVICES)
--service-url string AfterTouch service base URL, e.g. https://soundtouch.local (env SERVICE_URL)
--service-ca string  Path to the AfterTouch service CA certificate (PEM) to trust (env SERVICE_CA)
--help, -h           Show help information
```

### Text-to-Speech (TTS)

TTS synthesis and the Bose `app_key` live in the AfterTouch service, not in
soundtouch-player, so the "Speak" feature proxies to the service's
`/setup/tts/speak` endpoint. To use it, point soundtouch-player at the service
with `--service-url`.

When the service is served over HTTPS with its own self-signed certificate
(the default), soundtouch-player also needs to trust the service's CA, or the
proxied call fails with `x509: certificate signed by unknown authority`. Pass
the CA with `--service-ca`; it is the service's `<dataDir>/certs/ca.crt`:

```bash
soundtouch-player \
  --service-url https://soundtouch.fritz.box \
  --service-ca /path/to/certs/ca.crt
```

The CA is appended to the system trust store, so a service URL that uses a
publicly trusted certificate keeps working without the flag. The target
speaker must be known to the service (it resolves the speaker against its own
device datastore).

## Usage

### Accessing the Interface
1. Start the application
2. Open your web browser and navigate to `http://localhost:8080`
3. Click "Discover Devices" to find SoundTouch devices on your network
4. Click on any device for detailed control, or use quick controls from the main page

### Device Discovery
The application automatically discovers SoundTouch devices using:
- **mDNS discovery** for local network devices
- **UPnP/SSDP discovery** as fallback
- **Manual device addition** via IP address

### Real-time Updates
The interface maintains WebSocket connections to each device for instant updates of:
- Now playing information and artwork
- Volume and audio settings changes
- Playback status (play/pause/stop)
- Connection status and device health

### Responsive Design
- **Desktop**: Full-featured interface with side-by-side panels
- **Tablet**: Optimized layout with touch-friendly controls
- **Mobile**: Stacked interface with gesture support

## API Endpoints

The web UI exposes a REST API for programmatic control:

### Device Management
```
GET  /api/devices           # List all discovered devices
GET  /api/device/{id}       # Get specific device info
POST /api/discover          # Trigger device discovery
```

### Device Control
```
GET  /api/control/{id}/play        # Start playback
GET  /api/control/{id}/pause       # Pause playback
GET  /api/control/{id}/stop        # Stop playback
GET  /api/control/{id}/next        # Next track
GET  /api/control/{id}/previous    # Previous track
POST /api/control/{id}/volume      # Set volume (body: {"level": 50})
GET  /api/control/{id}/mute        # Mute audio
GET  /api/control/{id}/unmute      # Unmute audio
POST /api/control/{id}/bass        # Set bass (body: {"level": 0})
GET  /api/control/{id}/preset?id=1 # Select preset
GET  /api/control/{id}/source?name=SPOTIFY # Select source
```

### WebSocket Events
Connect to `/ws` for real-time updates:
```javascript
const ws = new WebSocket('ws://localhost:8080/ws');
ws.onmessage = function(event) {
    const data = JSON.parse(event.data);
    // Handle device updates, status changes, etc.
};
```

## Architecture

### Single-Page Application Architecture
- **JSON API Backend**: Go server providing RESTful endpoints
- **Client-Side Rendering**: JavaScript handles all UI rendering
- **WebSocket Real-time**: Bi-directional real-time communication
- **No Template Dependencies**: Eliminates server-side template issues

### Backend Components
- **Discovery Service**: Finds and manages SoundTouch devices
- **WebSocket Manager**: Maintains real-time connections to devices
- **JSON API Server**: RESTful interface returning only JSON
- **Device Manager**: Tracks device state and health

### Frontend Components
- **Bootstrap 5**: Modern responsive UI framework
- **Vanilla JavaScript**: No framework dependencies, fast loading
- **WebSocket Client**: Real-time bidirectional communication
- **Dynamic Rendering**: Client-side HTML generation from JSON

### Communication Flow
1. **SPA Loading**: Single HTML file with embedded CSS and JavaScript
2. **JSON API**: Device discovery and control via REST endpoints
3. **WebSocket (Device)**: Real-time status updates from SoundTouch devices
4. **WebSocket (Browser)**: Real-time UI updates to web clients
5. **Client Rendering**: JavaScript dynamically creates all UI elements

## Development

### Project Structure
```
cmd/soundtouch-player/
├── main.go              # Application entry point and SPA routing
├── handlers/            # HTTP and WebSocket handlers
│   ├── handlers.go     # JSON API endpoints
│   └── websocket.go    # WebSocket management
├── webtypes/           # Type definitions
│   └── types.go        # Request/response types
├── static/             # Static assets
│   ├── index.html      # Single-page application
│   └── js/             # Legacy JS files (reference)
├── templates/          # Legacy templates (unused in SPA)
└── README.md          # This file
```

### Adding New Features
1. **API Endpoints**: Add new JSON routes in `setupRoutes()` and `handlers.go`
2. **WebSocket Events**: Extend event handlers in WebSocket client
3. **UI Components**: Add JavaScript rendering functions in `static/index.html`
4. **Device Controls**: Implement new control commands and update client-side handlers

### Testing
```bash
# Unit tests
go test ./...

# Manual testing with multiple devices
./soundtouch-player -port 8080

# API testing
curl http://localhost:8080/api/devices
```

## WebSocket Protocol Analysis

This UI is based on extensive analysis of captured SoundTouch WebSocket interactions, including:

### Message Types Implemented
- **SoundTouchSdkInfo**: Initial handshake and version info
- **nowPlayingUpdated**: Real-time track information
- **volumeUpdated**: Audio level changes
- **recentsUpdated**: Recently played items
- **userActivityUpdate**: User interaction notifications

### Request/Response Patterns
- **Device Information**: System details and capabilities
- **Audio Controls**: Volume, bass, mute controls
- **Playback Control**: Play/pause/stop/skip commands
- **Source Selection**: Input switching (Spotify, TuneIn, etc.)
- **Preset Management**: Saved station/playlist access

### Gabbo Protocol Features
- **Persistent Connections**: Maintains long-lived WebSocket connections
- **Request Correlation**: Uses request IDs for response matching
- **Real-time Events**: Instant updates for all device state changes
- **Bi-directional Control**: Both status monitoring and device control

## Browser Compatibility

### Supported Browsers
- **Chrome 80+** (recommended)
- **Firefox 75+**
- **Safari 13+**
- **Edge 80+**

### Required Features
- WebSocket support
- CSS Grid and Flexbox
- ES6 JavaScript features
- Responsive CSS media queries

## Security Considerations

- **Local Network Only**: Designed for local network device control
- **No Authentication**: Assumes trusted local network environment
- **CORS Policy**: Restricted to same-origin requests
- **WebSocket Security**: Uses same-origin WebSocket connections

## Troubleshooting

### Common Issues

**Devices Not Found**
- Ensure devices are on the same network
- Check firewall settings (ports 8090, 8080)
- Click "Discover Devices" button to trigger discovery

**WebSocket Connection Failed**
- Verify device supports WebSocket connections
- Check browser console for connection errors
- Refresh the page to reconnect WebSocket

**Control Commands Not Working**
- Check device is powered on and connected
- Verify device is not in exclusive mode (e.g., Spotify Connect active)
- Look for error notifications in the UI

**Page Shows Template Errors**
- This has been fixed in the SPA implementation
- Ensure you're accessing the correct URL (localhost:8080)
- Clear browser cache if you see old template-based content

### Debug Mode
Add verbose logging by setting environment variable:
```bash
export DEBUG=true
./soundtouch-player
```

## Contributing

This web UI is part of the larger SoundTouch Go library project. See the main project README for contribution guidelines.

### Architecture Benefits
The new SPA approach provides:
- **Better Performance**: No server-side template rendering
- **Easier Development**: Clear separation of frontend/backend
- **Mobile Ready**: Same JSON API can power mobile apps
- **Scalable**: Single-page app architecture

### Feature Requests
Based on WebSocket interaction analysis, potential future features:
- Zone/multi-room management
- Clock display control
- Software update management
- Advanced preset programming
- Progressive Web App (PWA) features

## License

Same as the parent project - see main repository LICENSE file.

## Acknowledgments

- Built on the comprehensive SoundTouch Go library
- UI design inspired by modern audio control interfaces
- WebSocket protocol reverse-engineered from captured device interactions
- Bootstrap and Bootstrap Icons for responsive design components
