Skip to content
This repository has been archived by the owner on Oct 11, 2024. It is now read-only.

Rich Presence #15

Merged
merged 5 commits into from
Jun 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 63 additions & 0 deletions libs/rpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
const DiscordRPC = require('discord-rpc');

const rpcClient = new DiscordRPC.Client({ transport: 'ipc' });

const STATES = [
'Browsing the games list',
'Playing a game'
];

module.exports.DRPC = class DRPC {
#enabled = false;
#status = {
state: ' ',
details: STATES[0],
startTimestamp: 0,
largeImageKey: 'allblack',
largeImageText: 'The PlayStation 4 emulator',
// smallImageKey: '',
// smallImageText: '',
instance: false
};

constructor(enabled = false) {
this.#status.startTimestamp = Date.now();
this.#enabled = enabled;

rpcClient.on('ready', () => {
this.renderStatus();

setInterval(() => {
if (this.#enabled)
this.renderStatus();
}, 15e3);
});

rpcClient.login({ clientId: '1247271614459023424' }).catch(console.error);
}

setGame = (gname = null) => {
const status = this.#status;

status.startTimestamp = Date.now();
status.details = STATES[gname === null ? 0 : 1];
status.state = gname === null ? ' ' : gname;
};

renderStatus = async () => rpcClient.setActivity(this.#status);

set state(b) {
if (b === false) {
this.#enabled = false;
rpcClient.clearActivity();
return;
}

this.#enabled = true;
this.renderStatus();
}

get state() {
return this.#enabled;
}
};
2 changes: 2 additions & 0 deletions libs/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ module.exports.Config = class Config {
update_channel: 'release',
update_freq: 'weekly',
inpadcolor: '#3B3E95',
discord_rpc: true,
first_launch: true,
dblcl_run: false,
dblcl_ask: true,
Expand Down Expand Up @@ -184,6 +185,7 @@ module.exports.Config = class Config {
return;
}

if (src_obj[key] === null) return;
dst_obj[key] = src_obj[key];
};

Expand Down
16 changes: 12 additions & 4 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const path = require('node:path');
const fs = require('node:fs');
const { Config } = require('./libs/settings.js');
const { Trophies, TrophySharedConfig, TrophyDataReader } = require('./libs/trophies.js');
const { DRPC } = require('./libs/rpc.js');

const SCE_PIC_PATH = '/sce_sys/pic0.png';
const SCE_TROPHY_PATH = '/sce_sys/trophy/';
Expand All @@ -22,7 +23,8 @@ let settwin = undefined;
let gameproc = undefined;
let updateWorker = undefined;
let compatWorker = undefined;
let binname = 'psoff.exe';
let binname = undefined;
let discordRPC = undefined;

const converter = new Convert({
newline: true
Expand Down Expand Up @@ -123,8 +125,8 @@ const updateGameSummary = (gid, update, loadtrophies = false) => {
};

const updateBinaryPath = (path, checkfirst = false) => {
binname = path ?? binname;
exec(`"${binname}" -h`, { cwd: config.getValue('emu_path') }).on('close', (code) => {
if (!path) throw new Error('Empty emulator path!');
exec(`"${binname = path}" -h`, { cwd: config.getValue('emu_path') }).on('close', (code) => {
if (code === 0 || code === 4294967295) config.reloadEmulatorSettings();
else throw new Error('Failed to make a test emulator run!');
});
Expand Down Expand Up @@ -277,6 +279,7 @@ const commandHandler = (channel, cmd, info) => {
gameproc.stderr.on('data', terminalListener);
gameproc._gameID = info.gid;
gameproc._startTime = Date.now();
discordRPC.setGame(info.gtitle);

gameproc.on('error', (err) => {
genericWarnMsg('{$tr:main.actions.gerror}', true, { error: err.toString() });
Expand All @@ -289,6 +292,7 @@ const commandHandler = (channel, cmd, info) => {
win.send('gamesum', updateGameSummary(gameproc._gameID, { lastrun: gameproc._startTime }, true));
win.send('term-data', converter.toHtml(`Process exited with code ${code}`));
win.send('ingame', false);
discordRPC.setGame();
gameproc = null;
});
break;
Expand Down Expand Up @@ -379,6 +383,7 @@ const commandHandler = (channel, cmd, info) => {
const main = (userdir = __dirname) => {
fs.mkdirSync(userdir, { recursive: true });
config = new Config(userdir);
discordRPC = new DRPC(config.getValue('discord_rpc'));

const emupath = config.getValue('emu_path');

Expand Down Expand Up @@ -525,7 +530,7 @@ const main = (userdir = __dirname) => {
type: 'radio',
label: patch.version,
checked: currpatch === patch.path
})
});
}

try {
Expand Down Expand Up @@ -659,6 +664,9 @@ const main = (userdir = __dirname) => {

config.addCallback('launcher', (key, value) => {
switch (key) {
case 'discord_rpc':
discordRPC.state = value;
return;
case 'scan_dirs':
gdirchanged = true;
return;
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
],
"dependencies": {
"ansi-to-html": "^0.7.2",
"discord-rpc": "^4.0.1",
"follow-redirects": "^1.15.6",
"xml-js": "^1.6.11"
}
Expand Down
5 changes: 0 additions & 5 deletions services/updater.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,6 @@ const searchBinary = () => {
if (fs.lstatSync(binpath).isFile()) return binpath;
} catch (e) { }

try { // Deprecated name, this check will be deleted after v.0.5 gets released
binpath = path.join(emupath, '/emulator.exe');
if (fs.lstatSync(binpath).isFile()) return binpath;
} catch (e) { }

return null;
};

Expand Down
8 changes: 8 additions & 0 deletions webroot/css/settings.css
Original file line number Diff line number Diff line change
Expand Up @@ -62,4 +62,12 @@ select {
#inusers {
display: flex;
flex-direction: row;
gap: 5px;
}

#inusers>.user {
display: flex;
overflow: hidden;
flex-direction: column;
gap: 2px;
}
4 changes: 2 additions & 2 deletions webroot/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ window._onLangReady = (() => {
const sg = window.gamelistAPI.getSelectedGame();
if (sg == null) return alert(window.trAPI.get('main.actions.nogame'));

const { gpath, gid } = sg.dataset;
const { gpath, gid, gtitle } = sg.dataset;

if (target.classList.contains('ofolder')) {
window.electronAPI.sendCommand('openfolder', gpath);
} else if (target.classList.contains('rgame')) {
window.electronAPI.sendCommand('rungame', { path: gpath, gid: gid, dblclick: false });
window.electronAPI.sendCommand('rungame', { path: gpath, dblclick: false, gid, gtitle });
}
}, true);

Expand Down
8 changes: 5 additions & 3 deletions webroot/js/main/gamelist.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

const getGameBadgeById = (id) => $(`.gamebadge[data-gid="${id}"]`);
const isGameBadge = (target) => target.classList.contains('gamebadge');
const getGameTitleFromBadge = (target) => target.$('.gbi-name').innerText;
const getGameTitleFromBadge = (target) => target.dataset.gtitle;
const getGameTitleIdFromBadge = (target) => target.dataset.gid;
const getGamePathFromBadge = (target) => target.dataset.gpath;
const getGameVersionFromBadge = (target) => target.dataset.gver;
Expand Down Expand Up @@ -60,7 +60,7 @@
const possible_paths = [];
if (gipatch) possible_paths.push(gipatch);
possible_paths.push(gpath);
window.electronAPI.sendCommand('getgamesum', { gpath: possible_paths, gid: gid });
window.electronAPI.sendCommand('getgamesum', { gpath: possible_paths, gid });
if (gtroph) {
window.electronAPI.readTrophies(possible_paths).then((data) => {
window.trophyAPI.updateTrophies(data);
Expand Down Expand Up @@ -113,7 +113,8 @@
if (!isGameBadge(gbadge)) return;
window.electronAPI.sendCommand('rungame', {
path: getGamePathFromBadge(gbadge),
gid: getGameTitleFromBadge(gbadge),
gid: getGameTitleIdFromBadge(gbadge),
gtitle: getGameTitleFromBadge(gbadge),
dblclick: true
});
});
Expand Down Expand Up @@ -192,6 +193,7 @@
rootel.dataset.gid = msg.id;
rootel.dataset.gver = msg.version;
rootel.dataset.gpath = msg.path;
rootel.dataset.gtitle = msg.title;
rootel._patches = [];

if (msg.icon)
Expand Down
82 changes: 52 additions & 30 deletions webroot/js/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ window._onLangReady = (() => {
let modified_cfg = [{
general: {},
graphics: {},
audio: {},
audio: { padspeakers: [] },
controls: {
keybinds: {},
pads: [{}, {}, {}, {}]
Expand Down Expand Up @@ -119,22 +119,6 @@ window._onLangReady = (() => {
gsd.innerHTML = opts.join('');
};

const aliases = {
kb: {
keyboard: true,
kbd: true,
kb: true
},
de: {
sdl: true,
gamepad: true
},
xi: {
xinput: true,
xbox: true
}
};

window.electronAPI.requestConfig().then(async (msg) => {
saved_cfg = msg;
refillScanDirs(saved_cfg);
Expand All @@ -161,22 +145,27 @@ window._onLangReady = (() => {
for (let i = 0; i < 4; ++i) {
opts.push(`<option data-cfgvalue="${i + 1}">${profiles[i].name}</option>`);
inbacks.push(`
<div>
<div class="user">
<label>${profiles[i].name}</label>
<select
data-cfgfacility="emu_controls"
data-cfgnoselect="1"
data-cfgkey="pads"
data-cfghint="arrobj"
data-cfgarridx="${i}"
data-cfginkey="type"
data-cfgtype="string"
style="flex: 1"
>
<option data-cfgvalue="sdl" ${aliases.de[pads[i].type] ? 'selected' : ''}>SDL2</option>
<option data-cfgvalue="xinput" ${aliases.xi[pads[i].type] ? 'selected' : ''}>XInput</option>
<option data-cfgvalue="keyboard" ${aliases.kb[pads[i].type] ? 'selected' : ''}>Keyboard</option>
<option data-cfgvalue="sdl"}>SDL2</option>
<option data-cfgvalue="xinput"}>XInput</option>
<option data-cfgvalue="keyboard"}>Keyboard</option>
</select>
<select
data-cfgfacility="emu_audio"
data-cfgkey="padspeakers"
data-cfghint="arr"
data-cfgarridx="${i}"
data-cfgtype="string"
>${$('#madevice').innerHTML}</select>
</div>`);
}
inusers.innerHTML = inbacks.join('');
Expand Down Expand Up @@ -213,12 +202,35 @@ window._onLangReady = (() => {
break;

case 'SELECT':
if (elem.dataset.cfgnoselect === '1') continue;
for (let i = 0; i < elem.options.length; ++i) {
if (getOptionValue(elem.dataset.cfgtype, elem.options[i]) == fac[key]) {
elem.selectedIndex = i;
break;
}
switch (elem.dataset.cfghint) {
case 'arrobj': {
const idx = getArrayIndex(elem);
const innkey = getInnerObjKey(elem);
for (let i = 0; i < elem.options.length; ++i) {
if (getOptionValue(elem.dataset.cfgtype, elem.options[i]) === fac[key][idx][innkey]) {
elem.selectedIndex = i;
break;
}
}
} break;
case 'arr': {
const idx = getArrayIndex(elem);
for (let i = 0; i < elem.options.length; ++i) {
if (getOptionValue(elem.dataset.cfgtype, elem.options[i]) == fac[key][idx]) {
elem.selectedIndex = i;
break;
}
}
} break;

default: {
for (let i = 0; i < elem.options.length; ++i) {
if (getOptionValue(elem.dataset.cfgtype, elem.options[i]) == fac[key]) {
elem.selectedIndex = i;
break;
}
}
} break;
}
break;
}
Expand Down Expand Up @@ -260,6 +272,10 @@ window._onLangReady = (() => {
const innkey = getInnerObjKey(target);
fac[key][idx][innkey] = getOptionValue(target.dataset.cfgtype, target.options[target.selectedIndex]);
} break;
case 'arr': {
const idx = getArrayIndex(target);
fac[key][idx] = getOptionValue(target.dataset.cfgtype, target.options[target.selectedIndex]);
} break;
default: {
const newvalue = getOptionValue(target.dataset.cfgtype, target.options[target.selectedIndex]);
if (!runSelectChecker(target, newvalue)) return;
Expand Down Expand Up @@ -312,14 +328,20 @@ window._onLangReady = (() => {
case 'save':
if (haveUnsaved()) {
let haskb = false;
const spks = modified_cfg[0].audio.padspeakers;

for (let i = 0; i < 4; ++i) {
if (aliases.kb[modified_cfg[0].controls.pads[i].type]) {
if (modified_cfg[0].controls.pads[i].type === 'keyboard') {
if (haskb) {
if (!confirm(window.trAPI.get('settings.alerts.multiplekb'))) return;
break;
}
haskb = true;
}

if (spks.length > 0 && spks[i] === undefined) {
modified_cfg[0].audio.padspeakers[i] = null;
}
}
window.electronAPI.sendCommand('sett-update', modified_cfg);
wrapper.dataset.ready = 0;
Expand Down
2 changes: 2 additions & 0 deletions webroot/langs/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
}
},
"doubleclick": "Doubleclick will run the game",
"drpc": "Enable Discord Rich Presence",
"gsd": {
"label": "Game scan directories:",
"buttons": {
Expand All @@ -34,6 +35,7 @@
},
"emulator": {
"header": "Emulator settings",
"ousers": "Connected controllers count:",
"currusr": {
"label": "Current user:",
"opt": {
Expand Down
Loading