=Work on Music command
This commit is contained in:
Binary file not shown.
@@ -9,6 +9,7 @@ import dataStructures.KittyRole;
|
||||
import dataStructures.KittyUser;
|
||||
import dataStructures.UserInput;
|
||||
import network.NetworkYoutube;
|
||||
import utils.audio.AudioController;
|
||||
|
||||
public class SubCommandAddTrack extends SubCommand
|
||||
{
|
||||
@@ -16,12 +17,16 @@ public class SubCommandAddTrack extends SubCommand
|
||||
public SubCommandAddTrack(KittyRole level, KittyRating rating) { super(level, rating); }
|
||||
|
||||
NetworkYoutube YT = new NetworkYoutube();
|
||||
AudioController ac = new AudioController();
|
||||
|
||||
@Override
|
||||
public SubCommandFormattable OnRun(KittyGuild guild, KittyChannel channel, KittyUser user, UserInput input)
|
||||
{
|
||||
//Get track from Youtube
|
||||
String video = YT.getYT(input.args);
|
||||
ac.loadAndPlay(video, guild);
|
||||
|
||||
String response = YT.getYT(input.args);
|
||||
return new SubCommandFormattable(response);
|
||||
System.out.println(ac.response);
|
||||
return new SubCommandFormattable(video);
|
||||
}
|
||||
}
|
||||
@@ -20,10 +20,10 @@ import net.dv8tion.jda.core.entities.*;
|
||||
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
||||
import offline.Ref;
|
||||
import utils.AdminControl;
|
||||
import utils.AudioUtils;
|
||||
//import utils.AudioUtils;
|
||||
import utils.GlobalLog;
|
||||
import utils.LogFilter;
|
||||
import utils.audio.AudioUtils;
|
||||
|
||||
// NOTE(wisp): Isolated factory to assist with storage and caching if needed.
|
||||
// This also minimizes the number of places JDA interacts with our codebase.
|
||||
@@ -366,7 +366,8 @@ public class ObjectBuilderFactory
|
||||
{
|
||||
lazyInit();
|
||||
|
||||
kitty = new JDABuilder(AccountType.BOT).setToken(Ref.TestToken).buildBlocking();
|
||||
kitty = new JDABuilder(AccountType.BOT)
|
||||
.setToken(Ref.TestToken).buildBlocking();
|
||||
kitty.getPresence().setGame(Game.playing("with digital yarn"));
|
||||
kitty.addEventListener(new Main());
|
||||
|
||||
|
||||
@@ -2,10 +2,15 @@ package dataStructures;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
|
||||
import core.DatabaseManager;
|
||||
import core.DatabaseTrackedObject;
|
||||
import utils.AdminControl;
|
||||
import utils.AudioUtils;
|
||||
import utils.audio.AudioUtils;
|
||||
import utils.audio.GuildMusicManager;
|
||||
|
||||
// Context for a given guild for kittybot. Primarily designed to hold guild-specific settings.
|
||||
public class KittyGuild extends DatabaseTrackedObject
|
||||
@@ -23,6 +28,8 @@ public class KittyGuild extends DatabaseTrackedObject
|
||||
public ArrayList <KittyPoll> choices = new ArrayList<KittyPoll>();
|
||||
public AdminControl control;
|
||||
public AudioUtils audio;
|
||||
public GuildMusicManager musicManager;
|
||||
public AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
public ArrayList <KittyUser> raffleUsersUnchosen = new ArrayList<KittyUser>();
|
||||
public ArrayList <KittyUser> raffleUsersChosen = new ArrayList<KittyUser>();
|
||||
|
||||
@@ -45,10 +52,13 @@ public class KittyGuild extends DatabaseTrackedObject
|
||||
public KittyGuild(String uniqueID, AdminControl adminControl, ArrayList <String> emoji, AudioUtils audio)
|
||||
{
|
||||
super(uniqueID);
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
AudioSourceManagers.registerLocalSource(playerManager);
|
||||
this.uniqueID = uniqueID;
|
||||
roleList = new KittyTrackedVector(roleListName, uniqueID);
|
||||
beans = new KittyTrackedLong(beansName, uniqueID);
|
||||
registerTrackedObjects();
|
||||
musicManager = new GuildMusicManager(playerManager);
|
||||
|
||||
control = adminControl;
|
||||
this.contentRating = KittyRating.Safe;
|
||||
|
||||
+4
-3
@@ -4,6 +4,10 @@ import java.util.List;
|
||||
|
||||
import javax.security.auth.login.LoginException;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
|
||||
import core.CharacterManager;
|
||||
import core.CommandEnabler;
|
||||
import core.CommandManager;
|
||||
@@ -20,7 +24,6 @@ import dataStructures.Response;
|
||||
import dataStructures.UserInput;
|
||||
import net.dv8tion.jda.core.events.message.guild.GuildMessageReceivedEvent;
|
||||
import net.dv8tion.jda.core.hooks.ListenerAdapter;
|
||||
import utils.AudioController;
|
||||
import utils.GlobalLog;
|
||||
|
||||
// http://www.slf4j.org/ - this JDA logging tool has been disabled by specifying NOP implementation.
|
||||
@@ -37,7 +40,6 @@ public class Main extends ListenerAdapter
|
||||
private static RPManager rpManager;
|
||||
private static PluginManager pluginManager;
|
||||
private static CharacterManager charManager;
|
||||
private static AudioController audioControl;
|
||||
|
||||
|
||||
// Initialization and setup
|
||||
@@ -49,7 +51,6 @@ public class Main extends ListenerAdapter
|
||||
commandManager = ObjectBuilderFactory.constructCommandManager(CommandEnabler.instance); // TODO: Untangle this singleton
|
||||
stats = ObjectBuilderFactory.constructStats(commandManager);
|
||||
charManager = new CharacterManager();
|
||||
audioControl = new AudioController();
|
||||
rpManager = ObjectBuilderFactory.constructRPManager();
|
||||
pluginManager = ObjectBuilderFactory.constructPluginManager();
|
||||
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
package utils;
|
||||
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
|
||||
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
|
||||
|
||||
public class AudioController
|
||||
{
|
||||
public static AudioController instance;
|
||||
AudioPlayerManager playerManager = new DefaultAudioPlayerManager();
|
||||
|
||||
public AudioController ()
|
||||
{
|
||||
if(instance == null)
|
||||
{
|
||||
instance = this;
|
||||
}
|
||||
else
|
||||
{
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public AudioPlayer createPlayer()
|
||||
{
|
||||
return playerManager.createPlayer();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package utils.audio;
|
||||
|
||||
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 dataStructures.KittyGuild;
|
||||
|
||||
public class AudioController
|
||||
{
|
||||
private final AudioPlayerManager playerManager;
|
||||
public String response;
|
||||
|
||||
public AudioController()
|
||||
{
|
||||
playerManager = new DefaultAudioPlayerManager();
|
||||
AudioSourceManagers.registerRemoteSources(playerManager);
|
||||
AudioSourceManagers.registerLocalSource(playerManager);
|
||||
}
|
||||
|
||||
public void loadAndPlay(final String trackUrl, KittyGuild guild)
|
||||
{
|
||||
GuildMusicManager musicManager = guild.musicManager;
|
||||
response = "HERE";
|
||||
|
||||
playerManager.loadItemOrdered(musicManager, trackUrl, new AudioLoadResultHandler()
|
||||
{
|
||||
@Override
|
||||
public void trackLoaded(AudioTrack track)
|
||||
{
|
||||
response = "Adding to queue " + track.getInfo().title;
|
||||
System.out.println("QUEUED");
|
||||
play(musicManager, track);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playlistLoaded(AudioPlaylist playlist)
|
||||
{
|
||||
AudioTrack firstTrack = playlist.getSelectedTrack();
|
||||
|
||||
if (firstTrack == null)
|
||||
{
|
||||
firstTrack = playlist.getTracks().get(0);
|
||||
}
|
||||
|
||||
response = "Adding to queue " + firstTrack.getInfo().title + " (first track of playlist " + playlist.getName() + ")";
|
||||
|
||||
play(musicManager, firstTrack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void noMatches()
|
||||
{
|
||||
System.out.println("NOT QUEUED");
|
||||
response = "Nothing found by " + trackUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadFailed(FriendlyException exception)
|
||||
{
|
||||
System.out.println("EXCEPTION");
|
||||
System.out.println(exception.getCause());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void play(GuildMusicManager musicManager, AudioTrack track)
|
||||
{
|
||||
|
||||
musicManager.scheduler.queue(track);
|
||||
}
|
||||
|
||||
private void skipTrack(KittyGuild guild)
|
||||
{
|
||||
GuildMusicManager musicManager = guild.musicManager;
|
||||
musicManager.scheduler.nextTrack();
|
||||
|
||||
response = "Skipped to next track.";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
package utils.audio;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,4 @@
|
||||
package utils;
|
||||
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
|
||||
|
||||
package utils.audio;
|
||||
import net.dv8tion.jda.core.entities.Guild;
|
||||
import net.dv8tion.jda.core.entities.VoiceChannel;
|
||||
import net.dv8tion.jda.core.managers.AudioManager;
|
||||
@@ -9,14 +7,12 @@ public class AudioUtils
|
||||
{
|
||||
private Guild guild;
|
||||
public AudioManager audio;
|
||||
public final AudioPlayer player;
|
||||
|
||||
|
||||
public AudioUtils(Guild guild)
|
||||
{
|
||||
this.guild = guild;
|
||||
audio = guild.getAudioManager();
|
||||
player = AudioController.instance.createPlayer();
|
||||
}
|
||||
|
||||
public boolean joinChannel(String channelName)
|
||||
@@ -0,0 +1,36 @@
|
||||
package utils.audio;
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package utils.audio;
|
||||
|
||||
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<AudioTrack> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user