The four overlays that read /data/playlist.js (loading, goodbye,
music-box, music/nc) only ever consumed `tracks.length` for cosmetic
"LIBRARY :: N TRACKS" / "indexed N tracks" flavor text — all live
playback signal flows through bridges/mpd-state.py over OBS WS. The
142 KB JSON, ffprobe walk, and ETag-cached route were all producing
one integer that MPD itself already knows.
RigData::playlistCount() now shells `mpc stats` and parses "Songs: N",
returning 0 on any failure (treated by callers as empty library).
Removes RigPlaylistCommand, DataController::playlist(), the
/data/playlist.js route, the per-overlay <script src> + window.__PLAYLIST
shims, and the stale storage/data/playlist.json artifact.
AudioController still consumes config('rig.music_dirs') for the HTTP
audio stream — that's orthogonal and stays.
96 lines
2.8 KiB
PHP
96 lines
2.8 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use Symfony\Component\Process\Process;
|
|
use Throwable;
|
|
|
|
class RigData
|
|
{
|
|
private array $cache = [];
|
|
private ?int $mpdSongCount = null;
|
|
|
|
public function loading(): array
|
|
{
|
|
return $this->read('loading.json', [
|
|
'game' => null, 'gameId' => null, 'subtitle' => null,
|
|
'countdownMin' => 5, 'camera' => true, 'microphone' => true,
|
|
'compiledAt' => null,
|
|
]);
|
|
}
|
|
|
|
public function telemetry(): array
|
|
{
|
|
return $this->read('telemetry.json', [
|
|
'rig' => config('rig.rig_name') ?? 'unknown',
|
|
'host' => [], 'cpu' => [], 'gpu' => [], 'mem' => [], 'obs' => [],
|
|
]);
|
|
}
|
|
|
|
/**
|
|
* Track count from MPD (the live library, queried via `mpc stats`).
|
|
* Returns 0 if mpc is missing or MPD is unreachable — callers treat
|
|
* that as "empty library" and degrade their flavor text accordingly.
|
|
*/
|
|
public function playlistCount(): int
|
|
{
|
|
if ($this->mpdSongCount !== null) return $this->mpdSongCount;
|
|
|
|
try {
|
|
$proc = new Process(['mpc', 'stats']);
|
|
$proc->setTimeout(2);
|
|
$proc->run();
|
|
if ($proc->isSuccessful() && preg_match('/^Songs:\s*(\d+)/m', $proc->getOutput(), $m)) {
|
|
return $this->mpdSongCount = (int) $m[1];
|
|
}
|
|
} catch (Throwable) {
|
|
// fall through
|
|
}
|
|
return $this->mpdSongCount = 0;
|
|
}
|
|
|
|
public function cmd(): array
|
|
{
|
|
return $this->read('cmd.json', ['id' => 0, 'type' => 'none', 'ts' => 0]);
|
|
}
|
|
|
|
public function writeCmd(string $type): array
|
|
{
|
|
$cmd = ['id' => (int) (microtime(true) * 1000), 'type' => $type, 'ts' => time()];
|
|
$this->write('cmd.json', $cmd);
|
|
$this->cache['cmd.json'] = $cmd;
|
|
return $cmd;
|
|
}
|
|
|
|
public function coverPath(): string
|
|
{
|
|
return (string) config('rig.cover_jpg');
|
|
}
|
|
|
|
private function read(string $file, array $fallback): array
|
|
{
|
|
if (isset($this->cache[$file])) return $this->cache[$file];
|
|
|
|
$path = rtrim(config('rig.storage_data'), '/') . '/' . $file;
|
|
if (!is_file($path)) return $this->cache[$file] = $fallback;
|
|
|
|
$raw = @file_get_contents($path);
|
|
if ($raw === false) return $this->cache[$file] = $fallback;
|
|
|
|
$parsed = json_decode($raw, true);
|
|
if (!is_array($parsed)) return $this->cache[$file] = $fallback;
|
|
|
|
return $this->cache[$file] = $parsed + $fallback;
|
|
}
|
|
|
|
private function write(string $file, array $data): void
|
|
{
|
|
$dir = rtrim(config('rig.storage_data'), '/');
|
|
if (!is_dir($dir)) @mkdir($dir, 0775, true);
|
|
file_put_contents(
|
|
$dir . '/' . $file,
|
|
json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE)
|
|
);
|
|
}
|
|
}
|