diff --git a/apps/electron-backend/src/app/app.ts b/apps/electron-backend/src/app/app.ts index 785d77a96..f94e1cd32 100644 --- a/apps/electron-backend/src/app/app.ts +++ b/apps/electron-backend/src/app/app.ts @@ -1,22 +1,9 @@ import { BrowserWindow, screen, shell } from 'electron'; -import Store from 'electron-store'; import { join } from 'path'; import { format } from 'url'; import { environment } from '../environments/environment'; import { rendererAppName, rendererAppPort } from './constants'; - -const WINDOW_BOUNDS = 'WINDOW_BOUNDS'; -const MPV_PLAYER_PATH = 'MPV_PLAYER_PATH'; -const VLC_PLAYER_PATH = 'VLC_PLAYER_PATH'; - -type StoreType = { - [WINDOW_BOUNDS]: Electron.Rectangle; - [MPV_PLAYER_PATH]: string; - [VLC_PLAYER_PATH]: string; -}; - -Store.initRenderer(); -const store = new Store(); +import { store, WINDOW_BOUNDS } from './services/store.service'; export default class App { // Keep a global reference of the window object, if you don't, the window will @@ -24,7 +11,6 @@ export default class App { static mainWindow: Electron.BrowserWindow; static application: Electron.App; static BrowserWindow; - store = new Store(); public static isDevelopmentMode() { const isEnvironmentSet: boolean = 'ELECTRON_IS_DEV' in process.env; diff --git a/apps/electron-backend/src/app/events/epg.events.ts b/apps/electron-backend/src/app/events/epg.events.ts new file mode 100644 index 000000000..2679226ee --- /dev/null +++ b/apps/electron-backend/src/app/events/epg.events.ts @@ -0,0 +1,7 @@ +import { ipcMain } from 'electron'; + +export default class EpgEvents { + static bootstrapEpgEvents(): Electron.IpcMain { + return ipcMain; + } +} diff --git a/apps/electron-backend/src/app/events/player.events.ts b/apps/electron-backend/src/app/events/player.events.ts index 71bda0e6b..7a94f6492 100644 --- a/apps/electron-backend/src/app/events/player.events.ts +++ b/apps/electron-backend/src/app/events/player.events.ts @@ -1,7 +1,95 @@ import { ipcMain } from 'electron'; +import { + OPEN_MPV_PLAYER, + OPEN_VLC_PLAYER, + SET_MPV_PLAYER_PATH, + SET_VLC_PLAYER_PATH, +} from 'shared-interfaces'; +import { + MPV_PLAYER_PATH, + store, + VLC_PLAYER_PATH, +} from '../services/store.service'; + +import { spawn } from 'child_process'; +import path from 'path'; export default class PlayerEvents { static bootstrapPlayerEvents(): Electron.IpcMain { return ipcMain; } } + +ipcMain.handle(OPEN_MPV_PLAYER, async (event, { url }) => { + /* try { + if (this.mpv === null) { + this.mpv = this.createMpvInstance(); + } + if (this.mpv.isRunning()) { + await this.mpv.load(url); + } else { + await this.mpv.start(); + await this.mpv.load(url); + } + } catch (error) { + console.log(error); + event.sender.send(ERROR, { + message: `Error: ${ + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + error?.verbose ?? + 'Something went wrong. Make sure that mpv player is installed on your system.' + } `, + }); + } */ +}); + +ipcMain.handle(SET_MPV_PLAYER_PATH, (_event, mpvPlayerPath) => { + console.log('... setting mpv player path', mpvPlayerPath); + store.set(MPV_PLAYER_PATH, mpvPlayerPath); + + /* + // recreate mpv player instance with new binary path if it was changed + if (store.get(MPV_PLAYER_PATH, mpvPlayerPath) !== mpvPlayerPath) + mpv = createMpvInstance(); */ +}); + +ipcMain.handle(OPEN_VLC_PLAYER, (event, { url }) => { + const proc = spawn(getVlcPath(), [`"${url as string}"`], { + shell: true, + }); + + proc.on('exit', (code) => { + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + console.log(`VLC exited with code ${code}`); + }); +}); + +ipcMain.handle(SET_VLC_PLAYER_PATH, (_event, vlcPlayerPath) => { + console.log('... setting vlc player path', vlcPlayerPath); + store.set(VLC_PLAYER_PATH, vlcPlayerPath); +}); + +function getVlcPath() { + const customVlcPath = store.get(VLC_PLAYER_PATH); + if (customVlcPath) { + return customVlcPath; + } else { + return getDefaultVlcPath(); + } +} + +function getDefaultVlcPath() { + if (process.platform === 'win32') { + return path.join( + 'C:', + 'Program Files (x86)', + 'VideoLAN', + 'VLC', + 'vlc.exe' + ); // TODO: define more default paths like in tauri + } else if (process.platform === 'linux') { + return '/usr/bin/vlc'; + } else if (process.platform === 'darwin') { + return '/Applications/VLC.app/Contents/MacOS/VLC'; + } +} diff --git a/apps/electron-backend/src/app/events/playlist.events.ts b/apps/electron-backend/src/app/events/playlist.events.ts index 25a4da892..91e94d920 100644 --- a/apps/electron-backend/src/app/events/playlist.events.ts +++ b/apps/electron-backend/src/app/events/playlist.events.ts @@ -8,6 +8,7 @@ import { dialog, ipcMain } from 'electron'; import { parse } from 'iptv-playlist-parser'; import { createPlaylistObject, getFilenameFromUrl } from 'm3u-utils'; import { readFile } from 'node:fs/promises'; +import { AUTO_UPDATE_PLAYLISTS } from 'shared-interfaces'; export default class PlaylistEvents { static bootstrapPlaylistEvents(): Electron.IpcMain { @@ -94,3 +95,10 @@ ipcMain.handle('open-playlist-from-file', async () => { throw new Error('Failed to process the selected file.'); } }); + +ipcMain.handle(AUTO_UPDATE_PLAYLISTS, async (event, playlistUrls) => { + // TODO: Implement auto-update logic + for (const url of playlistUrls) { + console.log(`Auto-updating playlist from ${url}`); + } +}); diff --git a/apps/electron-backend/src/app/events/setttings.events.ts b/apps/electron-backend/src/app/events/setttings.events.ts new file mode 100644 index 000000000..d86e90be1 --- /dev/null +++ b/apps/electron-backend/src/app/events/setttings.events.ts @@ -0,0 +1,14 @@ +import { ipcMain } from 'electron'; +import { SETTINGS_UPDATE } from 'shared-interfaces'; + +export default class SettingsEvents { + static bootstrapSettingsEvents(): Electron.IpcMain { + return ipcMain; + } +} + +ipcMain.handle(SETTINGS_UPDATE, (_event, arg) => { + /* TODO: Implement settings update logic */ + /* this.settings = arg; + this.server.updateSettings(); */ +}); diff --git a/apps/electron-backend/src/app/events/shared.events.ts b/apps/electron-backend/src/app/events/shared.events.ts index 43ecd6917..faf62e1b4 100644 --- a/apps/electron-backend/src/app/events/shared.events.ts +++ b/apps/electron-backend/src/app/events/shared.events.ts @@ -7,7 +7,7 @@ export default class SharedEvents { } ipcMain.handle('set-user-agent', (event, userAgent, referer) => { - setUserAgent(userAgent, referer); + setUserAgent(userAgent, referer); // TODO: test if defaults needed return true; }); diff --git a/apps/electron-backend/src/app/services/store.service.ts b/apps/electron-backend/src/app/services/store.service.ts new file mode 100644 index 000000000..62aa66079 --- /dev/null +++ b/apps/electron-backend/src/app/services/store.service.ts @@ -0,0 +1,17 @@ +import Store from 'electron-store'; + +export const WINDOW_BOUNDS = 'WINDOW_BOUNDS'; +export const MPV_PLAYER_PATH = 'MPV_PLAYER_PATH'; +export const VLC_PLAYER_PATH = 'VLC_PLAYER_PATH'; + +export type StoreType = { + [WINDOW_BOUNDS]: Electron.Rectangle; + [MPV_PLAYER_PATH]: string; + [VLC_PLAYER_PATH]: string; +}; + +// Initialize renderer support +Store.initRenderer(); + +// Export singleton store instance +export const store = new Store();