Public release README.md fix
This commit is contained in:
@@ -1,2 +1,3 @@
|
|||||||
|
.DS_Store
|
||||||
build
|
build
|
||||||
imgui.ini
|
imgui.ini
|
||||||
|
|||||||
@@ -13,8 +13,9 @@ video and ImGui rendering; and
|
|||||||
> This project is under active development. Builds and feed playback have been
|
> This project is under active development. Builds and feed playback have been
|
||||||
> verified in current Ubuntu and Fedora environments and on a separate Ubuntu
|
> verified in current Ubuntu and Fedora environments and on a separate Ubuntu
|
||||||
> machine. Native builds and feed playback have also been verified on macOS
|
> machine. Native builds and feed playback have also been verified on macOS
|
||||||
> with MoltenVK. macOS packaging, stable releases, and MXL Fabrics support are
|
> with MoltenVK. A macOS application bundle has been tested in a clean virtual
|
||||||
> planned.
|
> machine; publication of release artifacts, stable releases, and MXL Fabrics
|
||||||
|
> support are planned.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -163,9 +164,29 @@ path, for example:
|
|||||||
install_name_tool -add_rpath /absolute/path/to/mxl/lib build/mxl-player
|
install_name_tool -add_rpath /absolute/path/to/mxl/lib build/mxl-player
|
||||||
```
|
```
|
||||||
|
|
||||||
These workarounds should not be necessary once the libraries are installed in
|
These workarounds are only needed for development builds. The packaged `.app`
|
||||||
a normal dynamic-loader path. A self-contained `.app` bundle and downloadable
|
uses bundled libraries and relative runtime paths instead.
|
||||||
GitHub release are planned but do not exist yet.
|
|
||||||
|
### Running the macOS application bundle
|
||||||
|
|
||||||
|
The ARM64 `.app` bundle has been tested on physical Apple Silicon hardware. The
|
||||||
|
application extracted from its release ZIP has also been launched successfully
|
||||||
|
in a clean macOS installation under UTM, without the development environment or
|
||||||
|
Homebrew dependencies.
|
||||||
|
|
||||||
|
The initial package is unsigned and is not notarized by Apple. Consequently,
|
||||||
|
Gatekeeper may block its first launch. Right-click **MXL Player.app**, select
|
||||||
|
**Open**, and confirm the prompt. It can also be allowed from **System Settings
|
||||||
|
→ Privacy & Security** after a blocked launch.
|
||||||
|
|
||||||
|
If macOS still retains a quarantine restriction, it can be removed manually:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
xattr -dr com.apple.quarantine "/Applications/MXL Player.app"
|
||||||
|
```
|
||||||
|
|
||||||
|
Only use this command for an archive downloaded from the project's official
|
||||||
|
GitHub release and verified against its published SHA-256 checksum.
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
@@ -480,11 +501,12 @@ local MXL flow; it will not be implemented as a separate playback backend. See
|
|||||||
|
|
||||||
- Linux builds and feed playback have been verified on Ubuntu and Fedora;
|
- Linux builds and feed playback have been verified on Ubuntu and Fedora;
|
||||||
broader runtime and hardware coverage is still limited.
|
broader runtime and hardware coverage is still limited.
|
||||||
- macOS/MoltenVK builds and feed playback work on tested hardware, but the
|
- macOS/MoltenVK builds and feed playback work on tested Apple Silicon
|
||||||
application is not yet packaged or release-tested on a clean machine.
|
hardware. The packaged application launches in a clean UTM macOS VM, but it
|
||||||
|
remains unsigned and unnotarized.
|
||||||
- Windows support is not currently claimed.
|
- Windows support is not currently claimed.
|
||||||
- GPU selection and verbose logging flags are incomplete.
|
- GPU selection and verbose logging flags are incomplete.
|
||||||
- There are no prebuilt packages or application bundles yet.
|
- Release artifacts have not yet been published.
|
||||||
- MXL Fabrics ingress is planned but not implemented.
|
- MXL Fabrics ingress is planned but not implemented.
|
||||||
- Native MXL headers and runtime libraries must be ABI-compatible.
|
- Native MXL headers and runtime libraries must be ABI-compatible.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,348 @@
|
|||||||
|
# MXL Player
|
||||||
|
MXL Player is a desktop player for local [Media eXchange Layer](https://github.com/dmf-mxl/mxl)
|
||||||
|
audio and video flows, with GUI controls and command-line startup configuration.
|
||||||
|
It can play either feed independently, play both simultaneously, or switch a
|
||||||
|
configured pair into and out of native MXL synchronization while running.
|
||||||
|
|
||||||
|
The application uses:
|
||||||
|
- SDL3 for its window, input, and audio output;
|
||||||
|
- Vulkan for video and ImGui rendering;
|
||||||
|
- [`go-mxl`](https://github.com/qvest-digital/go-mxl) for MXL access.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Synchronized playback for compatible same-domain feeds; cross-domain feeds
|
||||||
|
currently use independent readers.
|
||||||
|
- Finite or unlimited reconnect attempts with exponential backoff.
|
||||||
|
- JSON playlists with manual selection, timed advance, looping, and failure
|
||||||
|
policies.
|
||||||
|
- Playback, media, timing, retry, and dropped-frame statistics.
|
||||||
|
|
||||||
|
## Planned
|
||||||
|
|
||||||
|
- MXL Fabrics support;
|
||||||
|
- MXL URI/addressability support;
|
||||||
|
- Coordinated cross-domain reading using TAI timestamps;
|
||||||
|
- GUI-created playlist;
|
||||||
|
- GPU selection;
|
||||||
|
- LUFS meter;
|
||||||
|
- patching audio channels to selected device.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
Prebuilt packages are available from
|
||||||
|
[GitHub Releases](../../releases).
|
||||||
|
|
||||||
|
- **macOS ARM64:** `.app` bundle with SDL3, libmxl, and MoltenVK included.
|
||||||
|
- **Linux AMD64:** binary built on Ubuntu. A compatible libmxl installation,
|
||||||
|
SDL3, Vulkan loader, and Vulkan-capable driver are required.
|
||||||
|
|
||||||
|
Download the archive for your platform and verify its SHA-256 checksum before
|
||||||
|
running it.
|
||||||
|
|
||||||
|
## Tested platforms
|
||||||
|
|
||||||
|
- Ubuntu and Fedora: build and feed playback tested.
|
||||||
|
- macOS ARM64: build and feed playback tested.
|
||||||
|
|
||||||
|
## Building from source: requirements
|
||||||
|
|
||||||
|
- Go 1.26 or newer.
|
||||||
|
- A C/C++ build toolchain for cgo dependencies.
|
||||||
|
- A compatible shared build of `libmxl` and its development headers.
|
||||||
|
- pkg-config metadata for `libmxl`.
|
||||||
|
- SDL3 shared library.
|
||||||
|
- Vulkan loader and a working Vulkan driver.
|
||||||
|
- libmxl 1.2.0 or a compatible build providing
|
||||||
|
`mxlCreateFlowSynchronizationGroup`.
|
||||||
|
|
||||||
|
The project currently pins:
|
||||||
|
```text
|
||||||
|
github.com/qvest-digital/go-mxl v1.1.0-rc.2
|
||||||
|
```
|
||||||
|
|
||||||
|
## Building on Linux
|
||||||
|
|
||||||
|
First verify that pkg-config resolves the intended MXL installation:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
pkg-config --modversion libmxl
|
||||||
|
pkg-config --cflags --libs libmxl
|
||||||
|
pkg-config --variable=pcfiledir libmxl
|
||||||
|
pkg-config --variable=libdir libmxl
|
||||||
|
```
|
||||||
|
|
||||||
|
If MXL is installed in a nonstandard prefix:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export MXL_PREFIX=/opt/mxl/1.2.0
|
||||||
|
export PKG_CONFIG_PATH="$MXL_PREFIX/lib/pkgconfig"
|
||||||
|
export LD_LIBRARY_PATH="$MXL_PREFIX/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then build and test:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
go mod download
|
||||||
|
go test ./...
|
||||||
|
mkdir -p build
|
||||||
|
go build -o build/mxl-player ./cmd/mxl-player
|
||||||
|
```
|
||||||
|
|
||||||
|
Confirm which native library the executable will use:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
ldd build/mxl-player | grep libmxl
|
||||||
|
```
|
||||||
|
|
||||||
|
## macOS
|
||||||
|
|
||||||
|
The SDL3 and Vulkan loaders contain macOS library-name support. The Vulkan
|
||||||
|
dependency is temporarily replaced by a portability fork while the upstream
|
||||||
|
change is reviewed.
|
||||||
|
|
||||||
|
Building currently requires:
|
||||||
|
- Xcode Command Line Tools;
|
||||||
|
- Go;
|
||||||
|
- SDL3;
|
||||||
|
- MoltenVK;
|
||||||
|
- a macOS build of libmxl with matching headers and pkg-config metadata.
|
||||||
|
|
||||||
|
When libmxl has been built from its source tree but has not been installed into
|
||||||
|
a standard prefix, expose its build metadata, source headers, and library
|
||||||
|
directory to cgo. For example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export MXL_SOURCE=/path/to/mxl
|
||||||
|
export MXL_BUILD="$MXL_SOURCE/build/Darwin-Clang-Release"
|
||||||
|
|
||||||
|
export PKG_CONFIG_PATH="$MXL_BUILD${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}"
|
||||||
|
export CGO_CFLAGS="-I$MXL_SOURCE/lib/include"
|
||||||
|
export CGO_LDFLAGS="-L$MXL_BUILD/lib"
|
||||||
|
|
||||||
|
mkdir -p build
|
||||||
|
go build -o build/mxl-player ./cmd/mxl-player
|
||||||
|
```
|
||||||
|
|
||||||
|
The `CGO_CFLAGS` workaround is needed because the headers are still in the MXL
|
||||||
|
source tree. A properly installed MXL SDK should expose them through
|
||||||
|
`libmxl.pc` instead.
|
||||||
|
|
||||||
|
Nonstandard loader locations can be supplied explicitly (for example, in case of installing with homebrew):
|
||||||
|
|
||||||
|
```sh
|
||||||
|
export SDL3_LIBRARY="$(brew --prefix sdl3)/lib/libSDL3.dylib"
|
||||||
|
export VULKAN_LIBRARY=/absolute/path/to/libMoltenVK.dylib
|
||||||
|
export DYLD_LIBRARY_PATH="$MXL_BUILD/lib${DYLD_LIBRARY_PATH:+:$DYLD_LIBRARY_PATH}"
|
||||||
|
|
||||||
|
./build/mxl-player
|
||||||
|
```
|
||||||
|
|
||||||
|
The resulting executable may currently need an additional libmxl runtime search
|
||||||
|
path, for example:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
install_name_tool -add_rpath "$MXL_BUILD/lib" build/mxl-player
|
||||||
|
```
|
||||||
|
|
||||||
|
These workarounds are only needed for development builds. The packaged `.app`
|
||||||
|
uses bundled libraries and relative runtime paths instead.
|
||||||
|
|
||||||
|
### Running the macOS application bundle
|
||||||
|
|
||||||
|
The package is ad-hoc signed but is not signed with an Apple Developer ID or notarized by Apple.
|
||||||
|
Consequently, Gatekeeper may block its first launch. Right-click **MXL Player.app**,
|
||||||
|
select **Open**, and confirm the prompt. It can also be allowed
|
||||||
|
from **System Settings → Privacy & Security** after a blocked launch.
|
||||||
|
|
||||||
|
If macOS still retains a quarantine restriction, it can be removed manually:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
xattr -dr com.apple.quarantine "/Applications/MXL Player.app"
|
||||||
|
```
|
||||||
|
Only remove quarantine from an archive downloaded from the official project release and verified against its SHA-256 checksum.
|
||||||
|
|
||||||
|
## Running
|
||||||
|
|
||||||
|
Start with no configured feed and enter domains/UUIDs in the GUI:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player
|
||||||
|
```
|
||||||
|
|
||||||
|
Video only:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player \
|
||||||
|
--domain /dev/shm/mxl \
|
||||||
|
--video VIDEO_UUID
|
||||||
|
```
|
||||||
|
|
||||||
|
Audio only:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player \
|
||||||
|
--domain /dev/shm/mxl \
|
||||||
|
--audio AUDIO_UUID
|
||||||
|
```
|
||||||
|
|
||||||
|
Independent video and audio:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player \
|
||||||
|
--video-domain /dev/shm/video \
|
||||||
|
--video VIDEO_UUID \
|
||||||
|
--audio-domain /dev/shm/audio \
|
||||||
|
--audio AUDIO_UUID
|
||||||
|
```
|
||||||
|
|
||||||
|
Start a compatible pair synchronized:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player \
|
||||||
|
--domain /dev/shm/mxl \
|
||||||
|
--video VIDEO_UUID \
|
||||||
|
--audio AUDIO_UUID \
|
||||||
|
--sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Synchronization is not a permanent startup mode. It can be enabled and
|
||||||
|
disabled at runtime from the settings window.
|
||||||
|
|
||||||
|
## Command-line options
|
||||||
|
|
||||||
|
| Option | Short | Meaning |
|
||||||
|
|---|---:|---|
|
||||||
|
| `--help` | `-h` | Show help and exit. |
|
||||||
|
| `--domain PATH` | `-d` | Default domain for feeds without a specific domain. |
|
||||||
|
| `--video-domain PATH` | | Domain for the video feed. |
|
||||||
|
| `--audio-domain PATH` | | Domain for the audio feed. |
|
||||||
|
| `--video UUID` | `-v` | Initial video flow UUID. |
|
||||||
|
| `--audio UUID` | `-a` | Initial audio flow UUID. |
|
||||||
|
| `--sync` | `-s` | Start a configured A/V pair synchronized. |
|
||||||
|
| `--max-attempts N` | | Attempts per playback lifecycle; `0` means unlimited. |
|
||||||
|
| `--playlist FILE` | | Load a JSON playlist. |
|
||||||
|
| `--fullscreen` | `-f` | Start fullscreen. |
|
||||||
|
| `--gpu-id N` | `-g` | Select GPU ID; currently incomplete. |
|
||||||
|
| `--playback-id N` | `-p` | Select the SDL playback-device ID. |
|
||||||
|
| `--list-playback` | | List SDL playback devices and exit. |
|
||||||
|
| `--list-gpu` | | List Vulkan physical devices and exit. |
|
||||||
|
| `--verbose` | | Reserved; currently incomplete. |
|
||||||
|
|
||||||
|
Run `./build/mxl-player --help` for the authoritative list.
|
||||||
|
|
||||||
|
## GUI controls
|
||||||
|
|
||||||
|
The settings window accepts separate video/audio domains and UUIDs.
|
||||||
|
|
||||||
|
- **Apply feeds** applies the complete desired configuration.
|
||||||
|
- **Stop** stops a feed while retaining its UUID and domain.
|
||||||
|
- **Resume** starts a stopped configured feed with a fresh lifecycle.
|
||||||
|
- **Remove** stops a feed and clears its configuration.
|
||||||
|
- **Stop all** and **Resume all** operate on both configured feeds.
|
||||||
|
- **Synchronize** switches a compatible active pair between synchronized and
|
||||||
|
independent playback.
|
||||||
|
|
||||||
|
Keyboard shortcuts:
|
||||||
|
|
||||||
|
| Key | Action |
|
||||||
|
|---|---|
|
||||||
|
| `F1` | Show or hide settings. |
|
||||||
|
| `F2` | Show or hide statistics. |
|
||||||
|
| `F` | Toggle fullscreen. |
|
||||||
|
| `Q` or `Esc` | Quit. |
|
||||||
|
|
||||||
|
## Retry behavior
|
||||||
|
|
||||||
|
Each playback lifecycle starts at attempt 1. Failed connections/readers are
|
||||||
|
retried with exponential delay from 500 ms up to 5 seconds.
|
||||||
|
|
||||||
|
```sh
|
||||||
|
# Retry indefinitely
|
||||||
|
./build/mxl-player -d /dev/shm/mxl -v VIDEO_UUID --max-attempts 0
|
||||||
|
|
||||||
|
# Stop after three failed attempts
|
||||||
|
./build/mxl-player -d /dev/shm/mxl -v VIDEO_UUID --max-attempts 3
|
||||||
|
```
|
||||||
|
|
||||||
|
With independent A/V, one failed feed retries without stopping the other. A
|
||||||
|
synchronized pair reconnects as one lifecycle.
|
||||||
|
|
||||||
|
## Playlists
|
||||||
|
|
||||||
|
Start a playlist with:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
./build/mxl-player --playlist playlist.json
|
||||||
|
```
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"loop": true,
|
||||||
|
"on_failure": "next",
|
||||||
|
"retry": {
|
||||||
|
"max_attempts": 3,
|
||||||
|
"initial_delay": "500ms",
|
||||||
|
"max_delay": "5s"
|
||||||
|
},
|
||||||
|
"entries": [
|
||||||
|
{
|
||||||
|
"name": "Synchronized pair",
|
||||||
|
"video": {
|
||||||
|
"domain": "/dev/shm/mxl",
|
||||||
|
"uuid": "VIDEO_UUID"
|
||||||
|
},
|
||||||
|
"audio": {
|
||||||
|
"domain": "/dev/shm/mxl",
|
||||||
|
"uuid": "AUDIO_UUID"
|
||||||
|
},
|
||||||
|
"sync": true,
|
||||||
|
"duration": "10s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Video only",
|
||||||
|
"video": {
|
||||||
|
"domain": "/dev/shm/mxl",
|
||||||
|
"uuid": "ANOTHER_VIDEO_UUID"
|
||||||
|
},
|
||||||
|
"duration": "15s"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Audio until manually advanced",
|
||||||
|
"audio": {
|
||||||
|
"domain": "/dev/shm/mxl",
|
||||||
|
"uuid": "ANOTHER_AUDIO_UUID"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Playlist rules:
|
||||||
|
|
||||||
|
- `duration` uses Go duration syntax such as `500ms`, `10s`, or `2m`.
|
||||||
|
- Missing/empty duration means manual advance.
|
||||||
|
- `loop: true` returns to the first entry after the last.
|
||||||
|
- `on_failure: "wait"` remains on an exhausted entry.
|
||||||
|
- `on_failure: "next"` advances after retry exhaustion.
|
||||||
|
- A synchronized entry must contain both video and audio.
|
||||||
|
- Playlist retry settings override the CLI defaults unless
|
||||||
|
`--max-attempts` was explicitly supplied.
|
||||||
|
|
||||||
|
The GUI supports entry selection, previous/next navigation, and pausing or
|
||||||
|
resuming a timed entry.
|
||||||
|
|
||||||
|
## Third-party assets
|
||||||
|
|
||||||
|
The embedded JetBrainsMonoNL Nerd Font Mono is distributed under the SIL Open
|
||||||
|
Font License 1.1. Its copyright notice, license, and source information are in
|
||||||
|
[`internal/assets/fonts`](internal/assets/fonts/).
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MXL Player is licensed under the GNU General Public License, version 3 or any
|
||||||
|
later version. See [`LICENSE`](LICENSE).
|
||||||
|
|
||||||
|
The embedded font retains its separate SIL Open Font License 1.1.
|
||||||
Vendored
BIN
Binary file not shown.
Reference in New Issue
Block a user