SomaFM Player
A terminal-based music player for SomaFM internet radio stations, built with Rust and featuring a beautiful TUI (Terminal User Interface).
Features
- 🎵 Stream SomaFM Radio Stations - Access all available SomaFM channels
- 🖥️ Beautiful Terminal UI - Clean, intuitive TUI built with ratatui
- 🎛️ Volume Control - Adjust volume with
+
/-
keys (0-100%) - 📊 Live Spectrum Visualizer - Real-time audio frequency display with animated bars
- ⏯️ Pause/Resume Playback - Control playback with
P
key - 💾 Persistent Configuration - Remembers your last channel and settings
- 🎤 Real-time Metadata - Display current artist and track information
Quick Start
Install with a single command:
curl -sSL https://raw.githubusercontent.com/mpuccini/soma-play/main/install.sh | bash
Then run:
soma-player
Development Status
⚠️ This project is currently under active development and should be considered alpha software. While functional, you may encounter bugs, incomplete features, or breaking changes between versions.
Documentation Structure
This documentation is organized into several sections:
- User Guide: Everything you need to know to install and use SomaFM Player
- Developer Guide: Information for contributors and developers
- Reference: Detailed reference materials
Installation
Quick Install (Recommended)
Install SomaFM Player with a single command:
Using curl
curl -sSL https://raw.githubusercontent.com/mpuccini/soma-play/main/install.sh | bash
Using wget
wget -qO- https://raw.githubusercontent.com/mpuccini/soma-play/main/install.sh | bash
This script will:
- ✅ Automatically detect your platform (Linux x64 or macOS ARM64)
- ✅ Download the latest release binary
- ✅ Install to
~/.local/bin/soma-player
- ✅ Make the binary executable
- ✅ Verify the installation
Note: Make sure ~/.local/bin
is in your PATH. If not, the installer will show you how to add it.
Manual Installation
Prerequisites
Linux only - Install audio dependencies:
# Ubuntu/Debian
sudo apt-get install libasound2-dev
# Fedora/CentOS/RHEL
sudo dnf install alsa-lib-devel
# Arch Linux
sudo pacman -S alsa-lib
Download and Install Binary
-
Download the latest release:
- Go to Releases
- Download the appropriate archive for your platform:
soma-player-linux-x64.tar.gz
(Linux x86_64)soma-player-macos-arm64.tar.gz
(macOS Apple Silicon)
-
Extract and install:
# Extract the archive tar -xzf soma-player-*.tar.gz # Move to a directory in your PATH mv soma-player ~/.local/bin/ # or system-wide (requires sudo) sudo mv soma-player /usr/local/bin/ # Make executable (if needed) chmod +x ~/.local/bin/soma-player
-
Verify installation:
soma-player --version
Build from Source
If you prefer to build from source or need to customize the build:
-
Install Rust:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
Install system dependencies (Linux only):
# Ubuntu/Debian sudo apt-get install libasound2-dev pkg-config # Fedora/CentOS/RHEL sudo dnf install alsa-lib-devel pkg-config # Arch Linux sudo pacman -S alsa-lib pkg-config
-
Clone and build:
git clone https://github.com/mpuccini/soma-play.git cd soma-play cargo build --release
-
Install the binary:
# Copy to local bin directory cp target/release/soma-player ~/.local/bin/ # Or system-wide (requires sudo) sudo cp target/release/soma-player /usr/local/bin/
Updating
To update SomaFM Player, simply run the installation command again:
curl -sSL https://raw.githubusercontent.com/mpuccini/soma-play/main/install.sh | bash
This will automatically download and install the latest version.
Usage
This guide covers how to use SomaFM Player effectively.
First Run
When you first run soma-player
, you'll see the channel selection screen:
soma-player
The interface will show:
- A list of available SomaFM channels
- Channel descriptions and current listener counts
- Navigation instructions at the bottom
Basic Controls
Channel Selection Screen
- ↑/↓ Arrow Keys - Navigate through channels
- Enter - Select and start playing a channel
- Q - Quit the application
Playing Mode
Once a channel is selected and playing:
- C - Change channel (opens overlay)
- P - Pause/Resume playback
- +/= - Increase volume by 5%
- -/_ - Decrease volume by 5%
- Q/Esc - Quit application
Channel Selection Overlay
While music is playing, press C to open the channel selection overlay:
- ↑/↓ Arrow Keys - Navigate channels
- Enter - Switch to selected channel
- Esc - Cancel and return to playing mode
- Q - Quit application
Interface Elements
Main Display
The playing interface shows:
- Current Channel - Name and description
- Now Playing - Artist and track information (when available)
- Volume Level - Current volume percentage
- Spectrum Visualizer - Real-time frequency visualization
- Controls - Available keyboard shortcuts
Spectrum Visualizer
The built-in spectrum visualizer features:
- Real-time Animation - Responds to music frequency data
- Auto-scaling - Adapts to your terminal size
- Color Gradient - Low frequencies (blue) to high frequencies (red)
- Smart Pausing - Stops animating when playback is paused
Volume Control
Volume can be adjusted in 5% increments:
- Range: 0% to 100%
- Default: 50%
- Persistence: Volume settings are automatically saved
- Instant: Changes apply immediately
Popular Channels
Some recommended SomaFM channels to try:
- Groove Salad - Ambient/downtempo perfect for work
- Secret Agent - Spy jazz and lounge music
- Lush - Lush, gorgeous vocals
- Drone Zone - Ambient space music for deep listening
- Beat Blender - Electronic music
Tips for Best Experience
- Terminal Size: Use a terminal window at least 80x24 for optimal display
- Audio Quality: Ensure your system audio is properly configured
- Network: Stable internet connection recommended for uninterrupted streaming
- Colors: Enable 256-color support in your terminal for best visuals
Keyboard Shortcuts Quick Reference
Key | Action |
---|---|
↑/↓ | Navigate channels |
Enter | Select/Switch channel |
C | Open channel selector |
P | Pause/Resume |
+/= | Volume up |
-/_ | Volume down |
Q/Esc | Quit |
Configuration
SomaFM Player uses a TOML configuration file to store settings and preferences.
Configuration File Location
The configuration file is automatically created at:
~/.config/soma-player/config.toml
On different systems:
- Linux:
~/.config/soma-player/config.toml
- macOS:
~/.config/soma-player/config.toml
- Windows:
%APPDATA%\soma-player\config.toml
Default Configuration
When you first run the application, it creates a default configuration:
last_channel_id = ""
volume = 50
auto_start = false
Configuration Options
last_channel_id
- Type: String
- Default:
""
(empty) - Description: ID of the last played channel
- Auto-saved: Yes, updated automatically when you change channels
Example:
last_channel_id = "groovesalad"
volume
- Type: Integer
- Range: 0-100
- Default: 50
- Description: Audio volume level as a percentage
- Auto-saved: Yes, updated when you adjust volume with +/- keys
Example:
volume = 75
auto_start
- Type: Boolean
- Default:
false
- Description: Skip channel selection and automatically play the last channel
- Behavior:
true
: Starts playinglast_channel_id
immediatelyfalse
: Shows channel selection screen
Example:
auto_start = true
Complete Example Configuration
# Last played channel (auto-saved)
last_channel_id = "groovesalad"
# Volume level (0-100, auto-saved)
volume = 75
# Auto-start last channel on startup
auto_start = false
Logging Configuration
Logging behavior can be controlled via environment variables:
Log Levels
Set the RUST_LOG
environment variable:
# Debug level (very verbose)
RUST_LOG=debug soma-player
# Info level (default)
RUST_LOG=info soma-player
# Warning level (minimal logging)
RUST_LOG=warn soma-player
Log Files
Log files are automatically created at:
~/.config/soma-player/logs/soma-player.log
Features:
- Daily rotation: New log file each day
- Automatic cleanup: Old logs are removed
- Size management: Prevents excessive disk usage
Manual Configuration
You can manually edit the configuration file while the application is not running:
- Stop the application (if running)
- Edit the file:
nano ~/.config/soma-player/config.toml
- Save and restart the application
Troubleshooting Configuration
Configuration Not Saving
- Check file permissions for
~/.config/soma-player/
- Ensure the directory is writable
- Look for error messages in the logs
Configuration File Corrupted
If the configuration file becomes corrupted:
- Stop the application
- Remove the config file:
rm ~/.config/soma-player/config.toml
- Restart the application - it will create a new default configuration
Reset to Defaults
To reset all settings to defaults:
# Remove the entire configuration directory
rm -rf ~/.config/soma-player/
# Restart the application
soma-player
Advanced Configuration
Multiple Profiles
While not built-in, you can use different config directories:
# Use a custom config directory
XDG_CONFIG_HOME=/path/to/custom/config soma-player
System-wide Configuration
For system-wide defaults, you could:
- Create a template configuration
- Copy it to user directories as needed
- Use deployment scripts for multiple users
Configuration Schema
The configuration follows this schema:
# String: Channel ID from SomaFM API
last_channel_id = "string"
# Integer: Volume level 0-100
volume = 50
# Boolean: Auto-start behavior
auto_start = false
Future Configuration Options
Planned configuration options for future releases:
theme
- Color theme selectionkeybindings
- Custom keyboard shortcutsnetwork_timeout
- Connection timeout settingsretry_attempts
- Network retry configuration
Troubleshooting
Common issues and solutions for SomaFM Player.
Installation Issues
Binary Not Found
Problem: soma-player: command not found
Solutions:
-
Check PATH: Ensure
~/.local/bin
is in your PATHecho $PATH | grep -o ~/.local/bin
-
Add to PATH (if missing):
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc source ~/.bashrc
-
Verify installation:
ls -la ~/.local/bin/soma-player
Permission Denied
Problem: Permission denied
when running
Solution:
chmod +x ~/.local/bin/soma-player
Audio Dependencies (Linux)
Problem: Audio playback fails on Linux
Solutions:
# Ubuntu/Debian
sudo apt-get install libasound2-dev
# Fedora/CentOS/RHEL
sudo dnf install alsa-lib-devel
# Arch Linux
sudo pacman -S alsa-lib
Playback Issues
No Audio Output
Symptoms: Player starts but no sound
Debugging Steps:
-
Check system audio:
# Test system audio speaker-test -t sine -f 1000 -l 1
-
Check volume levels:
- System volume is not muted
- Player volume is above 0%
-
Audio device selection:
- Ensure correct audio output device is selected
- Try switching audio devices in system settings
Stream Connection Fails
Symptoms: "Failed to connect to stream"
Solutions:
-
Check internet connection:
ping somafm.com
-
Try different channel: Some channels may be temporarily unavailable
-
Check firewall: Ensure outbound HTTP connections are allowed
-
Restart application: Connection issues may be temporary
Stuttering Audio
Symptoms: Audio cuts out or stutters
Causes & Solutions:
- Network issues: Check internet stability
- High CPU usage: Close other applications
- Audio buffer issues: Restart the application
- System audio driver: Update audio drivers
Interface Issues
Display Problems
Problem: Interface looks corrupted or misaligned
Solutions:
-
Terminal size: Ensure terminal is at least 80x24
resize -s 24 80
-
Terminal compatibility: Use a modern terminal emulator
- ✅ Recommended: Alacritty, Kitty, iTerm2, Windows Terminal
- ⚠️ May have issues: Old terminals, basic consoles
-
Color support: Enable 256-color support
echo $TERM # Should show something like xterm-256color
Spectrum Visualizer Issues
Problem: Visualizer not showing or appears static
Solutions:
- Terminal size: Ensure sufficient space for visualizer
- Color support: Enable color in terminal
- Refresh rate: Try resizing terminal window
Keyboard Input Not Working
Problem: Keys don't respond
Solutions:
- Terminal focus: Ensure terminal window has focus
- Input capture: Some terminals may capture certain keys
- Restart: Try restarting the application
Configuration Issues
Settings Not Saving
Problem: Volume/channel changes don't persist
Debugging:
-
Check permissions:
ls -la ~/.config/soma-player/
-
Create directory (if missing):
mkdir -p ~/.config/soma-player
-
Check disk space:
df -h ~/.config
Configuration File Corrupted
Problem: Application fails to start with config error
Solution:
# Backup existing config
mv ~/.config/soma-player/config.toml ~/.config/soma-player/config.toml.backup
# Restart application (creates new default config)
soma-player
Performance Issues
High CPU Usage
Symptoms: System becomes slow while playing
Solutions:
-
Check running processes:
top | grep soma-player
-
Reduce terminal effects: Use simpler terminal themes
-
Update system: Ensure OS and drivers are current
Memory Usage
Symptoms: Memory usage grows over time
Solutions:
- Restart periodically: Long-running sessions may accumulate memory
- Check logs: Look for memory-related errors in logs
- Update: Ensure you're running the latest version
Network Issues
Proxy/Corporate Network
Problem: Cannot connect through corporate proxy
Solutions:
-
HTTP proxy: Set proxy environment variables
export http_proxy=http://proxy.company.com:8080 export https_proxy=http://proxy.company.com:8080
-
Direct connection: Try from personal network to isolate issue
Firewall Blocking
Problem: Connections blocked by firewall
Required access:
- Outbound HTTP (port 80)
- Outbound HTTPS (port 443)
- Audio streams (various ports)
Logging and Debugging
Enable Debug Logging
RUST_LOG=debug soma-player
Check Log Files
# View recent logs
tail -f ~/.config/soma-player/logs/soma-player.log
# Search for errors
grep -i error ~/.config/soma-player/logs/soma-player.log
Collect Debug Information
For bug reports, collect:
-
Version information:
soma-player --version
-
System information:
uname -a
-
Terminal information:
echo $TERM tput colors
-
Log excerpt (relevant error messages)
Getting Help
Before Reporting Issues
- Check this troubleshooting guide
- Search existing issues on GitHub
- Try with debug logging enabled
- Test basic functionality (can you run
soma-player --version
?)
Reporting Bugs
Include this information:
- Exact error message
- Steps to reproduce
- System information (OS, terminal)
- Log files (with debug enabled)
- Expected vs actual behavior
Community Support
- GitHub Issues: Technical problems and bugs
- GitHub Discussions: General questions and usage help
Quick Fixes
Complete Reset
If all else fails, completely reset the application:
# Stop the application
# Remove all application data
rm -rf ~/.config/soma-player
# Reinstall (if using install script)
curl -sSL https://raw.githubusercontent.com/mpuccini/soma-play/main/install.sh | bash
# Or rebuild from source
git clone https://github.com/mpuccini/soma-play.git
cd soma-play
cargo build --release
cp target/release/soma-player ~/.local/bin/
Emergency Commands
If the interface becomes unresponsive:
- Ctrl+C: Force quit (may leave terminal in bad state)
- Ctrl+Z: Suspend (then
fg
to resume orkill %1
to terminate) - Close terminal: Last resort
Architecture
Technical overview of SomaFM Player's internal structure and design.
Project Structure
SomaFM Player follows a modular architecture with clear separation of concerns:
src/
├── main.rs # Application entry point and CLI handling
├── lib.rs # Module declarations and exports
├── api/ # SomaFM API integration
│ ├── mod.rs # API module exports
│ ├── client.rs # HTTP client for SomaFM API
│ └── channels.rs # Channel data structures and parsing
├── audio/ # Audio playback engine
│ ├── mod.rs # Audio module exports
│ ├── player.rs # Main audio player implementation
│ ├── stream.rs # Audio stream handling
│ └── commands.rs # Player command definitions
├── config/ # Configuration management
│ ├── mod.rs # Config module exports
│ ├── settings.rs # Configuration data structures
│ └── file.rs # File I/O operations
├── models/ # Data structures and types
│ ├── mod.rs # Models module exports
│ ├── channel.rs # Channel data model
│ ├── player.rs # Player state model
│ ├── errors.rs # Custom error types
│ └── spectrum.rs # Spectrum visualizer data
└── ui/ # Terminal User Interface
├── mod.rs # UI module exports
├── app.rs # Main application state
├── player.rs # Player interface screen
├── channels.rs # Channel selection screen
└── spectrum.rs # Spectrum visualizer widget
Core Components
1. Main Application (main.rs
)
Responsibilities:
- Command-line argument parsing
- Logging initialization
- Error handling setup
- Application bootstrap
Key Features:
- Early argument processing (--version, --help)
- Color error reporting with
color-eyre
- Structured logging with
tracing
// Simplified flow fn main() -> Result<()> { // 1. Parse CLI args // 2. Setup logging // 3. Load configuration // 4. Initialize TUI // 5. Run main loop }
2. API Layer (api/
)
Purpose: Interface with SomaFM's public API and stream endpoints.
Components:
client.rs
: HTTP client wrapper aroundreqwest
channels.rs
: Channel data parsing and caching
Key Features:
- Async HTTP requests with retry logic
- Channel list caching
- ICY metadata parsing for "now playing" info
- Error handling for network issues
#![allow(unused)] fn main() { pub struct SomaClient { client: reqwest::Client, base_url: String, } impl SomaClient { pub async fn get_channels() -> Result<Vec<Channel>>; pub async fn get_stream_url(channel_id: &str) -> Result<String>; } }
3. Audio Engine (audio/
)
Purpose: Handle audio streaming and playback control.
Components:
player.rs
: Main audio player usingrodio
stream.rs
: Stream management and bufferingcommands.rs
: Command patterns for player control
Key Features:
- Cross-platform audio output via
rodio
- Volume control with persistent settings
- Pause/resume functionality
- Stream reconnection handling
#![allow(unused)] fn main() { pub enum PlayerCommand { Play(String), // Stream URL Pause, Resume, SetVolume(f32), Stop, } pub struct AudioPlayer { sink: Option<rodio::Sink>, volume: f32, state: PlayerState, } }
4. Configuration (config/
)
Purpose: Manage application settings and persistence.
Components:
settings.rs
: Configuration data structuresfile.rs
: TOML file I/O operations
Key Features:
- TOML-based configuration
- Automatic directory creation
- Default value handling
- Type-safe configuration access
#![allow(unused)] fn main() { #[derive(Serialize, Deserialize, Debug, Clone)] pub struct Config { pub last_channel_id: Option<String>, pub volume: u8, pub auto_start: bool, } }
5. Data Models (models/
)
Purpose: Define core data structures and business logic.
Components:
channel.rs
: SomaFM channel representationplayer.rs
: Player state managementerrors.rs
: Custom error types with contextspectrum.rs
: Spectrum analyzer data structures
Key Features:
- Serde serialization support
- Rich error types with stack traces
- Type safety throughout the application
#![allow(unused)] fn main() { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Channel { pub id: String, pub title: String, pub description: String, pub listeners: u32, pub genre: String, } }
6. User Interface (ui/
)
Purpose: Terminal-based user interface using ratatui
.
Components:
app.rs
: Application state machineplayer.rs
: Main playback interfacechannels.rs
: Channel selection screensspectrum.rs
: Real-time spectrum visualizer
Key Features:
- Event-driven architecture
- Responsive layout system
- Real-time spectrum visualization
- Keyboard input handling
#![allow(unused)] fn main() { pub enum AppState { ChannelSelection, Playing, ChannelOverlay, Quitting, } pub struct App { pub state: AppState, pub channels: Vec<Channel>, pub selected_channel: Option<usize>, pub player_state: PlayerState, } }
Data Flow
Application Startup
- CLI Parsing → Parse command-line arguments
- Logging Setup → Initialize structured logging
- Config Loading → Load/create configuration file
- API Initialization → Fetch channel list from SomaFM
- UI Startup → Initialize terminal interface
- Event Loop → Start main application loop
Channel Selection Flow
- User Input → Keyboard navigation
- UI Update → Highlight selected channel
- Channel Selection → User presses Enter
- Stream Resolution → Get stream URL from API
- Audio Playback → Start audio player
- State Transition → Switch to playing mode
Audio Playback Flow
- Stream Request → HTTP request to stream URL
- Stream Decoding → Audio format detection and decoding
- Audio Output → Platform-specific audio output
- Metadata Parsing → Extract "now playing" information
- UI Updates → Display current track info
- Spectrum Analysis → Generate frequency data for visualizer
Threading Model
Main Thread
- UI rendering and event handling
- Configuration management
- Application state coordination
Audio Thread (via rodio
)
- Audio decoding and playback
- Stream buffering
- Volume control
Network Thread (via tokio
)
- HTTP requests to SomaFM API
- Stream data fetching
- Metadata updates
Error Handling Strategy
Error Types
- Network Errors: API timeouts, connection failures
- Audio Errors: Codec issues, hardware problems
- Configuration Errors: File I/O, parsing failures
- UI Errors: Terminal capabilities, rendering issues
Error Propagation
#![allow(unused)] fn main() { // Custom Result type with context pub type Result<T> = std::result::Result<T, SomaError>; // Rich error context #[derive(Debug, thiserror::Error)] pub enum SomaError { #[error("Network error: {0}")] Network(#[from] reqwest::Error), #[error("Audio error: {0}")] Audio(String), #[error("Configuration error: {0}")] Config(#[from] toml::de::Error), } }
Performance Considerations
Memory Management
- Channel List Caching: Avoid repeated API calls
- Audio Buffering: Optimal buffer sizes for smooth playback
- UI Rendering: Efficient terminal updates
Network Optimization
- Connection Reuse: HTTP client connection pooling
- Retry Logic: Exponential backoff for failed requests
- Stream Recovery: Automatic reconnection on network issues
CPU Usage
- Spectrum Analysis: Optimized FFT calculations
- UI Updates: Minimal redraws, only when necessary
- Event Processing: Efficient input handling
Dependencies
Core Dependencies
ratatui
: Terminal UI frameworkrodio
: Cross-platform audio playbackreqwest
: HTTP client with async supporttokio
: Async runtimeserde
: Serialization frameworktoml
: Configuration file format
Development Dependencies
tracing
: Structured loggingcolor-eyre
: Enhanced error reportingtempfile
: Testing utilities
Testing Strategy
Unit Tests
- Configuration loading/saving
- Error type conversions
- Data model validation
- API response parsing
Integration Tests
- Audio playback scenarios
- UI state transitions
- Configuration persistence
- Network error handling
Test Structure
tests/
├── integration/
│ ├── config_tests.rs
│ ├── audio_tests.rs
│ └── ui_tests.rs
└── common/
└── test_helpers.rs
Future Architecture Considerations
Planned Enhancements
- Plugin System: Extensible architecture for additional features
- Themes Support: Customizable UI themes and colors
- Keyboard Customization: User-defined keybindings
- Multi-instance Support: Multiple concurrent streams
- Remote Control: HTTP API for external control
Scalability
- Modular Design: Easy to add new features
- Clear Interfaces: Well-defined module boundaries
- Minimal Coupling: Loose dependencies between components
- Testable Code: Architecture supports comprehensive testing
This architecture provides a solid foundation for a reliable, maintainable, and extensible audio streaming application.
API Reference
Developer reference for SomaFM Player's internal APIs and data structures.
Note: This page covers the internal Rust API. For the complete generated API documentation with full type information, see the API Documentation section.
Core Modules
soma_player::config
Configuration management for persistent settings.
Config
#![allow(unused)] fn main() { pub struct Config { pub last_channel_id: Option<String>, pub volume: u8, pub auto_start: bool, } }
Methods:
Config::load() -> Result<Config>
- Load configuration from fileConfig::save(&self) -> Result<()>
- Save configuration to fileConfig::default_path() -> PathBuf
- Get default config file path
Example:
#![allow(unused)] fn main() { use soma_player::config::Config; let mut config = Config::load()?; config.volume = 75; config.save()?; }
soma_player::models
Core data structures and types.
Channel
#![allow(unused)] fn main() { pub struct Channel { pub id: String, pub title: String, pub description: String, pub listeners: u32, pub genre: String, } }
Represents a SomaFM radio channel with metadata.
PlayerState
#![allow(unused)] fn main() { pub enum PlayerState { Stopped, Playing, Paused, Buffering, Error(String), } }
Current state of the audio player.
SomaError
#![allow(unused)] fn main() { pub enum SomaError { Network(reqwest::Error), Audio(String), Config(toml::de::Error), Io(std::io::Error), Parse(String), } }
Comprehensive error types with context information.
soma_player::api
SomaFM API integration and HTTP client.
SomaClient
#![allow(unused)] fn main() { pub struct SomaClient { // Internal HTTP client } }
Methods:
SomaClient::new() -> Self
- Create new API clientget_channels(&self) -> Result<Vec<Channel>>
- Fetch available channelsget_stream_url(&self, channel_id: &str) -> Result<String>
- Get stream URL
Example:
#![allow(unused)] fn main() { use soma_player::api::SomaClient; let client = SomaClient::new(); let channels = client.get_channels().await?; let stream_url = client.get_stream_url("groovesalad").await?; }
soma_player::audio
Audio playback engine and controls.
AudioPlayer
#![allow(unused)] fn main() { pub struct AudioPlayer { // Audio sink and state } }
Methods:
AudioPlayer::new() -> Result<Self>
- Create new audio playerplay(&mut self, url: String) -> Result<()>
- Start playing streampause(&mut self) -> Result<()>
- Pause playbackresume(&mut self) -> Result<()>
- Resume playbackset_volume(&mut self, volume: f32) -> Result<()>
- Set volume (0.0-1.0)stop(&mut self) -> Result<()>
- Stop playback
PlayerCommand
#![allow(unused)] fn main() { pub enum PlayerCommand { Play(String), Pause, Resume, SetVolume(f32), Stop, } }
Commands for controlling audio playback.
Example:
#![allow(unused)] fn main() { use soma_player::audio::{AudioPlayer, PlayerCommand}; let mut player = AudioPlayer::new()?; player.play("http://stream.url".to_string())?; player.set_volume(0.75)?; }
soma_player::ui
Terminal user interface components.
App
#![allow(unused)] fn main() { pub struct App { pub state: AppState, pub channels: Vec<Channel>, pub selected_channel: Option<usize>, // ... other fields } }
Main application state container.
AppState
#![allow(unused)] fn main() { pub enum AppState { ChannelSelection, Playing, ChannelOverlay, Quitting, } }
Current UI state for the application.
Methods:
App::new(channels: Vec<Channel>) -> Self
- Create new app instancehandle_input(&mut self, event: KeyEvent) -> Result<()>
- Process keyboard inputupdate(&mut self) -> Result<()>
- Update application stateshould_quit(&self) -> bool
- Check if app should exit
Data Flow APIs
Configuration Flow
#![allow(unused)] fn main() { // Load configuration let config = Config::load().unwrap_or_default(); // Use configuration if config.auto_start { // Auto-start last channel } // Save changes config.volume = new_volume; config.save()?; }
Channel Management
#![allow(unused)] fn main() { // Fetch channels from API let client = SomaClient::new(); let channels = client.get_channels().await?; // Select channel let selected = &channels[index]; let stream_url = client.get_stream_url(&selected.id).await?; }
Audio Control
#![allow(unused)] fn main() { // Initialize player let mut player = AudioPlayer::new()?; // Control playback player.play(stream_url)?; player.set_volume(0.8)?; player.pause()?; player.resume()?; }
UI Event Handling
#![allow(unused)] fn main() { // Create app let mut app = App::new(channels); // Main event loop loop { if let Ok(event) = event::read() { app.handle_input(event)?; app.update()?; if app.should_quit() { break; } } } }
Error Handling
Result Types
All fallible operations return Result<T, SomaError>
:
#![allow(unused)] fn main() { pub type Result<T> = std::result::Result<T, SomaError>; }
Error Context
Errors include rich context information:
#![allow(unused)] fn main() { use soma_player::Result; fn example_function() -> Result<()> { config.load() .map_err(|e| SomaError::Config(e))?; Ok(()) } }
Error Conversion
Automatic conversion from standard error types:
#![allow(unused)] fn main() { impl From<std::io::Error> for SomaError { fn from(err: std::io::Error) -> Self { SomaError::Io(err) } } }
Async Patterns
API Calls
use tokio; #[tokio::main] async fn main() -> Result<()> { let client = SomaClient::new(); let channels = client.get_channels().await?; Ok(()) }
Non-blocking Operations
#![allow(unused)] fn main() { // Spawn background task for API calls let handle = tokio::spawn(async move { client.get_channels().await }); // Continue with UI work // ... // Get result when needed let channels = handle.await??; }
Testing APIs
Unit Testing
#![allow(unused)] fn main() { #[cfg(test)] mod tests { use super::*; use tempfile::tempdir; #[test] fn test_config_save_load() { let dir = tempdir().unwrap(); let config_path = dir.path().join("config.toml"); let config = Config { volume: 75, last_channel_id: Some("groovesalad".to_string()), auto_start: true, }; config.save_to_path(&config_path).unwrap(); let loaded = Config::load_from_path(&config_path).unwrap(); assert_eq!(config.volume, loaded.volume); } } }
Mock Objects
#![allow(unused)] fn main() { // Mock API client for testing pub struct MockSomaClient { channels: Vec<Channel>, } impl MockSomaClient { pub fn new(channels: Vec<Channel>) -> Self { Self { channels } } } #[async_trait] impl ApiClient for MockSomaClient { async fn get_channels(&self) -> Result<Vec<Channel>> { Ok(self.channels.clone()) } } }
Extension Points
Custom Audio Backends
#![allow(unused)] fn main() { pub trait AudioBackend { fn play(&mut self, url: String) -> Result<()>; fn pause(&mut self) -> Result<()>; fn set_volume(&mut self, volume: f32) -> Result<()>; } // Implement for different audio systems impl AudioBackend for RodioBackend { /* ... */ } impl AudioBackend for PulseAudioBackend { /* ... */ } }
Custom UI Themes
#![allow(unused)] fn main() { pub struct Theme { pub primary_color: Color, pub secondary_color: Color, pub background_color: Color, pub accent_color: Color, } impl App { pub fn set_theme(&mut self, theme: Theme) { self.theme = theme; } } }
Performance APIs
Caching
#![allow(unused)] fn main() { use std::collections::HashMap; pub struct ChannelCache { cache: HashMap<String, Vec<Channel>>, ttl: Duration, } impl ChannelCache { pub fn get_or_fetch(&mut self, key: &str) -> Result<Vec<Channel>> { // Return cached data or fetch new } } }
Metrics
#![allow(unused)] fn main() { pub struct Metrics { pub api_calls: u64, pub cache_hits: u64, pub audio_buffer_underruns: u64, } impl App { pub fn get_metrics(&self) -> Metrics { // Return current metrics } } }
Constants and Configuration
Default Values
#![allow(unused)] fn main() { pub const DEFAULT_VOLUME: u8 = 50; pub const DEFAULT_CONFIG_DIR: &str = ".config/soma-player"; pub const API_BASE_URL: &str = "https://somafm.com"; pub const STREAM_TIMEOUT: Duration = Duration::from_secs(30); }
Build Information
#![allow(unused)] fn main() { pub const VERSION: &str = env!("CARGO_PKG_VERSION"); pub const BUILD_TARGET: &str = env!("TARGET"); pub const BUILD_TIMESTAMP: &str = env!("BUILD_TIMESTAMP"); }
Feature Flags
Conditional Compilation
#![allow(unused)] fn main() { #[cfg(feature = "spectrum-analyzer")] pub mod spectrum { // Spectrum analyzer functionality } #[cfg(not(feature = "spectrum-analyzer"))] pub mod spectrum { // Stub implementation } }
This API reference provides the essential interfaces for working with SomaFM Player's codebase. For complete type information and implementation details, refer to the generated API Documentation.
Contributing
Welcome to SomaFM Player! We're excited to have you contribute to this project.
Getting Started
Prerequisites
Before you begin, ensure you have the following installed:
-
Rust (1.70 or later)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
-
System Dependencies (Linux only)
# Ubuntu/Debian sudo apt-get install libasound2-dev pkg-config # Fedora/CentOS/RHEL sudo dnf install alsa-lib-devel pkg-config # Arch Linux sudo pacman -S alsa-lib pkg-config
-
Git
git --version
Development Setup
-
Fork the repository on GitHub
-
Clone your fork
git clone https://github.com/yourusername/soma-play.git cd soma-play
-
Add upstream remote
git remote add upstream https://github.com/mpuccini/soma-play.git
-
Install development tools
# Code formatting rustup component add rustfmt # Linting rustup component add clippy # Documentation cargo install mdbook # Security auditing cargo install cargo-audit # Test coverage cargo install cargo-tarpaulin
-
Build and test
cargo build cargo test cargo run
Development Workflow
1. Create a Feature Branch
git checkout -b feature/your-feature-name
Branch Naming Conventions:
feature/
- New featuresfix/
- Bug fixesdocs/
- Documentation updatesrefactor/
- Code refactoringtest/
- Test improvements
2. Make Your Changes
Follow our coding standards and guidelines (see below).
3. Test Your Changes
# Run all tests
cargo test
# Run tests with output
cargo test -- --nocapture
# Run specific test module
cargo test config::tests
# Check code formatting
cargo fmt --check
# Run linter
cargo clippy -- -D warnings
# Generate test coverage
cargo tarpaulin --out Html
4. Commit Your Changes
Commit Message Format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat
- New featurefix
- Bug fixdocs
- Documentationstyle
- Code style changesrefactor
- Code refactoringtest
- Test additions/improvementschore
- Maintenance tasks
Examples:
git commit -m "feat(audio): add volume fade transitions"
git commit -m "fix(ui): resolve channel list scrolling issue"
git commit -m "docs(api): update configuration examples"
5. Push and Create Pull Request
git push origin feature/your-feature-name
Then create a pull request on GitHub.
Coding Standards
Rust Code Style
-
Use
cargo fmt
for consistent formatting -
Follow Rust naming conventions
snake_case
for functions and variablesPascalCase
for types and structsSCREAMING_SNAKE_CASE
for constants
-
Add documentation comments
#![allow(unused)] fn main() { /// Plays audio from the specified stream URL. /// /// # Arguments /// * `url` - The stream URL to play from /// /// # Examples /// ``` /// let mut player = AudioPlayer::new()?; /// player.play("http://stream.somafm.com/groovesalad".to_string())?; /// ``` pub fn play(&mut self, url: String) -> Result<()> { // Implementation } }
-
Handle errors properly
#![allow(unused)] fn main() { // Good: Use Result types and proper error handling fn load_config() -> Result<Config, ConfigError> { let content = fs::read_to_string(&path) .map_err(ConfigError::FileRead)?; toml::from_str(&content) .map_err(ConfigError::Parse) } // Avoid: Using unwrap() or expect() in library code }
-
Use meaningful variable names
#![allow(unused)] fn main() { // Good let selected_channel_index = 0; let stream_url = "http://..."; // Avoid let i = 0; let url = "http://..."; }
Module Organization
- Keep modules focused - Each module should have a single responsibility
- Use clear imports - Prefer explicit imports over glob imports
- Organize by feature - Group related functionality together
#![allow(unused)] fn main() { // Good: Explicit imports use crate::config::Config; use crate::models::{Channel, PlayerState}; // Avoid: Glob imports (in most cases) use crate::models::*; }
Error Handling
- Use custom error types with
thiserror
- Provide context for errors
- Convert errors at module boundaries
#![allow(unused)] fn main() { #[derive(Debug, thiserror::Error)] pub enum AudioError { #[error("Failed to initialize audio device: {0}")] DeviceInit(String), #[error("Stream error: {0}")] Stream(#[from] StreamError), #[error("Invalid volume level: {level} (must be 0-100)")] InvalidVolume { level: u8 }, } }
Testing Guidelines
- Write unit tests for all public functions
- Use integration tests for complex workflows
- Mock external dependencies in tests
- Test error conditions as well as success cases
#![allow(unused)] fn main() { #[cfg(test)] mod tests { use super::*; use tempfile::tempdir; #[test] fn test_config_save_and_load() { let dir = tempdir().unwrap(); let config_path = dir.path().join("config.toml"); let original_config = Config { volume: 75, last_channel_id: Some("groovesalad".to_string()), auto_start: true, }; // Test save original_config.save_to_path(&config_path).unwrap(); // Test load let loaded_config = Config::load_from_path(&config_path).unwrap(); assert_eq!(original_config.volume, loaded_config.volume); assert_eq!(original_config.last_channel_id, loaded_config.last_channel_id); assert_eq!(original_config.auto_start, loaded_config.auto_start); } #[test] fn test_invalid_volume_returns_error() { let mut player = AudioPlayer::new().unwrap(); let result = player.set_volume(150); // Invalid volume > 100 assert!(result.is_err()); } } }
Documentation
Code Documentation
- Document all public APIs with examples
- Include usage examples in documentation
- Document error conditions and return types
- Keep documentation up to date with code changes
User Documentation
- Update relevant guide sections when adding features
- Include configuration examples for new settings
- Add troubleshooting entries for known issues
- Update the changelog with user-facing changes
Building Documentation
# Generate API documentation
cargo doc --open
# Build user guide
cd docs && mdbook serve --open
# Build all documentation
./build-docs.sh
Feature Development
Adding New Features
- Create an issue describing the feature
- Discuss the approach with maintainers
- Start with tests (TDD approach when possible)
- Implement incrementally with small, focused commits
- Update documentation before marking as complete
Feature Guidelines
- Maintain backward compatibility when possible
- Add configuration options for user preferences
- Consider performance impact of new features
- Ensure cross-platform compatibility
Example: Adding a New Feature
#![allow(unused)] fn main() { // 1. Define the feature interface pub trait Equalizer { fn set_bands(&mut self, bands: Vec<f32>) -> Result<()>; fn get_bands(&self) -> Vec<f32>; } // 2. Add configuration support #[derive(Serialize, Deserialize)] pub struct EqualizerConfig { pub enabled: bool, pub bands: Vec<f32>, } // 3. Implement the feature pub struct GraphicEqualizer { bands: Vec<f32>, enabled: bool, } // 4. Add tests #[cfg(test)] mod tests { #[test] fn test_equalizer_bands() { let mut eq = GraphicEqualizer::new(); let bands = vec![0.0, 2.0, 4.0, 2.0, 0.0]; eq.set_bands(bands.clone()).unwrap(); assert_eq!(eq.get_bands(), bands); } } // 5. Update UI integration impl App { pub fn toggle_equalizer(&mut self) -> Result<()> { // Implementation } } }
Bug Fixes
Finding and Reporting Bugs
- Search existing issues before creating new ones
- Provide detailed reproduction steps
- Include system information (OS, Rust version, etc.)
- Add logs or error messages when applicable
Fixing Bugs
- Write a test that reproduces the bug
- Fix the issue with minimal changes
- Verify the test passes with your fix
- Check for similar issues in related code
Performance Considerations
Optimization Guidelines
- Profile before optimizing - Measure, don't guess
- Focus on hot paths - Audio playback, UI rendering
- Consider memory usage - Avoid unnecessary allocations
- Benchmark changes - Ensure improvements are real
Performance Testing
# Run benchmarks (if available)
cargo bench
# Profile memory usage
cargo run --release -- --log-level=debug
# Monitor resource usage during development
htop # or similar system monitor
Security
Security Guidelines
- Validate all inputs from external sources
- Use secure HTTP for API communications
- Handle credentials safely (if any)
- Audit dependencies regularly
# Run security audit
cargo audit
# Check for known vulnerabilities
cargo audit --database advisory
Release Process
Preparing a Release
- Update version numbers in
Cargo.toml
- Update CHANGELOG.md with new features and fixes
- Run full test suite with
cargo test
- Generate and review documentation
- Test on target platforms
Release Checklist
- All tests pass
- Documentation is up to date
- Changelog is updated
- Version numbers are bumped
- No security vulnerabilities
- Performance regressions checked
- Cross-platform compatibility verified
Community Guidelines
Communication
- Be respectful and inclusive
- Ask questions when you're unsure
- Provide constructive feedback in reviews
- Help newcomers get started
Code Reviews
- Review for correctness and style
- Suggest improvements rather than just pointing out problems
- Acknowledge good work and clever solutions
- Be open to feedback on your own code
Issue Management
- Provide clear descriptions for issues and PRs
- Link related issues and PRs
- Update status as work progresses
- Close issues when resolved
Getting Help
Resources
- Documentation: User Guide and API Reference
- Source Code: Well-commented and documented
- Issues: Check existing issues for similar problems
- Discussions: GitHub Discussions for questions and ideas
Contact
- GitHub Issues: For bugs and feature requests
- GitHub Discussions: For questions and general discussion
- Pull Requests: For code contributions and reviews
Thank you for contributing to SomaFM Player! Your efforts help make this project better for everyone. 🎵
Controls Reference
Complete keyboard controls for SomaFM Player.
Overview
SomaFM Player has three main interface modes, each with its own set of controls:
- Channel Selection Screen - Initial startup screen
- Playing Mode - Main playback interface
- Channel Selection Overlay - Quick channel switching while playing
Channel Selection Screen
This is the first screen you see when starting the application.
Key | Action | Description |
---|---|---|
↑ | Navigate Up | Move selection to previous channel |
↓ | Navigate Down | Move selection to next channel |
Enter | Select Channel | Start playing the selected channel |
Q | Quit | Exit the application |
Mouse Support
- Scroll Wheel: Navigate through channels (if terminal supports it)
- Click: Select channel (if terminal supports it)
Playing Mode
Once you've selected a channel and music is playing.
Playback Controls
Key | Action | Description |
---|---|---|
P | Pause/Resume | Toggle playback state |
Q | Quit | Exit the application |
Esc | Quit | Alternative quit key |
Volume Controls
Key | Action | Description |
---|---|---|
+ | Volume Up | Increase volume by 5% |
= | Volume Up | Alternative volume up key |
- | Volume Down | Decrease volume by 5% |
_ | Volume Down | Alternative volume down key |
Volume Range: 0% to 100%
Volume Step: 5% per key press
Auto-save: Volume changes are automatically saved
Channel Controls
Key | Action | Description |
---|---|---|
C | Change Channel | Open channel selection overlay |
Channel Selection Overlay
Accessible by pressing C while in playing mode.
Key | Action | Description |
---|---|---|
↑ | Navigate Up | Move selection to previous channel |
↓ | Navigate Down | Move selection to next channel |
Enter | Switch Channel | Change to selected channel and close overlay |
Esc | Cancel | Close overlay without changing channel |
Q | Quit | Exit the application |
Behavior Notes
- Seamless switching: Audio continues playing while browsing
- Instant change: New channel starts immediately when selected
- Previous state: If cancelled, returns to current playing channel
Special Key Combinations
Force Quit
Key Combination | Action | When to Use |
---|---|---|
Ctrl+C | Force Quit | If application becomes unresponsive |
Ctrl+Z | Suspend | Pause process (use fg to resume) |
⚠️ Note: Force quit may leave your terminal in an inconsistent state. Use normal quit (Q) when possible.
Universal Controls
These keys work in all modes:
Key | Available In | Action |
---|---|---|
Q | All modes | Quit application |
Ctrl+C | All modes | Force quit |
Key Behavior Details
Navigation Keys
- Continuous scrolling: Hold arrow keys to scroll quickly
- Wrap-around: Navigation wraps from bottom to top and vice versa
- Visual feedback: Current selection is highlighted
Volume Keys
- Immediate effect: Volume changes apply instantly
- Visual feedback: Volume level displayed in interface
- Bounds checking: Cannot go below 0% or above 100%
- Persistence: Settings saved automatically
Response Time
- Instant: All key presses register immediately
- No delay: No artificial delays or key repeat issues
- Reliable: Input processing is prioritized
Accessibility Features
Keyboard-Only Operation
- No mouse required: Full functionality via keyboard
- Clear navigation: Obvious visual indicators for current selection
- Consistent patterns: Similar controls across all modes
Visual Indicators
- Highlighted selection: Current item clearly marked
- Status display: Current channel, volume, and playback state visible
- Color coding: Different colors for different interface elements
Terminal Compatibility
Recommended Terminals
- ✅ Alacritty: Full compatibility
- ✅ Kitty: Full compatibility
- ✅ iTerm2 (macOS): Full compatibility
- ✅ Windows Terminal: Full compatibility
- ✅ GNOME Terminal: Full compatibility
Key Support Notes
- Function keys: Not used (for maximum compatibility)
- Alt combinations: Not used (may conflict with terminal)
- Standard keys only: Uses only common, reliable key codes
Customization
Current Limitations
- Fixed keybindings: Keys cannot be customized currently
- Future feature: Customizable controls planned for future release
Workarounds
- Terminal keybinding: Some terminals allow key remapping
- Screen/tmux: Can provide additional key handling if needed
Quick Reference Card
Essential Keys
Playing Mode:
P = Pause/Resume C = Change Channel
+ = Volume Up - = Volume Down
Q = Quit
Channel Selection:
↑↓ = Navigate Enter = Select
Q = Quit
Channel Overlay:
↑↓ = Navigate Enter = Switch
Esc = Cancel Q = Quit
Memory Tips
- Pause for Playback control
- Change for Channel selection
- +/- for volume (like calculator)
- Quit to Quit (universal)
- Escape to cancel overlay
This control scheme is designed to be intuitive and memorable while providing full functionality through the keyboard interface.
Configuration Options
Complete reference for all configuration options in SomaFM Player.
Configuration File
Location
~/.config/soma-player/config.toml
Format
The configuration file uses TOML format for human-readable settings.
Example Configuration
# SomaFM Player Configuration
# Last played channel (auto-saved)
last_channel_id = "groovesalad"
# Audio volume (0-100)
volume = 75
# Skip channel selection on startup
auto_start = false
# Logging configuration
[logging]
level = "info"
file_rotation = true
max_files = 7
# User interface settings
[ui]
show_spectrum = true
spectrum_style = "bars"
color_scheme = "default"
# Audio settings
[audio]
buffer_size = 4096
sample_rate = 44100
reconnect_attempts = 3
Core Options
last_channel_id
Type: String
(optional)
Default: None
Auto-managed: Yes
The ID of the last played channel. This is automatically saved when you switch channels and used to restore your session.
Valid Values:
- Any valid SomaFM channel ID (e.g., "groovesalad", "dronezone", "lush")
null
or empty for no default channel
Example:
last_channel_id = "groovesalad"
volume
Type: Integer
Default: 50
Range: 0-100
Auto-managed: Yes
Audio volume level as a percentage. Changes are automatically saved when you adjust volume during playback.
Example:
volume = 75
auto_start
Type: Boolean
Default: false
Skip the channel selection screen and automatically start playing the last channel on startup.
Behavior:
true
: Immediately start playinglast_channel_id
(if set)false
: Show channel selection screen (default behavior)
Example:
auto_start = true
Logging Options
[logging]
Section
Configure logging behavior and output.
level
Type: String
Default: "info"
Values: "error"
, "warn"
, "info"
, "debug"
, "trace"
Sets the minimum log level for file and console output.
Log Levels:
error
: Only critical errorswarn
: Warnings and errorsinfo
: General information (recommended)debug
: Detailed debugging informationtrace
: Very verbose tracing (development only)
Example:
[logging]
level = "debug"
file_rotation
Type: Boolean
Default: true
Enable automatic log file rotation to prevent disk space issues.
Behavior:
true
: Rotate logs daily, keep last 7 daysfalse
: Single log file (grows indefinitely)
Example:
[logging]
file_rotation = true
max_files
Type: Integer
Default: 7
Range: 1-365
Number of rotated log files to keep when file_rotation
is enabled.
Example:
[logging]
max_files = 14 # Keep 2 weeks of logs
User Interface Options
[ui]
Section
Configure the terminal user interface appearance and behavior.
show_spectrum
Type: Boolean
Default: true
Enable or disable the spectrum visualizer display.
Example:
[ui]
show_spectrum = false
spectrum_style
Type: String
Default: "bars"
Values: "bars"
, "line"
, "minimal"
Visual style for the spectrum analyzer.
Styles:
bars
: Vertical bars (default)line
: Connected line graphminimal
: Simple dots/characters
Example:
[ui]
spectrum_style = "line"
color_scheme
Type: String
Default: "default"
Values: "default"
, "dark"
, "light"
, "monochrome"
Color scheme for the user interface.
Schemes:
default
: Standard colorsdark
: Dark theme optimized for dark terminalslight
: Light theme optimized for light terminalsmonochrome
: No colors (accessibility)
Example:
[ui]
color_scheme = "dark"
Audio Options
[audio]
Section
Configure audio playback and streaming behavior.
buffer_size
Type: Integer
Default: 4096
Range: 1024-16384
Audio buffer size in samples. Larger buffers reduce skipping but increase latency.
Recommendations:
1024-2048
: Low latency, may skip on slow systems4096
: Balanced (recommended)8192-16384
: High latency, very stable
Example:
[audio]
buffer_size = 8192
sample_rate
Type: Integer
Default: 44100
Values: 22050
, 44100
, 48000
Preferred audio sample rate in Hz.
Common Rates:
22050
: Lower quality, lower bandwidth44100
: CD quality (recommended)48000
: Professional audio quality
Example:
[audio]
sample_rate = 48000
reconnect_attempts
Type: Integer
Default: 3
Range: 0-10
Number of automatic reconnection attempts when stream is lost.
Example:
[audio]
reconnect_attempts = 5
Network Options
[network]
Section
Configure network and streaming behavior.
timeout
Type: Integer
Default: 30
Range: 5-300
Network timeout in seconds for API requests and stream connections.
Example:
[network]
timeout = 60
user_agent
Type: String
Default: "SomaFM-Player/{version}"
Custom User-Agent string for HTTP requests.
Example:
[network]
user_agent = "MyCustomPlayer/1.0"
proxy
Type: String
(optional)
Default: None
HTTP proxy URL for network requests.
Example:
[network]
proxy = "http://proxy.example.com:8080"
Advanced Options
[advanced]
Section
Advanced configuration options for power users.
config_reload_interval
Type: Integer
Default: 0
Range: 0-3600
Automatic configuration reload interval in seconds. 0
disables auto-reload.
Example:
[advanced]
config_reload_interval = 300 # Reload every 5 minutes
memory_limit
Type: Integer
Default: 100
Range: 50-1000
Memory usage limit in MB for caching and buffers.
Example:
[advanced]
memory_limit = 200
Environment Variable Overrides
Logging
RUST_LOG
: Override log level (e.g.,RUST_LOG=debug
)SOMA_LOG_FILE
: Custom log file path
Configuration
SOMA_CONFIG_DIR
: Custom configuration directorySOMA_CONFIG_FILE
: Custom configuration file path
Audio
SOMA_AUDIO_BACKEND
: Force specific audio backendSOMA_SAMPLE_RATE
: Override sample rate
Examples
# Debug logging
RUST_LOG=debug soma-player
# Custom config location
SOMA_CONFIG_DIR=~/.soma soma-player
# Force sample rate
SOMA_SAMPLE_RATE=48000 soma-player
Configuration Validation
Automatic Validation
The application validates all configuration values on startup:
- Range Checks: Numeric values within valid ranges
- Type Validation: Correct data types for all options
- Enum Validation: Valid choices for string options
- Path Validation: Writeable paths for logs and cache
Error Handling
Invalid configuration values result in:
- Warning Message: Logged to console and file
- Default Fallback: Invalid values replaced with defaults
- Graceful Degradation: Application continues with valid settings
Example Validation Error
WARNING: Invalid volume value '150' (must be 0-100), using default: 50
WARNING: Unknown color_scheme 'rainbow', using default: 'default'
Configuration File Management
Automatic Creation
If no configuration file exists, one is created with default values on first run.
Backup and Restore
# Backup current configuration
cp ~/.config/soma-player/config.toml ~/.config/soma-player/config.toml.backup
# Restore from backup
cp ~/.config/soma-player/config.toml.backup ~/.config/soma-player/config.toml
# Reset to defaults (delete config file)
rm ~/.config/soma-player/config.toml
Migration
Configuration is automatically migrated when upgrading between versions:
- Backward Compatibility: Old configurations continue to work
- New Options: Added with default values
- Deprecated Options: Ignored with warnings
Security Considerations
File Permissions
Configuration files are created with user-only permissions (600
):
# Check permissions
ls -la ~/.config/soma-player/config.toml
# Should show: -rw------- (user read/write only)
Sensitive Data
The configuration file contains no sensitive information:
- ✅ Safe: Volume levels, UI preferences, channel history
- ❌ Never Stored: Passwords, tokens, personal data
Network Settings
When using proxy settings:
- HTTP Proxies: Supported for SomaFM API requests
- Authentication: Not currently supported in proxy URLs
- HTTPS: All SomaFM communication uses HTTPS when available
Troubleshooting Configuration
Common Issues
Configuration Not Loading
# Check file exists
ls ~/.config/soma-player/config.toml
# Check file permissions
ls -la ~/.config/soma-player/config.toml
# Check syntax with TOML validator
python3 -c "import toml; toml.load(open('~/.config/soma-player/config.toml'))"
Settings Not Persisting
- Check directory permissions:
~/.config/soma-player/
must be writable - Check disk space: Ensure sufficient space for config file
- Check file locks: No other processes accessing the file
Invalid Values Ignored
- Check logs for validation warnings
- Verify values are within valid ranges
- Ensure correct TOML syntax and types
Reset Configuration
# Remove config file to reset to defaults
rm ~/.config/soma-player/config.toml
# Or rename to backup and recreate
mv ~/.config/soma-player/config.toml ~/.config/soma-player/config.toml.old
Configuration Examples
Minimal Configuration
# Basic setup - most users
volume = 70
auto_start = false
Power User Configuration
# Advanced setup with all options
last_channel_id = "dronezone"
volume = 80
auto_start = true
[logging]
level = "info"
file_rotation = true
max_files = 14
[ui]
show_spectrum = true
spectrum_style = "bars"
color_scheme = "dark"
[audio]
buffer_size = 8192
sample_rate = 48000
reconnect_attempts = 5
[network]
timeout = 45
user_agent = "SomaPlayer-Custom/1.0"
[advanced]
config_reload_interval = 300
memory_limit = 150
Development Configuration
# Setup for development and debugging
volume = 50
auto_start = false
[logging]
level = "debug"
file_rotation = false
max_files = 1
[ui]
show_spectrum = true
spectrum_style = "minimal"
color_scheme = "default"
[audio]
buffer_size = 2048
reconnect_attempts = 1
[advanced]
config_reload_interval = 60
memory_limit = 50
This comprehensive configuration reference covers all available options for customizing SomaFM Player to your preferences.
Command Line
Command-line interface and options for SomaFM Player.
Basic Usage
Start the Application
soma-player
This starts the application with the default terminal user interface.
Quick Help
soma-player --help
Version Information
soma-player --version
Command-Line Options
Global Options
--help
, -h
Display help information and exit.
soma-player --help
soma-player -h
Output:
SomaFM Player 0.1.6
A terminal-based music player for SomaFM internet radio
USAGE:
soma-player [OPTIONS] [COMMAND]
OPTIONS:
-h, --help Print help information
-v, --version Print version information
-c, --config Custom configuration file path
-l, --log-level Override log level [debug|info|warn|error]
-q, --quiet Suppress non-essential output
-V, --verbose Enable verbose output
COMMANDS:
play Start playing a specific channel
list List available channels
config Manage configuration
help Print this message or the help of a given subcommand
--version
, -v
Display version information and build details.
soma-player --version
Output:
soma-player 0.1.6
Build: release
Target: x86_64-unknown-linux-gnu
Rustc: 1.75.0
--config
, -c
Specify a custom configuration file path.
soma-player --config /path/to/custom/config.toml
soma-player -c ~/.config/soma-alt/config.toml
Default: ~/.config/soma-player/config.toml
--log-level
, -l
Override the log level for this session.
soma-player --log-level debug
soma-player -l warn
Valid Levels: error
, warn
, info
, debug
, trace
--quiet
, -q
Suppress non-essential output (warnings, info messages).
soma-player --quiet
Effect: Only errors are displayed to the console.
--verbose
, -V
Enable verbose output for debugging.
soma-player --verbose
Effect: Equivalent to --log-level debug
with additional startup information.
Subcommands
play
- Direct Channel Playback
Start playing a specific channel immediately without the UI.
soma-player play <CHANNEL_ID>
Examples:
# Play Groove Salad
soma-player play groovesalad
# Play Drone Zone
soma-player play dronezone
# Play with custom volume
soma-player play groovesalad --volume 75
Options for play
--volume
, -V
Set initial volume level (0-100).
soma-player play groovesalad --volume 80
soma-player play dronezone -V 60
--no-ui
Play without launching the terminal interface (headless mode).
soma-player play groovesalad --no-ui
Use Cases:
- Background music in scripts
- System service integration
- Remote/headless servers
--duration
, -d
Play for a specific duration then exit.
soma-player play groovesalad --duration 30m
soma-player play dronezone -d 1h
Time Formats:
30s
- 30 seconds5m
- 5 minutes2h
- 2 hours90
- 90 seconds (default unit)
list
- Channel Information
Display available SomaFM channels.
soma-player list
Output:
Available SomaFM Channels:
groovesalad Groove Salad 1,234 listeners
dronezone Drone Zone 987 listeners
lush Lush 756 listeners
folkfwd Folk Forward 543 listeners
...
Options for list
--format
, -f
Specify output format.
soma-player list --format json
soma-player list --format csv
soma-player list -f table
Formats:
table
- Human-readable table (default)json
- JSON format for scriptingcsv
- CSV format for spreadsheetssimple
- Simple list of channel IDs
--filter
, -F
Filter channels by genre or keyword.
soma-player list --filter electronic
soma-player list --filter ambient
soma-player list -F jazz
--sort
, -s
Sort channels by criteria.
soma-player list --sort listeners
soma-player list --sort name
soma-player list -s genre
Sort Options:
name
- Alphabetical by channel namelisteners
- By listener count (descending)genre
- By genre, then nameid
- By channel ID
config
- Configuration Management
Manage application configuration.
config show
Display current configuration.
soma-player config show
Output:
last_channel_id = "groovesalad"
volume = 75
auto_start = false
[logging]
level = "info"
file_rotation = true
config get
Get a specific configuration value.
soma-player config get volume
soma-player config get logging.level
config set
Set a configuration value.
soma-player config set volume 80
soma-player config set auto_start true
soma-player config set logging.level debug
config reset
Reset configuration to defaults.
# Reset all settings
soma-player config reset
# Reset specific section
soma-player config reset logging
# Reset specific key
soma-player config reset volume
config validate
Validate configuration file syntax and values.
soma-player config validate
Output on success:
Configuration is valid ✓
Output on errors:
Configuration errors:
- Invalid volume value '150' (must be 0-100)
- Unknown color_scheme 'rainbow'
config backup
Create a backup of the current configuration.
soma-player config backup
soma-player config backup --file /path/to/backup.toml
config restore
Restore configuration from a backup.
soma-player config restore
soma-player config restore --file /path/to/backup.toml
Environment Variables
Logging Control
RUST_LOG
Override log level and filtering.
# Debug level for all modules
RUST_LOG=debug soma-player
# Specific module debugging
RUST_LOG=soma_player::audio=debug soma-player
# Multiple modules
RUST_LOG=soma_player::audio=debug,soma_player::ui=info soma-player
SOMA_LOG_FILE
Custom log file location.
SOMA_LOG_FILE=/tmp/soma-debug.log soma-player
Configuration Override
SOMA_CONFIG_DIR
Custom configuration directory.
SOMA_CONFIG_DIR=~/.soma soma-player
SOMA_CONFIG_FILE
Custom configuration file.
SOMA_CONFIG_FILE=/etc/soma-player.toml soma-player
Audio Settings
SOMA_AUDIO_BACKEND
Force specific audio backend.
# Linux: Force ALSA
SOMA_AUDIO_BACKEND=alsa soma-player
# macOS: Force Core Audio
SOMA_AUDIO_BACKEND=coreaudio soma-player
SOMA_SAMPLE_RATE
Override audio sample rate.
SOMA_SAMPLE_RATE=48000 soma-player
Network Settings
SOMA_PROXY
HTTP proxy for all requests.
SOMA_PROXY=http://proxy.example.com:8080 soma-player
SOMA_TIMEOUT
Network timeout in seconds.
SOMA_TIMEOUT=60 soma-player
Exit Codes
Standard Exit Codes
Code | Meaning | Description |
---|---|---|
0 | Success | Normal exit |
1 | General Error | Unspecified error |
2 | Argument Error | Invalid command-line arguments |
3 | Config Error | Configuration file issues |
4 | Network Error | Network connectivity problems |
5 | Audio Error | Audio system issues |
130 | Interrupted | Ctrl+C or SIGINT received |
Examples
# Check exit code
soma-player play invalid_channel
echo $? # Outputs: 4 (network error - channel not found)
# Use in scripts
if soma-player list --quiet; then
echo "Channels available"
else
echo "Failed to fetch channels"
fi
Scripting and Automation
Background Playback
# Start playing in background
nohup soma-player play groovesalad --no-ui > /dev/null 2>&1 &
# Save the process ID
echo $! > soma-player.pid
# Stop later
kill $(cat soma-player.pid)
System Service Integration
# systemd service example
[Unit]
Description=SomaFM Player
After=network.target
[Service]
Type=simple
User=music
ExecStart=/usr/local/bin/soma-player play groovesalad --no-ui
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
Scheduled Playback
# cron job to play during work hours
# Play Mon-Fri 9 AM to 5 PM
0 9 * * 1-5 /usr/local/bin/soma-player play groovesalad --duration 8h --no-ui
Integration with Other Tools
i3/Polybar Integration
# Get current playing status
soma-player status --format=json | jq -r '.channel.title'
# Volume control
soma-player volume +5
soma-player volume -5
dmenu/rofi Channel Selection
# Channel selection menu
channel=$(soma-player list --format=simple | dmenu -p "Channel:")
if [ -n "$channel" ]; then
soma-player play "$channel"
fi
Troubleshooting Command-Line Issues
Common Problems
Command Not Found
# Check if installed
which soma-player
# Check PATH
echo $PATH
# Add to PATH if needed
export PATH="$HOME/.local/bin:$PATH"
Permission Denied
# Check file permissions
ls -la $(which soma-player)
# Make executable if needed
chmod +x ~/.local/bin/soma-player
Configuration Errors
# Validate configuration
soma-player config validate
# Reset if corrupted
soma-player config reset
# Use custom config temporarily
soma-player --config /dev/null
Audio Issues
# Test audio system
soma-player play groovesalad --log-level debug
# Try different backend
SOMA_AUDIO_BACKEND=pulse soma-player
# Check audio permissions
groups $USER | grep -E "(audio|pulse-access)"
Debug Mode
# Full debug information
RUST_LOG=debug soma-player --verbose
# Save debug log
RUST_LOG=debug soma-player --verbose 2> debug.log
Integration Examples
Shell Functions
# Add to ~/.bashrc or ~/.zshrc
# Quick channel switching
soma() {
if [ $# -eq 0 ]; then
soma-player
else
soma-player play "$1"
fi
}
# Channel search
soma-search() {
soma-player list --filter "$1"
}
# Current status
soma-status() {
soma-player status --format=simple
}
Fish Shell Completions
# ~/.config/fish/completions/soma-player.fish
complete -c soma-player -n '__fish_use_subcommand' -a 'play list config help'
complete -c soma-player -n '__fish_seen_subcommand_from play' -a '(soma-player list --format=simple)'
Zsh Completions
# Add to ~/.zshrc
compdef '_files -W ~/.config/soma-player' soma-player --config
This comprehensive command-line reference covers all aspects of using SomaFM Player from the terminal and in automated scenarios.