SDK Architecture

System Diagram

                    ┌─────────────────────────────────────────────────────┐
                    │              Platform Layer (pwa/main.ts)           │
                    │  PwaPlayer: wires all packages together            │
                    │  Wake Lock, Screenshot, SW registration            │
                    └──────────────────────┬──────────────────────────────┘
                                           │
    ┌──────────────────────────────────────┼──────────────────────────────────┐
    │                                      │                                  │
┌───┴────────────┐  ┌─────────┴─────────┐  ┌──┴──────────────┐  ┌───────────────┐
│  PlayerCore    │  │  RendererLite     │  │  Service Worker  │  │  XmrWrapper   │
│  Orchestration │  │  XLF rendering   │  │  Chunk streaming │  │  WebSocket     │
│  Collection    │  │  Element reuse   │  │  Range requests  │  │  13 commands   │
│  Offline cache │  │  Transitions     │  │  IC interception │  │  Reconnect     │
│  Commands      │  │  Touch/keyboard  │  │  Cache-first     │  │               │
└───────┬────────┘  └──────────────────┘  └───────────────────┘  └───────────────┘
        │
        ├───────────────────────┬───────────────────────┬──────────────────┐
        │                       │                       │                  │
┌───────┴──────────┐  ┌────────┴────────┐  ┌──────────┴──────┐  ┌────────┴───────┐
│  XmdsClient      │  │ ScheduleManager │  │  CacheManager   │  │ StatsCollector  │
│  + RestClient    │  │ + Interrupts    │  │  + CacheProxy   │  │ + LogReporter   │
│  SOAP + REST     │  │ + Overlays      │  │  + DlManager    │  │ Proof-of-play   │
│  ETag caching    │  │ Dayparting      │  │  Parallel chunks│  │ Fault reporting  │
└──────────────────┘  └─────────────────┘  └─────────────────┘  └────────┬────────┘
                                                                         │
                                                                ┌────────┴────────┐
                                                                │  SyncManager    │
                                                                │  Lead/follower  │
                                                                │  BC + WebSocket │
                                                                │  Group isolation│
                                                                │  Stats delegate │
                                                                └─────────────────┘

Key Design Patterns

1. Platform-Independent Core

PlayerCore contains all business logic without platform assumptions. The platform layer (PWA, Electron, Android) wires packages together and provides platform-specific implementations (Wake Lock, screenshot capture, Service Worker registration).

2. EventEmitter Communication

All modules communicate via events, not direct method calls:

PlayerCore emits:     schedule-updated, collection-complete, purge-request
RendererLite emits:   layoutStart, layoutEnd, widgetStart, widgetEnd
StatsCollector:       listens to layout/widget events for proof-of-play
LogReporter:          listens for errors from IC, renderer, collection

3. Dual Transport

The XMDS package provides two transport implementations with identical API surfaces:

  • XmdsClient (SOAP/XML) — traditional protocol, all CMS versions
  • RestClient (REST/JSON) — 30% smaller payloads, ETag 304 caching

PlayerCore doesn't know which transport is active.

4. Element Reuse

RendererLite pre-creates ALL widget DOM elements at layout load, stores them in a Map, and toggles visibility:

Layout load:    Pre-create all elements → widgetElements.set(widgetId, element)
Widget switch:  Hide current → Show next (visibility toggle, no DOM create/destroy)
Layout replay:  Detect isSameLayout → Reuse elements → Restart videos
Layout change:  Revoke blob URLs → Destroy elements → Create new set

5. Service Worker as Media Server

Instead of a local HTTP server, the PWA uses its Service Worker to intercept fetch requests and serve cached media:

  • Chunk streaming with Range request support
  • IC interception (Interactive Control routes)
  • Font CSS URL rewriting
  • Cache-first with network fallback
  • Offline operation

Data Flow

Collection Cycle

1. RegisterDisplay()      → CMS settings, commands, XMR address
2. CRC32 comparison       → Skip if unchanged
3. RequiredFiles()        → File list with MD5 hashes
4. Download missing files → 4 parallel chunks, MD5 verify
5. Schedule()             → Layout schedule XML
6. Parse schedule         → Layouts, overlays, actions, commands
7. MediaInventory()       → Report cached file inventory
8. NotifyStatus()         → Report status (disk, timezone, layout)
9. SubmitStats()          → Proof-of-play records
10. SubmitLog()           → Queued log entries
11. SubmitScreenShot()    → If captured

Offline Mode

Network down:
  → XMDS calls fail → Use IndexedDB-cached schedule/settings
  → Media requests → Service Worker serves from Cache API
  → Stats/logs → Queued in IndexedDB, submitted when network returns
  → Player continues rendering with last known schedule

Storage Architecture

Cache API (Binary Files)

Cache: xibo-media
├── /media/{id}           → Images, videos, audio
├── /widget/{widgetId}    → Widget HTML (getWidgetHtml)
├── /font/{fontFile}      → Font files
└── /static/{path}        → Static player assets

IndexedDB (Structured Data)

Database: xibo-player
├── files         → File metadata (id, type, md5, size)
├── stats         → Proof-of-play (pending submission)
├── logs          → Log entries (pending submission)
├── schedule      → Last known schedule (offline fallback)
├── settings      → Last known CMS settings
└── requiredFiles → Last known required files

Technology Stack

LayerTechnologyRationale
LanguageJavaScript (ES2020+)Cross-platform, no transpilation
HTTP clientfetch() + fetchWithRetryBuilt-in, configurable retry
XML parsingDOMParserBuilt-in, namespace-aware
StorageCache API + IndexedDBBuilt-in PWA APIs
OfflineService WorkerIntercepts all fetches
MD5 hashingspark-md54KB, ArrayBuffer support
PDFPDF.js (lazy-loaded)Industry standard
HLShls.js (lazy-loaded)Polyfill for non-Safari
AnimationsWeb Animations APIBuilt-in, GPU-accelerated
BuildViteTree-shaking, minification
Packagespnpm workspacesWorkspace management

Runtime dependencies: spark-md5 (4KB), hls.js (lazy), PDF.js (lazy), xibo-communication-framework