Skip to content

Architecture

iPodRocks is an Electron desktop app. This page explains how its two processes are structured and how they communicate.

Overview

iPodRocks architecture overview

Main Process

Runs in Node.js. Has full filesystem and OS access.

ModuleResponsibility
IPC Handlers (ipc.ts)~60 channels bridged to the renderer. Applies safe() wrapper, sanitizeErrorMessage, rate limiting.
LibraryCoreCRUD for tracks, artists, albums, genres, folders.
LibraryScannerWalks library folders, extracts metadata via music-metadata, writes to DB.
ShadowLibraryManagerManages pre-transcoded mirror libraries (e.g. FLAC → MPC).
HashManagerSHA-256 content hashing for change detection.
SyncCore / SyncExecutorCompares library against device; copies, transcodes, or removes files.
SyncConversionTranscodes audio via FFmpeg or mpcenc.
RatingMerge3-way merge algorithm that reconciles ratings between the device and the library. Detects device changes, resolves conflicts, and computes what to propagate back.
TagcacheIOReads and writes the Rockbox database_changelog.txt on the device mount. Handles Phase 1 (ingest) and Phase 3 (propagate) of the ratings sync cycle.
AppDatabaseSingle better-sqlite3 instance. All reads/writes go through here.
DevicesCoreStores and retrieves device profiles.
PlaylistCoreSmart and Genius playlist creation.
GeniusEngineGenerates Genius playlists from playback history (graph-based scoring).
OpenRouterClientCalls the OpenRouter API with timeout, rate limiting, and prompt injection mitigation.
SavantEngine / AssistantChatLLM orchestration for playlist generation and Rocksy.
Essentia.jsWASM module for key and BPM detection (harmonic analysis).
PrefsReads and writes prefs.json (settings, encrypted API key via safeStorage).
PathAllowlistValidates that library and shadow library paths stay within allowed directories.

Renderer Process

Runs in a Chromium sandbox. Cannot access the filesystem directly.

ModuleResponsibility
IPC API Layer (renderer/ipc/api.ts)Thin wrappers around window.api.invoke(). One function per IPC channel.
Zustand StoresuseLibraryStore, useDeviceStore, useSyncStore, useUIStore, useThemeStore. All server state lives here.
React PanelsOne panel per tab: Dashboard, Library, Devices, Sync, Playlists, Settings.
RatingStars5-star rating input with half-star support. Displays device-source and conflict badges.
RatingConflictsModalLists unresolved rating conflicts and lets the user resolve them (keep library, use device, or set manually).
ScanProgressModalShows file-by-file scan progress; captures folders in a ref to prevent restart on re-render.
SyncProgressModalShows copy progress; uses useRef counters to avoid stale-closure bugs in the onComplete callback.
FloatChatFloating Rocksy chat backed by AssistantChat on the main process.

IPC communication

The Preload script uses Electron's contextBridge to expose a strict allowlist of channels as window.api. The renderer calls window.api.invoke(channel, ...args); the main process handles it in ipcMain.handle() inside a safe() wrapper that:

  1. Catches all errors and returns { error: string } (never throws across IPC).
  2. Strips absolute paths from error messages before they reach the renderer.
  3. Enforces per-channel rate limits (10 calls / 60 s for LLM channels).

Database schema (high-level)

Core library

tracks · artists · albums · genres · playlists · playlist_tracks

Shadow libraries

shadow_libraries · shadow_tracks · shadow_files

System

devices · app_settings · content_hashes (mtime + SHA-256) · activity_log

Ratings

TableDescription
device_track_ratingsPer-device baseline manifest; last_seen / last_pushed
rating_conflictsUnresolved divergences awaiting user resolution
rating_eventsFull audit log of every rating change