Skip to content

Commit 4fd8db8

Browse files
committed
Fix being unable to persistently set certain volume multipliers
Volume multipliers which had a default value !- 100% were not saved to disk, and would thus revert to their default on subsequent startups. As of this commit each config now knows which power state it's for, and can compare whether it should save a volume override of 100% propery. Fixes #199.
1 parent d27c884 commit 4fd8db8

File tree

10 files changed

+74
-78
lines changed

10 files changed

+74
-78
lines changed

platforms/common/src/main/java/dynamic_fps/impl/DynamicFPSMod.java

Lines changed: 7 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
import dynamic_fps.impl.config.BatteryTrackerConfig;
66
import dynamic_fps.impl.config.Config;
77
import dynamic_fps.impl.config.DynamicFPSConfig;
8-
import dynamic_fps.impl.config.VolumeTransitionConfig;
98
import dynamic_fps.impl.config.option.GraphicsState;
109
import dynamic_fps.impl.service.ModCompat;
1110
import dynamic_fps.impl.feature.battery.BatteryToast;
@@ -41,8 +40,6 @@ public class DynamicFPSMod {
4140
private static Config config = Config.ACTIVE;
4241
private static PowerState state = PowerState.FOCUSED;
4342

44-
public static DynamicFPSConfig modConfig = DynamicFPSConfig.load();
45-
4643
private static boolean isForcingLowFPS = false;
4744
private static boolean isKeybindDisabled = false;
4845

@@ -80,7 +77,7 @@ public static boolean disabledByUser() {
8077
}
8178

8279
public static boolean isDisabled() {
83-
return isKeybindDisabled || !modConfig.enabled() || ModCompat.getInstance().isDisabled();
80+
return isKeybindDisabled || !DynamicFPSConfig.INSTANCE.enabled() || ModCompat.getInstance().isDisabled();
8481
}
8582

8683
public static String whyIsTheModNotWorking() {
@@ -90,7 +87,7 @@ public static String whyIsTheModNotWorking() {
9087
results.add("keybinding");
9188
}
9289

93-
if (!modConfig.enabled()) {
90+
if (!DynamicFPSConfig.INSTANCE.enabled()) {
9491
results.add("mod config");
9592
}
9693

@@ -108,7 +105,7 @@ public static void toggleDisabled() {
108105

109106
public static void onConfigChanged() {
110107
doInit();
111-
modConfig.save();
108+
DynamicFPSConfig.INSTANCE.save();
112109
checkForStateChanges(); // The unplugged state may now be enabled or disabled
113110
}
114111

@@ -164,22 +161,10 @@ public static int targetFrameRate() {
164161
return config.frameRateTarget();
165162
}
166163

167-
public static boolean uncapMenuFrameRate() {
168-
return modConfig.uncapMenuFrameRate();
169-
}
170-
171164
public static float volumeMultiplier(SoundSource source) {
172165
return config.volumeMultiplier(source);
173166
}
174167

175-
public static BatteryTrackerConfig batteryTracking() {
176-
return modConfig.batteryTracker();
177-
}
178-
179-
public static VolumeTransitionConfig volumeTransitionSpeed() {
180-
return modConfig.volumeTransitionSpeed();
181-
}
182-
183168
public static boolean shouldShowToasts() {
184169
return config.showToasts();
185170
}
@@ -213,7 +198,7 @@ private static void doInit() {
213198
}
214199

215200
private static void showNotification(String titleTranslationKey, String iconPath) {
216-
if (!batteryTracking().notifications()) {
201+
if (!DynamicFPSConfig.INSTANCE.batteryTracker().notifications()) {
217202
return;
218203
}
219204

@@ -235,7 +220,7 @@ public static void handleStateChange(PowerState previous, PowerState current) {
235220
}
236221

237222
Config before = config;
238-
config = modConfig.get(current);
223+
config = DynamicFPSConfig.INSTANCE.get(current);
239224

240225
GLFW.applyWorkaround(); // Apply mouse hover fix if required
241226
hasRenderedLastFrame = false; // Render next frame w/o delay
@@ -270,6 +255,7 @@ private static void checkForStateChanges() {
270255

271256
private static void checkForStateChanges0() {
272257
PowerState current;
258+
BatteryTrackerConfig batteryTracking = DynamicFPSConfig.INSTANCE.batteryTracker();
273259

274260
if (isDisabled()) {
275261
current = PowerState.FOCUSED;
@@ -278,7 +264,7 @@ private static void checkForStateChanges0() {
278264
} else if (window.isFocused()) {
279265
if (IdleHandler.isIdle()) {
280266
current = PowerState.ABANDONED;
281-
} else if (batteryTracking().enabled() && batteryTracking().switchStates() && BatteryTracker.status() == State.DISCHARGING) {
267+
} else if (batteryTracking.enabled() && batteryTracking.switchStates() && BatteryTracker.status() == State.DISCHARGING) {
282268
current = PowerState.UNPLUGGED;
283269
} else {
284270
current = PowerState.FOCUSED; // Default

platforms/common/src/main/java/dynamic_fps/impl/compat/ClothConfig.java

Lines changed: 28 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -39,25 +39,26 @@ public static Screen genConfigScreen(Screen parent) {
3939
localized("config", "category.general")
4040
);
4141

42-
DynamicFPSConfig defaultConfig = DynamicFPSConfig.DEFAULT;
42+
DynamicFPSConfig config = DynamicFPSConfig.INSTANCE;
43+
DynamicFPSConfig defaultConfig = DynamicFPSConfig.DEFAULTS;
4344

4445
general.addEntry(
4546
entryBuilder.startBooleanToggle(
4647
localized("config", "enabled"),
47-
DynamicFPSMod.modConfig.enabled()
48+
config.enabled()
4849
)
4950
.setDefaultValue(defaultConfig.enabled())
50-
.setSaveConsumer(DynamicFPSMod.modConfig::setEnabled)
51+
.setSaveConsumer(config::setEnabled)
5152
.build()
5253
);
5354

5455
general.addEntry(
5556
entryBuilder.startBooleanToggle(
5657
localized("config", "uncap_menu_frame_rate"),
57-
DynamicFPSMod.modConfig.uncapMenuFrameRate()
58+
config.uncapMenuFrameRate()
5859
)
5960
.setDefaultValue(defaultConfig.uncapMenuFrameRate())
60-
.setSaveConsumer(DynamicFPSMod.modConfig::setUncapMenuFrameRate)
61+
.setSaveConsumer(config::setUncapMenuFrameRate)
6162
.setTooltip(localized("config", "uncap_menu_frame_rate_tooltip"))
6263
.build()
6364
);
@@ -69,11 +70,11 @@ public static Screen genConfigScreen(Screen parent) {
6970
general.addEntry(
7071
entryBuilder.startIntSlider(
7172
localized("config", "idle_time"),
72-
DynamicFPSMod.modConfig.idle().timeout() / 60,
73+
config.idle().timeout() / 60,
7374
0, 30
7475
)
7576
.setDefaultValue(defaultConfig.idle().timeout() / 60)
76-
.setSaveConsumer(value -> DynamicFPSMod.modConfig.idle().setTimeout(value * 60))
77+
.setSaveConsumer(value -> config.idle().setTimeout(value * 60))
7778
.setTextGetter(ClothConfig::idleTimeMessage)
7879
.setTooltip(localized("config", "idle_time_tooltip"))
7980
.build()
@@ -83,10 +84,10 @@ public static Screen genConfigScreen(Screen parent) {
8384
entryBuilder.startEnumSelector(
8485
localized("config", "idle_condition"),
8586
IdleCondition.class,
86-
DynamicFPSMod.modConfig.idle().condition()
87+
config.idle().condition()
8788
)
8889
.setDefaultValue(defaultConfig.idle().condition())
89-
.setSaveConsumer(DynamicFPSMod.modConfig.idle()::setCondition)
90+
.setSaveConsumer(config.idle()::setCondition)
9091
.setEnumNameProvider(ClothConfig::IdleConditionMessage)
9192
.build()
9293
);
@@ -100,11 +101,11 @@ public static Screen genConfigScreen(Screen parent) {
100101
general.addEntry(
101102
entryBuilder.startIntSlider(
102103
localized("config", "volume_transition_speed_up"),
103-
volumeTransformer.toStep((int) (DynamicFPSMod.volumeTransitionSpeed().getUp() * 10)),
104+
volumeTransformer.toStep((int) (config.volumeTransitionSpeed().getUp() * 10)),
104105
1, 13
105106
)
106107
.setDefaultValue(volumeTransformer.toStep((int) (defaultConfig.volumeTransitionSpeed().getUp() * 10)))
107-
.setSaveConsumer(step -> DynamicFPSMod.volumeTransitionSpeed().setUp((float) volumeTransformer.toValue(step) / 10))
108+
.setSaveConsumer(step -> config.volumeTransitionSpeed().setUp((float) volumeTransformer.toValue(step) / 10))
108109
.setTextGetter(ClothConfig::volumeTransitionMessage)
109110
.setTooltip(localized("config", "volume_transition_speed_tooltip"))
110111
.build()
@@ -113,11 +114,11 @@ public static Screen genConfigScreen(Screen parent) {
113114
general.addEntry(
114115
entryBuilder.startIntSlider(
115116
localized("config", "volume_transition_speed_down"),
116-
volumeTransformer.toStep((int) (DynamicFPSMod.volumeTransitionSpeed().getDown() * 10)),
117+
volumeTransformer.toStep((int) (config.volumeTransitionSpeed().getDown() * 10)),
117118
1, 13
118119
)
119120
.setDefaultValue(volumeTransformer.toStep((int) (defaultConfig.volumeTransitionSpeed().getDown() * 10)))
120-
.setSaveConsumer(step -> DynamicFPSMod.volumeTransitionSpeed().setDown((float) volumeTransformer.toValue(step) / 10))
121+
.setSaveConsumer(step -> config.volumeTransitionSpeed().setDown((float) volumeTransformer.toValue(step) / 10))
121122
.setTextGetter(ClothConfig::volumeTransitionMessage)
122123
.setTooltip(localized("config", "volume_transition_speed_tooltip"))
123124
.build()
@@ -127,7 +128,7 @@ public static Screen genConfigScreen(Screen parent) {
127128
entryBuilder.startTextDescription(CommonComponents.SPACE).build()
128129
);
129130

130-
BatteryTrackerConfig batteryTracker = DynamicFPSMod.batteryTracking();
131+
BatteryTrackerConfig batteryTracker = config.batteryTracker();
131132

132133
general.addEntry(
133134
entryBuilder.startBooleanToggle(
@@ -194,7 +195,7 @@ public static Screen genConfigScreen(Screen parent) {
194195
continue;
195196
}
196197

197-
Config config = DynamicFPSMod.modConfig.get(state);
198+
Config instance = config.get(state);
198199
Config standard = defaultConfig.get(state);
199200

200201
ConfigCategory category = builder.getOrCreateCategory(
@@ -207,11 +208,11 @@ public static Screen genConfigScreen(Screen parent) {
207208
category.addEntry(
208209
entryBuilder.startIntSlider(
209210
localized("config", "frame_rate_target"),
210-
fpsTransformer.toStep(config.frameRateTarget()),
211+
fpsTransformer.toStep(instance.frameRateTarget()),
211212
0, 68
212213
)
213214
.setDefaultValue(fpsTransformer.toStep(standard.frameRateTarget()))
214-
.setSaveConsumer(step -> config.setFrameRateTarget(fpsTransformer.toValue(step)))
215+
.setSaveConsumer(step -> instance.setFrameRateTarget(fpsTransformer.toValue(step)))
215216
.setTextGetter(ClothConfig::fpsTargetMessage)
216217
.build()
217218
);
@@ -229,11 +230,11 @@ public static Screen genConfigScreen(Screen parent) {
229230
volumes.add(
230231
entryBuilder.startIntSlider(
231232
Component.translatable("soundCategory." + name),
232-
(int) (config.rawVolumeMultiplier(source) * 100),
233+
(int) (instance.rawVolumeMultiplier(source) * 100),
233234
0, 100
234235
)
235236
.setDefaultValue((int) (standard.rawVolumeMultiplier(source) * 100))
236-
.setSaveConsumer(value -> config.setVolumeMultiplier(source, value / 100f))
237+
.setSaveConsumer(value -> instance.setVolumeMultiplier(source, value / 100f))
237238
.setTextGetter(ClothConfig::volumeMultiplierMessage)
238239
.build()
239240
);
@@ -245,10 +246,10 @@ public static Screen genConfigScreen(Screen parent) {
245246
entryBuilder.startEnumSelector(
246247
localized("config", "graphics_state"),
247248
GraphicsState.class,
248-
config.graphicsState()
249+
instance.graphicsState()
249250
)
250251
.setDefaultValue(standard.graphicsState())
251-
.setSaveConsumer(config::setGraphicsState)
252+
.setSaveConsumer(instance::setGraphicsState)
252253
.setEnumNameProvider(ClothConfig::graphicsStateMessage)
253254
.setTooltipSupplier(ClothConfig::graphicsStateTooltip)
254255
.build()
@@ -257,21 +258,21 @@ public static Screen genConfigScreen(Screen parent) {
257258
category.addEntry(
258259
entryBuilder.startBooleanToggle(
259260
localized("config", "show_toasts"),
260-
config.showToasts()
261+
instance.showToasts()
261262
)
262263
.setDefaultValue(standard.showToasts())
263-
.setSaveConsumer(config::setShowToasts)
264+
.setSaveConsumer(instance::setShowToasts)
264265
.setTooltip(localized("config", "show_toasts_tooltip"))
265266
.build()
266267
);
267268

268269
category.addEntry(
269270
entryBuilder.startBooleanToggle(
270271
localized("config", "run_garbage_collector"),
271-
config.runGarbageCollector()
272+
instance.runGarbageCollector()
272273
)
273274
.setDefaultValue(standard.runGarbageCollector())
274-
.setSaveConsumer(config::setRunGarbageCollector)
275+
.setSaveConsumer(instance::setRunGarbageCollector)
275276
.setTooltip(localized("config", "run_garbage_collector_tooltip"))
276277
.build()
277278
);
@@ -284,10 +285,10 @@ public static Screen genConfigScreen(Screen parent) {
284285
advanced.addEntry(
285286
entryBuilder.startBooleanToggle(
286287
localized("config", "download_natives"),
287-
DynamicFPSMod.modConfig.downloadNatives()
288+
config.downloadNatives()
288289
)
289290
.setDefaultValue(defaultConfig.downloadNatives())
290-
.setSaveConsumer(DynamicFPSMod.modConfig::setDownloadNatives)
291+
.setSaveConsumer(config::setDownloadNatives)
291292
.setTooltip(new Component[]{
292293
localized("config", "download_natives_description_0"),
293294
localized("config", "download_natives_description_1")}

platforms/common/src/main/java/dynamic_fps/impl/config/Config.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public class Config {
1616
private boolean showToasts;
1717
private boolean runGarbageCollector;
1818

19+
protected transient PowerState state; // Set by main config, allows retrieving values from the default power state config
20+
1921
public static final Config ACTIVE = new Config(-1, new HashMap<>(), GraphicsState.DEFAULT, true, false);
2022

2123
public Config(int frameRateTarget, Map<String, Float> volumeMultipliers, GraphicsState graphicsState, boolean showToasts, boolean runGarbageCollector) {
@@ -57,8 +59,9 @@ public float rawVolumeMultiplier(SoundSource source) {
5759

5860
public void setVolumeMultiplier(SoundSource source, float value) {
5961
String key = soundSourceName(source);
62+
Config defaultConfig = DynamicFPSConfig.DEFAULTS.get(this.state);
6063

61-
if (value != 1.0f) {
64+
if (value != 1.0f || defaultConfig.rawVolumeMultiplier(source) != 1.0f) {
6265
this.volumeMultipliers.put(key, value);
6366
} else {
6467
this.volumeMultipliers.remove(key); // Same as default value

platforms/common/src/main/java/dynamic_fps/impl/config/DynamicFPSConfig.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package dynamic_fps.impl.config;
22

3-
import java.util.EnumMap;
43
import java.util.Map;
54

65
import com.google.gson.annotations.SerializedName;
@@ -17,7 +16,17 @@ public final class DynamicFPSConfig {
1716
@SerializedName("states")
1817
private Map<PowerState, Config> configs;
1918

20-
public static final DynamicFPSConfig DEFAULT = Serialization.loadDefault();
19+
public static final DynamicFPSConfig DEFAULTS;
20+
public static final DynamicFPSConfig INSTANCE;
21+
22+
static {
23+
DEFAULTS = Serialization.loadDefault();
24+
INSTANCE = Serialization.loadPersonalized();
25+
26+
for (Map.Entry<PowerState, Config> entry: INSTANCE.configs.entrySet()) {
27+
entry.getValue().state = entry.getKey();
28+
}
29+
}
2130

2231
public Config get(PowerState state) {
2332
if (state == PowerState.FOCUSED) {
@@ -63,14 +72,6 @@ public void setDownloadNatives(boolean value) {
6372
this.downloadNatives = value;
6473
}
6574

66-
private Map<PowerState, Config> configs() {
67-
return this.configs;
68-
}
69-
70-
public static DynamicFPSConfig load() {
71-
return Serialization.load();
72-
}
73-
7475
public void save() {
7576
Serialization.save(this);
7677
}

platforms/common/src/main/java/dynamic_fps/impl/config/Serialization.java

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class Serialization {
4242

4343
public static void save(DynamicFPSConfig instance) {
4444
JsonObject config = (JsonObject) GSON.toJsonTree(instance);
45-
JsonObject parent = (JsonObject) GSON.toJsonTree(DynamicFPSConfig.DEFAULT);
45+
JsonObject parent = (JsonObject) GSON.toJsonTree(DynamicFPSConfig.DEFAULTS);
4646

4747
String data = GSON.toJson(removeUnchangedFields(config, parent)) + "\n";
4848

@@ -81,18 +81,20 @@ private static JsonObject removeUnchangedFields(JsonObject config, JsonObject pa
8181
return;
8282
}
8383

84-
if (value.equals(other)) {
85-
config.remove(name);
86-
} else if (value.isJsonObject() && other.isJsonObject()) {
84+
if (value.isJsonObject() && other.isJsonObject()) {
8785
removeUnchangedFields((JsonObject) value, (JsonObject) other);
8886
}
87+
88+
if (value.equals(other) || (value.isJsonObject() && value.getAsJsonObject().isEmpty())) {
89+
config.remove(name);
90+
}
8991
});
9092

9193
return config;
9294
}
9395

9496
@SuppressWarnings("deprecation")
95-
public static DynamicFPSConfig load() {
97+
public static DynamicFPSConfig loadPersonalized() {
9698
byte[] data = null;
9799
Path config = Platform.getInstance().getConfigDir().resolve(CONFIG_FILE);
98100

@@ -143,7 +145,7 @@ private static void upgradeConfig(JsonObject config) {
143145
upgradeIdleConfig(config);
144146

145147
// version agnostic
146-
addMissingFields(config, (JsonObject) GSON.toJsonTree(DynamicFPSConfig.DEFAULT));
148+
addMissingFields(config, (JsonObject) GSON.toJsonTree(DynamicFPSConfig.DEFAULTS));
147149
}
148150

149151
private static void addMissingFields(JsonObject config, JsonObject parent) {

0 commit comments

Comments
 (0)