diff --git a/backend.js b/backend.js index 6a2cd99c..740caefb 100644 --- a/backend.js +++ b/backend.js @@ -12,6 +12,9 @@ app.on('ready', function() { let startAsTray = false; let isMainWinShown = false; let isMainWin2shown = false; + let remoteLib = {}; + let remoteVar = {}; + const winData = { "home" : { "width" : 600, @@ -201,8 +204,7 @@ app.on('ready', function() { backgroundColor: '#060621', webPreferences: { webSecurity: false, - nodeIntegration: true, - nodeIntegrationInWorker: true + nodeIntegration: true } }); if (!maximizable) { @@ -254,8 +256,9 @@ app.on('ready', function() { function loadIpc() { const ipc = require('electron').ipcMain; + ipc.on('remote', (event, data) => { - switch (data) { + switch (data.name) { case "exit": if (mainWindow2 != null) { mainWindow2.destroy(); @@ -295,12 +298,133 @@ app.on('ready', function() { mainWindow2.webContents.send('remote', { msg: 'reload' }); } break; + case "passConfigData": + remoteVar.configData = data.details; + break; + case "passIgnoreIoHookVal": + remoteVar.ignoreIoHook = data.details; + break; default: - console.log("Unhandled function - loadIpc()"); + console.log("Unhandled function - loadIpc(): " + data); mainWindow.destroy(); break; } }); + + ipc.on('require', (event, data) => { + /* + data.lib : string + data.func : string + data.on : string + data.args : array + */ + let ret = -1; + switch (data.lib) { + case "ffi": + if (data.func === null && data.args === null) { + remoteLib.ffi = require("ffi"); + try { + //const { remote } = require('electron'); + let { RTLD_NOW, RTLD_GLOBAL } = remoteLib.ffi.DynamicLibrary.FLAGS; + remoteLib.ffi.DynamicLibrary( + app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/Processing.NDI.Lib.x64.dll', + RTLD_NOW | RTLD_GLOBAL + ); + remoteVar.lib = remoteLib.ffi.Library(app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/PPTNDI.dll', { + 'init': [ 'int', [] ], + 'destroy': [ 'int', [] ], + 'send': [ 'int', [ "string", "bool" ] ] + }); + ret = remoteVar.lib; + } catch(e) { + console.log("remoteLib failed: " + e); + } + } + if (data.func === "init") { + let ret = -1; + if (typeof remoteVar.lib !== 'undefined') { + ret = remoteVar.lib.init(); + } + } else if (data.func === "destroy") { + let ret = -1; + if (typeof remoteVar.lib !== 'undefined') { + ret = remoteVar.lib.destroy(); + } + } else if (data.func === "send") { + let ret = -1; + if (typeof remoteVar.lib !== 'undefined') { + ret = remoteVar.lib.send( ...data.args ); + } + } + break; + case "iohook": + if (data.on === null && data.args === null) { + remoteLib.ioHook = require('iohook'); + ret = remoteLib.ioHook; + } else if (data.on === "start") { + ret = remoteLib.ioHook.start(); + } else if (data.on === "keyup") { + remoteLib.ioHook.on('keyup', event => { + if (typeof mainWindow2 === 'undefined' || mainWindow2 === null) return; + if (event.shiftKey && event.ctrlKey) { + let chr = String.fromCharCode( event.rawcode ); + if (chr === "") return; + switch (chr) { + case remoteVar.configData.hotKeys.prev: + mainWindow2.webContents.send('remote', { msg: 'gotoPrev' }); + break; + case remoteVar.configData.hotKeys.next: + mainWindow2.webContents.send('remote', { msg: 'gotoNext' }); + break; + case remoteVar.configData.hotKeys.transparent: + mainWindow2.webContents.send('remote', { msg: 'update_trn' }); + break; + case remoteVar.configData.hotKeys.black: + mainWindow2.webContents.send('remote', { msg: 'update_black' }); + break; + case remoteVar.configData.hotKeys.white: + mainWindow2.webContents.send('remote', { msg: 'update_white' }); + break; + default: + break; + } + } + }); + ret = 1; + } else if (data.on === "keydown") { + remoteLib.ioHook.on('keydown', event => { + if (typeof mainWindow2 === 'undefined' || mainWindow2 === null || remoteVar.ignoreIoHook) return; + if (((event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) && event.keycode === 63) || + !(event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) && ( + event.keycode === 63 || event.keycode === 3655 || event.keycode === 3663 || + event.keycode === 28 || event.keycode === 57 || event.keycode === 48 || event.keycode === 17 || + event.keycode === 49 || event.keycode === 25 || event.keycode === 60999 || event.keycode === 61007 || + event.keycode === 61003 || event.keycode === 61000 || event.keycode === 61005 || event.keycode === 61008 + )) { + mainWindow2.webContents.send('remote', { msg: 'stdin_write_newline' }); + } + }); + ret = 1; + } else if (data.on === "mouseup") { + remoteLib.ioHook.on('mouseup', event => { + if (typeof mainWindow2 === 'undefined' || mainWindow2 === null || remoteVar.ignoreIoHook) return; + mainWindow2.webContents.send('remote', { msg: 'stdin_write_newline' }); + }); + ret = 1; + } else if (data.on === "mousewheel") { + remoteLib.ioHook.on('mousewheel', event => { + if (typeof mainWindow2 === 'undefined' || mainWindow2 === null || remoteVar.ignoreIoHook) return; + mainWindow2.webContents.send('remote', { msg: 'stdin_write_newline' }); + }); + ret = 1; + } + break; + default: + break; + } + event.returnValue = ret; + }); + } init(); diff --git a/frontend/client.js b/frontend/client.js index ecf8f4a7..79bdf940 100644 --- a/frontend/client.js +++ b/frontend/client.js @@ -135,9 +135,8 @@ $(document).ready(function() { const { remote } = require('electron'); const ipc = require('electron').ipcRenderer; const fs = require("fs-extra"); - const ffi = require('ffi'); + let ffi; let lib; - let ioHook; let maxSlideNum = 0; let prevSlide = 1; let currentSlide = 1; @@ -168,24 +167,16 @@ $(document).ready(function() { process.chdir(remote.app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "")); } catch(e) { } - try { - let { RTLD_NOW, RTLD_GLOBAL } = ffi.DynamicLibrary.FLAGS; - ffi.DynamicLibrary( - remote.app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/Processing.NDI.Lib.x64.dll', - RTLD_NOW | RTLD_GLOBAL - ); - lib = ffi.Library(remote.app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/PPTNDI.dll', { - 'init': [ 'int', [] ], - 'destroy': [ 'int', [] ], - 'send': [ 'int', [ "string", "bool" ] ] - }); - } catch(e) { - alertMsg(e); - ipc.send('remote', "exit"); + ffi = ipc.sendSync("require", { lib: "ffi", func: null, args: null }); + if ( ffi === -1 ) { + alertMsg("DLL init failed"); + ipc.send('remote', { name: "exit" }); } - if (lib.init() === 1) { + + lib = ipc.sendSync("require", { lib: "ffi", func: "init", args: null }); + if (lib === 1) { alertMsg('Failed to create a listening server!'); - ipc.send('remote', "exit"); + ipc.send('remote', { name: "exit" }); return; } @@ -310,12 +301,26 @@ $(document).ready(function() { return; } slideTranTimers[10] = setTimeout(function() { - lib.send(tmpDir + "/Slide" + currentSlide.toString() + ".png", false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ + tmpDir + "/Slide" + currentSlide.toString() + ".png", + false + ] + }); updateCurNext(curSli, nextSli); }, 10 * parseFloat(duration) * 50); } slideTranTimers[i] = setTimeout(function() { - lib.send(tmpDir + "/t" + i.toString() + ".png", true); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ + tmpDir + "/t" + i.toString() + ".png", + true + ] + }); if ( i % 2 === 0 ) { let now = new Date().getTime(); $("img.image_picker_image:first").attr("src", tmpDir + "/t" + i.toString() + ".png?" + now); @@ -361,7 +366,14 @@ $(document).ready(function() { } else { stopSlideTransition(); updateCurNext(curSli, nextSli); - lib.send(curSli, false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ + curSli, + false + ] + }); } $("#slide_cnt").html("SLIDE " + currentSlide + " / " + maxSlideNum); blkBool = false; @@ -792,7 +804,14 @@ $(document).ready(function() { } $("img.image_picker_image:first").attr('src', dirTo); - lib.send(dirTo, false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ + dirTo, + false + ] + }); } $('#blk').click(function() { @@ -934,27 +953,15 @@ $(document).ready(function() { } function cleanupForExit() { - lib.destroy(); + ipc.sendSync("require", { lib: "ffi", func: "destroy", args: null }); cleanupForTemp(false); - ipc.send('remote', "exit"); + ipc.send('remote', { name: "exit" }); } function registerIoHook() { - ioHook = require('iohook'); - ioHook.on('keyup', event => { - if (event.shiftKey && event.ctrlKey) { - let chr = String.fromCharCode( event.rawcode ); - if (chr === "") return; - switch (chr) { - case configData.hotKeys.prev: gotoPrev(); break; - case configData.hotKeys.next: gotoNext(); break; - case configData.hotKeys.transparent: updateBlkWhtTrn("trn"); break; - case configData.hotKeys.black: updateBlkWhtTrn("black"); break; - case configData.hotKeys.white: updateBlkWhtTrn("white"); break; - } - } - }); - ioHook.start(); + let ioHook = ipc.sendSync("require", { lib: "iohook", on: null, args: null }); + ipc.sendSync("require", { lib: "iohook", on: "keyup", args: null }); + ipc.sendSync("require", { lib: "iohook", on: "start", args: null }); } function reflectConfig() { @@ -970,6 +977,7 @@ $(document).ready(function() { $.getJSON(configPath, function(json) { configData.hotKeys = json.hotKeys; configData.startWithTheFirstSlideSelected = json.startWithTheFirstSlideSelected; + ipc.send('remote', { name: "passConfigData", details: configData }); }); } else { // Do nothing @@ -977,34 +985,52 @@ $(document).ready(function() { } ipc.on('remote' , function(event, data){ - if (data.msg == "exit") { - cleanupForExit(); - return; - } - if (data.msg == "reload") { - reflectConfig(); - return; - } - if (data.msg == "focused") { - let stats; - let tmpPptTimestamp = 0; - if (pptTimestamp === 0) { - return; - } - try { - stats = fs.statSync(pptPath); - tmpPptTimestamp = stats.mtimeMs; - if (pptTimestamp === tmpPptTimestamp) { - } else { - pptTimestamp = tmpPptTimestamp; - askReloadFile("", "This file has been modified. Do you want to reload it?", ""); + switch (data.msg) { + case "exit": + cleanupForExit(); + break; + case "reload": + reflectConfig(); + break; + case "focused": + let stats; + let tmpPptTimestamp = 0; + if (pptTimestamp === 0) { + return; } - } catch(e) { - } - } - if (data.msg == "blurred") { - // we don't care here + try { + stats = fs.statSync(pptPath); + tmpPptTimestamp = stats.mtimeMs; + if (pptTimestamp === tmpPptTimestamp) { + } else { + pptTimestamp = tmpPptTimestamp; + askReloadFile("", "This file has been modified. Do you want to reload it?", ""); + } + } catch(e) { + } + break; + case "blurred": + // we don't care here + break; + case "gotoPrev": + gotoPrev(); + break; + case "gotoNext": + gotoNext(); + break; + case "update_trn": + updateBlkWhtTrn("trn"); + break; + case "update_black": + updateBlkWhtTrn("black"); + break; + case "update_white": + updateBlkWhtTrn("white"); + break; + default: + break; } + return; }); $('#minimize').click(function() { diff --git a/frontend/client_config.js b/frontend/client_config.js index bc3ccc66..dd32325b 100644 --- a/frontend/client_config.js +++ b/frontend/client_config.js @@ -74,7 +74,7 @@ $(document).ready(function() { if (err) { alertMsg("Could not save the configuration."); } else { - ipc.send('remote', "reflectConfig"); + ipc.send('remote', { name: "reflectConfig" }); alertMsg("Saved"); } }); @@ -96,7 +96,7 @@ $(document).ready(function() { } $('#closeImg').click(function() { - ipc.send('remote', "hideConfig"); + ipc.send('remote', { name: "hideConfig" }); }); $('#saveConfig').click(function() { setConfig(); diff --git a/frontend/client_control.js b/frontend/client_control.js index 3661b88c..4597f332 100644 --- a/frontend/client_control.js +++ b/frontend/client_control.js @@ -286,10 +286,8 @@ $(document).ready(function() { const spawn = require( 'child_process' ).spawn; const ipc = require('electron').ipcRenderer; const fs = require("fs-extra"); - const ffi = require('ffi'); + let ffi; let lib; - let ignoreIoHook = false; - let ioHook = null; let tmpDir = null; let preFile = ""; let slideWidth = 0; @@ -324,26 +322,16 @@ $(document).ready(function() { } function runLib() { - try { - const { remote } = require('electron'); - let { RTLD_NOW, RTLD_GLOBAL } = ffi.DynamicLibrary.FLAGS; - ffi.DynamicLibrary( - remote.app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/Processing.NDI.Lib.x64.dll', - RTLD_NOW | RTLD_GLOBAL - ); - lib = ffi.Library(remote.app.getAppPath().replace(/(\\|\/)resources(\\|\/)app\.asar/, "") + '/PPTNDI.dll', { - 'init': [ 'int', [] ], - 'destroy': [ 'int', [] ], - 'send': [ 'int', [ "string", "bool" ] ] - }); - } catch(e) { - alertMsg(e); - ipc.send('remote', "exit"); + ffi = ipc.sendSync("require", { lib: "ffi", func: null, args: null }); + if ( ffi === -1 ) { + alertMsg("DLL init failed"); + ipc.send('remote', { name: "exit" }); } - if (lib.init() === 1) { + lib = ipc.sendSync("require", { lib: "ffi", func: "init", args: null }); + if (lib === 1) { alertMsg('Failed to create a listening server!'); - ipc.send('remote', "exit"); + ipc.send('remote', { name: "exit" }); return; } } @@ -400,7 +388,11 @@ $(document).ready(function() { buffer = PNG.sync.write(png); fs.writeFileSync(file, buffer); $("#slidePreview").attr("src", file + "?" + now); - lib.send(file, false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ file, false ] + }); } function updateStat(cmd, details) { @@ -521,7 +513,11 @@ $(document).ready(function() { } catch(e) { console.log("file could not be generated: "+ preFile); } - lib.send(file, false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ file, false ] + }); } } @@ -534,9 +530,9 @@ $(document).ready(function() { break; case "tran": setTimeout(function() { - ignoreIoHook = true; + ignoreIoHook(true); sendColorNDI("tran"); - ignoreIoHook = false; + ignoreIoHook(false); }, 500); break; case "black": @@ -553,47 +549,17 @@ $(document).ready(function() { } } + function ignoreIoHook(val) { + ipc.sendSync("remote", { name: "passIgnoreIoHookVal", details: val }); + } + function registerIoHook() { - ioHook = require('iohook'); - ioHook.on('keyup', event => { - if (event.shiftKey && event.ctrlKey) { - let chr = String.fromCharCode( event.rawcode ); - if (chr === "") return; - switch (chr) { - case configData.hotKeys.prev: handleHook("prev"); break; - case configData.hotKeys.next: handleHook("next"); break; - case configData.hotKeys.transparent: handleHook("tran"); break; - case configData.hotKeys.black: handleHook("black"); break; - case configData.hotKeys.white: handleHook("white"); break; - default: break; - } - } - }); - ioHook.on('keydown', event => { - //console.log(event.keycode); - if (!ignoreIoHook) { - if (((event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) && event.keycode === 63) || - !(event.altKey || event.shiftKey || event.ctrlKey || event.metaKey) && ( - event.keycode === 63 || event.keycode === 3655 || event.keycode === 3663 || - event.keycode === 28 || event.keycode === 57 || event.keycode === 48 || event.keycode === 17 || - event.keycode === 49 || event.keycode === 25 || event.keycode === 60999 || event.keycode === 61007 || - event.keycode === 61003 || event.keycode === 61000 || event.keycode === 61005 || event.keycode === 61008 - )) { - res.stdin.write("\n"); - } - } - }); - ioHook.on('mouseup', event => { - if (!ignoreIoHook) { - res.stdin.write("\n"); - } - }); - ioHook.on('mousewheel', event => { - if (!ignoreIoHook) { - res.stdin.write("\n"); - } - }); - ioHook.start(); + let ioHook = ipc.sendSync("require", { lib: "iohook", on: null, args: null }); + ipc.sendSync("require", { lib: "iohook", on: "keyup", args: null }); + ipc.sendSync("require", { lib: "iohook", on: "keydown", args: null }); + ipc.sendSync("require", { lib: "iohook", on: "mouseup", args: null }); + ipc.sendSync("require", { lib: "iohook", on: "mousewheel", args: null }); + ipc.sendSync("require", { lib: "iohook", on: "start", args: null }); } function procTransition(file, data) { @@ -617,7 +583,11 @@ $(document).ready(function() { return; } slideTranTimers[10] = setTimeout(function() { - lib.send(tmpDir + "/Slide.png", false); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ tmpDir + "/Slide.png", false ] + }); if (fs.existsSync(file)) { try { fs.copySync(file, preFile); @@ -629,7 +599,11 @@ $(document).ready(function() { } slideTranTimers[i] = setTimeout(function() { - lib.send(tmpDir + "/t" + i.toString() + ".png", true); + ipc.sendSync("require", { + lib: "ffi", + func: "send", + args: [ tmpDir + "/t" + i.toString() + ".png", false ] + }); }, i * parseFloat(duration) * 50); if (i === transLvl) { const now = new Date().getTime(); @@ -759,7 +733,7 @@ $(document).ready(function() { }); // Enable Always On Top by default - ipc.send('remote', "onTop"); + ipc.send('remote', { name: "onTop" }); $("#pin").attr("src", "pin_green.png"); pin = true; @@ -804,6 +778,7 @@ $(document).ready(function() { if (fs.existsSync(configPath)) { $.getJSON(configPath, function(json) { configData.hotKeys = json.hotKeys; + ipc.send('remote', { name: "passConfigData", details: configData }); }); } else { // Do nothing @@ -811,20 +786,39 @@ $(document).ready(function() { } function cleanupForExit() { - lib.destroy(); + ipc.sendSync("require", { lib: "ffi", func: "destroy", args: null }); cleanupForTemp(); - ipc.send('remote', "exit"); + ipc.send('remote', { name: "exit" }); } ipc.on('remote' , function(event, data){ - if (data.msg == "exit") { - cleanupForExit(); - return; - } - if (data.msg == "reload") { - reflectConfig(); - return; + switch (data.msg) { + case "exit": + cleanupForExit(); + break; + case "reload": + reflectConfig(); + break; + case "stdin_write_newline": + res.stdin.write("\n"); + break; + case "gotoPrev": + handleHook("prev"); + break; + case "gotoNext": + handleHook("next"); + break; + case "update_trn": + handleHook("tran"); + break; + case "update_black": + handleHook("black"); + break; + case "update_white": + handleHook("white"); + break; } + return; }); $('#closeImg').click(function() { @@ -885,11 +879,11 @@ $(document).ready(function() { $('#pin').click(function() { if (pin) { - ipc.send('remote', "onTopOff"); + ipc.send('remote', { name: "onTopOff" }); $("#pin").attr("src", "pin_grey.png"); pin = false; } else { - ipc.send('remote', "onTop"); + ipc.send('remote', { name: "onTop" }); $("#pin").attr("src", "pin_green.png"); pin = true; } diff --git a/frontend/client_main.js b/frontend/client_main.js index 949482f9..804ab949 100644 --- a/frontend/client_main.js +++ b/frontend/client_main.js @@ -2,12 +2,12 @@ const ipc = require('electron').ipcRenderer; $(document).ready(function() { $("#select1img").click(function() { - ipc.send('remote', "select1"); + ipc.send('remote', { name: "select1" }); }); $("#select2img").click(function() { - ipc.send('remote', "select2"); + ipc.send('remote', { name: "select2" }); }); $("#closeImg").click(function() { - ipc.send('remote', "exit"); + ipc.send('remote', { name: "exit" }); }); }); \ No newline at end of file