Skip to content

Commit 115ce11

Browse files
authored
Add a filter builder to aid users in setting filters (#14)
* Add a filter builder to aid users in setting filters * Update documentation
1 parent c1d5321 commit 115ce11

File tree

10 files changed

+603
-11
lines changed

10 files changed

+603
-11
lines changed

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ Alternatively, you can use `Discord4JUtils.leave(gatewayClient, guildId);` as th
128128
## Examples
129129
The following examples are minimal implementations but show how the library works.
130130
- Java examples
131-
- JDA: [link](src/test/java/JavaJDAExample.java)
131+
- JDA (simple): [link](src/test/java/JavaJDAExample.java)
132+
- JDA (more complex example): [link](testbot/src/main/java/me/duncte123/testbot/Main.java)
132133
- Kotlin examples
133134
- JDA: [link](src/test/kotlin/testScript.kt)
134135
- Discord4J: [link](src/test/kotlin/d4jTestScript.kt)

build.gradle.kts

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,20 +35,22 @@ group = "dev.arbjerg"
3535
version = gitVersion
3636
val archivesBaseName = "lavalink-client"
3737

38+
allprojects {
39+
repositories {
40+
mavenCentral()
41+
maven("https://maven.lavalink.dev/releases")
42+
maven("https://maven.lavalink.dev/snapshots")
43+
maven("https://maven.topi.wtf/releases")
44+
// Note to self: jitpack always comes last
45+
maven("https://jitpack.io")
46+
}
47+
}
48+
3849
java {
3950
sourceCompatibility = JavaVersion.VERSION_17
4051
targetCompatibility = JavaVersion.VERSION_17
4152
}
4253

43-
repositories {
44-
mavenCentral()
45-
maven("https://maven.lavalink.dev/releases")
46-
maven("https://maven.lavalink.dev/snapshots")
47-
maven("https://maven.topi.wtf/releases")
48-
// Note to self: jitpack always comes last
49-
maven("https://jitpack.io")
50-
}
51-
5254
dependencies {
5355
// package libraries
5456
api(kotlin("stdlib"))

settings.gradle.kts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ rootProject.name = "lavalink-client"
22

33
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
44

5+
include(":testbot")
6+
57
dependencyResolutionManagement {
68
versionCatalogs {
79
create("libs") {

src/main/kotlin/dev/arbjerg/lavalink/client/IUpdatablePlayer.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ interface IUpdatablePlayer {
112112
* Please use [setVolume] to update the player's volume instead. Setting the volume via filters is
113113
* float based (1.0f is 100% volume) and takes the time of your buffer size to apply.
114114
*
115-
* @param filters The new filters to apply to the player.
115+
* @param filters The new filters to apply to the player. You can use the [dev.arbjerg.lavalink.client.protocol.FilterBuilder] to easily create this object.
116116
*
117117
* @return The updated builder, useful for chaining
118118
*/
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
package dev.arbjerg.lavalink.client.protocol
2+
3+
import dev.arbjerg.lavalink.internal.toJsonElement
4+
import dev.arbjerg.lavalink.protocol.v4.*
5+
import kotlinx.serialization.json.JsonElement
6+
7+
/**
8+
* Helper class fo builder [Filters].
9+
*/
10+
class FilterBuilder {
11+
private var volume: Omissible<Float> = Omissible.Omitted()
12+
private var equalizer: Omissible<List<Band>> = Omissible.Omitted()
13+
private var karaoke: Omissible<Karaoke?> = Omissible.Omitted()
14+
private var timescale: Omissible<Timescale?> = Omissible.Omitted()
15+
private var tremolo: Omissible<Tremolo?> = Omissible.Omitted()
16+
private var vibrato: Omissible<Vibrato?> = Omissible.Omitted()
17+
private var distortion: Omissible<Distortion?> = Omissible.Omitted()
18+
private var rotation: Omissible<Rotation?> = Omissible.Omitted()
19+
private var channelMix: Omissible<ChannelMix?> = Omissible.Omitted()
20+
private var lowPass: Omissible<LowPass?> = Omissible.Omitted()
21+
private var pluginFilters: MutableMap<String, JsonElement> = mutableMapOf()
22+
23+
/**
24+
* Sets the filter volume. If you just want to change the volume, it is highly recommended to use [dev.arbjerg.lavalink.client.IUpdatablePlayer.setVolume] instead.
25+
*
26+
* This volume takes the time of your buffer size to apply and should only be used if any other filters would increase the overall volume too much.
27+
*
28+
* @param volume The volume to apply to the filter.
29+
*
30+
* @return The updated builder, useful for chaining
31+
*/
32+
fun setVolume(volume: Float) = apply {
33+
this.volume = volume.toOmissible()
34+
}
35+
36+
/**
37+
* Set the equalizer bands on the player.
38+
*
39+
* @param equalizer Each band to set in the equalizer. Default gain is 1.0f.
40+
*
41+
* @return The updated builder, useful for chaining
42+
*/
43+
fun setEqualizer(equalizer: List<Band>) = apply {
44+
this.equalizer = equalizer.toOmissible()
45+
}
46+
47+
/**
48+
* Set a specific band on the equalizer.
49+
*
50+
* @param band The band to set.
51+
* @param gain The gain to apply to the band. Default gain is 1.0f.
52+
*
53+
* @return The updated builder, useful for chaining
54+
*/
55+
@JvmOverloads
56+
fun setEqualizerBand(band: Int, gain: Float = 1.0F) = apply {
57+
val eq = this.equalizer
58+
val bandObj = Band(band, gain)
59+
60+
if (eq.isPresent()) {
61+
val currEq = eq.value.toMutableList()
62+
val bandIndex = currEq.indexOfFirst { it.band == band }
63+
64+
if (bandIndex > -1) {
65+
currEq[bandIndex] = bandObj
66+
} else {
67+
currEq.add(bandObj)
68+
}
69+
70+
this.equalizer = currEq.toOmissible()
71+
} else {
72+
this.equalizer = listOf(bandObj).toOmissible()
73+
}
74+
}
75+
76+
/**
77+
* Set the karaoke filter on the player.
78+
*
79+
* @param karaoke The karaoke filter to apply to the player. Set to null to disable the filter.
80+
*
81+
* @return The updated builder, useful for chaining
82+
*/
83+
fun setKaraoke(karaoke: Karaoke?) = apply {
84+
this.karaoke = Omissible.of(karaoke)
85+
}
86+
87+
/**
88+
* Sets the timescale filter on the player.
89+
*
90+
* @param timescale The timescale filter to apply to the player. Set to null to disable the filter.
91+
*
92+
* @return The updated builder, useful for chaining
93+
*/
94+
fun setTimescale(timescale: Timescale?) = apply {
95+
this.timescale = Omissible.of(timescale)
96+
}
97+
98+
/**
99+
* Sets the tremolo filter on the player.
100+
*
101+
* @param tremolo The tremolo filter to apply to the player. Set to null to disable the filter.
102+
*
103+
* @return The updated builder, useful for chaining
104+
*/
105+
fun setTremolo(tremolo: Tremolo?) = apply {
106+
this.tremolo = Omissible.of(tremolo)
107+
}
108+
109+
/**
110+
* Sets the vibrato filter on the player.
111+
*
112+
* @param vibrato The vibrato filter to apply to the player. Set to null to disable the filter.
113+
*
114+
* @return The updated builder, useful for chaining
115+
*/
116+
fun setVibrato(vibrato: Vibrato?) = apply {
117+
this.vibrato = Omissible.of(vibrato)
118+
}
119+
120+
/**
121+
* Sets the distortion filter on the player.
122+
*
123+
* @param distortion The distortion filter to apply to the player. Set to null to disable the filter.
124+
*
125+
* @return The updated builder, useful for chaining
126+
*/
127+
fun setDistortion(distortion: Distortion?) = apply {
128+
this.distortion = Omissible.of(distortion)
129+
}
130+
131+
/**
132+
* Sets the rotation filter on the player.
133+
*
134+
* @param rotation The rotation filter to apply to the player. Set to null to disable the filter.
135+
*
136+
* @return The updated builder, useful for chaining
137+
*/
138+
fun setRotation(rotation: Rotation?) = apply {
139+
this.rotation = Omissible.of(rotation)
140+
}
141+
142+
/**
143+
* Sets the channel mix filter on the player.
144+
*
145+
* @param channelMix The channel mix filter to apply to the player. Set to null to disable the filter.
146+
*
147+
* @return The updated builder, useful for chaining
148+
*/
149+
fun setChannelMix(channelMix: ChannelMix?) = apply {
150+
this.channelMix = Omissible.of(channelMix)
151+
}
152+
153+
/**
154+
* Sets the low pass filter on the player.
155+
*
156+
* @param lowPass The low pass filter to apply to the player. Set to null to disable the filter.
157+
*
158+
* @return The updated builder, useful for chaining
159+
*/
160+
fun setLowPass(lowPass: LowPass?) = apply {
161+
this.lowPass = Omissible.of(lowPass)
162+
}
163+
164+
/**
165+
* Set custom filter data for a plugin.
166+
*
167+
* @param name the name of the plugin filter
168+
* @param filter the filter data, can be a custom class as it will be serialised to json
169+
* @return The updated builder, useful for chaining
170+
*/
171+
fun setPluginFilter(name: String, filter: Any) = apply {
172+
pluginFilters[name] = toJsonElement(filter)
173+
}
174+
175+
/**
176+
* Set custom filter data for a plugin.
177+
*
178+
* @param name the name of the plugin filter
179+
* @param filter kotlin [JsonElement] that holds the filter data.
180+
* @return The updated builder, useful for chaining
181+
*/
182+
fun setPluginFilter(name: String, filter: JsonElement) = apply {
183+
pluginFilters[name] = filter
184+
}
185+
186+
/**
187+
* Removes a plugin filter with the given name.
188+
*
189+
* @param name the name of the plugin filter
190+
* @return The updated builder, useful for chaining
191+
*/
192+
fun removePluginFilter(name: String) = apply {
193+
pluginFilters.remove(name)
194+
}
195+
196+
/**
197+
* Builds the [Filters] object with the current configuration.
198+
*
199+
* @return the [Filters] object with the current configuration
200+
*/
201+
fun build() = Filters(
202+
volume,
203+
equalizer,
204+
karaoke,
205+
timescale,
206+
tremolo,
207+
vibrato,
208+
distortion,
209+
rotation,
210+
channelMix,
211+
lowPass,
212+
pluginFilters
213+
)
214+
}

testbot/build.gradle.kts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
plugins {
2+
java
3+
application
4+
}
5+
6+
group = "me.duncte123"
7+
version = "1.0-SNAPSHOT"
8+
9+
java {
10+
sourceCompatibility = JavaVersion.VERSION_17
11+
targetCompatibility = JavaVersion.VERSION_17
12+
}
13+
14+
dependencies {
15+
// Include the lavalink client
16+
implementation(projects.lavalinkClient)
17+
18+
// other libs such as a discord client and a logger
19+
implementation(libs.jda)
20+
implementation(libs.logger.impl)
21+
}
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
package me.duncte123.testbot;
2+
3+
import dev.arbjerg.lavalink.client.AbstractAudioLoadResultHandler;
4+
import dev.arbjerg.lavalink.client.Link;
5+
import dev.arbjerg.lavalink.client.protocol.*;
6+
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
7+
import org.jetbrains.annotations.NotNull;
8+
9+
import java.util.List;
10+
11+
public class AudioLoader extends AbstractAudioLoadResultHandler {
12+
private final Link link;
13+
private final SlashCommandInteractionEvent event;
14+
15+
public AudioLoader(Link link, SlashCommandInteractionEvent event) {
16+
this.link = link;
17+
this.event = event;
18+
}
19+
20+
@Override
21+
public void ontrackLoaded(@NotNull TrackLoaded result) {
22+
final Track track = result.getTrack();
23+
24+
// Inner class at the end of this file
25+
var userData = new MyUserData(event.getUser().getIdLong());
26+
27+
track.setUserData(userData);
28+
29+
link.createOrUpdatePlayer()
30+
.setTrack(track)
31+
.setVolume(35)
32+
.subscribe((player) -> {
33+
final Track playingTrack = player.getTrack();
34+
final var trackTitle = playingTrack.getInfo().getTitle();
35+
final MyUserData customData = playingTrack.getUserData(MyUserData.class);
36+
37+
event.getHook().sendMessage("Now playing: " + trackTitle + "\nRequested by: <@" + customData.requester() + '>').queue();
38+
});
39+
}
40+
41+
@Override
42+
public void onPlaylistLoaded(@NotNull PlaylistLoaded result) {
43+
final int trackCount = result.getTracks().size();
44+
event.getHook()
45+
.sendMessage("This playlist has " + trackCount + " tracks!")
46+
.queue();
47+
}
48+
49+
@Override
50+
public void onSearchResultLoaded(@NotNull SearchResult result) {
51+
final List<Track> tracks = result.getTracks();
52+
53+
if (tracks.isEmpty()) {
54+
event.getHook().sendMessage("No tracks found!").queue();
55+
return;
56+
}
57+
58+
final Track firstTrack = tracks.get(0);
59+
60+
// This is a different way of updating the player! Choose your preference!
61+
// This method will also create a player if there is not one in the server yet
62+
link.updatePlayer((update) -> update.setTrack(firstTrack).setVolume(35))
63+
.subscribe((ignored) -> {
64+
event.getHook().sendMessage("Now playing: " + firstTrack.getInfo().getTitle()).queue();
65+
});
66+
}
67+
68+
@Override
69+
public void noMatches() {
70+
event.getHook().sendMessage("No matches found for your input!").queue();
71+
}
72+
73+
@Override
74+
public void loadFailed(@NotNull LoadFailed result) {
75+
event.getHook().sendMessage("Failed to load track! " + result.getException().getMessage()).queue();
76+
}
77+
}

0 commit comments

Comments
 (0)