const logger = require.main.require('./common/logger.js'), electron = require('electron'), { app, BrowserWindow, globalShortcut, ipcMain } = require('electron'), { fork, spawn } = require('child_process'), fs = require('fs'), lkt = require.main.require('./common/lkt.js'), isRunning = require('./common/isRunning.js'); const packageConfig = require('./package.json').config; logger.debug('main', 'Package config is ' + JSON.stringify(packageConfig)); var config = require('./common/config.js'); var db = require.main.require('./common/db.js'); var tail = require('tail').Tail; var client; /* Sub process for the express server */ class Lektor { constructor() { this.closed = true; isRunning({ win: 'lektord.exe', linux: 'lektord', mac: 'lektord' }).then(v => { if (v && config.attachmode) { logger.info('main', `Lektord is running! Attach to it`); } else if (v) { logger.error('error', `Lektord is running and attach mode is disable, exit!`); app.quit(); } else { logger.debug('main', `Lektord not running, start it!`); this.closed = false; this.process = spawn('lektord', ['-F']); this.process.stderr.on('data', data => { logger.lektord(data); }); this.process.on('close', code => { logger.warn('main', `Lektor exited with code ${code}`); this.lektor_closed = true; app.quit(); }); } }); } exit() { if (this.closed) { logger.warning('main', 'Lektord is already closed'); return; } logger.info('main', 'Closing lektord'); this.closed = true; this.process.kill('SIGTERM'); } } /* The last thing we got from the search bar */ var __lastFilter = ''; var win = null; /* The main window */ /********************** * Reinit the logfile * **********************/ fs.truncate(logger.logfile, 0, () => {}); var tail = new tail(logger.logfile); tail.on('line', function (data) { console.log(data); }); /*************************************************************** * Creates the main window and process for the admin interface * ***************************************************************/ function createInstanceWindow() { /* Main window */ win = new BrowserWindow({ width: 1280, height: 720, hasShadow: false, frame: false, menuBarVisible: true, webPreferences: { nodeIntegration: true, worldSafeExecuteJavaScript: true, contextIsolation: false /* XXX: Otherwise 'require' is not defined in instance/index.html */, }, }); win.loadFile('instance/index.html'); } function createKurisuWindow() { /* Kurisu window */ const kurisu = new BrowserWindow({ width: 1280, title: 'Kurisu', height: 720, frame: false, parent: win, webPreferences: { nodeIntegration: true, worldSafeExecuteJavaScript: true, contextIsolation: true, }, }); kurisu.loadURL(packageConfig.kurisu); kurisu.once('ready-to-show', () => { kurisu.show(); }); } /****************************** * The end of the application * ******************************/ ipcMain.on('close-app', (evt, arg) => { app.quit(); }); app.on('quit', () => { logger.info('main', 'Send SIGTERM to express process, lektord and tailler process'); client.kill('SIGTERM'); lektor.exit(); }); /********************************* * The beggin of the application * *********************************/ app.on('ready', () => { logger.info('main', 'Main window is ready'); createInstanceWindow(); client = fork('client/main.js'); lektor = new Lektor(); globalShortcut.register('CommandOrControl+D', () => { var win = BrowserWindow.getFocusedWindow(); if (win === null) { return; } logger.info('main', 'Reloading DB'); let contents = win.webContents; db.all().then(karas => { contents.send('reload-db-responce', karas); }); }); globalShortcut.register('F12', () => { var focused = BrowserWindow.getFocusedWindow(); if (focused) { focused.webContents.openDevTools(); } }); setTimeout(() => { lkt.idleActualisation(); }, 1000); setTimeout(() => { lkt.statusActualisation(); }, 1500); }); /*************** * Kurisu View * ***************/ ipcMain.on('toggle-kurisu', (event, arg) => { logger.debug('main', 'Toggle kurisu view'); createKurisuWindow(); }); /********************************* * Messages from the main window * *********************************/ ipcMain.on('cmd-play', (event, arg) => { lkt.commandPlay().then(arg => { logger.debug('main', 'Returned from cmd-play'); }); }); ipcMain.on('cmd-stop', (event, arg) => { lkt.commandStop().then(arg => { logger.debug('main', 'Returned from cmd-stop'); }); }); ipcMain.on('cmd-clear', (event, arg) => { lkt.commandClear().then(arg => { logger.debug('main', 'Cleared queue with cmd-clear'); }); }); /* Fill the pannel with the content of the DB. * The `arg` is the HTML object of the pannel */ ipcMain.on('reload-db-request', (event, arg) => { logger.info('main', 'Reloading the DB content'); var callback = karas => { event.reply('reload-db-responce', karas); }; if (arg && arg.search) { __lastFilter = arg.search; logger.debug('main', `Reload DB with search '${arg}'`); db.search(__lastFilter, 0, 15).then(callback); } else { logger.debug('main', `Reload DB with last filter '${__lastFilter}'`); db.search(__lastFilter, 0, 15).then(callback); } }); /* Send the queue to the webpage when asked to */ ipcMain.on('reload-queue-request', (event, arg) => { logger.info('main', 'Reloading next karas in queue'); db.queue(0, 100).then(karas => { event.reply('reload-queue-responce', karas); }); }); ipcMain.on('verify-queue-reloaded-request', (event, arg) => { if (lkt.isQueueUpdated()) { lkt.setQueueUpdated(false); db.queue(0, 100).then(karas => { event.reply('reload-queue-responce', karas); }); } }); ipcMain.on('queue-moved-kara', (event, movement) => { if (movement.to != movement.from) { lkt.commandMove(movement.from, movement.to); } }); ipcMain.on('play-kara-queue-pos', (event, arg) => { lkt.commandPlayPos(arg.position); }); ipcMain.on('add-kara-queue-id', (event, arg) => { lkt.commandQueueAddId(arg.id); }); ipcMain.on('insert-kara-queue-id', (event, arg) => { lkt.commandQueueInsertId(arg.id); }); ipcMain.on('delete-kara-queue-pos', (event, arg) => { lkt.commandQueueDelPos(arg.position); }); ipcMain.on('add-kara-queue-pos', (event, addparams) => { lkt.commandQueueAddId(addparams.id).then(() => lkt.commandMove(addparams.queueSize + 1, addparams.position)); }); var songTimeData = { elapsed: 0, total: 100, state: 'stop', song: '0' }; var counterTime = 0; ipcMain.on('get-song-time-data', (event, arg) => { var newSongTimeData = lkt.getSongTimeData(); if (newSongTimeData.elapsed != songTimeData.elapsed || newSongTimeData.song != songTimeData.song) { songTimeData = newSongTimeData; event.reply('send-song-time-data', { elapsed: songTimeData.elapsed, total: songTimeData.total, song: songTimeData.song, state: songTimeData.state, }); counterTime = 0; } else if (newSongTimeData.state == 'play') { counterTime++; event.reply('send-song-time-data', { elapsed: songTimeData.elapsed + counterTime / 20.0, total: songTimeData.total, song: songTimeData.song, state: songTimeData.state, }); } else { event.reply('send-song-time-data', { elapsed: songTimeData.elapsed + counterTime / 20.0, total: songTimeData.total, song: songTimeData.song, state: songTimeData.state, }); } }); ipcMain.on('get-runnings', (event, arg) => { isRunning({ win: 'klkt.exe', mac: 'klkt', linux: 'klkt' }).then(vklkt => { isRunning({ win: 'lektord.exe', mac: 'lektord', linux: 'lektord' }).then(vlektord => { event.reply('send-runnings', { klkt: vklkt, lektord: vlektord, }); }); }); }); ipcMain.on('set-settings', (event, arg) => { logger.info('main', `Settings are now: ${JSON.stringify(arg)}`); config.host = arg.host; config.port = arg.port; config.database = arg.db; config.loglektord = arg.loglektord; config.attachmode = arg.attachmode; /* prettier-ignore */ config.loglevel = arg.loglevel.ERROR ? 'error' : arg.loglevel.WARNING ? 'warning' : arg.loglevel.INFO ? 'info' : 'debug'; config.flush(); });