Mega-refactor: change song to track everywhere.

master
Nekojimi 6 months ago
parent abfab9a18d
commit 2a25e1368d
  1. 72
      pom.xml.orig
  2. 60
      src/main/java/moe/nekojimi/chords/Chords.java
  3. 94
      src/main/java/moe/nekojimi/chords/Downloader.java
  4. 44
      src/main/java/moe/nekojimi/chords/MusicHandler.java
  5. 42
      src/main/java/moe/nekojimi/chords/Playlist.java
  6. 48
      src/main/java/moe/nekojimi/chords/QueueManager.java
  7. 28
      src/main/java/moe/nekojimi/chords/Track.java
  8. 4
      src/main/java/moe/nekojimi/chords/TrackPlayer.java
  9. 35
      src/main/java/moe/nekojimi/chords/TrackRequest.java
  10. 8
      src/main/java/moe/nekojimi/chords/commands/HelpCommand.java
  11. 8
      src/main/java/moe/nekojimi/chords/commands/PlayCommand.java
  12. 20
      src/main/java/moe/nekojimi/chords/commands/QueueCommand.java
  13. 6
      src/main/java/moe/nekojimi/chords/commands/RemoveCommand.java
  14. 4
      src/main/java/moe/nekojimi/chords/commands/RestartCommand.java
  15. 6
      src/main/java/moe/nekojimi/chords/commands/SkipCommand.java

@ -0,0 +1,72 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>moe.nekojimi</groupId>
<artifactId>Chords</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<repositories>
<repository>
<id>dv8tion</id>
<name>m2-dv8tion</name>
<url>https://m2.dv8tion.net/releases</url>
</repository>
</repositories>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>
moe.nekojimi.chords.Chords
</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>net.dv8tion</groupId>
<artifactId>JDA</artifactId>
<<<<<<< HEAD
<version>5.0.0-beta.5</version>
=======
<version>5.0.0-beta.6</version>
>>>>>>> b24453d (Update JDA to v5.0.)
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>moe.nekojimi</groupId>
<artifactId>MusicSearcher</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.1.4</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.beust</groupId>
<artifactId>jcommander</artifactId>
<version>1.78</version>
</dependency>
</dependencies>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
</properties>
</project>

@ -128,9 +128,9 @@ public final class Chords extends ListenerAdapter
JDA jda = builder.build(); JDA jda = builder.build();
listener.setJda(jda); listener.setJda(jda);
} }
private final Consumer<Song> nowPlayingConsumer = new NowPlayingConsumer(); private final Consumer<Track> nowPlayingConsumer = new NowPlayingConsumer();
private final BiConsumer<SongRequest, Exception> downloaderMessageHandler = new DownloaderMessageHandler(); private final BiConsumer<TrackRequest, Exception> downloaderMessageHandler = new DownloaderMessageHandler();
public Chords() throws IOException public Chords() throws IOException
{ {
@ -253,12 +253,12 @@ public final class Chords extends ListenerAdapter
} }
} }
public void queueDownload(SongRequest request) public void queueDownload(TrackRequest request)
{ {
// Song song; // Track track;
// if (request.getUrl() != null) // if (request.getUrl() != null)
// { // {
// song = new Song(request.getUrl()); // track = new Track(request.getUrl());
// } else // } else
// { // {
// // interpret search result // // interpret search result
@ -268,15 +268,15 @@ public final class Chords extends ListenerAdapter
// { // {
// //
// } // }
// song.setNumber(trackNumber); // track.setNumber(trackNumber);
// trackNumber++; // trackNumber++;
// request.addSong(song); // request.addTrack(track);
request.getInvocation().respond("Request pending..."); request.getInvocation().respond("Request pending...");
downloader.accept(new Downloader.DownloadTask(request, queueManager)); downloader.accept(new Downloader.DownloadTask(request, queueManager));
// return song; // return track;
} }
public void setStatus(Song nowPlaying) public void setStatus(Track nowPlaying)
{ {
jda.getPresence().setActivity(Activity.listening(nowPlaying.toString())); jda.getPresence().setActivity(Activity.listening(nowPlaying.toString()));
} }
@ -396,7 +396,7 @@ public final class Chords extends ListenerAdapter
return settings; return settings;
} }
private class DownloaderMessageHandler implements BiConsumer<SongRequest, Exception> private class DownloaderMessageHandler implements BiConsumer<TrackRequest, Exception>
{ {
private static final String PROGRESS_SYMBOLS = " ▏▎▍▌▋▊▉█"; private static final String PROGRESS_SYMBOLS = " ▏▎▍▌▋▊▉█";
@ -407,23 +407,23 @@ public final class Chords extends ListenerAdapter
} }
@Override @Override
public void accept(SongRequest request, Exception ex) public void accept(TrackRequest request, Exception ex)
{ {
String response = ""; String response = "";
if (request.getSongs().size() > 1) if (request.getTracks().size() > 1)
response += "Downloading " + request.getSongs().size() + " tracks:\n"; response += "Downloading " + request.getTracks().size() + " tracks:\n";
for (Song song : request.getSongs()) for (Track track : request.getTracks())
{ {
// TextChannel channel = jda.getTextChannelById(song.getRequestedIn()); // TextChannel channel = jda.getTextChannelById(track.getRequestedIn());
// String bracketNo = "[" + song.getNumber() + "] "; // String bracketNo = "[" + track.getNumber() + "] ";
if (ex == null) if (ex == null)
if (song.getLocation() != null && song.getProgress() >= 100) if (track.getLocation() != null && track.getProgress() >= 100)
{ {
response += ("Finished downloading " + song + ", added to queue!"); response += ("Finished downloading " + track + "!");
log("DOWN", "Downloaded " + song); log("DOWN", "Downloaded " + track);
} else } else
{ {
Format format = song.getBestFormat(); Format format = track.getBestFormat();
String formatDetails = ""; String formatDetails = "";
if (format != null) if (format != null)
{ {
@ -435,16 +435,16 @@ public final class Chords extends ListenerAdapter
} }
String progressDetails = ""; String progressDetails = "";
if (song.getProgress() >= 0) if (track.getProgress() >= 0)
progressDetails = " [" + String.format("%.1f", song.getProgress()) + "%]"; progressDetails = " [" + String.format("%.1f", track.getProgress()) + "%]";
response += ("Now downloading " + song + formatDetails + progressDetails + " ..."); response += ("Now downloading " + track + formatDetails + progressDetails + " ...");
log("DOWN", "Downloading " + song + "..."); log("DOWN", "Downloading " + track + "...");
} }
else else
{ {
response += ("Failed to download " + song + "! Reason: " + ex.getMessage()); response += ("Failed to download " + track + "! Reason: " + ex.getMessage());
log("DOWN", "Failed to download " + song + "! Reason: " + ex.getMessage()); log("DOWN", "Failed to download " + track + "! Reason: " + ex.getMessage());
} }
response += "\n"; response += "\n";
} }
@ -453,7 +453,7 @@ public final class Chords extends ListenerAdapter
} }
} }
private class NowPlayingConsumer implements Consumer<Song> private class NowPlayingConsumer implements Consumer<Track>
{ {
public NowPlayingConsumer() public NowPlayingConsumer()
@ -461,10 +461,10 @@ public final class Chords extends ListenerAdapter
} }
@Override @Override
public void accept(Song song) public void accept(Track track)
{ {
if (song != null) if (track != null)
jda.getPresence().setActivity(Activity.of(Activity.ActivityType.LISTENING, song.toString())); jda.getPresence().setActivity(Activity.of(Activity.ActivityType.LISTENING, track.toString()));
else else
jda.getPresence().setActivity(null); jda.getPresence().setActivity(null);
} }

@ -49,8 +49,8 @@ public class Downloader implements Consumer<DownloadTask>
private final LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>(); private final LinkedBlockingDeque<Runnable> workQueue = new LinkedBlockingDeque<>();
private final ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 30, TimeUnit.SECONDS, workQueue); private final ThreadPoolExecutor executor = new ThreadPoolExecutor(2, 4, 30, TimeUnit.SECONDS, workQueue);
private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1); private final ScheduledExecutorService scheduler = new ScheduledThreadPoolExecutor(1);
// private Consumer<Song> next; // private Consumer<Track> next;
private BiConsumer<SongRequest, Exception> messageHandler; private BiConsumer<TrackRequest, Exception> messageHandler;
private File downloadDir = null; private File downloadDir = null;
@ -64,11 +64,11 @@ public class Downloader implements Consumer<DownloadTask>
@Override @Override
public void accept(DownloadTask task) public void accept(DownloadTask task)
{ {
// if all songs of the request are already downloaded, just skip // if all tracks of the request are already downloaded, just skip
if (!task.request.getSongs().isEmpty() && task.request.getSongs().stream().allMatch((t) -> t.isDownloaded())) if (!task.request.getTracks().isEmpty() && task.request.getTracks().stream().allMatch((t) -> t.isDownloaded()))
{ {
for (Song song : task.request.getSongs()) for (Track track : task.request.getTracks())
task.getDestination().accept(song); task.getDestination().accept(track);
return; return;
} }
@ -79,7 +79,7 @@ public class Downloader implements Consumer<DownloadTask>
{ {
try try
{ {
// getFormats(song); // getFormats(track);
download(task); download(task);
} catch (Exception ex) } catch (Exception ex)
{ {
@ -129,13 +129,13 @@ public class Downloader implements Consumer<DownloadTask>
return formats; return formats;
} }
private void getFormats(Song song) private void getFormats(Track track)
{ {
if (!song.getFormats().isEmpty()) if (!track.getFormats().isEmpty())
return; return;
try try
{ {
String cmd = Chords.getSettings().getYtdlCommand() + " --skip-download -F " + song.getUrl().toString(); String cmd = Chords.getSettings().getYtdlCommand() + " --skip-download -F " + track.getUrl().toString();
Process exec = runCommand(cmd, FORMAT_TIMEOUT); Process exec = runCommand(cmd, FORMAT_TIMEOUT);
InputStream input = exec.getInputStream(); InputStream input = exec.getInputStream();
String output = new String(input.readAllBytes(), Charset.defaultCharset()); String output = new String(input.readAllBytes(), Charset.defaultCharset());
@ -195,7 +195,7 @@ public class Downloader implements Consumer<DownloadTask>
format.setSampleRate(Util.parseSampleRate(split[bitrateCol])); format.setSampleRate(Util.parseSampleRate(split[bitrateCol]));
formats.add(format); formats.add(format);
} }
song.setFormats(formats); track.setFormats(formats);
} catch (Exception ex) } catch (Exception ex)
{ {
@ -204,31 +204,31 @@ public class Downloader implements Consumer<DownloadTask>
} }
} }
private List<Song> getInfo(SongRequest request) private List<Track> getInfo(TrackRequest request)
{ {
List<Song> ret = new ArrayList<>(); List<Track> ret = new ArrayList<>();
try try
{ {
String cmd = Chords.getSettings().getYtdlCommand() + " --skip-download --print-json " + request.getUrl().toString(); String cmd = Chords.getSettings().getYtdlCommand() + " --skip-download --print-json " + request.getUrl().toString();
Process exec = runCommand(cmd, INFO_TIMEOUT); Process exec = runCommand(cmd, INFO_TIMEOUT);
InputStream input = exec.getInputStream(); InputStream input = exec.getInputStream();
// read each line as JSON, turn each into a song object // read each line as JSON, turn each into a track object
Scanner sc = new Scanner(input); Scanner sc = new Scanner(input);
while (sc.hasNextLine()) while (sc.hasNextLine())
{ {
Song song = new Song(request.getUrl()); Track track = new Track(request.getUrl());
song.setNumber(trackNumber); track.setNumber(trackNumber);
trackNumber++; trackNumber++;
request.addSong(song); request.addTrack(track);
String line = sc.nextLine(); String line = sc.nextLine();
JsonReader reader = Json.createReader(new StringReader(line)); JsonReader reader = Json.createReader(new StringReader(line));
JsonObject object = reader.readObject(); JsonObject object = reader.readObject();
if (song.getTitle() == null) if (track.getTitle() == null)
song.setTitle(object.getString("title", null)); track.setTitle(object.getString("title", null));
if (song.getArtist() == null) if (track.getArtist() == null)
song.setArtist(object.getString("uploader", null)); track.setArtist(object.getString("uploader", null));
JsonArray formatsJSON = object.getJsonArray("formats"); JsonArray formatsJSON = object.getJsonArray("formats");
if (formatsJSON != null) if (formatsJSON != null)
@ -240,10 +240,10 @@ public class Downloader implements Consumer<DownloadTask>
if (format != null) if (format != null)
formats.add(format); formats.add(format);
} }
song.setFormats(formats); track.setFormats(formats);
} }
ret.add(song); ret.add(track);
} }
} catch (Exception ex) } catch (Exception ex)
{ {
@ -259,25 +259,25 @@ public class Downloader implements Consumer<DownloadTask>
return downloadDir; return downloadDir;
} }
private Song getSongFromRequest(SongRequest request, int idx) private Track getTrackFromRequest(TrackRequest request, int idx)
{ {
// if there's less songs in the request than expected, fill the array // if there's less tracks in the request than expected, fill the array
while (idx >= request.getSongs().size()) while (idx >= request.getTracks().size())
{ {
Song song = new Song(request.getUrl()); Track track = new Track(request.getUrl());
song.setNumber(trackNumber); track.setNumber(trackNumber);
trackNumber++; trackNumber++;
request.addSong(song); request.addTrack(track);
} }
return request.getSongs().get(idx); return request.getTracks().get(idx);
} }
private void download(DownloadTask task) private void download(DownloadTask task)
{ {
Set<Format> uniqueFormats = new HashSet<>(); Set<Format> uniqueFormats = new HashSet<>();
for (Song song : task.request.getSongs()) for (Track track : task.request.getTracks())
{ {
uniqueFormats.addAll(song.getFormats()); uniqueFormats.addAll(track.getFormats());
} }
List<Format> sortedFormats = sortFormats(uniqueFormats); List<Format> sortedFormats = sortFormats(uniqueFormats);
@ -313,7 +313,7 @@ public class Downloader implements Consumer<DownloadTask>
if (itemMatcher.find()) if (itemMatcher.find())
{ {
int idx = Integer.parseInt(itemMatcher.group(1)) - 1; int idx = Integer.parseInt(itemMatcher.group(1)) - 1;
int total = Integer.parseInt(cmd); // int total = Integer.parseInt(itemMatcher.group(2));
downloadIdx = idx; downloadIdx = idx;
} }
@ -321,20 +321,24 @@ public class Downloader implements Consumer<DownloadTask>
Matcher progMatcher = PROGRESS_PATTERN.matcher(line); Matcher progMatcher = PROGRESS_PATTERN.matcher(line);
if (progMatcher.find()) if (progMatcher.find())
{ {
getSongFromRequest(task.request, downloadIdx).setProgress(Double.parseDouble(progMatcher.group(1))); getTrackFromRequest(task.request, downloadIdx).setProgress(Double.parseDouble(progMatcher.group(1)));
messageHandler.accept(task.request, null); messageHandler.accept(task.request, null);
} }
Matcher destMatcher = DESTINATION_PATTERN.matcher(line); Matcher destMatcher = DESTINATION_PATTERN.matcher(line);
if (destMatcher.find()) if (destMatcher.find())
{ {
Song song = getSongFromRequest(task.request, downloadIdx); Track track = getTrackFromRequest(task.request, downloadIdx);
song.setLocation(new File(destMatcher.group(1))); track.setLocation(new File(destMatcher.group(1)));
// this is currently our criteria for completion; submit the song and move on // this is currently our criteria for completion; submit the track and move on
if (task.getDestination() != null) if (task.getDestination() != null)
task.getDestination().accept(song); task.getDestination().accept(track);
track.setProgress(100.0);
messageHandler.accept(task.request, null);
downloadIdx++; downloadIdx++;
} }
@ -383,12 +387,12 @@ public class Downloader implements Consumer<DownloadTask>
return exec; return exec;
} }
public BiConsumer<SongRequest, Exception> getMessageHandler() public BiConsumer<TrackRequest, Exception> getMessageHandler()
{ {
return messageHandler; return messageHandler;
} }
public void setMessageHandler(BiConsumer<SongRequest, Exception> messageHandler) public void setMessageHandler(BiConsumer<TrackRequest, Exception> messageHandler)
{ {
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
} }
@ -401,21 +405,21 @@ public class Downloader implements Consumer<DownloadTask>
public static class DownloadTask public static class DownloadTask
{ {
private final SongRequest request; private final TrackRequest request;
private final Consumer<Song> destination; private final Consumer<Track> destination;
public DownloadTask(SongRequest request, Consumer<Song> destination) public DownloadTask(TrackRequest request, Consumer<Track> destination)
{ {
this.request = request; this.request = request;
this.destination = destination; this.destination = destination;
} }
public SongRequest getSong() public TrackRequest getTrack()
{ {
return request; return request;
} }
public Consumer<Song> getDestination() public Consumer<Track> getDestination()
{ {
return destination; return destination;
} }

@ -23,21 +23,21 @@ public class MusicHandler implements AudioSendHandler, Closeable
{ {
private QueueManager queueManager; private QueueManager queueManager;
// private final LinkedList<Song> songQueue = new LinkedList<>(); // private final LinkedList<Track> trackQueue = new LinkedList<>();
// private final Queue<byte[]> queue = new ConcurrentLinkedQueue<>(); // private final Queue<byte[]> queue = new ConcurrentLinkedQueue<>();
// private final CircularByteBuffer audioBuffer = new CircularByteBuffer(3840 * 1024); // private final CircularByteBuffer audioBuffer = new CircularByteBuffer(3840 * 1024);
private boolean shouldPlay = true; private boolean shouldPlay = true;
private int byteCount; private int byteCount;
private boolean arrayErr = false; private boolean arrayErr = false;
private Consumer<Song> nowPlayingConsumer; private Consumer<Track> nowPlayingConsumer;
public void setNowPlayingConsumer(Consumer<Song> nowPlayingConsumer) public void setNowPlayingConsumer(Consumer<Track> nowPlayingConsumer)
{ {
this.nowPlayingConsumer = nowPlayingConsumer; this.nowPlayingConsumer = nowPlayingConsumer;
} }
private Song currentSong; private Track currentTrack;
// private TrackPlayer player; // private TrackPlayer player;
private final List<TrackPlayer> playingTracks = new ArrayList<>(); private final List<TrackPlayer> playingTracks = new ArrayList<>();
@ -66,21 +66,21 @@ public class MusicHandler implements AudioSendHandler, Closeable
public void playNext() public void playNext()
{ {
nextSong(true); nextTrack(true);
} }
public void playOver(Song song) public void playOver(Track track)
{ {
} }
private boolean nextSong() private boolean nextTrack()
{ {
return nextSong(false); return nextTrack(false);
} }
public boolean nextSong(boolean immediate) public boolean nextTrack(boolean immediate)
{ {
if (immediate) if (immediate)
{ {
@ -90,25 +90,25 @@ public class MusicHandler implements AudioSendHandler, Closeable
try try
{ {
if (currentSong != null) if (currentTrack != null)
{ {
if (!currentSong.isKept()) if (!currentTrack.isKept())
currentSong.delete(); currentTrack.delete();
currentSong = null; currentTrack = null;
} }
currentSong = queueManager.nextSongNeeded(); currentTrack = queueManager.nextTrackNeeded();
if (nowPlayingConsumer != null) if (nowPlayingConsumer != null)
nowPlayingConsumer.accept(currentSong); nowPlayingConsumer.accept(currentTrack);
if (currentSong == null) if (currentTrack == null)
{ {
System.out.println("End of queue."); System.out.println("End of queue.");
debugOut.flush(); debugOut.flush();
return false; return false;
} }
System.out.println("Playing song " + currentSong.getLocation().getAbsolutePath()); System.out.println("Playing track " + currentTrack.getLocation().getAbsolutePath());
arrayErr = false; arrayErr = false;
byteCount = 3840; byteCount = 3840;
TrackPlayer player = new TrackPlayer(currentSong); TrackPlayer player = new TrackPlayer(currentTrack);
playingTracks.add(player); playingTracks.add(player);
// System.out.println("Queue filled to " + audioBuffer.getCurrentNumberOfBytes()); // System.out.println("Queue filled to " + audioBuffer.getCurrentNumberOfBytes());
return true; return true;
@ -134,7 +134,7 @@ public class MusicHandler implements AudioSendHandler, Closeable
public void setShouldPlay(boolean shouldPlay) public void setShouldPlay(boolean shouldPlay)
{ {
if (!this.shouldPlay && shouldPlay) if (!this.shouldPlay && shouldPlay)
nextSong(); nextTrack();
this.shouldPlay = shouldPlay; this.shouldPlay = shouldPlay;
} }
@ -181,7 +181,7 @@ public class MusicHandler implements AudioSendHandler, Closeable
ret.put(mixBuffers(mixes)); ret.put(mixBuffers(mixes));
if (outOfInput) if (outOfInput)
{ {
boolean foundNext = nextSong(); boolean foundNext = nextTrack();
if (!foundNext) if (!foundNext)
break; break;
} }
@ -194,9 +194,9 @@ public class MusicHandler implements AudioSendHandler, Closeable
} }
public Song getCurrentSong() public Track getCurrentTrack()
{ {
return currentSong; return currentTrack;
} }
@Override @Override

@ -30,14 +30,14 @@ import java.util.logging.Logger;
* *
* @author jimj316 * @author jimj316
*/ */
public class Playlist implements Consumer<Song> public class Playlist implements Consumer<Track>
{ {
private static final int SHUFFLE_DONT_REPEAT_LAST = 3; private static final int SHUFFLE_DONT_REPEAT_LAST = 3;
private final String name; private final String name;
private final List<Song> songs = new ArrayList<>(); private final List<Track> tracks = new ArrayList<>();
private final LinkedList<Song> playHistory = new LinkedList<>(); private final LinkedList<Track> playHistory = new LinkedList<>();
public Playlist(String name) public Playlist(String name)
{ {
@ -46,25 +46,25 @@ public class Playlist implements Consumer<Song>
public YamlMapping toYaml() public YamlMapping toYaml()
{ {
YamlSequenceBuilder songList = Yaml.createYamlSequenceBuilder(); YamlSequenceBuilder trackList = Yaml.createYamlSequenceBuilder();
for (Song song : songs) for (Track track : tracks)
songList = songList.add(song.toYaml()); trackList = trackList.add(track.toYaml());
return Yaml.createYamlMappingBuilder() return Yaml.createYamlMappingBuilder()
.add("name", name) .add("name", name)
.add("songs", songList.build()) .add("tracks", trackList.build())
.build(); .build();
} }
public static Playlist fromYaml(YamlMapping yaml) public static Playlist fromYaml(YamlMapping yaml)
{ {
Playlist ret = new Playlist(yaml.string("name")); Playlist ret = new Playlist(yaml.string("name"));
YamlSequence songList = yaml.value("songs").asSequence(); YamlSequence trackList = yaml.value("tracks").asSequence();
for (int i = 0; i < songList.size(); i++) for (int i = 0; i < trackList.size(); i++)
{ {
try try
{ {
ret.addSong(Song.fromYaml(songList.yamlMapping(i))); ret.addTrack(Track.fromYaml(trackList.yamlMapping(i)));
} catch (MalformedURLException ex) } catch (MalformedURLException ex)
{ {
Logger.getLogger(Playlist.class.getName()).log(Level.SEVERE, null, ex); Logger.getLogger(Playlist.class.getName()).log(Level.SEVERE, null, ex);
@ -73,10 +73,10 @@ public class Playlist implements Consumer<Song>
return ret; return ret;
} }
public void addSong(Song song) public void addTrack(Track track)
{ {
song.setKept(true); track.setKept(true);
songs.add(song); tracks.add(track);
} }
public String getName() public String getName()
@ -84,17 +84,17 @@ public class Playlist implements Consumer<Song>
return name; return name;
} }
public List<Song> getSongs() public List<Track> getTracks()
{ {
return songs; return tracks;
} }
public Song getNextSong() public Track getNextTrack()
{ {
Song ret; Track ret;
// copy the song list // copy the track list
List<Song> toShuffle = new LinkedList<>(songs); List<Track> toShuffle = new LinkedList<>(tracks);
// remove play history from candidates, latest first, unless we'd have less than 2 options // remove play history from candidates, latest first, unless we'd have less than 2 options
for (int i = playHistory.size() - 1; i >= 0; i--) for (int i = playHistory.size() - 1; i >= 0; i--)
@ -114,9 +114,9 @@ public class Playlist implements Consumer<Song>
} }
@Override @Override
public void accept(Song t) public void accept(Track t)
{ {
addSong(t); addTrack(t);
} }
} }

@ -26,11 +26,11 @@ import java.util.function.Consumer;
* *
* @author jimj316 * @author jimj316
*/ */
public class QueueManager implements Consumer<Song> public class QueueManager implements Consumer<Track>
{ {
private Song restartingSong = null; private Track restartingTrack = null;
private final PriorityQueue<Song> jukeboxQueue = new PriorityQueue<>(); private final PriorityQueue<Track> jukeboxQueue = new PriorityQueue<>();
private Playlist playlist; private Playlist playlist;
private MusicHandler handler; private MusicHandler handler;
@ -40,30 +40,30 @@ public class QueueManager implements Consumer<Song>
} }
@Override @Override
public void accept(Song t) public void accept(Track t)
{ {
jukeboxQueue.add(t); jukeboxQueue.add(t);
if (!handler.isPlaying() || handler.getCurrentSong() == null) if (!handler.isPlaying() || handler.getCurrentTrack() == null)
handler.playNext(); handler.playNext();
if (handler.isPlaying() != (handler.getCurrentSong() == null)) if (handler.isPlaying() != (handler.getCurrentTrack() == null))
System.err.println("WARNING: handler isPlaying violates contract! Something dumb going on!"); System.err.println("WARNING: handler isPlaying violates contract! Something dumb going on!");
} }
/** /**
* Called by the music handler when the current song has ended, or if * Called by the music handler when the current track has ended, or if
* playNext is called with nothing playing. * playNext is called with nothing playing.
* *
* @return the next track to play, or null to stop playing. * @return the next track to play, or null to stop playing.
*/ */
public Song nextSongNeeded() public Track nextTrackNeeded()
{ {
// if we're restarting the current song: store, clear, and return it // if we're restarting the current track: store, clear, and return it
if (restartingSong != null) if (restartingTrack != null)
{ {
Song ret = restartingSong; Track ret = restartingTrack;
restartingSong = null; restartingTrack = null;
return ret; return ret;
} }
// if there's anything in the queue, play that first // if there's anything in the queue, play that first
@ -74,7 +74,7 @@ public class QueueManager implements Consumer<Song>
// otherwise if there's a playlist, shuffle from that // otherwise if there's a playlist, shuffle from that
else if (playlist != null) else if (playlist != null)
{ {
return playlist.getNextSong(); return playlist.getNextTrack();
} }
// otherwise stop playing // otherwise stop playing
else else
@ -86,27 +86,27 @@ public class QueueManager implements Consumer<Song>
return handler; return handler;
} }
public void addSong(Song song) public void addTrack(Track track)
{ {
System.out.println("Song added to queue: " + song.getLocation().getAbsolutePath()); System.out.println("Track added to queue: " + track.getLocation().getAbsolutePath());
jukeboxQueue.add(song); jukeboxQueue.add(track);
} }
public boolean removeSong(int i) public boolean removeTrack(int i)
{ {
try try
{ {
return jukeboxQueue.remove((Song) jukeboxQueue.toArray()[i]); return jukeboxQueue.remove((Track) jukeboxQueue.toArray()[i]);
} catch (ArrayIndexOutOfBoundsException ex) } catch (ArrayIndexOutOfBoundsException ex)
{ {
return false; return false;
} }
} }
public boolean removeSong(Song song) public boolean removeTrack(Track track)
{ {
return jukeboxQueue.remove(song); return jukeboxQueue.remove(track);
} }
public void setHandler(MusicHandler handler) public void setHandler(MusicHandler handler)
@ -115,7 +115,7 @@ public class QueueManager implements Consumer<Song>
handler.setQueueManager(this); handler.setQueueManager(this);
} }
public Queue<Song> getJukeboxQueue() public Queue<Track> getJukeboxQueue()
{ {
return jukeboxQueue; return jukeboxQueue;
} }
@ -130,10 +130,10 @@ public class QueueManager implements Consumer<Song>
this.playlist = playlist; this.playlist = playlist;
} }
public boolean restartSong() public boolean restartTrack()
{ {
restartingSong = handler.getCurrentSong(); restartingTrack = handler.getCurrentTrack();
if (restartingSong != null) if (restartingTrack != null)
{ {
handler.playNext(); handler.playNext();
return true; return true;

@ -19,7 +19,7 @@ import java.util.List;
* *
* @author jimj316 * @author jimj316
*/ */
public class Song implements Comparable<Song> public class Track implements Comparable<Track>
{ {
private String title; private String title;
private String artist; private String artist;
@ -33,7 +33,7 @@ public class Song implements Comparable<Song>
private double progress = -1; private double progress = -1;
private double eta = -1; private double eta = -1;
public Song(URL url) public Track(URL url)
{ {
this.url = url; this.url = url;
} }
@ -57,24 +57,24 @@ public class Song implements Comparable<Song>
.build(); .build();
} }
public static Song fromYaml(YamlMapping map) throws MalformedURLException public static Track fromYaml(YamlMapping map) throws MalformedURLException
{ {
Song song = new Song(new URL(map.string("url"))); Track track = new Track(new URL(map.string("url")));
song.setArtist(map.string("artist")); track.setArtist(map.string("artist"));
song.setTitle(map.string("title")); track.setTitle(map.string("title"));
song.setLocation(new File(map.string("location"))); track.setLocation(new File(map.string("location")));
song.setNumber(map.integer("num")); track.setNumber(map.integer("num"));
song.setKept(Boolean.parseBoolean(map.string("kept"))); track.setKept(Boolean.parseBoolean(map.string("kept")));
// song.setRequestedBy(map.string("requestedBy")); // track.setRequestedBy(map.string("requestedBy"));
// song.setRequestedIn(map.string("requestedIn")); // track.setRequestedIn(map.string("requestedIn"));
List<Format> formats = new ArrayList<>(); List<Format> formats = new ArrayList<>();
YamlSequence formatSeq = map.yamlSequence("formats"); YamlSequence formatSeq = map.yamlSequence("formats");
for (int i = 0; i < formats.size(); i++) for (int i = 0; i < formats.size(); i++)
formats.add(Format.fromYaml(formatSeq.yamlMapping(i))); formats.add(Format.fromYaml(formatSeq.yamlMapping(i)));
song.setFormats(formats); track.setFormats(formats);
return song; return track;
} }
public boolean isDownloaded() public boolean isDownloaded()
@ -199,7 +199,7 @@ public class Song implements Comparable<Song>
} }
@Override @Override
public int compareTo(Song o) public int compareTo(Track o)
{ {
return Integer.compare(number, o.number); return Integer.compare(number, o.number);
} }

@ -31,9 +31,9 @@ public class TrackPlayer implements Closeable
private boolean arrayErr = false; // supresses ArrayIndexOutOfBoundsException after the first time, to prevent spam private boolean arrayErr = false; // supresses ArrayIndexOutOfBoundsException after the first time, to prevent spam
public TrackPlayer(Song song) throws UnsupportedAudioFileException, IOException public TrackPlayer(Track track) throws UnsupportedAudioFileException, IOException
{ {
AudioInputStream in = AudioSystem.getAudioInputStream(song.getLocation()); AudioInputStream in = AudioSystem.getAudioInputStream(track.getLocation());
AudioFormat decodedFormat = AudioSendHandler.INPUT_FORMAT; AudioFormat decodedFormat = AudioSendHandler.INPUT_FORMAT;
input = AudioSystem.getAudioInputStream(decodedFormat, in); input = AudioSystem.getAudioInputStream(decodedFormat, in);
fillBuffer(false); fillBuffer(false);

@ -26,7 +26,7 @@ import moe.nekojimi.musicsearcher.Result;
* *
* @author jimj316 * @author jimj316
*/ */
public class SongRequest public class TrackRequest
{ {
private Invocation invocation; private Invocation invocation;
@ -37,7 +37,7 @@ public class SongRequest
private Result result; private Result result;
private final List<Song> songs = new ArrayList<>(); private final List<Track> tracks = new ArrayList<>();
private String requestedBy; private String requestedBy;
private String requestedIn; private String requestedIn;
@ -115,19 +115,19 @@ public class SongRequest
this.url = url; this.url = url;
} }
public List<Song> getSongs() public List<Track> getTracks()
{ {
return songs; return tracks;
} }
public void addSong(Song song) public void addTrack(Track track)
{ {
songs.add(song); tracks.add(track);
} }
public void clearSongs() public void clearTracks()
{ {
songs.clear(); tracks.clear();
} }
public String getRequestedBy() public String getRequestedBy()
@ -140,4 +140,23 @@ public class SongRequest
return requestedIn; return requestedIn;
} }
public String toString()
{
String trackName;
if (tracks.isEmpty())
trackName = "Request";
else
{
trackName = tracks.get(1).toString();
if (tracks.size() > 1)
trackName += " & " + (tracks.size() - 1) + " more tracks";
}
String requestName = "";
if (!requestedBy.isEmpty())
requestName = "for " + requestedBy;
return (trackName + " " + requestName).trim();
}
} }

@ -34,10 +34,10 @@ public class HelpCommand extends Command
+ "!leave - Leaves the current voice channel\n" + "!leave - Leaves the current voice channel\n"
+ "!play <URL> - Downloads the track at that URL and adds it to the queue.\n" + "!play <URL> - Downloads the track at that URL and adds it to the queue.\n"
+ "!play <Search> - Searches for a track and displays a selection menu.\n" + "!play <Search> - Searches for a track and displays a selection menu.\n"
+ "!queue - Show the songs currently playing and the current queue.\n" + "!queue - Show the tracks currently playing and the current queue.\n"
+ "!remove <Index> - Remove the song at position <Index> from the queue.\n" + "!remove <Index> - Remove the track at position <Index> from the queue.\n"
+ "!skip - Skip the current song and play the next one.\n" + "!skip - Skip the current track and play the next one.\n"
+ "!restart - Try playing the current song again in case it goes wrong.\n"; + "!restart - Try playing the current track again in case it goes wrong.\n";
// for (String key: commands.keySet()) // for (String key: commands.keySet())
// { // {
// help += "!" + key + ":" // help += "!" + key + ":"

@ -22,7 +22,7 @@ import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import moe.nekojimi.chords.Chords; import moe.nekojimi.chords.Chords;
import moe.nekojimi.chords.SongRequest; import moe.nekojimi.chords.TrackRequest;
import moe.nekojimi.musicsearcher.Query; import moe.nekojimi.musicsearcher.Query;
import moe.nekojimi.musicsearcher.Result; import moe.nekojimi.musicsearcher.Result;
@ -45,7 +45,7 @@ public class PlayCommand extends Command
@Override @Override
public void call(Invocation invocation) public void call(Invocation invocation)
{ {
SongRequest request = new SongRequest(); TrackRequest request = new TrackRequest();
request.setInvocation(invocation); request.setInvocation(invocation);
try try
{ {
@ -67,11 +67,11 @@ public class PlayCommand extends Command
Result result = request.getSearchResults().get(index - 1); Result result = request.getSearchResults().get(index - 1);
request.setResult(result); request.setResult(result);
bot.queueDownload(request); bot.queueDownload(request);
// event.getChannel().sendMessage("Song removed.").queue(); // event.getChannel().sendMessage("Track removed.").queue();
} else if (size > 1) } else if (size > 1)
invocation.respond("That's not a number between 1 and " + size + "!"); invocation.respond("That's not a number between 1 and " + size + "!");
else if (size == 1) else if (size == 1)
invocation.respond("There's only one song and that's not one of them!"); invocation.respond("There's only one track and that's not one of them!");
return; return;
} catch (NumberFormatException nfx) } catch (NumberFormatException nfx)

@ -20,7 +20,7 @@ import java.util.List;
import java.util.Queue; import java.util.Queue;
import moe.nekojimi.chords.Downloader; import moe.nekojimi.chords.Downloader;
import moe.nekojimi.chords.Chords; import moe.nekojimi.chords.Chords;
import moe.nekojimi.chords.Song; import moe.nekojimi.chords.Track;
public class QueueCommand extends Command public class QueueCommand extends Command
{ {
@ -36,19 +36,19 @@ public class QueueCommand extends Command
String message = ">>> "; String message = ">>> ";
int i = 1; int i = 1;
final Song currentSong = bot.getMusicHandler().getCurrentSong(); final Track currentTrack = bot.getMusicHandler().getCurrentTrack();
if (currentSong != null) if (currentTrack != null)
message += ":notes: **Now playing: " + currentSong + "**\n"; message += ":notes: **Now playing: " + currentTrack + "**\n";
else else
message += ":mute: **Not playing anything right now.**\n"; message += ":mute: **Not playing anything right now.**\n";
final Queue<Song> songQueue = bot.getQueueManager().getJukeboxQueue(); final Queue<Track> trackQueue = bot.getQueueManager().getJukeboxQueue();
if (!songQueue.isEmpty()) if (!trackQueue.isEmpty())
{ {
message += "__Ready to play:__\n"; message += "__Ready to play:__\n";
for (Song song : songQueue) for (Track track : trackQueue)
{ {
message += ":bread: **" + (i) + ":** " + song + "\n"; message += ":bread: **" + (i) + ":** " + track + "\n";
i++; i++;
} }
} }
@ -59,12 +59,12 @@ public class QueueCommand extends Command
message += "__Downloading:__\n"; message += "__Downloading:__\n";
for (Downloader.DownloadTask task : downloadQueue) for (Downloader.DownloadTask task : downloadQueue)
{ {
message += ":inbox_tray: **" + (i) + ":** " + task.getSong() + "\n"; message += ":inbox_tray: **" + (i) + ":** " + task.getTrack() + "\n";
i++; i++;
} }
} }
if (downloadQueue.isEmpty() && songQueue.isEmpty()) if (downloadQueue.isEmpty() && trackQueue.isEmpty())
message += ":mailbox_with_no_mail: The track queue is empty."; message += ":mailbox_with_no_mail: The track queue is empty.";
// :inbox_tray: // :inbox_tray:
invocation.respond(message); invocation.respond(message);

@ -32,14 +32,14 @@ public class RemoveCommand extends Command
try try
{ {
int i = Integer.parseInt(invocation.getArgs().get(0)); int i = Integer.parseInt(invocation.getArgs().get(0));
boolean removed = bot.getQueueManager().removeSong(i - 1); boolean removed = bot.getQueueManager().removeTrack(i - 1);
final int size = bot.getQueueManager().getJukeboxQueue().size(); final int size = bot.getQueueManager().getJukeboxQueue().size();
if (removed) if (removed)
invocation.respond("Song removed."); invocation.respond("Track removed.");
else if (size > 1) else if (size > 1)
invocation.respond("That's not a number between 1 and " + size + "!"); invocation.respond("That's not a number between 1 and " + size + "!");
else if (size == 1) else if (size == 1)
invocation.respond("There's only one song to remove and that's not one of them!"); invocation.respond("There's only one track to remove and that's not one of them!");
} catch (NumberFormatException ex) } catch (NumberFormatException ex)
{ {

@ -30,9 +30,9 @@ public class RestartCommand extends Command
public void call(Invocation invocation) public void call(Invocation invocation)
{ {
// TODO: this needs to clear the current data queue // TODO: this needs to clear the current data queue
boolean ok = bot.getQueueManager().restartSong(); boolean ok = bot.getQueueManager().restartTrack();
if (ok) if (ok)
invocation.respond("Restarted current song!"); invocation.respond("Restarted current track!");
else else
invocation.respond("Cannot restart!"); invocation.respond("Cannot restart!");
} }

@ -29,11 +29,11 @@ public class SkipCommand extends Command
@Override @Override
public void call(Invocation invocation) public void call(Invocation invocation)
{ {
boolean ok = bot.getMusicHandler().nextSong(true); boolean ok = bot.getMusicHandler().nextTrack(true);
if (ok) if (ok)
invocation.respond("Skipped to next song!"); invocation.respond("Skipped to next track!");
else else
invocation.respond("There's no more songs!"); invocation.respond("There's no more tracks!");
} }
} }

Loading…
Cancel
Save