Skip to content

Commit

Permalink
feat: update relevant settings from imported ini and add jukebox togg…
Browse files Browse the repository at this point in the history
…le (#385)

* feat: update relevant settings from imported ini

* feat: add jukebox toggle

* show/hide toggle instead of disable

* jukeboxEnabled -> jukebox
  • Loading branch information
NikhilNarayana authored Jul 13, 2023
1 parent 17cdb50 commit 4baea8a
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 14 deletions.
30 changes: 23 additions & 7 deletions src/dolphin/config/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { defaultAppSettings } from "@settings/defaultSettings";

import type { GeckoCode } from "./geckoCode";
import { loadGeckoCodes, setCodes } from "./geckoCode";
import type { IniFile } from "./iniFile";

export type SyncedDolphinSettings = {
useMonthlySubfolders: boolean;
replayPath: string;
jukebox: boolean;
};

export async function addGamePath(iniFile: IniFile, gameDir: string): Promise<void> {
const generalSection = iniFile.getOrCreateSection("General");
const numPaths = generalSection.get("ISOPaths", "0");
Expand All @@ -10,24 +18,32 @@ export async function addGamePath(iniFile: IniFile, gameDir: string): Promise<vo
await iniFile.save();
}

export async function setSlippiSettings(
iniFile: IniFile,
options: Partial<{
useMonthlySubfolders: boolean;
replayPath: string;
}>,
): Promise<void> {
export async function setSlippiSettings(iniFile: IniFile, options: Partial<SyncedDolphinSettings>): Promise<void> {
const useMonthlySubfolders = options.useMonthlySubfolders ? "True" : "False";
const jukebox = options.jukebox ? "True" : "False";
const coreSection = iniFile.getOrCreateSection("Core");
if (options.replayPath !== undefined) {
coreSection.set("SlippiReplayDir", options.replayPath);
}
if (options.useMonthlySubfolders !== undefined) {
coreSection.set("SlippiReplayMonthFolders", useMonthlySubfolders);
}
if (options.jukebox !== undefined) {
coreSection.set("SlippiJukeboxEnabled", jukebox);
}
await iniFile.save();
}

export async function getSlippiSettings(iniFile: IniFile): Promise<SyncedDolphinSettings> {
const coreSection = iniFile.getOrCreateSection("Core");
const useMonthlySubfolders = coreSection.get("SlippiReplayMonthFolders", "False") === "True";
const replayPath = coreSection.get("SlippiReplayDir", defaultAppSettings.settings.rootSlpPath);

const jukebox = coreSection.get("SlippiJukeboxEnabled", "True") === "True";

return { useMonthlySubfolders, replayPath, jukebox };
}

export async function setBootToCss(globalIni: IniFile, localIni: IniFile, enable: boolean): Promise<void> {
const geckoCodes = loadGeckoCodes(globalIni, localIni);
const bootCode = geckoCodes.find((code) => code.name === "Boot to CSS");
Expand Down
18 changes: 16 additions & 2 deletions src/dolphin/install/installation.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { addGamePath, setSlippiSettings } from "@dolphin/config/config";
import type { SyncedDolphinSettings } from "@dolphin/config/config";
import { addGamePath, getSlippiSettings, setSlippiSettings } from "@dolphin/config/config";
import { IniFile } from "@dolphin/config/iniFile";
import { findDolphinExecutable } from "@dolphin/util";
import { spawnSync } from "child_process";
Expand Down Expand Up @@ -89,6 +90,13 @@ export class DolphinInstallation {

// we shouldn't keep the old cache folder since it might be out of date
await this.clearCache();

// read the settings from the ini and update any settings
if (this.dolphinLaunchType === DolphinLaunchType.NETPLAY) {
const iniPath = path.join(this.userFolder, "Config", "Dolphin.ini");
const iniFile = await IniFile.init(iniPath);
await getSlippiSettings(iniFile);
}
}

public async validate({
Expand Down Expand Up @@ -178,7 +186,13 @@ export class DolphinInstallation {
await addGamePath(iniFile, gameDir);
}

public async updateSettings(options: Partial<{ useMonthlySubfolders: boolean; replayPath: string }>): Promise<void> {
public async getSettings(): Promise<SyncedDolphinSettings> {
const iniPath = path.join(this.userFolder, "Config", "Dolphin.ini");
const iniFile = await IniFile.init(iniPath);
return await getSlippiSettings(iniFile);
}

public async updateSettings(options: Partial<SyncedDolphinSettings>): Promise<void> {
const iniPath = path.join(this.userFolder, "Config", "Dolphin.ini");
const iniFile = await IniFile.init(iniPath);
await setSlippiSettings(iniFile, options);
Expand Down
21 changes: 17 additions & 4 deletions src/dolphin/manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ export class DolphinManager {
let playbackInstance = this.playbackDolphinInstances.get(id);
if (!playbackInstance) {
playbackInstance = new PlaybackDolphinInstance(dolphinPath, meleeIsoPath);
playbackInstance.on("close", (exitCode) => {
playbackInstance.on("close", async (exitCode) => {
await this._updateLauncherSettings(DolphinLaunchType.PLAYBACK);
this.eventSubject.next({
type: DolphinEventType.CLOSED,
instanceId: id,
Expand Down Expand Up @@ -93,7 +94,8 @@ export class DolphinManager {

// Create the Dolphin instance and start it
this.netplayDolphinInstance = new DolphinInstance(dolphinPath, meleeIsoPath);
this.netplayDolphinInstance.on("close", (exitCode) => {
this.netplayDolphinInstance.on("close", async (exitCode) => {
await this._updateLauncherSettings(DolphinLaunchType.NETPLAY);
this.eventSubject.next({
type: DolphinEventType.CLOSED,
dolphinType: DolphinLaunchType.NETPLAY,
Expand All @@ -120,7 +122,8 @@ export class DolphinManager {
if (launchType === DolphinLaunchType.NETPLAY && !this.netplayDolphinInstance) {
const instance = new DolphinInstance(dolphinPath);
this.netplayDolphinInstance = instance;
instance.on("close", (exitCode) => {
instance.on("close", async (exitCode) => {
await this._updateLauncherSettings(launchType);
this.eventSubject.next({
type: DolphinEventType.CLOSED,
dolphinType: DolphinLaunchType.NETPLAY,
Expand All @@ -137,7 +140,8 @@ export class DolphinManager {
const instanceId = "configure";
const instance = new PlaybackDolphinInstance(dolphinPath);
this.playbackDolphinInstances.set(instanceId, instance);
instance.on("close", (exitCode) => {
instance.on("close", async (exitCode) => {
await this._updateLauncherSettings(launchType);
this.eventSubject.next({
type: DolphinEventType.CLOSED,
dolphinType: DolphinLaunchType.PLAYBACK,
Expand Down Expand Up @@ -209,6 +213,15 @@ export class DolphinManager {
});
}

private async _updateLauncherSettings(launchType: DolphinLaunchType) {
const installation = this.getInstallation(launchType);
const newSettings = await installation.getSettings();

await this.settingsManager.setRootSlpPath(newSettings.replayPath);
await this.settingsManager.setUseMonthlySubfolders(newSettings.useMonthlySubfolders);
await this.settingsManager.setJukebox(newSettings.jukebox);
}

private _onStart(dolphinType: DolphinLaunchType) {
this.eventSubject.next({
type: DolphinEventType.DOWNLOAD_START,
Expand Down
20 changes: 19 additions & 1 deletion src/renderer/containers/Settings/MeleeOptions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@ import FormControlLabel from "@mui/material/FormControlLabel";
import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import React from "react";
import { gte } from "semver";

import { Toggle } from "@/components/FormInputs/Toggle";
import { PathInput } from "@/components/PathInput";
import { useDolphinStore } from "@/lib/dolphin/useDolphinStore";
import { useIsoVerification } from "@/lib/hooks/useIsoVerification";
import { useIsoPath, useLaunchMeleeOnPlay } from "@/lib/hooks/useSettings";
import { useIsoPath, useJukebox, useLaunchMeleeOnPlay } from "@/lib/hooks/useSettings";

import { SettingItem } from "./SettingItem";

Expand All @@ -37,9 +39,14 @@ export const MeleeOptions = React.memo(() => {
const isoValidity = useIsoVerification((state) => state.validity);
const [isoPath, setIsoPath] = useIsoPath();
const [launchMeleeOnPlay, setLaunchMelee] = useLaunchMeleeOnPlay();
const [jukebox, setJukebox] = useJukebox();
const netplayDolphinOpen = useDolphinStore((store) => store.netplayOpened);
const playbackDolphinOpen = useDolphinStore((store) => store.playbackOpened);

const dolphinVersion = useDolphinStore((store) => store.netplayDolphinVersion);

const showJukeboxToggle = dolphinVersion !== null && gte(dolphinVersion, "3.2.0");

const onLaunchMeleeChange = async (value: string) => {
const launchMelee = value === "true";
await setLaunchMelee(launchMelee);
Expand Down Expand Up @@ -79,6 +86,17 @@ export const MeleeOptions = React.memo(() => {
<FormControlLabel value={false} label="Launch Dolphin" control={<Radio />} />
</RadioGroup>
</SettingItem>
{showJukeboxToggle && (
<SettingItem name="">
<Toggle
value={jukebox}
onChange={(checked) => setJukebox(checked)}
label="Enable Music"
description="Enable music in game via Slippi Jukebox. Incompatible with WASAPI."
disabled={netplayDolphinOpen}
/>
</SettingItem>
)}
</div>
);
});
Expand Down
8 changes: 8 additions & 0 deletions src/renderer/lib/hooks/useSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@ export const useMonthlySubfolders = () => {
return [useMonthlySubfolders, setUseMonthlySubfolders] as const;
};

export const useJukebox = () => {
const jukebox = useSettings((store) => store.settings.jukebox);
const setJukebox = async (toggle: boolean) => {
await window.electron.settings.setJukebox(toggle);
};
return [jukebox, setJukebox] as const;
};

export const useSpectateSlpPath = () => {
const spectateSlpPath = useSettings((store) => store.settings.spectateSlpPath);
const setSpectateDir = async (path: string) => {
Expand Down
4 changes: 4 additions & 0 deletions src/settings/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ipc_setAutoUpdateLauncher,
ipc_setExtraSlpPaths,
ipc_setIsoPath,
ipc_setJukebox,
ipc_setLaunchMeleeOnPlay,
ipc_setNetplayDolphinPath,
ipc_setPlaybackDolphinPath,
Expand Down Expand Up @@ -44,6 +45,9 @@ export default {
async setUseMonthlySubfolders(toggle: boolean): Promise<void> {
await ipc_setUseMonthlySubfolders.renderer!.trigger({ toggle });
},
async setJukebox(toggle: boolean): Promise<void> {
await ipc_setJukebox.renderer!.trigger({ toggle });
},
async setSpectateSlpPath(spectateSlpPath: string): Promise<void> {
await ipc_setSpectateSlpPath.renderer!.trigger({ path: spectateSlpPath });
},
Expand Down
1 change: 1 addition & 0 deletions src/settings/defaultSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export const defaultAppSettings: AppSettings = {
isoPath: null,
rootSlpPath: getDefaultRootSlpPath(),
useMonthlySubfolders: false,
jukebox: true,
spectateSlpPath: path.join(getDefaultRootSlpPath(), "Spectate"),
extraSlpPaths: [],
netplayDolphinPath: path.join(app.getPath("userData"), "netplay"),
Expand Down
2 changes: 2 additions & 0 deletions src/settings/ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ export const ipc_setUseMonthlySubfolders = makeEndpoint.main(
<SuccessPayload>_,
);

export const ipc_setJukebox = makeEndpoint.main("setJukebox", <{ toggle: boolean }>_, <SuccessPayload>_);

export const ipc_setSpectateSlpPath = makeEndpoint.main("setSpectateSlpPath", <{ path: string }>_, <SuccessPayload>_);

export const ipc_setExtraSlpPaths = makeEndpoint.main("setExtraSlpPaths", <{ paths: string[] }>_, <SuccessPayload>_);
Expand Down
4 changes: 4 additions & 0 deletions src/settings/settingsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ export class SettingsManager {
await this._set("settings.useMonthlySubfolders", toggle);
}

public async setJukebox(toggle: boolean): Promise<void> {
await this._set("settings.jukebox", toggle);
}

public async setSpectateSlpPath(slpPath: string): Promise<void> {
await this._set("settings.spectateSlpPath", slpPath);
}
Expand Down
8 changes: 8 additions & 0 deletions src/settings/setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
ipc_setAutoUpdateLauncher,
ipc_setExtraSlpPaths,
ipc_setIsoPath,
ipc_setJukebox,
ipc_setLaunchMeleeOnPlay,
ipc_setNetplayDolphinPath,
ipc_setPlaybackDolphinPath,
Expand Down Expand Up @@ -62,6 +63,13 @@ export default function setupSettingsIpc({
return { success: true };
});

ipc_setJukebox.main!.handle(async ({ toggle }) => {
await settingsManager.setJukebox(toggle);
const installation = dolphinManager.getInstallation(DolphinLaunchType.NETPLAY);
await installation.updateSettings({ jukebox: toggle });
return { success: true };
});

ipc_setSpectateSlpPath.main!.handle(async ({ path }) => {
await settingsManager.setSpectateSlpPath(path);
return { success: true };
Expand Down
1 change: 1 addition & 0 deletions src/settings/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export type AppSettings = {
isoPath: string | null;
rootSlpPath: string;
useMonthlySubfolders: boolean;
jukebox: boolean;
spectateSlpPath: string;
extraSlpPaths: string[];
netplayDolphinPath: string;
Expand Down

0 comments on commit 4baea8a

Please sign in to comment.