diff --git a/.classpath b/.classpath
index 571ccd1..6cf8f5a 100644
--- a/.classpath
+++ b/.classpath
@@ -24,8 +24,8 @@
-
-
-
+
+
+
diff --git a/src/commands/music/CommandMusicMain.java b/src/commands/music/CommandMusicMain.java
index 7176498..f9417b8 100644
--- a/src/commands/music/CommandMusicMain.java
+++ b/src/commands/music/CommandMusicMain.java
@@ -2,6 +2,7 @@ package commands.music;
import core.Command;
import core.LocStrings;
+import core.SubCommandFormattable;
import core.SubCommandFramework;
import dataStructures.*;
@@ -9,7 +10,7 @@ public class CommandMusicMain extends Command
{
SubCommandFramework framework = new SubCommandFramework();
public CommandMusicMain(KittyRole level, KittyRating rating)
- {
+ {
super(level, rating);
framework.addCommand("join", new SubCommandJoin(KittyRole.General, KittyRating.Safe));
framework.addCommand("leave", new SubCommandLeave(KittyRole.General, KittyRating.Safe));
@@ -22,6 +23,8 @@ public class CommandMusicMain extends Command
@Override
public void onRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input, Response res)
{
- framework.run(guild, channel, user, input).Call(res);
+ SubCommandFormattable scf = framework.run(guild, channel, user, input);
+ System.out.println("SCF: " + scf.resString);
+ scf.Call(res);
}
}
\ No newline at end of file
diff --git a/src/commands/music/SubCommandAddTrack.java b/src/commands/music/SubCommandAddTrack.java
index d8f7472..8ffef3f 100644
--- a/src/commands/music/SubCommandAddTrack.java
+++ b/src/commands/music/SubCommandAddTrack.java
@@ -25,8 +25,8 @@ public class SubCommandAddTrack extends SubCommand
//Get track from Youtube
String video = YT.getYT(input.args);
ac.loadAndPlay(video, guild);
+ System.out.println("Internal: " + ac.response);
- System.out.println(ac.response);
return new SubCommandFormattable(video);
}
}
\ No newline at end of file
diff --git a/src/main/Main.java b/src/main/Main.java
index 5f4beaa..463ad75 100644
--- a/src/main/Main.java
+++ b/src/main/Main.java
@@ -24,13 +24,14 @@ import dataStructures.Response;
import dataStructures.UserInput;
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
import net.dv8tion.jda.core.hooks.ListenerAdapter;
+import trash.MainFAKE;
import utils.GlobalLog;
// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation.
// This is the application entry point, and bot startup location!
@SuppressWarnings("unused")
-public class Main extends ListenerAdapter
+public class Main// extends ListenerAdapter
{
// Variables and bot specific objects
private static KittyCore kittyCore;
@@ -45,6 +46,9 @@ public class Main extends ListenerAdapter
// Initialization and setup
public static void main(String[] args) throws InterruptedException, LoginException, Exception
{
+ MainFAKE.mainFAKE(args);
+ }
+ /*
// Factory startup. The ordering is intentional.
GlobalLog.initialize();
databaseManager = ObjectBuilderFactory.constructDatabaseManager();
@@ -115,4 +119,5 @@ public class Main extends ListenerAdapter
if(!Superintendent.perCommandUpkeepPost(kittyCore, databaseManager))
return;
}
+ */
}
\ No newline at end of file
diff --git a/src/trash/AudioPlayerSendHandler.java b/src/trash/AudioPlayerSendHandler.java
new file mode 100644
index 0000000..daf7414
--- /dev/null
+++ b/src/trash/AudioPlayerSendHandler.java
@@ -0,0 +1,41 @@
+package trash;
+
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
+import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
+
+import net.dv8tion.jda.core.audio.AudioSendHandler;
+
+/**
+ * This is a wrapper around AudioPlayer which makes it behave as an AudioSendHandler for JDA. As JDA calls canProvide
+ * before every call to provide20MsAudio(), we pull the frame in canProvide() and use the frame we already pulled in
+ * provide20MsAudio().
+ */
+public class AudioPlayerSendHandler implements AudioSendHandler
+{
+ private final AudioPlayer audioPlayer;
+ private AudioFrame lastFrame;
+
+ public AudioPlayerSendHandler(AudioPlayer audioPlayer)
+ {
+ this.audioPlayer = audioPlayer;
+ }
+
+ @Override
+ public boolean canProvide()
+ {
+ lastFrame = audioPlayer.provide();
+ return lastFrame != null;
+ }
+
+ @Override
+ public byte[] provide20MsAudio()
+ {
+ return lastFrame.getData();
+ }
+
+ @Override
+ public boolean isOpus()
+ {
+ return true;
+ }
+}
\ No newline at end of file
diff --git a/src/trash/GuildMusicManager.java b/src/trash/GuildMusicManager.java
new file mode 100644
index 0000000..478a3b0
--- /dev/null
+++ b/src/trash/GuildMusicManager.java
@@ -0,0 +1,34 @@
+package trash;
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
+
+/**
+ * Holder for both the player and a track scheduler for one guild.
+ */
+public class GuildMusicManager {
+ /**
+ * Audio player for the guild.
+ */
+ public final AudioPlayer player;
+ /**
+ * Track scheduler for the player.
+ */
+ public final TrackScheduler scheduler;
+
+ /**
+ * Creates a player and a track scheduler.
+ * @param manager Audio player manager to use for creating the player.
+ */
+ public GuildMusicManager(AudioPlayerManager manager) {
+ player = manager.createPlayer();
+ scheduler = new TrackScheduler(player);
+ player.addListener(scheduler);
+ }
+
+ /**
+ * @return Wrapper around AudioPlayer to use it as an AudioSendHandler.
+ */
+ public AudioPlayerSendHandler getSendHandler() {
+ return new AudioPlayerSendHandler(player);
+ }
+}
\ No newline at end of file
diff --git a/src/trash/MainFAKE.java b/src/trash/MainFAKE.java
new file mode 100644
index 0000000..9b4f006
--- /dev/null
+++ b/src/trash/MainFAKE.java
@@ -0,0 +1,126 @@
+package trash;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
+import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
+import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
+import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
+import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
+import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
+
+import net.dv8tion.jda.core.AccountType;
+import net.dv8tion.jda.core.JDA;
+import net.dv8tion.jda.core.JDABuilder;
+import net.dv8tion.jda.core.entities.Guild;
+import net.dv8tion.jda.core.entities.TextChannel;
+import net.dv8tion.jda.core.entities.VoiceChannel;
+import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
+import net.dv8tion.jda.core.hooks.ListenerAdapter;
+import net.dv8tion.jda.core.managers.AudioManager;
+import offline.Ref;
+
+public class MainFAKE extends ListenerAdapter {
+ public static void mainFAKE(String[] args) throws Exception {
+ JDA bot = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
+ bot.addEventListener(new MainFAKE());
+ }
+
+ private final AudioPlayerManager playerManager;
+ private final Map musicManagers;
+
+ private MainFAKE() {
+ this.musicManagers = new HashMap<>();
+
+ this.playerManager = new DefaultAudioPlayerManager();
+ AudioSourceManagers.registerRemoteSources(playerManager);
+ AudioSourceManagers.registerLocalSource(playerManager);
+ }
+
+ private synchronized GuildMusicManager getGuildAudioPlayer(Guild guild) {
+ long guildId = Long.parseLong(guild.getId());
+ GuildMusicManager musicManager = musicManagers.get(guildId);
+
+ if (musicManager == null) {
+ musicManager = new GuildMusicManager(playerManager);
+ musicManagers.put(guildId, musicManager);
+ }
+
+ guild.getAudioManager().setSendingHandler(musicManager.getSendHandler());
+
+ return musicManager;
+ }
+
+ @Override
+ public void onGuildMessageReceived(GuildMessageReceivedEvent event) {
+ String[] command = event.getMessage().getContentRaw().split(" ", 2);
+
+ if ("!play".equals(command[0]) && command.length == 2) {
+ loadAndPlay(event.getChannel(), command[1]);
+ } else if ("!skip".equals(command[0])) {
+ skipTrack(event.getChannel());
+ }
+
+ super.onGuildMessageReceived(event);
+ }
+
+ private void loadAndPlay(final TextChannel channel, final String trackUrl) {
+ GuildMusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
+
+ playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler() {
+ @Override
+ public void trackLoaded(AudioTrack track) {
+ channel.sendMessage("Adding to queue " + track.getInfo().title).queue();
+
+ play(channel.getGuild(), musicManager, track);
+ }
+
+ @Override
+ public void playlistLoaded(AudioPlaylist playlist) {
+ AudioTrack firstTrack = playlist.getSelectedTrack();
+
+ if (firstTrack == null) {
+ firstTrack = playlist.getTracks().get(0);
+ }
+
+ channel.sendMessage("Adding to queue " + firstTrack.getInfo().title + " (first track of playlist " + playlist.getName() + ")").queue();
+
+ play(channel.getGuild(), musicManager, firstTrack);
+ }
+
+ @Override
+ public void noMatches() {
+ channel.sendMessage("Nothing found by " + trackUrl).queue();
+ }
+
+ @Override
+ public void loadFailed(FriendlyException exception) {
+ System.out.println(exception.getCause());
+ channel.sendMessage("Could not play: " + exception.getMessage()).queue();
+ }
+ });
+ }
+
+ private void play(Guild guild, GuildMusicManager musicManager, AudioTrack track) {
+ connectToFirstVoiceChannel(guild.getAudioManager());
+
+ musicManager.scheduler.queue(track);
+ }
+
+ private void skipTrack(TextChannel channel) {
+ GuildMusicManager musicManager = getGuildAudioPlayer(channel.getGuild());
+ musicManager.scheduler.nextTrack();
+
+ channel.sendMessage("Skipped to next track.").queue();
+ }
+
+ private static void connectToFirstVoiceChannel(AudioManager audioManager) {
+ if (!audioManager.isConnected() && !audioManager.isAttemptingToConnect()) {
+ for (VoiceChannel voiceChannel : audioManager.getGuild().getVoiceChannels()) {
+ audioManager.openAudioConnection(voiceChannel);
+ break;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/trash/TrackScheduler.java b/src/trash/TrackScheduler.java
new file mode 100644
index 0000000..b61b4e3
--- /dev/null
+++ b/src/trash/TrackScheduler.java
@@ -0,0 +1,55 @@
+package trash;
+import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
+import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
+import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
+import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
+
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+
+/**
+ * This class schedules tracks for the audio player. It contains the queue of tracks.
+ */
+public class TrackScheduler extends AudioEventAdapter {
+ private final AudioPlayer player;
+ private final BlockingQueue queue;
+
+ /**
+ * @param player The audio player this scheduler uses
+ */
+ public TrackScheduler(AudioPlayer player) {
+ this.player = player;
+ this.queue = new LinkedBlockingQueue<>();
+ }
+
+ /**
+ * Add the next track to queue or play right away if nothing is in the queue.
+ *
+ * @param track The track to play or add to queue.
+ */
+ public void queue(AudioTrack track) {
+ // Calling startTrack with the noInterrupt set to true will start the track only if nothing is currently playing. If
+ // something is playing, it returns false and does nothing. In that case the player was already playing so this
+ // track goes to the queue instead.
+ if (!player.startTrack(track, true)) {
+ queue.offer(track);
+ }
+ }
+
+ /**
+ * Start the next track, stopping the current one if it is playing.
+ */
+ public void nextTrack() {
+ // Start the next track, regardless of if something is already playing or not. In case queue was empty, we are
+ // giving null to startTrack, which is a valid argument and will simply stop the player.
+ player.startTrack(queue.poll(), false);
+ }
+
+ @Override
+ public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
+ // Only start the next track if the end reason is suitable for it (FINISHED or LOAD_FAILED)
+ if (endReason.mayStartNext) {
+ nextTrack();
+ }
+ }
+}
\ No newline at end of file