MusicBee TrueShuffle | Documentation | HALRAD Research

Randy

MusicBee TrueShuffle

Documentation

MusicBee TrueShuffle ensures every track in your library plays exactly once before any repeats.

Explain: How It Works

The Problem: Standard shuffle algorithms pick tracks randomly each time. With a large library, this means some tracks play repeatedly while others are rarely heard. It's like rolling dice - you might roll the same number multiple times before hitting others.

The Solution: TrueShuffle treats your library like a deck of cards. Each track is "dealt" exactly once. Only after every card has been played does the deck reshuffle.

Step-by-Step Process

  1. You play music normally — TrueShuffle runs silently in the background
  2. Track plays past threshold — When you listen to enough of a track (e.g., 50%), it's marked as "played"
  3. State is saved — Your progress is stored in a JSON file that survives restarts, updates, and reboots
  4. Shuffle excludes played tracks — MusicBee's shuffle will skip tracks you've already heard
  5. Cycle completes — Once every track has played, you can reset manually or let it auto-reset

What Counts as "Played"?

You configure the threshold — how much of a track must play before it counts:

Skipping a track before the threshold? It stays "unplayed" and will come up again in shuffle.

Enabling and Disabling

TrueShuffle is always active when the plugin is loaded. To disable tracking:

Configuration Options

Setting Options Description
Play Threshold 30 sec, 50%, 75%, Full How much of a track must play before it counts as "played"
Auto-Reset On/Off Automatically start over when you've heard everything
Show Panel On/Off Display the dockable progress panel

State Storage

The plugin stores its state in JSON format:

%AppData%\MusicBee\mb_trueshuffle\state.json

State file contents:

{
  "playedTracks": ["file://path/to/song1.mp3", "file://path/to/song2.mp3"],
  "libraryHash": "a3f8b2c1",
  "totalTracks": 12847,
  "lastReset": "2025-12-01T00:00:00Z",
  "lastPlayed": "2025-12-28T21:45:00Z"
}

Technical Details

Architecture

MusicBee TrueShuffle/
├── Plugin.cs              # Main entry point, MusicBee integration
├── ShuffleState.cs        # Persisted state management
├── ShuffleEngine.cs       # Shuffle logic and track selection
├── ShuffleSettings.cs     # Configuration options
└── MusicBeeInterface.cs   # MusicBee API definitions (from SDK)

MusicBee API Integration

API Method Purpose
Library_QueryFilesEx()Get all library tracks
NowPlaying_GetFileUrl()Current playing track (unique ID)
NowPlaying_GetDuration()Track duration for threshold calculation
Player_GetPosition()Current playback position
TrackChanged notificationTrigger to check if previous track was "played"
Setting_GetPersistentStoragePath()Plugin data folder location

Play Detection Logic

// On track change, check if PREVIOUS track was played long enough
if (lastTrackUrl != null && lastTrackDuration > 0)
{
    int playedMs = lastTrackPosition;
    double playedPercent = (double)playedMs / lastTrackDuration;

    if (playedPercent >= playThreshold)
    {
        engine.MarkPlayed(lastTrackUrl);
    }
}

Building from Source

Prerequisites

Build Commands

# Debug build
dotnet build -c Debug

# Release build
dotnet build -c Release

Output: bin\Release\net48\mb_trueshuffle.dll

Library Change Handling

When your library changes:

Known Limitations

License

GPL3 - See GNU General Public License v3 for details.

Randy

MusicBee TrueShuffle