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' => [], ]); } public function playlist(): array { return $this->read('playlist.json', [ 'syncedAt' => null, 'sourceDirs' => [], 'trackCount' => 0, 'tracks' => [], ]); } public function playlistCount(): int { $p = $this->playlist(); return (int) ($p['trackCount'] ?? count($p['tracks'] ?? [])); } 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 playlistPath(): string { return rtrim(config('rig.storage_data'), '/') . '/playlist.json'; } 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) ); } }