IrosTheBeggar/mstream-mp3-player

Notes, docs, and code for an experimental mp3 player

C++

2

3 commits

updated Jun 14, 2026

See the code

See what people are saying

SourceMessageScoreDate

I'm building an open source mp3 player that works with selfhosted software (r/selfhosted)

I'm working on an open source mp3 player built on affordable hardware. \* $50 - built on the [m5 Core2](https://shop.m5stack.com/products/m5stack-core2-esp32-iot-development-kit-v1-3) \* has bluetooth, 3.5mm, and a built in speaker \* supports SD cards up to 2TB \* 500mAh battery, upgradeable to…

28

Sep 29, 2026

README

mstream-mp3-player

An experimental portable MP3/FLAC player built on the ESP32-S3, designed to dock to a host running mStream over USB-C and sync its library as a mass-storage device.

This repo is the firmware + dev harness. You can build and run the whole UI and logic today on this laptop in the Wokwi simulator — no hardware required — while the dev board ships.

Status: scaffold. UI, playlist/transport, and the dock state machine work in simulation. Real audio output and the USB mass-storage handoff are stubbed behind a HAL until the physical board arrives. See docs/ARCHITECTURE.md.

What's emulated vs. not

WhereStatus
UI, menus, encoder/button nav, playlist, transportWokwi✅ works in sim
Dock-detect + MSC handoff state machineWokwi (DOCK button)✅ works in sim
mStream server + sync targetDocker✅ runs locally
Real I2S audio (you can hear it)physical board⛔ needs hardware
USB-OTG mass-storage dock handoffphysical board⛔ needs hardware

Quick start

1. Install PlatformIO

# via pipx (recommended) or pip
pip install -U platformio
pio --version

Or install the PlatformIO IDE + Wokwi extensions in VS Code.

2. Build the firmware

pio run -e esp32-s3-wokwi

3. Run it in the simulator

  • VS Code: open the folder, press F1 → Wokwi: Start Simulator (uses wokwi.toml + diagram.json).
  • The simulated device boots into the Library screen. Turn the encoder to scroll, press it (or PLAY) to start a track → Now Playing with a live progress bar. PREV/NEXT change tracks. Press the DOCK button to toggle the USB mass-storage "docked" screen.

No SD files needed — a built-in demo library loads if the card is empty. To use real files, drop them in sd_card/.

4. Run the host unit tests

The portable core (lib/core) is tested off-target — no board, no emulator:

pio test -e native

(Needs a host C/C++ compiler — MinGW-w64 or MSVC on Windows.)

5. Start the mStream dev server (optional, for the sync side)

docker compose -f docker/docker-compose.yml up -d
# http://localhost:3000

Point a USB stick or a local folder at docker/dev-data/music to stand in for the docked player. See docker/docker-compose.yml.

Layout

platformio.ini        Build envs: esp32-s3-wokwi | hardware | native
wokwi.toml            Wokwi <-> firmware binding
diagram.json          Simulated board: S3 + ILI9341 + KY-040 + microSD + buttons
include/Pins.h        Central pin map (build flags are source of truth)
lib/core/             Portable, framework-agnostic logic (compiles for native)
  PlaybackController  Transport + playlist
  DockController      Dock-detect + MSC handoff state machine
  hal/                IAudioBackend, IStorage, IDock interfaces
src/                  Hardware side (Arduino/ESP32 only)
  audio/ storage/ dock/ input/ ui/   HAL impls + UI/input
  main.cpp            Wires core to hardware, runs the UI loop
test/                 Host unit tests (Unity)
docker/               mStream server for the sync side
docs/ARCHITECTURE.md  Layering, HAL seams, pin map, roadmap

Hardware (target prototype, ~$65–80)

ESP32-S3-DevKitC-1 (N16R8) · PCM5102A I2S DAC · microSD (4-bit SDIO) · 1.9" ST7789 TFT · rotary encoder + 3 buttons · 1500mAh LiPo + TP4056 + load-sharing. The "dock" is just a USB-C cable to any machine running the mStream image.

IrosTheBeggar/mstream-mp3-player

Notes, docs, and code for an experimental mp3 player

C++

2

3 commits

updated Jun 14, 2026

See the code

See what people are saying

SourceMessageScoreDate

I'm building an open source mp3 player that works with selfhosted software (r/selfhosted)

I'm working on an open source mp3 player built on affordable hardware. \* $50 - built on the [m5 Core2](https://shop.m5stack.com/products/m5stack-core2-esp32-iot-development-kit-v1-3) \* has bluetooth, 3.5mm, and a built in speaker \* supports SD cards up to 2TB \* 500mAh battery, upgradeable to…

28

Sep 29, 2026

README

mstream-mp3-player

An experimental portable MP3/FLAC player built on the ESP32-S3, designed to dock to a host running mStream over USB-C and sync its library as a mass-storage device.

This repo is the firmware + dev harness. You can build and run the whole UI and logic today on this laptop in the Wokwi simulator — no hardware required — while the dev board ships.

Status: scaffold. UI, playlist/transport, and the dock state machine work in simulation. Real audio output and the USB mass-storage handoff are stubbed behind a HAL until the physical board arrives. See docs/ARCHITECTURE.md.

What's emulated vs. not

WhereStatus
UI, menus, encoder/button nav, playlist, transportWokwi✅ works in sim
Dock-detect + MSC handoff state machineWokwi (DOCK button)✅ works in sim
mStream server + sync targetDocker✅ runs locally
Real I2S audio (you can hear it)physical board⛔ needs hardware
USB-OTG mass-storage dock handoffphysical board⛔ needs hardware

Quick start

1. Install PlatformIO

# via pipx (recommended) or pip
pip install -U platformio
pio --version

Or install the PlatformIO IDE + Wokwi extensions in VS Code.

2. Build the firmware

pio run -e esp32-s3-wokwi

3. Run it in the simulator

  • VS Code: open the folder, press F1 → Wokwi: Start Simulator (uses wokwi.toml + diagram.json).
  • The simulated device boots into the Library screen. Turn the encoder to scroll, press it (or PLAY) to start a track → Now Playing with a live progress bar. PREV/NEXT change tracks. Press the DOCK button to toggle the USB mass-storage "docked" screen.

No SD files needed — a built-in demo library loads if the card is empty. To use real files, drop them in sd_card/.

4. Run the host unit tests

The portable core (lib/core) is tested off-target — no board, no emulator:

pio test -e native

(Needs a host C/C++ compiler — MinGW-w64 or MSVC on Windows.)

5. Start the mStream dev server (optional, for the sync side)

docker compose -f docker/docker-compose.yml up -d
# http://localhost:3000

Point a USB stick or a local folder at docker/dev-data/music to stand in for the docked player. See docker/docker-compose.yml.

Layout

platformio.ini        Build envs: esp32-s3-wokwi | hardware | native
wokwi.toml            Wokwi <-> firmware binding
diagram.json          Simulated board: S3 + ILI9341 + KY-040 + microSD + buttons
include/Pins.h        Central pin map (build flags are source of truth)
lib/core/             Portable, framework-agnostic logic (compiles for native)
  PlaybackController  Transport + playlist
  DockController      Dock-detect + MSC handoff state machine
  hal/                IAudioBackend, IStorage, IDock interfaces
src/                  Hardware side (Arduino/ESP32 only)
  audio/ storage/ dock/ input/ ui/   HAL impls + UI/input
  main.cpp            Wires core to hardware, runs the UI loop
test/                 Host unit tests (Unity)
docker/               mStream server for the sync side
docs/ARCHITECTURE.md  Layering, HAL seams, pin map, roadmap

Hardware (target prototype, ~$65–80)

ESP32-S3-DevKitC-1 (N16R8) · PCM5102A I2S DAC · microSD (4-bit SDIO) · 1.9" ST7789 TFT · rotary encoder + 3 buttons · 1500mAh LiPo + TP4056 + load-sharing. The "dock" is just a USB-C cable to any machine running the mStream image.

Languages

C++

96.5%

C

3.5%