Skip to content

Commit

Permalink
Added support for ECP launch, input and exit-app endpoints (#170)
Browse files Browse the repository at this point in the history
* Added support for `launch` event

* Added support to new event `browser`

* Bump `brs-engine` and `restana`

* Added missing BrightScript language coloring config

* Removed unsupported locale ids

* Updated received `currentApp` object to use `.path` instead of `.file` and send package as ArrayBuffer instead of of Buffer

* Upgraded dependencies

* Changed settings folder to the default (removed development suffix)

* Changed file loading to support `brs-engine` v1.8.x

* Fixed `appList` management and ECP Launch

* Fixed status bar `brs` file icon

* Removed debug code

* Implemented Deep Link support on `launch` from ECP

* Fixed the windows focus event to support changes in engine v1.8.x

* Added ECP endpoint for `input` that includes the app id

* Bumped `brs-engine` to v1.8.5 and other dependencies

* Implemented ECP `exit-app` endpoint
  • Loading branch information
lvcabral authored Feb 1, 2025
1 parent 0e45dac commit 7509e71
Show file tree
Hide file tree
Showing 18 changed files with 883 additions and 301 deletions.
8 changes: 4 additions & 4 deletions build/webpack.app.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ module.exports = env => {
{ context: "src/app/", from: "fonts/**", to: "../app" },
{ context: "src/app/", from: "css/**", to: "../app" },
{ context: "src/app/", from: "web/**", to: "../app" },
{ context: "node_modules/brs-engine/app/lib", from: fileApi, to: "lib" },
{ context: "node_modules/brs-engine/app/lib", from: fileWrk, to: "lib" },
{ context: "node_modules/brs-engine/app/", from: "audio/**", to: "../app" },
{ context: "node_modules/brs-engine/app/", from: "fonts/**", to: "../app" },
{ context: "node_modules/brs-engine/browser/lib", from: fileApi, to: "lib" },
{ context: "node_modules/brs-engine/browser/lib", from: fileWrk, to: "lib" },
{ context: "node_modules/brs-engine/browser/", from: "audio/**", to: "../app" },
{ context: "node_modules/brs-engine/browser/", from: "fonts/**", to: "../app" },
]
})
],
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@
"nanoid": "^4.0.1",
"node-ssdp": "^4.0.1",
"postman-request": "^2.88.1-postman.33",
"restana": "^3.4.2",
"restana": "^4.9.9",
"toastify-js": "^1.12.0",
"vanilla-terminal": "lvcabral/vanilla-terminal",
"ws": "^7.5.0",
Expand All @@ -98,7 +98,7 @@
"@types/luxon": "^1.27.1",
"@types/request": "^2.47.0",
"babel-loader": "^8.0.6",
"brs-engine": "^1.7.1",
"brs-engine": "^1.8.0",
"copy-webpack-plugin": "^11.0.0",
"css-loader": "^6.7.3",
"electron": "^25.9.7",
Expand Down
99 changes: 73 additions & 26 deletions src/app/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*---------------------------------------------------------------------------------------------
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
*
* Copyright (c) 2019-2024 Marcelo Lv Cabral. All Rights Reserved.
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
*
* Licensed under the MIT License. See LICENSE in the repository root for license information.
*--------------------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -54,16 +54,42 @@ api.send("deviceData", brs.deviceData);
api.send("serialNumber", brs.getSerialNumber());
api.send("engineVersion", brs.getVersion());

let selectedApp = "";

brs.subscribe("desktop", (event, data) => {
if (event === "loaded") {
selectedApp = "";
currentApp = data;
appLoaded(data);
} else if (event === "started") {
currentApp = data;
stats.style.visibility = "visible";
} else if (event === "launch") {
console.info(`App launched: ${data}`);
if (data?.app) {
selectedApp = data.app;
}
} else if (event === "browser") {
if (data?.url) {
const newWindow = window.open(
data.url,
"_blank",
`width=${data.width},height=${data.height},popup`
);
if (newWindow) {
newWindow.focus();
} else {
showToast("Warning: It was not possible to open a new window!", true);
}
}
} else if (event === "closed" || event === "error") {
showCloseMessage(event, data);
appTerminated();
if (selectedApp !== "" && event === "closed") {
api.send("runUrl", selectedApp);
} else {
showCloseMessage(event, data);
}
selectedApp = "";
} else if (event === "redraw") {
redrawEvent(data);
} else if (event === "control") {
Expand All @@ -79,7 +105,7 @@ brs.subscribe("desktop", (event, data) => {
debugMode = data.level;
}
} else if (event === "icon") {
api.send("saveIcon", [currentApp.id, data]);
api.send("saveIcon", [currentApp.path.hashCode(), data]);
} else if (event === "registry") {
api.send("updateRegistry", data);
} else if (event === "reset") {
Expand Down Expand Up @@ -115,29 +141,39 @@ api.receive("setDeviceInfo", function (key, value) {
}
}
});
api.receive("fileSelected", function (filePath, data, clear, mute, debug, source) {
api.receive("executeFile", function (filePath, data, clear, mute, debug, input) {
try {
const fileExt = filePath.split(".").pop()?.toLowerCase();
let password = "";
if (fileExt === "bpk") {
const settings = api.getPreferences();
password = settings?.device?.developerPwd ?? "";
}
brs.execute(filePath, data, {
clearDisplayOnExit: clear,
muteSound: mute,
execSource: source,
debugOnCrash: debug,
password: password,
});
if (fileExt !== "brs") {
data = data.buffer;
}
brs.execute(
filePath,
data,
{
clearDisplayOnExit: clear,
muteSound: mute,
debugOnCrash: debug,
password: password,
},
input
);
} catch (error) {
const errorMsg = `Error opening ${filePath}:${error.message}`;
console.error(errorMsg);
showToast(errorMsg, 5000, true);
}
});
api.receive("closeChannel", function (source) {
api.receive("closeChannel", function (source, appID) {
if (currentApp.running) {
if (appID && appID !== currentApp.id) {
return;
}
brs.terminate(source);
}
});
Expand All @@ -152,6 +188,9 @@ api.receive("console", function (text, error) {
api.receive("debugCommand", function (cmd) {
brs.debug(cmd);
});
api.receive("postInputParams", function (params) {
brs.sendInput(params);
});
api.receive("setCustomKeys", function (keys) {
brs.setCustomKeys(keys);
});
Expand Down Expand Up @@ -200,20 +239,28 @@ window.onload = window.onresize = function () {
};

// Window Focus Events
window.onfocus = function () {
if (currentApp.running && debugMode === "pause") {
brs.debug("cont");
}
};
window.addEventListener(
"focus",
function () {
if (currentApp.running && debugMode === "pause") {
brs.debug("cont");
}
},
false
);

window.onblur = function () {
if (currentApp.running && debugMode === "continue") {
let settings = api.getPreferences();
if (settings?.simulator?.options?.includes("pauseOnBlur")) {
brs.debug("pause");
window.addEventListener(
"blur",
function () {
if (currentApp.running && debugMode === "continue") {
let settings = api.getPreferences();
if (settings?.simulator?.options?.includes("pauseOnBlur")) {
brs.debug("pause");
}
}
}
};
},
false
);

// Toggle Full Screen when Double Click
display.ondblclick = function () {
Expand Down Expand Up @@ -244,8 +291,8 @@ function appLoaded(appData) {
brs.enableStats(settings.simulator.options.includes("perfStats"));
}
api.updateTitle(`${appData.title} - ${defaultTitle}`);
if (appData.id === "brs") {
api.send("addRecentSource", appData.file);
if (appData.path.toLowerCase().endsWith(".brs")) {
api.send("addRecentSource", appData.path);
} else {
api.send("addRecentPackage", appData);
}
Expand Down
22 changes: 13 additions & 9 deletions src/app/brightscript.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ BrightScript Language Mode
https://developer.roku.com/docs/references/brightscript/language/brightscript-language-reference.md
Adapted from the Visual Basic mode for CodeMirror by Marcelo Lv Cabral
*/

export function defineMode(CodeMirror) {
Expand All @@ -23,11 +25,11 @@ export function defineMode(CodeMirror) {
let functions = /^[_A-Za-z]\w*(?=\()/;
let identifiers = /^[_A-Za-z]\w*/;

let openingKeywords = ["sub", "function"];
let endKeywords = ["endsub", "endfunction"];
const openingKeywords = ["sub", "function"];
const endKeywords = ["endsub", "endfunction"];

let openingControl = ["while", "if", "for", "try"];
let middleControl = [
const openingControl = ["while", "if", "for", "try"];
const middleControl = [
"catch",
"continue for",
"continue while",
Expand All @@ -39,15 +41,17 @@ export function defineMode(CodeMirror) {
"to",
"step",
"in",
"then",
"each",
"as",
"return",
"stop",
"throw",
];
let endControl = ["next", "endif", "end if", "endfor", "end for", "endwhile", "end while", "endtry", "end try"];
let wordOperators = wordRegexp(["and", "or", "not", "mod"]);
let commonkeywords = ["dim", "print", "goto", "library"];
let commontypes = [
const endControl = ["next", "endif", "end if", "endfor", "end for", "endwhile", "end while", "endtry", "end try"];
const wordOperators = wordRegexp(["and", "or", "not", "mod"]);
const commonkeywords = ["dim", "print", "goto", "library"];
const commontypes = [
"object",
"dynamic",
"boolean",
Expand All @@ -59,7 +63,7 @@ export function defineMode(CodeMirror) {
"void",
];

let atomWords = ["true", "false", "invalid"];
const atomWords = ["true", "false", "invalid"];
let builtinFuncsWords = [
"box",
"createobject",
Expand Down
9 changes: 4 additions & 5 deletions src/app/css/editor.css
Original file line number Diff line number Diff line change
Expand Up @@ -247,8 +247,7 @@ pre {
}

.more-options {
/* styles for the ellipsis button */
position: relative; /* add this */
position: relative;
}

.dropdown {
Expand All @@ -257,7 +256,7 @@ pre {
background-color: var(--control-background-color);
border: 1px solid var(--control-border-color);
padding: 2px;
z-index: 1; /* set a higher z-index value */
z-index: 1;
top: calc(100% + 1px);
left: 0;
border-radius: 0.25em;
Expand All @@ -280,8 +279,8 @@ pre {
align-items: center;
text-decoration: none;
color: var(--control-color);
padding: 3px; /* add padding to the link */
width: 100%; /* make the link take up the full width */
padding: 3px;
width: 100%;
}

.dropdown li a i {
Expand Down
8 changes: 4 additions & 4 deletions src/app/editor.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*---------------------------------------------------------------------------------------------
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
*
* Copyright (c) 2019-2024 Marcelo Lv Cabral. All Rights Reserved.
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
*
* Licensed under the MIT License. See LICENSE in the repository root for license information.
*--------------------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -110,7 +110,7 @@ function main() {
const cm = document.querySelector(".CodeMirror");
delete cm.CodeMirror.constructor.keyMap.emacsy["Ctrl-V"];
}
hideEditor(!(currentApp.title === undefined || currentApp.title === "editor_code.brs"));
hideEditor(!(currentApp.title === undefined || currentApp.title.endsWith("editor_code.brs")));
populateCodeSelector();
// Subscribe to Engine events and initialize Console
brs.subscribe(appId, handleEngineEvents);
Expand Down Expand Up @@ -145,7 +145,7 @@ function updateButtons() {
function handleEngineEvents(event, data) {
if (event === "loaded") {
currentApp = data;
hideEditor(currentApp.title !== "editor_code.brs");
hideEditor(!currentApp.title.endsWith("editor_code.brs"));
} else if (event === "started") {
currentApp = data;
console.info(`Execution started ${appId}`);
Expand Down Expand Up @@ -446,7 +446,7 @@ export function runCode() {
const code = editorManager.editor.getValue();
if (code && code.trim() !== "") {
try {
api.send("runCode", editorManager.editor.getValue());
api.send("runCode", code);
terminal.output(`<br /><pre>Executing source code...</pre><br /><br />`);
terminal.idle();
} catch (e) {
Expand Down
Binary file modified src/app/images/device-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 4 additions & 2 deletions src/app/preload.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*---------------------------------------------------------------------------------------------
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
*
* Copyright (c) 2019-2024 Marcelo Lv Cabral. All Rights Reserved.
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
*
* Licensed under the MIT License. See LICENSE in the repository root for license information.
*--------------------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -112,6 +112,7 @@ contextBridge.exposeInMainWorld("api", {
"showEditor",
"keySent",
"runCode",
"runUrl",
"reset",
];
if (validChannels.includes(channel)) {
Expand All @@ -126,6 +127,7 @@ contextBridge.exposeInMainWorld("api", {
"postKeyDown",
"postKeyUp",
"postKeyPress",
"postInputParams",
"closeChannel",
"debugCommand",
"setTheme",
Expand All @@ -139,7 +141,7 @@ contextBridge.exposeInMainWorld("api", {
"serverStatus",
"copyScreenshot",
"saveScreenshot",
"fileSelected",
"executeFile",
"openEditor",
];
if (validChannels.includes(channel)) {
Expand Down
8 changes: 4 additions & 4 deletions src/app/statusbar.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*---------------------------------------------------------------------------------------------
* BrightScript Simulation Desktop Application (https://github.com/lvcabral/brs-desktop)
*
* Copyright (c) 2019-2024 Marcelo Lv Cabral. All Rights Reserved.
* Copyright (c) 2019-2025 Marcelo Lv Cabral. All Rights Reserved.
*
* Licensed under the MIT License. See LICENSE in the repository root for license information.
*--------------------------------------------------------------------------------------------*/
Expand Down Expand Up @@ -239,12 +239,12 @@ function updateStatus(data) {
clearCounters();
setStatusColor();
statusIconFile.innerHTML =
data.id === "brs" ? "<i class='far fa-file'></i>" : "<i class='fa fa-cube'></i>";
data.path.toLowerCase().endsWith(".brs")? "<i class='fa fa-file'></i>" : "<i class='fa fa-cube'></i>";
statusFile.innerText = shortenPath(
data.file,
data.path,
Math.max(MIN_PATH_SIZE, window.innerWidth * PATH_SIZE_FACTOR)
);
filePath = data.file;
filePath = data.path;
if (data.version !== "") {
statusVersion.innerText = data.version;
statusIconVersion.innerHTML = "<i class='fa fa-tag'></i>";
Expand Down
Loading

0 comments on commit 7509e71

Please sign in to comment.