108 lines
3.3 KiB
JavaScript
108 lines
3.3 KiB
JavaScript
const express = require('express');
|
|
const fs = require('fs');
|
|
const http = require('http');
|
|
const path = require('path');
|
|
const common = require('./common');
|
|
const { createPlayerRuntime } = require('./player/runtime');
|
|
const { createPlayerPlaylistService } = require('./player/playlist');
|
|
const { createRtmpStreamService } = require('./player/modules/rtmp-streams');
|
|
const { normalizeDeviceId, registerPlayerOnboardingRoutes, commitDeviceBinding } = require('./player/onboarding');
|
|
const { createOnboardingStore } = require('./player/onboarding/store');
|
|
const { registerPlayerRoutes } = require('./player/routes');
|
|
const { pruneStaleOnboardingDevices } = require('./db');
|
|
|
|
|
|
// Player runtime, media API, and websocket wiring.
|
|
async function start() {
|
|
const app = express();
|
|
const pool = common.createPool();
|
|
const PORT = Number(process.env.PLAYER_PORT || 3001);
|
|
const ASSET_DIR = path.join(__dirname, 'player', 'public');
|
|
const MEDIA_DIR = path.join(__dirname, '..', 'media');
|
|
const ONBOARDING_QUEUE_FILE = path.join(MEDIA_DIR, 'player-onboarding-queue.json');
|
|
const DB_SYNC_INTERVAL_MS = Number(process.env.PLAYER_DB_SYNC_INTERVAL_MS || 15000);
|
|
const onboardingStore = createOnboardingStore(ONBOARDING_QUEUE_FILE);
|
|
const playerRuntime = createPlayerRuntime({
|
|
pool: pool,
|
|
normalizeDeviceId: normalizeDeviceId
|
|
});
|
|
const playerPlaylistService = createPlayerPlaylistService({
|
|
pool: pool,
|
|
common: common,
|
|
snapshotDir: path.join(MEDIA_DIR, 'player-cache', 'screen-playlists')
|
|
});
|
|
const rtmpStreamService = createRtmpStreamService({
|
|
mediaDir: MEDIA_DIR
|
|
});
|
|
const server = http.createServer(app);
|
|
playerRuntime.installWebsocket(server);
|
|
app.use(express.json());
|
|
registerPlayerOnboardingRoutes(app, {
|
|
pool: pool,
|
|
common: common,
|
|
playerRuntime: playerRuntime,
|
|
onboardingStore: onboardingStore,
|
|
QRCode: require('qrcode')
|
|
});
|
|
registerPlayerRoutes(app, {
|
|
pool: pool,
|
|
common: common,
|
|
mediaDir: MEDIA_DIR,
|
|
assetDir: ASSET_DIR,
|
|
playerRuntime: playerRuntime,
|
|
playerPlaylistService: playerPlaylistService,
|
|
rtmpStreamService: rtmpStreamService
|
|
});
|
|
|
|
app.use(function (error, _req, res, _next) {
|
|
console.error(error);
|
|
res.status(error.statusCode || 500).send(error.statusCode ? error.message : 'Internal server error');
|
|
});
|
|
|
|
fs.mkdirSync(MEDIA_DIR, { recursive: true });
|
|
|
|
server.listen(PORT, function () {
|
|
console.log(`Pulse Signage app listening on port ${PORT}`);
|
|
});
|
|
|
|
async function syncDatabaseState() {
|
|
try {
|
|
await common.ensureSchema(pool, { mediaDir: MEDIA_DIR });
|
|
|
|
if (playerRuntime.snapshotAllConnections().length > 0) {
|
|
await pruneStaleOnboardingDevices(pool);
|
|
}
|
|
|
|
await onboardingStore.flushBindings(function (entry) {
|
|
return commitDeviceBinding(
|
|
pool,
|
|
entry.deviceId,
|
|
entry.clientName,
|
|
entry.screenSlug,
|
|
playerRuntime.isClientNameAvailableOnScreen,
|
|
playerRuntime.snapshotAllConnections()
|
|
);
|
|
});
|
|
} catch (error) {
|
|
console.error(error);
|
|
}
|
|
}
|
|
|
|
await syncDatabaseState();
|
|
setInterval(function () {
|
|
syncDatabaseState().catch(function (error) {
|
|
console.error(error);
|
|
});
|
|
}, DB_SYNC_INTERVAL_MS);
|
|
}
|
|
|
|
module.exports = { start };
|
|
|
|
if (require.main === module) {
|
|
start().catch(function (error) {
|
|
console.error(error);
|
|
process.exit(1);
|
|
});
|
|
}
|
|
|