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"
This commit is contained in:
jesse1412
2019-02-10 19:28:17 +00:00
parent f2e9ad048a
commit 17ac37cecf
2 changed files with 191 additions and 20 deletions

View File

@@ -25,21 +25,32 @@
*/ */
package net.runelite.client.plugins.metronome; package net.runelite.client.plugins.metronome;
import net.runelite.api.events.ConfigChanged;
import net.runelite.client.eventbus.Subscribe;
import com.google.inject.Provides; import com.google.inject.Provides;
import javax.inject.Inject; import javax.inject.Inject;
import net.runelite.api.Client; import net.runelite.api.Client;
import net.runelite.api.SoundEffectID; import net.runelite.api.SoundEffectID;
import net.runelite.api.events.GameTick; import net.runelite.api.events.GameTick;
import net.runelite.client.config.ConfigManager; import net.runelite.client.config.ConfigManager;
import net.runelite.client.eventbus.Subscribe;
import net.runelite.client.plugins.Plugin; import net.runelite.client.plugins.Plugin;
import net.runelite.client.plugins.PluginDescriptor; 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( @PluginDescriptor(
name = "Metronome", name = "Metronome extended",
description = "Play a sound on a specified tick to aid in efficient skilling", description = "Play sounds in a customisable pattern",
tags = {"skilling", "tick", "timers"}, tags = {"skilling", "tick", "timers"},
enabledByDefault = false enabledByDefault = false
) )
public class MetronomePlugin extends Plugin public class MetronomePlugin extends Plugin
{ {
@@ -50,7 +61,9 @@ public class MetronomePlugin extends Plugin
private MetronomePluginConfiguration config; private MetronomePluginConfiguration config;
private int tickCounter = 0; private int tickCounter = 0;
private boolean shouldTock = false; private int tockCounter = 0;
private Clip tickClip;
private Clip tockClip;
@Provides @Provides
MetronomePluginConfiguration provideConfig(ConfigManager configManager) MetronomePluginConfiguration provideConfig(ConfigManager configManager)
@@ -58,6 +71,88 @@ public class MetronomePlugin extends Plugin
return configManager.getConfig(MetronomePluginConfiguration.class); 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 @Subscribe
public void onGameTick(GameTick tick) public void onGameTick(GameTick tick)
{ {
@@ -66,17 +161,40 @@ public class MetronomePlugin extends Plugin
return; 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 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;
} }
} }
} }

View File

@@ -28,15 +28,15 @@ package net.runelite.client.plugins.metronome;
import net.runelite.client.config.Config; import net.runelite.client.config.Config;
import net.runelite.client.config.ConfigGroup; import net.runelite.client.config.ConfigGroup;
import net.runelite.client.config.ConfigItem; import net.runelite.client.config.ConfigItem;
import net.runelite.client.config.Range;
@ConfigGroup("metronome") @ConfigGroup("metronomeExtended")
public interface MetronomePluginConfiguration extends Config public interface MetronomePluginConfiguration extends Config
{ {
@ConfigItem( @ConfigItem(
keyName = "tickCount", keyName = "tickCount",
name = "Tick count", name = "Tick count",
description = "Configures the tick on which a sound will be played", description = "Configures the number of game ticks between metronome sounds"
position = 2
) )
default int tickCount() default int tickCount()
{ {
@@ -44,13 +44,66 @@ public interface MetronomePluginConfiguration extends Config
} }
@ConfigItem( @ConfigItem(
keyName = "enableTock", keyName = "enableTock",
name = "Enable tock (alternating) sound", name = "Enable tock (alternating) sound",
description = "Toggles whether to play two alternating sounds", description = "Toggles whether to play \"tock\" sounds"
position = 3
) )
default boolean enableTock() default boolean enableTock()
{ {
return false; 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;
}
} }