Skip to content

Commit d965e0e

Browse files
committed
Add playlists
1 parent 0435e0b commit d965e0e

File tree

11 files changed

+150
-20
lines changed

11 files changed

+150
-20
lines changed

TestBot/src/main/java/com/shirkanesi/magmaplayer/testbot/MagmaPlayerTestBot.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.shirkanesi.magmaplayer.AudioPlayer;
44
import com.shirkanesi.magmaplayer.AudioTrack;
55
import com.shirkanesi.magmaplayer.AudioTrackInformation;
6-
import com.shirkanesi.magmaplayer.YTDLPAudioTrack;
6+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioTrack;
77
import com.shirkanesi.magmaplayer.testbot.discord.DiscordController;
88
import com.shirkanesi.magmaplayer.testbot.discord.SlashCommandListener;
99
import com.shirkanesi.magmaplayer.listener.AudioTrackEventListener;
@@ -87,7 +87,7 @@ private static void addTestTrack(AudioPlayer audioPlayer) {
8787
String[] tracks = System.getenv("TEST_TRACKS").split(";");
8888
for (String track : tracks) {
8989
AudioTrack ytdlpAudioTrack = new YTDLPAudioTrack(track);
90-
audioPlayer.enqueueTrack(ytdlpAudioTrack);
90+
audioPlayer.enqueue(ytdlpAudioTrack);
9191
}
9292
}
9393

@@ -128,7 +128,7 @@ public void onAudioTrackEnded(AudioTrackEndEvent event) {
128128
});
129129

130130
guildById.getAudioManager().setSendingHandler(audioPlayer.createSendHandler());
131-
audioPlayer.enqueueTrack(ytdlpAudioTrack3);
131+
audioPlayer.enqueue(ytdlpAudioTrack3);
132132
}
133133

134134
}

TestBot/src/main/java/com/shirkanesi/magmaplayer/testbot/discord/SlashCommandListener.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33
import com.shirkanesi.magmaplayer.AudioPlayer;
44
import com.shirkanesi.magmaplayer.AudioTrack;
55
import com.shirkanesi.magmaplayer.AudioTrackInformation;
6-
import com.shirkanesi.magmaplayer.YTDLPAudioTrack;
6+
import com.shirkanesi.magmaplayer.util.YTDLPManager;
7+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioItem;
8+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioPlaylist;
9+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioTrack;
710
import net.dv8tion.jda.api.EmbedBuilder;
811
import net.dv8tion.jda.api.events.interaction.command.SlashCommandInteractionEvent;
912
import net.dv8tion.jda.api.hooks.ListenerAdapter;
@@ -22,15 +25,22 @@ public void onSlashCommandInteraction(SlashCommandInteractionEvent event) {
2225
switch (event.getName()) {
2326
case "play" -> {
2427
String url = event.getOption("url", OptionMapping::getAsString);
25-
audioPlayer.enqueueTrack(new YTDLPAudioTrack(url));
26-
event.reply("Track enqueued").setEphemeral(true).queue();
28+
YTDLPAudioItem item = YTDLPManager.loadUrl(url);
29+
if (item instanceof YTDLPAudioTrack track) {
30+
audioPlayer.enqueue(track);
31+
event.reply("Track enqueued").setEphemeral(true).queue();
32+
} else if (item instanceof YTDLPAudioPlaylist playlist) {
33+
audioPlayer.enqueue(playlist);
34+
event.reply(playlist.getTracks().size() + " tracks enqueued").setEphemeral(true).queue();
35+
}
2736
}
2837
case "skip" -> {
2938
audioPlayer.next();
3039
event.reply("Skipped").setEphemeral(true).queue();
3140
}
3241
case "queue" -> {
3342
EmbedBuilder embedBuilder = new EmbedBuilder();
43+
event.deferReply(true).queue();
3444

3545
int index = 1;
3646
for (AudioTrack audioTrack : audioPlayer.getTrackQueue()) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package com.shirkanesi.magmaplayer;
2+
3+
import java.util.ArrayList;
4+
import java.util.List;
5+
6+
public abstract class AbstractAudioPlaylist implements AudioPlaylist {
7+
8+
protected List<AudioTrack> tracks = new ArrayList<>();
9+
10+
@Override
11+
public List<AudioTrack> getTracks() {
12+
return tracks;
13+
}
14+
15+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.shirkanesi.magmaplayer;
2+
3+
import java.io.Closeable;
4+
5+
public interface AudioItem {
6+
7+
void load();
8+
9+
}

main/src/main/java/com/shirkanesi/magmaplayer/AudioPlayer.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public boolean isPaused() {
6868
return paused || !this.canProvide();
6969
}
7070

71-
public synchronized void enqueueTrack(AudioTrack audioTrack) {
71+
private synchronized void enqueueTrack(AudioTrack audioTrack) {
7272
this.trackQueue.add(audioTrack);
7373
log.debug("Enqueue track {}", audioTrack);
7474
audioTrack.getAudioTrackObserver().addEventListener(this);
@@ -77,6 +77,20 @@ public synchronized void enqueueTrack(AudioTrack audioTrack) {
7777
}
7878
}
7979

80+
public synchronized void enqueue(AudioTrack audioTrack) {
81+
this.enqueueTrack(audioTrack);
82+
}
83+
84+
public synchronized void enqueue(AudioPlaylist audioPlaylist) {
85+
if (audioPlaylist.getTracks().isEmpty()) {
86+
audioPlaylist.load();
87+
}
88+
89+
for (AudioTrack audioTrack : audioPlaylist.getTracks()) {
90+
this.enqueueTrack(audioTrack);
91+
}
92+
}
93+
8094
public boolean isFinished() {
8195
return this.audioTrack.isFinished();
8296
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package com.shirkanesi.magmaplayer;
2+
3+
import java.util.List;
4+
5+
public interface AudioPlaylist extends AudioItem {
6+
7+
List<AudioTrack> getTracks();
8+
9+
}

main/src/main/java/com/shirkanesi/magmaplayer/AudioTrack.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,7 @@
77
import java.io.Closeable;
88
import java.nio.ByteBuffer;
99

10-
public interface AudioTrack extends Closeable {
11-
12-
void load();
10+
public interface AudioTrack extends Closeable, AudioItem {
1311

1412
@FiresEvent(value = AudioTrackJumpEvent.class, onEveryPass = true)
1513
void jumpTo(int seconds);

main/src/main/java/com/shirkanesi/magmaplayer/util/YTDLPManager.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
package com.shirkanesi.magmaplayer.util;
22

3+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioItem;
4+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioPlaylist;
5+
import com.shirkanesi.magmaplayer.ytdlp.YTDLPAudioTrack;
36
import lombok.extern.slf4j.Slf4j;
47
import org.apache.commons.io.FileUtils;
58

@@ -16,14 +19,12 @@ public final class YTDLPManager {
1619
private static final String YT_DLP_LINUX_DOWNLOAD_URL = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp";
1720
private static final String YT_DLP_WINDOWS_DOWNLOAD_URL = "https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe";
1821

19-
private static final YTDLPManager INSTANCE = new YTDLPManager();
20-
2122
/**
2223
* Get the version of yt-dlp
2324
*
2425
* @return an optional containing the version-string of yt-dlp (or empty iff not found)
2526
*/
26-
private synchronized Optional<String> getYTDLPVersion() {
27+
public static synchronized Optional<String> getYTDLPVersion() {
2728
try {
2829
Process exec = Runtime.getRuntime().exec("yt-dlp --version");
2930
return Optional.ofNullable(new BufferedReader(new InputStreamReader(exec.getInputStream())).readLine());
@@ -36,7 +37,7 @@ private synchronized Optional<String> getYTDLPVersion() {
3637
* Downloads the latest version of yt-dlp into the current working-directory.
3738
* Note: this will currently only work with windows and linux
3839
*/
39-
private synchronized void downloadYTDLP() {
40+
public static synchronized void downloadYTDLP() {
4041
String osName = System.getProperty("os.name").toLowerCase();
4142

4243
String downloadUrl;
@@ -61,11 +62,21 @@ private synchronized void downloadYTDLP() {
6162
}
6263

6364
/**
64-
* Get the default {@link YTDLPManager}
65-
* @return the default {@link YTDLPManager}
65+
* Load an url that is compatible with yt-dlp.
66+
* This will return a playlist if this is the case.
67+
* Otherwise, it will return a track.
68+
* @param url url of playlist or track
69+
* @return {@link YTDLPAudioPlaylist} if playlist and {@link YTDLPAudioTrack} otherwise
6670
*/
67-
public static YTDLPManager getDefault() {
68-
return YTDLPManager.INSTANCE;
71+
public static YTDLPAudioItem loadUrl(String url) {
72+
YTDLPAudioPlaylist playlist = new YTDLPAudioPlaylist(url);
73+
playlist.load();
74+
75+
if (playlist.getTracks().isEmpty()) {
76+
return new YTDLPAudioTrack(url);
77+
}
78+
79+
return playlist;
6980
}
7081

7182
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.shirkanesi.magmaplayer.ytdlp;
2+
3+
import com.shirkanesi.magmaplayer.AudioItem;
4+
5+
public interface YTDLPAudioItem extends AudioItem {
6+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package com.shirkanesi.magmaplayer.ytdlp;
2+
3+
import com.shirkanesi.magmaplayer.AbstractAudioPlaylist;
4+
import com.shirkanesi.magmaplayer.exception.AudioTrackPullException;
5+
6+
import java.io.BufferedReader;
7+
import java.io.IOException;
8+
import java.io.InputStreamReader;
9+
import java.util.ArrayList;
10+
import java.util.List;
11+
12+
public class YTDLPAudioPlaylist extends AbstractAudioPlaylist implements YTDLPAudioItem {
13+
14+
private static final String LOAD_PLAYLIST_COMMAND = "yt-dlp --flat-playlist --print \"%(url)s\"";
15+
16+
private final String url;
17+
18+
public YTDLPAudioPlaylist(String url) {
19+
this.url = url;
20+
}
21+
22+
@Override
23+
public void load() {
24+
try {
25+
List<String> urls = getPlaylistTracks();
26+
27+
for (String url : urls) {
28+
tracks.add(new YTDLPAudioTrack(url));
29+
}
30+
} catch (IOException e) {
31+
throw new AudioTrackPullException("Failed while loading playlist " + url, e);
32+
}
33+
}
34+
35+
private List<String> getPlaylistTracks() throws IOException {
36+
Process process = Runtime.getRuntime().exec(LOAD_PLAYLIST_COMMAND + " " + url);
37+
try {
38+
process.waitFor();
39+
} catch (InterruptedException e) {
40+
process.destroy();
41+
}
42+
43+
List<String> urls = new ArrayList<>();
44+
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
45+
String line;
46+
while ((line = bufferedReader.readLine()) != null) {
47+
if (line.startsWith("http")) {
48+
urls.add(line);
49+
}
50+
}
51+
}
52+
return urls;
53+
}
54+
55+
}

0 commit comments

Comments
 (0)