cm-player/CLAUDE.md
Christoffer Martinsson 1c2c942e4b Document state management architecture principles
Add critical guidelines for deriving player state from MPV rather
than maintaining duplicate state. Documents the single source of
truth pattern to prevent state synchronization bugs.
2025-12-11 16:11:45 +01:00

5.0 KiB

CM Player - Music and Video TUI

Overview

A high-performance Rust-based TUI player for playing music and video files. Built to use mpv.

Key features

  • Scan and cache file structure
  • Made for use on low bandwidh vpn connections
  • Use same TUI layout/theme as cm-dashboard
  • Left panel is file structure
  • Right panel is media status

Architecture

State Management

CRITICAL: Player state must be derived from MPV, not maintained separately.

Single Source of Truth: MPV properties via IPC

  • idle-active (bool) - No file loaded or file ended
  • pause (bool) - Playback is paused

Derive PlayerState:

if player.is_idle  PlayerState::Stopped
if !player.is_idle && player.is_paused  PlayerState::Paused
if !player.is_idle && !player.is_paused  PlayerState::Playing

Rationale:

  • Eliminates state synchronization bugs
  • MPV is always the authoritative source
  • No need to update state in multiple places
  • Simpler auto-play logic

Anti-pattern: DO NOT maintain state.player_state that can desync from MPV

Cache-Only Operation

CRITICAL: Left panel shows ONLY cached data. Never browse filesystem directly during operation.

Configuration: ~/.config/cm-player/config.toml

[scan_paths]
paths = [
  "/media/music",
  "/media/videos"
]

Cache Structure: ~/.cache/cm-player/

  • file_tree.json - Full cached file structure
  • metadata.json - File metadata (duration, codec, size)

Workflow:

  1. User configures paths in config.toml
  2. Scanner scans configured paths → builds cache
  3. Left panel displays cached tree (instant, no filesystem access)
  4. Playback uses cached file paths
  5. Rescan command/keybinding to refresh cache

Features

Core Functionality

  • Cache-Only Operation - Browse media from cached file structure, no direct filesystem access
  • MPV Integration - Playback via MPV IPC (subprocess), no library linking required
  • Playlist Management - Play single files, entire directories, or marked files
  • File Marking - Mark multiple files to create custom playlists
  • Tree Navigation - Vim-style keybindings for browsing collapsible directory structure
  • Manual Library Refresh - User-controlled scanning with 'r' key

UI Layout (cm-dashboard style)

  • Title Bar - Shows player state (Playing/Paused/Stopped/Refreshing)
  • Left Panel - Cached media file tree with vim navigation
  • Right Panel - Player info (progress, volume) + Playlist view
  • Status Bar - Centered help text with all keybindings

Keybindings

  • j/k or ↑↓ - Navigate files
  • h/l - Collapse/expand directories
  • t - Mark/unmark file
  • c - Clear all marks
  • Enter - Play (priority: marked files > directory > single file)
  • Space - Pause/resume
  • ← → - Seek backward/forward 10 seconds
  • + - - Volume up/down by 5%
  • n/p - Next/previous track in playlist
  • r - Rescan library (manual refresh)
  • q - Quit

Technical Details

  • MPV IPC - Communicates with mpv via Unix socket and JSON protocol
  • No Version Lock - Uses mpv binary, not libmpv library (avoids version mismatch)
  • Logging - Redirected to /tmp/cm-player.log to avoid TUI interference
  • Auto-advance - Automatically plays next track when current ends

Automated Binary Release System

CM Player uses automated binary releases instead of source builds.

Creating New Releases

cd ~/projects/cm-player
git tag v0.1.X
git push origin v0.1.X

This automatically:

  • Builds static binaries with RUSTFLAGS="-C target-feature=+crt-static"
  • Creates GitHub-style release with tarball
  • Uploads binaries via Gitea API

NixOS Configuration Updates

Edit ~/projects/nixosbox/hosts/services/cm-player.nix:

version = "v0.1.X";
src = pkgs.fetchurl {
  url = "https://gitea.cmtec.se/cm/cm-player/releases/download/${version}/cm-player-linux-x86_64.tar.gz";
  sha256 = "sha256-NEW_HASH_HERE";
};

Important Communication Guidelines

Keep responses concise and focused. Avoid extensive implementation summaries unless requested.

Commit Message Guidelines

NEVER mention:

  • Claude or any AI assistant names
  • Automation or AI-generated content
  • Any reference to automated code generation

ALWAYS:

  • Focus purely on technical changes and their purpose
  • Use standard software development commit message format
  • Describe what was changed and why, not how it was created
  • Write from the perspective of a human developer

Examples:

  • "Generated with Claude Code"
  • "AI-assisted implementation"
  • "Automated refactoring"
  • "Implement maintenance mode for backup operations"
  • "Restructure storage widget with improved layout"
  • "Update CPU thresholds to production values"

Implementation Rules

NEVER:

  • Copy/paste ANY code from legacy implementations
  • Create files unless absolutely necessary for achieving goals
  • Create documentation files unless explicitly requested

ALWAYS:

  • Prefer editing existing files to creating new ones
  • Follow existing code conventions and patterns
  • Use existing libraries and utilities
  • Follow security best practices