Reference App
The SDK package includes a reference app: a complete player written in C that drives every part of the SDK and is controlled from a web UI in your browser.
Why it exists
We designed and wrote the reference app to show how we think the SDK could be used. The reference app shows how the SDK functions fit together in a running player, including the obligations that come with them, who owns a returned object, when a result has to be consumed, how to poll asynchronous operations, and in which order to shut things down.
Use it to:
- Learn our patterns. Every interaction an integration needs is implemented in plain C, with comments at the points where the SDK contract places obligations on the caller.
- Experiment. Build it on your development machine or target hardware, pair it with your test account and try things out before you write your own integration. Change the code and see what happens.
- See the SDK working end to end. When your own integration behaves unexpectedly, the reference app can give you a baseline to compare against on the same hardware.
Free to reuse
Everything in the reference app, including the automatic updater, may be used in your own project. Copy individual functions, adapt whole files, or use it as the starting point for your player.
Your code, your responsibility
Code you take from the reference app becomes part of your player. Testing, maintaining and certifying it is your responsibility, just like code you wrote yourself.
The reference app is not a certified product. It shows the patterns, but your own player still has to meet the requirements and pass certification on your hardware, including any parts used from the reference app.
Where to look
| SDK concept | Demonstrated in |
|---|---|
Loading the SDK (dlopen and entry symbol) |
src/splayer_context.c |
| Player configuration and options | src/splayer_context.c |
| Pairing (browser redirect and manual code) | src/routes.c |
| Playback control and state polling | src/routes.c, src/splayer_json.c |
| Track metadata and album art | src/splayer_json.c |
| Asynchronous library fetch (submit, poll, consume) | src/library_fetch.c |
| Troubleshooting report (error codes) | src/splayer_json.c (build_troubles) |
| Automatic updater | src/updater.c, run.sh |
| Clean shutdown ordering | src/main.c |
| Audio output callbacks | ../src/audio_output_*.c |
The C code in src/ is where the patterns live. The web frontend in html/ only exists to give you something
to click, it is not a pattern to follow.
Getting started
The reference app ships as source in splayerapi-v5/reference-app/. Build and run instructions, the
architecture, the REST endpoints and the file layout are described in README.md in that directory.
The app runs everything on a single thread, so it uses only the non-blocking SDK functions
(fetch_library, initiate_pair_with_code, unpair) and never the blocking *_sync variants.
Automatic updater
We release new versions of the Player Library on a regular schedule, and
every player must pick them up automatically to follow it. The updater is therefore a
certification requirement, and the reference app
includes an updater that we wrote ourselves, in src/updater.c. It shows one way to meet the
Upgrade and Provisioning requirements, and you are free to use it in
your own player.
What it does
The updater is a small state machine driven by a libuv timer:
IDLE --> CHECKING --> DOWNLOADING --> AWAITING_SHUTDOWN
^ |
|_______________________________| (on any failure)
- Poll the release channel every 15 minutes (the first check runs 15 minutes after start).
- Compare versions. If
versionin the response equals the running library's versionget_current_version(), there is nothing to do. - Download the file from
linkto a temporary file next to the library, computing the SHA-1 checksum while writing. - Verify the checksum against
checksumin the response. On a mismatch the file is discarded and the updater returns to idle. - Replace the library by renaming the downloaded file over the current one.
- Exit by calling
request_exit()withSPLAYER_EXIT_UPGRADE. The SDK finishes the current track, thenshould_exit()returns1, the app shuts down cleanly and exits with code0. - Restart.
run.shstarts the app again as soon as it exits, and the appdlopens the new library.
Configuring it
- Release channel: set
MANIFEST_URLto the release channel endpoint we give you. The updater is disabled while it is empty, which is the default in the SDK package's build (CMakeLists.txt). - Library path: the file that is replaced is
SDK_LIB_PATH, the same path the app loads the library from.
Start the app through run.sh rather than running the binary directly, otherwise nothing restarts it after
an update. run.sh also restarts the app after a crash, two seconds after a non-zero exit.
Testing the update flow locally
src/webserver.py in the SDK package is a small local provisioning server. Point it at one or more library
files and it serves a response for them at /latest.json, in the same format as the release channel. Set
MANIFEST_URL to that address to exercise the whole flow on your desk. The mock libraries built from the
package's top-level CMakeLists.txt (splayer-mock-123 and splayer-mock-321) report different versions,
which makes them useful for testing a library swap.