# R36S DLNA Browser A lightweight DLNA media browser for the R36S handheld, built with Python, SDL2, and GStreamer. Author: Matteo Benedetto ## Features - Discover DLNA/UPnP media servers on local LAN via SSDP - Browse media libraries hierarchically with D-pad navigation - Play audio and video locally via integrated GStreamer playback inside the SDL window - Optimised for 640×480 screen and low-power RK3326 hardware ## System Prerequisites Install these system packages before running (Ubuntu/Debian-based): ```bash sudo apt install libsdl2-2.0-0 libsdl2-ttf-2.0-0 python3 python3-pip python3-gi gir1.2-gstreamer-1.0 gstreamer1.0-tools gstreamer1.0-plugins-base gstreamer1.0-plugins-good ``` On Fedora the equivalent runtime packages are: ```bash sudo dnf install SDL2_ttf python3-gobject gstreamer1 gstreamer1-plugins-base gstreamer1-plugins-good python3 python3-pip ``` The current playback path is SDL-only: GStreamer decodes into frames and the app renders them inside the SDL renderer. This avoids any dependency on X11, Wayland embedding, or a window manager and is aligned with DRM/KMS-only targets. On ArkOS-derived firmware the SDL2 libraries are typically pre-installed. A TrueType font is bundled inside the package at `src/r36s_dlna_browser/assets/` so packaged builds do not depend on a system font path. System font fallbacks are still kept for development machines. ## Quick Start ```bash cd /path/to/R36SHack python3 -m pip install -e ".[dev]" python3 -m r36s_dlna_browser ``` ## Miniforge / Conda Deploy Use Miniforge or Miniconda when you want a reproducible Linux development or packaging environment with GStreamer and SDL dependencies managed together. ```bash cd /path/to/R36SHack conda env create -f environment.yml conda activate r36s-dlna-browser python -m r36s_dlna_browser ``` To update an existing environment after dependency changes: ```bash conda env update -f environment.yml --prune conda activate r36s-dlna-browser ``` Or without installing: ```bash cd /path/to/R36SHack pip install -r requirements.txt PYTHONPATH=src python3 -m r36s_dlna_browser ``` ## Controls | Key / Button | Action | |-------------|----------------------| | Up / Down | Navigate items | | Left / Right | Page up / down | | A (Return) | Select / Enter | | B (Escape) | Back | | Start | Quit | During playback, the same controls are remapped to transport actions: - `A`: pause / resume - `B`: stop and return to browser - `Left / Right`: seek `-10s / +10s` - `Up / Down`: volume `+5 / -5` - `H` / `Y`: cycle HUD mode (`auto / fixed / hidden`) ## On-Device (R36S / ArkOS) 1. Copy the project to a writable location such as `/home/ark/MatHacks/R36SHack`. 2. Ensure Wi-Fi is connected. 3. Install or reuse a conda env at `/home/ark/miniconda3/envs/r36s-dlna-browser`. 4. Run via PortMaster or a launch script: ```bash cd /home/ark/MatHacks/R36SHack export LD_LIBRARY_PATH=/home/ark/miniconda3/envs/r36s-dlna-browser/lib export GST_PLUGIN_SCANNER=/home/ark/miniconda3/envs/r36s-dlna-browser/libexec/gstreamer-1.0/gst-plugin-scanner python -m r36s_dlna_browser ``` An ArkOS launcher script for this layout is included at `deploy/arkos/MatHacks.sh`. ## Git / Release Workflow For publication on a Gitea instance with `tea`, initialize git locally, create a remote repository, then push the current branch. ```bash git init git add . git commit -m "Initial import" tea repos create --name R36SHack --description "SDL2/GStreamer DLNA browser for R36S" --owner enne2 git remote add origin ssh://git@git.enne2.net:222/enne2/R36SHack.git git push -u origin main ``` Published repository: https://git.enne2.net/enne2/R36SHack ## Project Structure ``` src/r36s_dlna_browser/ ├── __main__.py # Entrypoint ├── app.py # Application lifecycle ├── assets/ │ └── NotoSans-Regular.ttf ├── dlna/ │ ├── discovery.py # SSDP media-server discovery │ ├── client.py # ContentDirectory browsing via DmsDevice │ ├── models.py # Domain models for servers/items │ └── browser_state.py # Navigation stack and cache ├── ui/ │ ├── sdl_app.py # SDL2 window, event loop, rendering │ ├── screens.py # Screen definitions │ └── theme.py # Layout constants for 640×480 ├── player/ │ ├── backend.py # Player interface │ └── gstreamer_backend.py # integrated GStreamer playback backend └── platform/ ├── controls.py # Input mapping └── runtime.py # Runtime detection and logging ``` ## License MIT