8.4 KiB
8.4 KiB
AGENTS.md - SimpMusic (Custom Fork) Agent Guidelines
This document provides essential architectural context, operational rules, workflow conventions, and gotchas for AI coding agents working on this repository.
🎯 1. Repository Identity & Branch Workflow
1.1 Fork Hierarchy
- Main App Repository:
muriloscolari/SimpMusic(forked frommaxrave-dev/SimpMusic). - Core Submodule (
core/):muriloscolari/core(forked frommaxrave-dev/coreorMediaServiceCore). - Base Integration Branch:
customin BOTH repositories.
1.2 Branching Rules (MANDATORY)
- Never work directly on
mainordev: Upstream updates land there. - Always branch off
custom:- Create atomic branches named
feat/<feature-name>,fix/<bug-name>, orperf/<improvement-name>directly fromcustom. - Test and verify changes locally.
- Commit atomic changes with clear Conventional Commit messages (
feat:,fix:,refactor:,chore:). - Bump app version (
version-nameandversion-codeingradle/libs.versions.toml) before merging intocustom. - Merge back into
customand push both the feature branch andcustomtoorigin.
- Create atomic branches named
- Always Bump Version Before Merging into
custom(MANDATORY):- Every push to
customtriggers the automated CI/CD release workflow (.github/workflows/custom-build-release.yml), creating a public release tagged asv${VERSION}. - To avoid release tag collisions and ensure the in-app auto-updater (
VersionManager.kt) notifies users of new builds, always increment the version numbers ingradle/libs.versions.toml:version-name(e.g.2.3.2->2.3.3)version-code(e.g.62->63)
- Never merge into
customwith an already-released version number.
- Every push to
- Submodule Synchronization:
- If a change requires edits inside
core/, work on an atomic branch insidecorederived from itscustombranch. - Commit and push to
muriloscolari/core:customFIRST. - Only then stage and commit the updated
coresubmodule commit pointer in the rootSimpMusicrepository.
- If a change requires edits inside
1.3 Communication & Language Convention
- User Interaction: Respond in the user's preferred language (Portuguese by default in this workspace).
- Code Comments & Commits: Write in English with descriptive summaries and rationale. Preserve all pre-existing architectural comments and notes.
🏗️ 2. High-Level Architecture & Code Map
The project is built on Kotlin Multiplatform (Compose Multiplatform) targeting Android and Desktop (Linux, Windows, macOS):
SimpMusic (Root)
├── composeApp/ # Shared UI & ViewModels (Android + Desktop JVM)
│ ├── src/commonMain/kotlin/ # Multiplatform shared Compose UI & logic
│ │ └── com/maxrave/simpmusic/
│ │ ├── ui/screen/player/
│ │ │ ├── NowPlayingScreen.kt # Shell, sheets, dialogs, state machines
│ │ │ ├── MiniPlayer.kt # Bottom bar player across desktop & mobile
│ │ │ ├── FullscreenPlayer.kt # Fullscreen landscape player
│ │ │ └── content/ # Three distinct player styles
│ │ │ ├── NowPlayingContentSpotify.kt # Spotify / Classic mode
│ │ │ ├── NowPlayingContentAppleMusic.kt # Apple Music mode
│ │ │ ├── NowPlayingContentM3Expressive.kt # Material 3 Expressive mode
│ │ │ ├── NowPlayingContentState.kt # Shared immutable state & actions
│ │ │ └── applemusic/ # Apple Music sub-components
│ │ ├── viewModel/ # SharedViewModel, LibraryViewModel, etc.
│ │ └── service/ # SimpConnect (LAN remote control)
│ ├── src/androidMain/kotlin/ # Android-specific Compose adaptations
│ └── src/jvmMain/kotlin/ # Desktop-specific adaptations (JNA, Taskbar, System Tray)
│
├── core/ (Git Submodule) # Business logic, repositories, media players
│ ├── domain/ # Models, interfaces (MediaPlayerHandler, Repositories)
│ ├── data/ # Data sources, Room database, network APIs, Media handlers
│ │ ├── src/androidMain/ # Android MediaServiceHandlerImpl
│ │ └── src/jvmMain/ # Desktop JvmMediaPlayerHandlerImpl (libmpv)
│ ├── media/media3/ # Android ExoPlayer / Media3 service & Android Auto
│ ├── media/media-jvm/ # Desktop MPV player (MpvPlayer.kt)
│ └── service/ # Background sync, scraper, AI, lyrics
│
├── androidApp/ # Android application entry point & manifest
└── desktopApp/ # Desktop JVM launcher & Conveyor packaging configuration
🎨 3. Key Custom Features & Parity Rules
When modifying or introducing features, keep these custom fork components in mind:
- Player Style Parity (3 Player Modes):
- SimpMusic supports 3 selectable player visual modes: Spotify, Apple Music, and Material 3 Expressive.
- When adding controls, toggles, or playback features (e.g., Start Radio, queue controls, device handoff), implement in all 3 styles. Never leave any mode behind.
- SimpConnect (LAN Remote Control & Handoff):
- Spotify Connect-like LAN discovery via mDNS and WebSocket/P2P control between Android and Desktop instances.
- Controller state and playback handoff live in
SimpConnectManagerandSharedViewModel.
- Desktop Media Enhancements:
- Perceptual Volume Scaling: Located in
core/media/media-jvm/src/main/java/com/simpmusic/media_jvm/mpv/MpvPlayer.kt. Volume curve usesmasterFraction.pow(1.45)to ensure smooth acoustic granularity below 50%. - Windows Taskbar Thumbnail Toolbar: Located in
composeApp/src/jvmMain/kotlin/com/maxrave/simpmusic/WindowsTaskbarThumbnailController.kt. Controls media buttons (Prev/Play/Next) natively via JNAITaskbarList3. - Linux AppImage Auto-Updates: Integrated zsync delta updates against GitHub releases.
- Windows Silent Updates: Handled via
.appinstaller/ MSIX background updates.
- Perceptual Volume Scaling: Located in
⚙️ 4. Build, Verification & Testing Commands
4.1 Fast Development Validation
# 1. Compile Shared UI and Desktop JVM:
./gradlew :composeApp:compileKotlinJvm :desktopApp:compileKotlinJvm
# 2. Compile Android Main:
./gradlew :composeApp:compileAndroidMain
# 3. Run Unit Tests:
./gradlew :composeApp:jvmTest
4.2 Packaging & Local Release Builds
Release builds follow .github/workflows/custom-build-release.yml:
# Export library definitions
./gradlew exportLibraryDefinitions --no-configuration-cache
# Build Android APKs (arm64, armv7, x86_64, universal)
./gradlew :androidApp:assembleRelease --no-configuration-cache
# Prepare Desktop MPV native binaries
./gradlew :composeApp:mpvSetupAll --no-configuration-cache
# Write Conveyor configuration
./gradlew :desktopApp:writeConveyorConfig --no-configuration-cache
# Package Linux AppImage
conveyor --agree-to-license=1 --console=plain -Kapp.machines=linux.amd64-glibc make linux-app
./gradlew :desktopApp:packageConveyorAppImage --no-configuration-cache
# Package Windows MSIX and site
conveyor --agree-to-license=1 --console=plain -Kapp.machines=windows.amd64 make site
Caution
Never prefix Gradle or Conveyor commands with
timeoutwhen running on the local machine unless explicitly instructed, as this can orphan child processes or break terminal locks.
🚨 5. Common Pitfalls & Rules of Thumb (Gotchas)
- Submodule Drift:
- Always run
git statusANDgit -C core statusbefore starting and after finishing work. - Avoid unintentional dirty submodule pointer commits.
- Always run
- DataStore Disk Writes:
- Persisting to DataStore is an asynchronous, suspending disk write. Never block the UI thread or gate immediate audio/visual feedback behind DataStore completion.
- Do Not Touch iOS or macOS Targets:
- Focus strictly on Android, Linux, and Windows unless the user explicitly requests otherwise.
- Preserve Existing Documentation:
- Maintain documentation integrity. Do not delete or summarize away explanatory comments explaining edge cases (e.g. Android 12 background restrictions, MPV soname workarounds, Skia rendering constraints).