Skip to content

Commit

Permalink
Created BrsDevice static object with deviceInfo, registry and `…
Browse files Browse the repository at this point in the history
…sharedArray` (#469)

* Created `BrsDevice` static object with `deviceInfo`, `registry` and `sharedArray`

* Reset `lastKeyTime` on app start
  • Loading branch information
lvcabral authored Feb 16, 2025
1 parent c76c8d3 commit a499551
Show file tree
Hide file tree
Showing 45 changed files with 290 additions and 267 deletions.
66 changes: 66 additions & 0 deletions src/core/BrsDevice.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { dataBufferIndex, DataType, DebugCommand } from "./common";

export class BrsDevice {
static readonly deviceInfo: Map<string, any> = new Map<string, any>();
static readonly registry: Map<string, string> = new Map<string, string>();
static sharedArray: Int32Array = new Int32Array(0);
static displayEnabled: boolean = true;
static lastRemote: number = 0;
static lastKeyTime: number = Date.now();
static currKeyTime: number = Date.now();

/**
* Updates the device registry with the provided data
* @param registry Map with registry content.
*/
static setRegistry(registry: Map<string, string>) {
registry.forEach((value: string, key: string) => {
this.registry.set(key, value);
});
}

/**
* Setup the device sharedArray
* @param sharedArray Int32Array to be used as sharedArray
*/
static setSharedArray(sharedArray: Int32Array) {
this.sharedArray = sharedArray;
}

/**
* Method to check if the Break Command is set in the sharedArray
* @returns the last debug command
*/
static checkBreakCommand(debugMode: boolean): number {
let cmd = debugMode ? DebugCommand.BREAK : -1;
if (!debugMode) {
cmd = Atomics.load(this.sharedArray, DataType.DBG);
if (cmd === DebugCommand.BREAK) {
Atomics.store(this.sharedArray, DataType.DBG, -1);
} else if (cmd === DebugCommand.PAUSE) {
postMessage("debug,pause");
Atomics.wait(this.sharedArray, DataType.DBG, DebugCommand.PAUSE);
Atomics.store(this.sharedArray, DataType.DBG, -1);
cmd = -1;
postMessage("debug,continue");
}
}
return cmd;
}

/**
* Method to extract the data buffer from the sharedArray
* @returns the data buffer as a string
*/
static readDataBuffer(): string {
let data = "";
this.sharedArray.slice(dataBufferIndex).every((char) => {
if (char > 0) {
data += String.fromCharCode(char);
}
return char; // if \0 stops decoding
});
Atomics.store(this.sharedArray, DataType.BUF, -1);
return data;
}
}
File renamed without changes.
17 changes: 8 additions & 9 deletions src/core/brsTypes/components/BrsObjects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ export const BrsObjects = new BrsObjectsMap([
["roEVPCipher", (_: Interpreter) => new RoEVPCipher()],
["roEVPDigest", (_: Interpreter) => new RoEVPDigest()],
["roHMAC", (_: Interpreter) => new RoHMAC()],
["roDeviceCrypto", (interpreter: Interpreter) => new RoDeviceCrypto(interpreter)],
["roDeviceCrypto", (_: Interpreter) => new RoDeviceCrypto()],
["roChannelStore", (_: Interpreter) => new RoChannelStore()],
["roDateTime", (_: Interpreter) => new RoDateTime()],
["roList", (_: Interpreter) => new RoList()],
Expand All @@ -153,27 +153,26 @@ export const BrsObjects = new BrsObjectsMap([
["roInput", (interpreter: Interpreter) => new RoInput(interpreter)],
["roSystemLog", (interpreter: Interpreter) => new RoSystemLog(interpreter)],
["roFileSystem", (_: Interpreter) => new RoFileSystem()],
["roLocalization", (interpreter: Interpreter) => new RoLocalization(interpreter)],
["roLocalization", (_: Interpreter) => new RoLocalization()],
["roFontRegistry", (interpreter: Interpreter) => new RoFontRegistry(interpreter)],
["roRegistry", (_: Interpreter) => new RoRegistry()],
[
"roRegistrySection",
(interpreter: Interpreter, section: BrsString) =>
new RoRegistrySection(interpreter, section),
(_: Interpreter, section: BrsString) => new RoRegistrySection(section),
1,
],
["roAppInfo", (_: Interpreter) => new RoAppInfo()],
["roDeviceInfo", (interpreter: Interpreter) => new RoDeviceInfo(interpreter)],
["roDeviceInfo", (_: Interpreter) => new RoDeviceInfo()],
["roRemoteInfo", (_: Interpreter) => new RoRemoteInfo()],
["roAppMemoryMonitor", (_: Interpreter) => new RoAppMemoryMonitor()],
["roAudioPlayer", (interpreter: Interpreter) => new RoAudioPlayer(interpreter)],
["roAudioPlayer", (_: Interpreter) => new RoAudioPlayer()],
[
"roAudioResource",
(interpreter: Interpreter, name: BrsString) => createAudioResource(interpreter, name),
1,
],
["roAudioMetadata", (_: Interpreter) => new RoAudioMetadata()],
["roVideoPlayer", (interpreter: Interpreter) => new RoVideoPlayer(interpreter)],
["roVideoPlayer", (_: Interpreter) => new RoVideoPlayer()],
["roCompositor", (_: Interpreter) => new RoCompositor()],
[
"roRegion",
Expand All @@ -197,8 +196,8 @@ export const BrsObjects = new BrsObjectsMap([
["roURLTransfer", (interpreter: Interpreter) => new RoURLTransfer(interpreter)],
["roInvalid", (_: Interpreter) => new RoInvalid(), -1],
["roNDK", (_: Interpreter) => new RoNDK()],
["roCECStatus", (interpreter: Interpreter) => new RoCECStatus(interpreter)],
["roHdmiStatus", (interpreter: Interpreter) => new RoHdmiStatus(interpreter)],
["roCECStatus", (_: Interpreter) => new RoCECStatus()],
["roHdmiStatus", (_: Interpreter) => new RoHdmiStatus()],
["roSocketAddress", (interpreter: Interpreter) => new RoSocketAddress(interpreter)],
["roStreamSocket", (interpreter: Interpreter) => new RoStreamSocket(interpreter)],
]);
3 changes: 2 additions & 1 deletion src/core/brsTypes/components/RoAppInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { BrsComponent } from "./BrsComponent";
import { BrsType } from "..";
import { Callable, StdlibArgument } from "../Callable";
import { Interpreter } from "../../interpreter";
import { BrsDevice } from "../../BrsDevice";

export class RoAppInfo extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand Down Expand Up @@ -60,7 +61,7 @@ export class RoAppInfo extends BrsComponent implements BrsValue {
returns: ValueKind.String,
},
impl: (interpreter: Interpreter) => {
return new BrsString(interpreter.deviceInfo.get("developerId"));
return new BrsString(BrsDevice.deviceInfo.get("developerId"));
},
});

Expand Down
17 changes: 9 additions & 8 deletions src/core/brsTypes/components/RoAppManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Interpreter } from "../../interpreter";
import { Int32 } from "../Int32";
import { RoTimespan } from "./RoTimespan";
import { AppData, AppExitReason, isAppData } from "../../common";
import { BrsDevice } from "../../BrsDevice";

export class RoAppManager extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand Down Expand Up @@ -75,8 +76,8 @@ export class RoAppManager extends BrsComponent implements BrsValue {
args: [],
returns: ValueKind.Void,
},
impl: (interpreter: Interpreter) => {
interpreter.lastKeyTime = Date.now();
impl: (_: Interpreter) => {
BrsDevice.lastKeyTime = Date.now();
return BrsInvalid.Instance;
},
});
Expand Down Expand Up @@ -135,7 +136,7 @@ export class RoAppManager extends BrsComponent implements BrsValue {
returns: ValueKind.Object,
},
impl: (interpreter: Interpreter) => {
const app = interpreter.deviceInfo.get("appList")?.find((app: AppData) => app.running);
const app = BrsDevice.deviceInfo.get("appList")?.find((app: AppData) => app.running);
const exitInfo = {
exit_code: app?.exitReason ?? AppExitReason.UNKNOWN,
media_player_state: "stopped",
Expand Down Expand Up @@ -192,7 +193,7 @@ export class RoAppManager extends BrsComponent implements BrsValue {
returns: ValueKind.Boolean,
},
impl: (interpreter: Interpreter, channelId: BrsString, version: BrsString) => {
const appList = interpreter.deviceInfo.get("appList");
const appList = BrsDevice.deviceInfo.get("appList");
if (appList instanceof Array) {
const app = appList.find((app) => {
return app.id === channelId.value;
Expand All @@ -219,7 +220,7 @@ export class RoAppManager extends BrsComponent implements BrsValue {
version: BrsString,
params: RoAssociativeArray
) => {
const appList = interpreter.deviceInfo.get("appList");
const appList = BrsDevice.deviceInfo.get("appList");
if (appList instanceof Array) {
const app = appList.find((app) => {
return app.id === channelId.value;
Expand Down Expand Up @@ -270,7 +271,7 @@ export class RoAppManager extends BrsComponent implements BrsValue {
},
impl: (interpreter: Interpreter) => {
const result = new RoArray([]);
const appList = interpreter.deviceInfo.get("appList");
const appList = BrsDevice.deviceInfo.get("appList");
if (appList instanceof Array) {
appList.forEach((app) => {
const appObj = { id: app.id, title: app.title, version: app.version };
Expand Down Expand Up @@ -298,8 +299,8 @@ export class RoAppManager extends BrsComponent implements BrsValue {
args: [new StdlibArgument("disabled", ValueKind.Boolean)],
returns: ValueKind.Void,
},
impl: (interpreter: Interpreter, disabled: BrsBoolean) => {
interpreter.displayEnabled = !disabled.toBoolean();
impl: (_: Interpreter, disabled: BrsBoolean) => {
BrsDevice.displayEnabled = !disabled.toBoolean();
postMessage({ displayEnabled: !disabled.toBoolean() });
return Uninitialized.Instance;
},
Expand Down
9 changes: 4 additions & 5 deletions src/core/brsTypes/components/RoAudioPlayer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,18 @@ import { Int32 } from "../Int32";
import { DataType } from "../../common";
import { BrsHttpAgent, IfHttpAgent } from "../interfaces/IfHttpAgent";
import { IfSetMessagePort, IfGetMessagePort } from "../interfaces/IfMessagePort";
import { BrsDevice } from "../../BrsDevice";

export class RoAudioPlayer extends BrsComponent implements BrsValue, BrsHttpAgent {
readonly kind = ValueKind.Object;
readonly customHeaders: Map<string, string>;
private readonly interpreter: Interpreter;
private port?: RoMessagePort;
private contentList: RoAssociativeArray[];
private audioFlags: number;
cookiesEnabled: boolean;

constructor(interpreter: Interpreter) {
constructor() {
super("roAudioPlayer");
this.interpreter = interpreter;
this.contentList = new Array();
this.audioFlags = -1;
this.cookiesEnabled = false;
Expand Down Expand Up @@ -86,14 +85,14 @@ export class RoAudioPlayer extends BrsComponent implements BrsValue, BrsHttpAgen

private getNewEvents() {
const events: BrsEvent[] = [];
const flags = Atomics.load(this.interpreter.sharedArray, DataType.SND);
const flags = Atomics.load(BrsDevice.sharedArray, DataType.SND);
if (flags !== this.audioFlags) {
this.audioFlags = flags;
if (this.audioFlags >= 0) {
events.push(
new RoAudioPlayerEvent(
this.audioFlags,
Atomics.load(this.interpreter.sharedArray, DataType.IDX)
Atomics.load(BrsDevice.sharedArray, DataType.IDX)
)
);
}
Expand Down
5 changes: 3 additions & 2 deletions src/core/brsTypes/components/RoAudioResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { Callable, StdlibArgument } from "../Callable";
import { Interpreter } from "../../interpreter";
import { Int32 } from "../Int32";
import { DataType } from "../../common";
import { BrsDevice } from "../../BrsDevice";

export class RoAudioResource extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand All @@ -17,7 +18,7 @@ export class RoAudioResource extends BrsComponent implements BrsValue {

constructor(interpreter: Interpreter, name: BrsString) {
super("roAudioResource");
this.maxStreams = Math.min(interpreter.deviceInfo.get("maxSimulStreams"), 3) || 2;
this.maxStreams = Math.min(BrsDevice.deviceInfo.get("maxSimulStreams"), 3) || 2;
this.valid = true;
const systemwav = ["select", "navsingle", "navmulti", "deadend"];
const sysIndex = systemwav.findIndex((wav) => wav === name.value.toLowerCase());
Expand Down Expand Up @@ -87,7 +88,7 @@ export class RoAudioResource extends BrsComponent implements BrsValue {
impl: (interpreter: Interpreter) => {
if (this.audioId) {
const currentWav = Atomics.load(
interpreter.sharedArray,
BrsDevice.sharedArray,
DataType.WAV + this.currentIndex
);
this.playing = currentWav === this.audioId;
Expand Down
3 changes: 2 additions & 1 deletion src/core/brsTypes/components/RoBitmap.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import UPNG from "upng-js";
import * as JPEG from "jpeg-js";
import BMP from "decode-bmp";
import { WebPRiffParser, WebPDecoder } from "libwebpjs";
import { BrsDevice } from "../../BrsDevice";

export class RoBitmap extends BrsComponent implements BrsValue, BrsDraw2D {
readonly kind = ValueKind.Object;
Expand All @@ -48,7 +49,7 @@ export class RoBitmap extends BrsComponent implements BrsValue, BrsDraw2D {
this.rgbaLast = 0;
this.rgbaRedraw = true;
this.valid = true;
const platform = interpreter.deviceInfo.get("platform");
const platform = BrsDevice.deviceInfo.get("platform");
this.disposeCanvas = platform?.inIOS ?? false;
this.width = 1;
this.height = 1;
Expand Down
11 changes: 5 additions & 6 deletions src/core/brsTypes/components/RoCECStatus.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,15 @@ import { Interpreter } from "../../interpreter";
import { RoCECStatusEvent } from "../events/RoCECStatusEvent";
import { DataType } from "../../common";
import { IfSetMessagePort, IfGetMessagePort } from "../interfaces/IfMessagePort";
import { BrsDevice } from "../../BrsDevice";

export class RoCECStatus extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
private readonly interpreter: Interpreter;
private port?: RoMessagePort;
private active: number;

constructor(interpreter: Interpreter) {
constructor() {
super("roCECStatus");
this.interpreter = interpreter;
this.active = 1; // Default to active
const setPortIface = new IfSetMessagePort(this, this.getNewEvents.bind(this));
const getPortIface = new IfGetMessagePort(this);
Expand Down Expand Up @@ -44,7 +43,7 @@ export class RoCECStatus extends BrsComponent implements BrsValue {

private getNewEvents() {
const events: BrsEvent[] = [];
const cecActive = Atomics.load(this.interpreter.sharedArray, DataType.CEC);
const cecActive = Atomics.load(BrsDevice.sharedArray, DataType.CEC);
if (cecActive >= 0 && cecActive !== this.active) {
this.active = cecActive;
events.push(new RoCECStatusEvent(this.active !== 0));
Expand All @@ -60,8 +59,8 @@ export class RoCECStatus extends BrsComponent implements BrsValue {
args: [],
returns: ValueKind.Boolean,
},
impl: (interpreter: Interpreter) => {
const cecActive = Atomics.load(interpreter.sharedArray, DataType.CEC);
impl: (_: Interpreter) => {
const cecActive = Atomics.load(BrsDevice.sharedArray, DataType.CEC);
return BrsBoolean.from(cecActive !== 0);
},
});
Expand Down
5 changes: 3 additions & 2 deletions src/core/brsTypes/components/RoChannelStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { RoAssociativeArray } from "./RoAssociativeArray";
import { AppData } from "../../common";
import { parseString, processors } from "xml2js";
import { IfSetMessagePort, IfGetMessagePort } from "../interfaces/IfMessagePort";
import { BrsDevice } from "../../BrsDevice";

export class RoChannelStore extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand Down Expand Up @@ -465,11 +466,11 @@ export class RoChannelStore extends BrsComponent implements BrsValue {
json = `{channel_data="${this.credData}"}`;
status = 0;
}
const app = interpreter.deviceInfo.get("appList")?.find((app: AppData) => app.running);
const app = BrsDevice.deviceInfo.get("appList")?.find((app: AppData) => app.running);
const channelCred = {
channelId: app?.id ?? "dev",
json: json,
publisherDeviceId: interpreter.deviceInfo.get("clientId") ?? "",
publisherDeviceId: BrsDevice.deviceInfo.get("clientId") ?? "",
status: status,
};
return toAssociativeArray(channelCred);
Expand Down
7 changes: 4 additions & 3 deletions src/core/brsTypes/components/RoDateTime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Int32 } from "../Int32";
import dayjs from "dayjs";
import utc from "dayjs/plugin/utc";
import customParseFormat from "dayjs/plugin/customParseFormat";
import { BrsDevice } from "../../BrsDevice";

export class RoDateTime extends BrsComponent implements BrsValue {
readonly kind = ValueKind.Object;
Expand Down Expand Up @@ -265,7 +266,7 @@ export class RoDateTime extends BrsComponent implements BrsValue {
},
impl: (interpreter: Interpreter, format: BrsString) => {
const rokuDateTokens = ["EEEE", "EEE", "dd", "d", "MMMM", "MMM", "MM", "M", "yy", "y"];
const locale = (interpreter.deviceInfo.get("locale") ?? "en_US").replace("_", "-");
const locale = (BrsDevice.deviceInfo.get("locale") ?? "en_US").replace("_", "-");
const dateFormat = format.value.trim() === "" ? "short" : format.value;
let dateString = this.formatDate(dateFormat, locale);
if (dateString === "") {
Expand All @@ -284,7 +285,7 @@ export class RoDateTime extends BrsComponent implements BrsValue {
},
impl: (interpreter: Interpreter, format: BrsString) => {
const rokuTimeTokens = ["HH", "H", "hh", "h", "mm", "m", "a"];
const locale = (interpreter.deviceInfo.get("locale") ?? "en_US").replace("_", "-");
const locale = (BrsDevice.deviceInfo.get("locale") ?? "en_US").replace("_", "-");
const dateFormat = format.value.trim() === "" ? "short" : format.value;
let timeString = this.formatTime(dateFormat, locale);
if (timeString === "") {
Expand Down Expand Up @@ -468,7 +469,7 @@ export class RoDateTime extends BrsComponent implements BrsValue {
const tzDate = new Date(date.toLocaleString("en-US", { timeZone: timeZone }));
return Math.round((tzDate.getTime() - utcDate.getTime()) / 6e4);
};
return new Int32(-getOffset(interpreter.deviceInfo.get("timeZone")) + 0);
return new Int32(-getOffset(BrsDevice.deviceInfo.get("timeZone")) + 0);
},
});

Expand Down
Loading

0 comments on commit a499551

Please sign in to comment.