Source & modules
How the source is organised: every Flutter module and backend file, and how the parts fit.
Repository: github.com/R3CT01/PEK-TV. You may read the code; see the LICENCE file for what else you may do with it.
One branch #
Everything lives on main: the backend, the Flutter UI, the Android host, plugins, skins, cloud workers, the build workflow and these docs. There is no separate branch per platform, so a change to shared code (backend/, flutter_ui/, plugins/, skins/ or cloud/) is made once.
| Part | Folder | Build guide |
|---|---|---|
| C++ backend | backend/ |
The backend |
| Android app (Kotlin host, libmpv, Chaquopy, JNI) | android/ |
The Android app |
Shared code stays in backend/ and flutter_ui/. A new platform gets its own runner folder (for example linux/ or windows/) and its own workflow file, next to android/ and build_android.yml. Android is the only one today.
Repository layout #
backend/ C++ server + embedded Python (dev.sh builds it). API only, no web pages
flutter_ui/ the screens: the Flutter / Dart app shared by every platform
android/ Gradle project: Kotlin host, JNI, Python runner, resources
assets/ branding (icon, banner, splash) and the screenshots the README and docs show
plugins/ bundled plugins: tmdb-discover, weather, skin-maker
plugin_packages/ plugin zips and sources prepared for distribution
skins/ bundled skins: default (PEK Ember), green, neon
cloud/ Cloudflare Workers: PEK Cloud (sync, accounts, subtitles) and the PEK Store
tools/ sync_providers.js, make_skin.py, providers.json
docs/ this site (GitHub Pages)
.github/workflows/build_android.yml the Android APK build
FLUTTER.md FLUTTER_PLUGINS.md PLUGINS.md SKINS.md MUSIC.md SUBTITLES.md LOCAL_METADATA.md reference docsHow the parts fit #
Flutter UI (flutter_ui/) <----HTTP, port 8080---> C++ backend (backend/)
| plugin screens (Python screen.py) are drawn | scans folders and network shares
| natively by the app | streams files, subtitles, trailers
| libmpv is driven over platform channels (pek/*) | runs plugin backends via embedded Python,
| | behind hesper_guard.py
v v
PEK Cloud + PEK Store (Cloudflare Workers + D1), optionalOn Android the Kotlin host (MainActivity) starts the backend through JNI and runs plugin Python with Chaquopy. Video and music are played by libmpv (MpvController, MpvAudioController) and the Flutter UI controls them over the pek/* platform channels. The Flutter UI is the only front end; on other systems you can run the backend with dev.sh.
The server only answers the device it runs on unless you set PEK_BIND and PEK_TOKEN.
Flutter UI modules (flutter_ui/lib/src/) #
| Files | What they do |
|---|---|
shell.dart, home.dart, layouts.dart, focus.dart |
App shell: swipe pages and bottom bar on phones, sidebar on TV, the More page, layouts (Classic, Top bar, Wall, Compact) and D-pad focus. |
tokens.dart, theme.dart, tv_mode.dart |
Design tokens, theme, and TV mode (the 10-foot look, screen margins). |
library.dart, library_pages.dart, detail.dart, pages.dart, watched.dart |
Movies and TV Shows grids, movie / show / season / episode pages, search, Favorites, Watch History, Duplicates, Unknown, and watched marks. |
dashboard.dart, dash_widgets.dart, clock.dart, weather.dart, pin_grid.dart |
The customizable dashboard and its widgets, clock and weather, and the pinned plugin tiles. |
player.dart, mpv.dart, subtitles.dart, skip.dart, settings_extra.dart |
The player and its channels to libmpv, online subtitles, Skip Intro / Recap and Up next, and the subtitle, video output and audio output settings. |
music.dart, music_controller.dart, music_session.dart, music_fullscreen.dart, lyrics.dart, playlists.dart, playlist_ui.dart |
The Music tab: Albums / Artists / Songs / Playlists, queue, mini player, the full-screen player with lyrics, and playlists (see MUSIC.md). |
profiles.dart, profile_pages.dart, account_pages.dart, cloud.dart, store.dart |
Profiles with passcodes, PEK Cloud sign-in and sync, and the on-device store for progress, favorites and dashboard layout. |
skins.dart, skin_install.dart, skin_install_ui.dart, skin_builder.dart, skin_maker.dart, skin_widgets.dart |
Skins, installing them from .zip or GitHub, and the skin maker. |
plugin_host.dart, plugin_ui.dart, plugin_zip.dart, plugin_install_ui.dart, plugin_github.dart, plugin_store.dart, plugin_store_ui.dart, plugin_backup.dart, plugin_backup_ui.dart, plugin_pins.dart, plugin_updates.dart |
Plugin screens drawn natively, the install flow and zip reader, install from GitHub, the PEK Store, plugin backup to PEK Cloud, pins and updates (see FLUTTER_PLUGINS.md). |
app_update.dart, whats_new.dart |
The in-app updater (finds a newer GitHub release for this CPU type and installs it after confirmation) and the one-time "What's new" screen after an update. |
ratings.dart, ratings_export.dart, library_match.dart |
1 to 10 star ratings per profile, the CSV / export of history and ratings for Letterboxd, Trakt and Simkl, and matching titles a plugin reports to the library. |
suggest.dart, key_guard.dart, music_filters.dart, music_mode.dart |
Search drop-down suggestions, taming a held remote button, the Genre / Year filters under Music search, and Music mode (the app shows only music). |
plugin_hooks.dart, plugin_favorites.dart, live_tv.dart, store_browser.dart |
Playback hooks for plugins, the favorites plugins may read and change, Live TV in the player, and the PEK Store as a full page for plugins and skins. |
torrent.dart, torrent_search.dart |
Torrent playback for plugins and search through sites you list. PEK TV ships with no search provider or index. |
api.dart, net.dart, net_folders.dart, activity.dart, art_cache.dart, widgets.dart, common.dart, fields.dart |
The HTTP client for the backend, the online / offline dot, network folders, the activity line and loading ring, the artwork cache, and shared widgets. |
The Android host side of the pek/* channels is in android/app/src/main/java/com/pektv/app/ (FlutterHostActivity.kt, FlutterMusic.kt, MpvController.kt) and the Python screen layer is in android/app/src/main/python/ (pek_flutter.py, pek_ui.py).
Backend modules (backend/) #
| Files | What they do |
|---|---|
core.cpp, server.cpp |
Program entry, embedded Python, the HTTP server on port 8080, plugin / skin routes, remote-access token. |
media_scanner.cpp, nfo.h |
Library scanner, NFO and artwork reading. |
vfs.cpp, vfs_smb.cpp, vfs_nfs.cpp, vfs_ftp.cpp, vfs_http.cpp, discovery.cpp |
One virtual file system over local folders, SMB, NFS, FTP, WebDAV and UPnP / DLNA, plus network discovery. |
playback.cpp, range_stream.h |
Streaming files with byte ranges, including files over 4 GB on 32-bit builds. |
music.cpp, music_tags.cpp |
The music library and its /api/music/* routes (albums, artists, songs, search, cover art, audio streaming). Song tags and embedded covers are read straight from MP3, FLAC, Ogg / Opus and M4A files, so it works without ffprobe, on Android and over network shares. It refreshes after every normal scan; see MUSIC.md. |
plugin_install.h, skin_install.h, github_install.h |
Server-side checks and installation for plugin zips, skin zips and GitHub releases. |
hesper_guard.py |
The plugin guard: decides whether a plugin's Python backend may run and with what access. The file keeps its old name. |
torrent.cpp, torrent_routes.cpp |
Optional libtorrent engine and its /api/torrent/* routes. |
subtitles.h, trailer.h |
Subtitle look-up through the cloud worker; trailer playback without the YouTube embed. |
Other reference #
- PLUGINS.md: the full plugin reference.
- SKINS.md: skin format and limits.
- LOCAL_METADATA.md: NFO files and artwork names that PEK TV reads.
- SUBTITLES.md: how automatic subtitles work.
- cloud/DEPLOY.md and cloud/STORE-DEPLOY.md: deploying the workers.
A note on old names #
The project used to be called Hesper. Some internal names still say so on purpose, so existing installs keep working: saved settings keys (hesper_*), the hesper and hesper_host plugin names, HESPER_* environment variables, and hesper_guard.py. Do not rename them without a migration.