From 17ac37cecf3f02739ac1861d06cbc4fc48a0197a Mon Sep 17 00:00:00 2001 From: jesse1412 Date: Sun, 10 Feb 2019 19:28:17 +0000 Subject: [PATCH 1/3] Extend the metronome plugin. Add custom sound file support (short .wav only) Add offset option (for aligning tock sounds with in-game events on a cycle) Add independent volume control for custom sounds Add option to configure the number of "ticks" between each "tock" --- .../plugins/metronome/MetronomePlugin.java | 140 ++++++++++++++++-- .../MetronomePluginConfiguration.java | 71 +++++++-- 2 files changed, 191 insertions(+), 20 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java index 9a0b709aab..9c2bad4654 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java @@ -25,21 +25,32 @@ */ package net.runelite.client.plugins.metronome; +import net.runelite.api.events.ConfigChanged; +import net.runelite.client.eventbus.Subscribe; import com.google.inject.Provides; + import javax.inject.Inject; + import net.runelite.api.Client; import net.runelite.api.SoundEffectID; import net.runelite.api.events.GameTick; import net.runelite.client.config.ConfigManager; -import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.FloatControl; +import java.io.File; + @PluginDescriptor( - name = "Metronome", - description = "Play a sound on a specified tick to aid in efficient skilling", - tags = {"skilling", "tick", "timers"}, - enabledByDefault = false + name = "Metronome extended", + description = "Play sounds in a customisable pattern", + tags = {"skilling", "tick", "timers"}, + enabledByDefault = false ) public class MetronomePlugin extends Plugin { @@ -50,7 +61,9 @@ public class MetronomePlugin extends Plugin private MetronomePluginConfiguration config; private int tickCounter = 0; - private boolean shouldTock = false; + private int tockCounter = 0; + private Clip tickClip; + private Clip tockClip; @Provides MetronomePluginConfiguration provideConfig(ConfigManager configManager) @@ -58,6 +71,88 @@ public class MetronomePlugin extends Plugin return configManager.getConfig(MetronomePluginConfiguration.class); } + private Clip GetAudioClip(String path) + { + File audioFile = new File(path); + if (audioFile.exists()) + { + AudioInputStream audioStream = null; + try + { + audioStream = AudioSystem.getAudioInputStream(audioFile); + } + catch (Exception e) + { + return null; + } + AudioFormat audioFormat = audioStream.getFormat(); + DataLine.Info audioInfo = new DataLine.Info(Clip.class, audioFormat); + try + { + Clip audioClip = AudioSystem.getClip(); + audioClip.open(audioStream); + FloatControl gainControl = (FloatControl) audioClip.getControl(FloatControl.Type.MASTER_GAIN); + float gainValue = (((float) config.volume()) * 40f / 100f) - 35f; + gainControl.setValue(gainValue); + return audioClip; + } + catch (Exception e) + { + return null; + } + } + return null; + } + + @Override + protected void startUp() + { + tickClip = GetAudioClip(config.tickPath()); + tockClip = GetAudioClip(config.tockPath()); + } + + @Override + protected void shutDown() + { + if (tickClip != null) + { + tickClip.close(); + } + if (tockClip != null) + { + tockClip.close(); + } + } + + @Subscribe + public void onConfigChanged(ConfigChanged event) + { + if (event.getKey().equals("volume")) + { + float gainValue = (((float) config.volume()) * 40f / 100f) - 35f; + FloatControl gainControlTick = (FloatControl) tickClip.getControl(FloatControl.Type.MASTER_GAIN); + gainControlTick.setValue(gainValue); + FloatControl gainControlTock = (FloatControl) tockClip.getControl(FloatControl.Type.MASTER_GAIN); + gainControlTock.setValue(gainValue); + } + if (event.getKey().equals("tickSoundFilePath")) + { + if (tickClip != null) + { + tickClip.close(); + } + tickClip = GetAudioClip(config.tickPath()); + } + if (event.getKey().equals("tockSoundFilePath")) + { + if (tockClip != null) + { + tockClip.close(); + } + tockClip = GetAudioClip(config.tockPath()); + } + } + @Subscribe public void onGameTick(GameTick tick) { @@ -66,17 +161,40 @@ public class MetronomePlugin extends Plugin return; } - if (++tickCounter % config.tickCount() == 0) + if ((++tickCounter + config.tickOffset()) % config.tickCount() == 0) { - if (config.enableTock() && shouldTock) + if (++tockCounter % config.tockNumber() == 0 & config.enableTock()) { - client.playSoundEffect(SoundEffectID.GE_DECREMENT_PLOP); + if (tockClip == null) + { + client.playSoundEffect(SoundEffectID.GE_INCREMENT_PLOP); + } + else + { + if (tockClip.isRunning()) + { + tockClip.stop(); + } + tockClip.setFramePosition(0); + tockClip.start(); + } } else { - client.playSoundEffect(SoundEffectID.GE_INCREMENT_PLOP); + if (tickClip == null) + { + client.playSoundEffect(SoundEffectID.GE_DECREMENT_PLOP); + } + else + { + if (tickClip.isRunning()) + { + tickClip.stop(); + } + tickClip.setFramePosition(0); + tickClip.start(); + } } - shouldTock = !shouldTock; } } } diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java index cb2ff60889..cfd573b98a 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java @@ -28,15 +28,15 @@ package net.runelite.client.plugins.metronome; import net.runelite.client.config.Config; import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; +import net.runelite.client.config.Range; -@ConfigGroup("metronome") +@ConfigGroup("metronomeExtended") public interface MetronomePluginConfiguration extends Config { @ConfigItem( - keyName = "tickCount", - name = "Tick count", - description = "Configures the tick on which a sound will be played", - position = 2 + keyName = "tickCount", + name = "Tick count", + description = "Configures the number of game ticks between metronome sounds" ) default int tickCount() { @@ -44,13 +44,66 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "enableTock", - name = "Enable tock (alternating) sound", - description = "Toggles whether to play two alternating sounds", - position = 3 + keyName = "enableTock", + name = "Enable tock (alternating) sound", + description = "Toggles whether to play \"tock\" sounds" ) default boolean enableTock() { return false; } + + @ConfigItem( + keyName = "tockNumber", + name = "Tock every nth \"tick\"", + description = "Configures how many \"ticks\" between each \"tock\"" + ) + default int tockNumber() + { + return 2; + } + + @ConfigItem( + keyName = "tickOffset", + name = "Offset", + description = "Amount of ticks to offset the metronome (only useful for \"tocks\")" + ) + default int tickOffset() + { + return 0; + } + + @ConfigItem( + keyName = "tickSoundFilePath", + name = "Tick .wav file path", + description = "The path to the file to be used for \"tick\" sounds (short .wav only)" + ) + default String tickPath() + { + return ""; + } + + @ConfigItem( + keyName = "tockSoundFilePath", + name = "Tock .wav file path", + description = "The path to the file to be used for \"tock\" sounds (short .wav only)" + ) + default String tockPath() + { + return ""; + } + + @Range( + min = 0, + max = 100 + ) + @ConfigItem( + keyName = "volume", + name = "Volume modification", + description = "Configures tick/tock volume; only effects custom sounds." + ) + default int volume() + { + return 35; + } } From be8cf58173f065f94c06b679f76ec7ae73386608 Mon Sep 17 00:00:00 2001 From: jesse1412 Date: Sun, 10 Feb 2019 19:37:23 +0000 Subject: [PATCH 2/3] Re-order imports and fix code migration issues --- .../runelite/client/plugins/metronome/MetronomePlugin.java | 6 +++--- .../plugins/metronome/MetronomePluginConfiguration.java | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java index 9c2bad4654..c84dc8953e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java @@ -25,16 +25,16 @@ */ package net.runelite.client.plugins.metronome; -import net.runelite.api.events.ConfigChanged; -import net.runelite.client.eventbus.Subscribe; import com.google.inject.Provides; import javax.inject.Inject; import net.runelite.api.Client; import net.runelite.api.SoundEffectID; +import net.runelite.api.events.ConfigChanged; import net.runelite.api.events.GameTick; import net.runelite.client.config.ConfigManager; +import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; @@ -47,7 +47,7 @@ import javax.sound.sampled.FloatControl; import java.io.File; @PluginDescriptor( - name = "Metronome extended", + name = "Metronome", description = "Play sounds in a customisable pattern", tags = {"skilling", "tick", "timers"}, enabledByDefault = false diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java index cfd573b98a..e7178e80cb 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java @@ -30,7 +30,7 @@ import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigItem; import net.runelite.client.config.Range; -@ConfigGroup("metronomeExtended") +@ConfigGroup("metronome") public interface MetronomePluginConfiguration extends Config { @ConfigItem( @@ -72,7 +72,7 @@ public interface MetronomePluginConfiguration extends Config { return 0; } - + @ConfigItem( keyName = "tickSoundFilePath", name = "Tick .wav file path", From d8cb648003598e98f1197d650bb0daf00b07931f Mon Sep 17 00:00:00 2001 From: jesse1412 Date: Mon, 11 Feb 2019 23:22:07 +0000 Subject: [PATCH 3/3] Use proper project styling --- .../plugins/metronome/MetronomePlugin.java | 25 +++++----- .../MetronomePluginConfiguration.java | 46 +++++++++---------- 2 files changed, 34 insertions(+), 37 deletions(-) diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java index c84dc8953e..5cea04a613 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePlugin.java @@ -26,9 +26,14 @@ package net.runelite.client.plugins.metronome; import com.google.inject.Provides; - import javax.inject.Inject; - +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.DataLine; +import javax.sound.sampled.AudioFormat; +import javax.sound.sampled.FloatControl; +import java.io.File; import net.runelite.api.Client; import net.runelite.api.SoundEffectID; import net.runelite.api.events.ConfigChanged; @@ -38,19 +43,11 @@ import net.runelite.client.eventbus.Subscribe; import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.PluginDescriptor; -import javax.sound.sampled.AudioInputStream; -import javax.sound.sampled.AudioSystem; -import javax.sound.sampled.Clip; -import javax.sound.sampled.DataLine; -import javax.sound.sampled.AudioFormat; -import javax.sound.sampled.FloatControl; -import java.io.File; - @PluginDescriptor( - name = "Metronome", - description = "Play sounds in a customisable pattern", - tags = {"skilling", "tick", "timers"}, - enabledByDefault = false + name = "Metronome", + description = "Play sounds in a customisable pattern", + tags = {"skilling", "tick", "timers"}, + enabledByDefault = false ) public class MetronomePlugin extends Plugin { diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java index e7178e80cb..27cca4ccec 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/metronome/MetronomePluginConfiguration.java @@ -34,9 +34,9 @@ import net.runelite.client.config.Range; public interface MetronomePluginConfiguration extends Config { @ConfigItem( - keyName = "tickCount", - name = "Tick count", - description = "Configures the number of game ticks between metronome sounds" + keyName = "tickCount", + name = "Tick count", + description = "Configures the number of game ticks between metronome sounds" ) default int tickCount() { @@ -44,9 +44,9 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "enableTock", - name = "Enable tock (alternating) sound", - description = "Toggles whether to play \"tock\" sounds" + keyName = "enableTock", + name = "Enable tock (alternating) sound", + description = "Toggles whether to play \"tock\" sounds" ) default boolean enableTock() { @@ -54,9 +54,9 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "tockNumber", - name = "Tock every nth \"tick\"", - description = "Configures how many \"ticks\" between each \"tock\"" + keyName = "tockNumber", + name = "Tock every nth \"tick\"", + description = "Configures how many \"ticks\" between each \"tock\"" ) default int tockNumber() { @@ -64,9 +64,9 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "tickOffset", - name = "Offset", - description = "Amount of ticks to offset the metronome (only useful for \"tocks\")" + keyName = "tickOffset", + name = "Offset", + description = "Amount of ticks to offset the metronome (only useful for \"tocks\")" ) default int tickOffset() { @@ -74,9 +74,9 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "tickSoundFilePath", - name = "Tick .wav file path", - description = "The path to the file to be used for \"tick\" sounds (short .wav only)" + keyName = "tickSoundFilePath", + name = "Tick .wav file path", + description = "The path to the file to be used for \"tick\" sounds (short .wav only)" ) default String tickPath() { @@ -84,9 +84,9 @@ public interface MetronomePluginConfiguration extends Config } @ConfigItem( - keyName = "tockSoundFilePath", - name = "Tock .wav file path", - description = "The path to the file to be used for \"tock\" sounds (short .wav only)" + keyName = "tockSoundFilePath", + name = "Tock .wav file path", + description = "The path to the file to be used for \"tock\" sounds (short .wav only)" ) default String tockPath() { @@ -94,13 +94,13 @@ public interface MetronomePluginConfiguration extends Config } @Range( - min = 0, - max = 100 + min = 0, + max = 100 ) @ConfigItem( - keyName = "volume", - name = "Volume modification", - description = "Configures tick/tock volume; only effects custom sounds." + keyName = "volume", + name = "Volume modification", + description = "Configures tick/tock volume; only effects custom sounds." ) default int volume() {