Reworked how mp3s are being read and loaded int player

This commit is contained in:
Isaac Parenteau
2019-10-15 00:19:48 -05:00
parent 68a472d804
commit 232fd1746d
11 changed files with 221 additions and 188 deletions

View File

@@ -0,0 +1,62 @@
/**
*
* Project: Eight Track, File: EightTrackAudioSendHandler.java
*
* Copyright 2019-2019 Locusworks LLC.
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
* any means and imposes fines up to $25,000 for violation. No part of this material
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
* modified, duplicated, adapted or translated into another program language in any
* form or by any means, electronic, mechanical, photocopying, recording, or
* otherwise, without the prior written permission from Locusworks. Locusworks
* affirms that Eight-Track(R) software and data is subject to United States
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
*
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*/
package net.locusworks.discord.eighttrack.audio;
import java.nio.ByteBuffer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.track.playback.AudioFrame;
import net.dv8tion.jda.api.audio.AudioSendHandler;
public class EightTrackAudioSendHandler implements AudioSendHandler {
private final AudioPlayer audioPlayer;
private AudioFrame lastFrame;
public EightTrackAudioSendHandler(AudioPlayer audioPlayer) {
this.audioPlayer = audioPlayer;
}
public boolean canProvide() {
lastFrame = audioPlayer.provide();
return lastFrame != null;
}
public ByteBuffer provide20MsAudio() {
if (lastFrame == null || lastFrame.getData() == null) {
return ByteBuffer.wrap(new byte[0]);
}
return ByteBuffer.wrap(lastFrame.getData());
}
public boolean isOpus() {
return true;
}
}

View File

@@ -0,0 +1,87 @@
/**
*
* Project: Eight Track, File: Mp3UploadHandler.java
*
* Copyright 2019-2019 Locusworks LLC.
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
* any means and imposes fines up to $25,000 for violation. No part of this material
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
* modified, duplicated, adapted or translated into another program language in any
* form or by any means, electronic, mechanical, photocopying, recording, or
* otherwise, without the prior written permission from Locusworks. Locusworks
* affirms that Eight-Track(R) software and data is subject to United States
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
*
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*/
package net.locusworks.discord.eighttrack.audio;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.UUID;
import org.springframework.stereotype.Component;
import org.xml.sax.SAXException;
import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.UnsupportedTagException;
@Component
public class Mp3UploadHandler {
public Mp3UploadResults parse(Path file) throws IOException {
InputStream is = Files.newInputStream(file);
return parse(is);
}
public Mp3UploadResults parse(InputStream is) throws IOException {
byte[] data;
String id = null;
try(InputStream in = is; ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
int read = 0;
byte[] buffer = new byte[1024 * 1024];
while((read = in.read(buffer)) > 0) {
baos.write(buffer, 0, read);
}
data = baos.toByteArray();
id = UUID.nameUUIDFromBytes(data).toString();
Files.write(Paths.get(id), data);
Mp3File mp3 = new Mp3File(Paths.get(id));
ID3v2 tag = mp3.getId3v2Tag();
return new Mp3UploadResults(tag, data);
} catch (Exception ex) {
return new Mp3UploadResults(ex);
} finally {
if (id != null) {
Files.deleteIfExists(Paths.get(id));
}
}
}
public static void main(String args[]) throws IOException, SAXException, UnsupportedTagException, InvalidDataException {
String file = "E:\\Music2\\AronChupa\\01 I'm an Albatraoz.mp3";
Path path = Paths.get(file);
Mp3UploadHandler fuh = new Mp3UploadHandler();
System.out.println(fuh.parse(path));
}
}

View File

@@ -0,0 +1,172 @@
/**
*
* Project: Eight Track, File: Mp3UploadResults.java
*
* Copyright 2019-2019 Locusworks LLC.
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
* any means and imposes fines up to $25,000 for violation. No part of this material
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
* modified, duplicated, adapted or translated into another program language in any
* form or by any means, electronic, mechanical, photocopying, recording, or
* otherwise, without the prior written permission from Locusworks. Locusworks
* affirms that Eight-Track(R) software and data is subject to United States
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
*
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*/
package net.locusworks.discord.eighttrack.audio;
import com.mpatric.mp3agic.ID3v2;
public class Mp3UploadResults {
private String genre;
private String composure;
private String album;
private String trackNumber;
private String discNumber;
private String artist;
private String title;
private String releaseDate;
private byte[] rawData;
private Throwable err;
public Mp3UploadResults(ID3v2 tag, byte[] data) {
parseResults(tag);
this.rawData = data;
}
public Mp3UploadResults(Throwable err) {
this.err = err;
}
private void parseResults(ID3v2 metadata) {
genre = metadata.getGenreDescription();
composure = metadata.getComposer();
album = metadata.getAlbum();
trackNumber = metadata.getTrack();
discNumber = metadata.getPartOfSet();
artist = metadata.getArtist();
title = metadata.getTitle();
releaseDate = metadata.getDate();
}
public final byte[] getData() {
return this.rawData;
}
/**
* @return the genre
*/
public final String getGenre() {
return genre;
}
/**
* @return the composure
*/
public final String getComposure() {
return composure;
}
/**
* @return the album
*/
public final String getAlbum() {
return album;
}
/**
* @return the trackNumber
*/
public final String getTrackNumber() {
return trackNumber;
}
/**
* @return the discNumber
*/
public final String getDiscNumber() {
return discNumber;
}
/**
* @return the artist
*/
public final String getArtist() {
return artist;
}
/**
* @return the title
*/
public final String getTitle() {
return title;
}
/**
* @return the releaseDate
*/
public final String getReleaseDate() {
return releaseDate;
}
public boolean validFile() {
return (getTitle() != null && !getTitle().isEmpty() && getArtist() != null && !getArtist().trim().isEmpty()) || this.err != null;
}
public boolean hasError() {
return this.err != null;
}
public Throwable getError() {
return this.err;
}
@Override
public String toString() {
if (this.hasError()) {
return "Unable to parse file due to exception: " + this.err.getMessage();
}
StringBuilder sb = new StringBuilder();
if (getTitle() != null)
sb.append(String.format("%-10s: %s%n", "Title", getTitle()));
if (getArtist() != null)
sb.append(String.format("%-10s: %s%n", "Artist", getArtist()));
if (getAlbum() != null)
sb.append(String.format("%-10s: %s%n", "Album", getAlbum()));
if (getTrackNumber() != null)
sb.append(String.format("%-10s: %s%n", "Track", getTrackNumber()));
if (getDiscNumber() != null)
sb.append(String.format("%-10s: %s%n", "Disc", getDiscNumber()));
if (getReleaseDate() != null)
sb.append(String.format("%-10s: %s%n", "Year", getReleaseDate()));
if (getGenre() != null)
sb.append(String.format("%-10s: %s%n", "Genre", getGenre()));
return sb.toString();
}
public void clear() {
rawData = new byte[0];
}
}

View File

@@ -0,0 +1,74 @@
package net.locusworks.discord.eighttrack.audio;
import java.lang.reflect.Field;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.function.Consumer;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.DefaultAudioPlayerManager;
import com.sedmelluq.discord.lavaplayer.source.AudioSourceManagers;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
public class TrackManager extends DefaultAudioPlayer {
private LinkedBlockingDeque<String> queue;
private AudioPlayerManager playerManager;
private TrackScheduler trackScheduler;
private String currentItem;
public TrackManager() {
super(new DefaultAudioPlayerManager());
this.queue = new LinkedBlockingDeque<String>();
this.trackScheduler = new TrackScheduler();
addListener(trackScheduler);
try {
Field f = this.getClass().getSuperclass().getDeclaredField("manager");
f.setAccessible(true);
this.playerManager = (AudioPlayerManager) f.get(this);
} catch (SecurityException | NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
throw new IllegalArgumentException(e);
}
AudioSourceManagers.registerLocalSource(this.playerManager);
}
public void queueLast(String track) {
queue.addLast(track);
}
public void queueNext(String track) {
queue.addFirst(track);
}
public boolean hasTracks() {
return queue.peek() != null && !queue.isEmpty();
}
public String getCurrentItem() {
return currentItem;
}
public AudioTrack play() {
if (!queue.isEmpty()) {
try {
currentItem = queue.poll();
playerManager.loadItem(currentItem, trackScheduler).get();
return trackScheduler.getNextTrack();
} catch (InterruptedException | ExecutionException e) {}
}
return null;
}
public void setFinishedCallback(Consumer<AudioTrackEndReason> callback) {
trackScheduler.setFinishedCallback(callback);
}
public void clearTracks() {
queue.clear();
trackScheduler.clearTracks();
}
}

View File

@@ -0,0 +1,114 @@
/**
*
* Project: Eight Track, File: TrackScheduler.java
*
* Copyright 2019-2019 Locusworks LLC.
* All rights reserved. Federal copyright law prohibits unauthorized reproduction by
* any means and imposes fines up to $25,000 for violation. No part of this material
* may be reproduced, transmitted, transcribed, stored in a retrieval system, copied,
* modified, duplicated, adapted or translated into another program language in any
* form or by any means, electronic, mechanical, photocopying, recording, or
* otherwise, without the prior written permission from Locusworks. Locusworks
* affirms that Eight-Track(R) software and data is subject to United States
* Government Purpose Rights. Contact Locusworks, 1313 Lawnview Drive
* Forney TX 75126, (802) 488-0438, for commercial licensing opportunities.
*
* IN NO EVENT SHALL LOCUSWORKS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL,
* INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING OUT
* OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF LOCUSWORKS HAS BEEN
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. NO RESPONSIBILITY IS ASSUMED BY
* LOCUSWORKS FOR ITS USE, OR FOR ANY INFRINGEMENTS OF PATENTS OR OTHER RIGHTS OF
* THIRD PARTIES RESULTING FROM ITS USE. LOCUSWORKS SPECIFICALLY DISCLAIMS ANY
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE AND
* ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS
* IS". LOCUSWORKS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
* ENHANCEMENTS, OR MODIFICATIONS.
*/
package net.locusworks.discord.eighttrack.audio;
import java.util.Deque;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.function.Consumer;
import com.sedmelluq.discord.lavaplayer.player.AudioLoadResultHandler;
import com.sedmelluq.discord.lavaplayer.player.AudioPlayer;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventAdapter;
import com.sedmelluq.discord.lavaplayer.player.event.AudioEventListener;
import com.sedmelluq.discord.lavaplayer.tools.FriendlyException;
import com.sedmelluq.discord.lavaplayer.track.AudioPlaylist;
import com.sedmelluq.discord.lavaplayer.track.AudioTrack;
import com.sedmelluq.discord.lavaplayer.track.AudioTrackEndReason;
public class TrackScheduler extends AudioEventAdapter implements AudioEventListener, AudioLoadResultHandler {
private Deque<AudioTrack> trackQueue;
private boolean started;
private Consumer<AudioTrackEndReason> finished;
public TrackScheduler() {
trackQueue = new LinkedBlockingDeque<AudioTrack>();
}
@Override
public void onTrackStart(AudioPlayer player, AudioTrack track) {
this.started = true;
super.onTrackStart(player, track);
}
@Override
public void onTrackEnd(AudioPlayer player, AudioTrack track, AudioTrackEndReason endReason) {
this.started = false;
super.onTrackEnd(player, track, endReason);
if (finished != null) finished.accept(endReason);
}
public void setFinishedCallback(Consumer<AudioTrackEndReason> callback) {
if (this.finished == null) this.finished = callback;
}
public void trackLoaded(AudioTrack track) {
trackQueue.addFirst(track);
}
public void playlistLoaded(AudioPlaylist playlist) {
for (AudioTrack at : playlist.getTracks()) {
trackQueue.add(at);
}
}
public void clearTracks() {
trackQueue.clear();
}
public void noMatches() {
// TODO Auto-generated method stub
}
public void loadFailed(FriendlyException exception) {
// TODO Auto-generated method stub
}
public int trackCount() {
return trackQueue.size();
}
public AudioTrack peek() {
return trackQueue.peek();
}
public boolean hasTracks() {
return !trackQueue.isEmpty();
}
public AudioTrack getNextTrack() {
return trackQueue.poll();
}
public boolean playing() {
return started;
}
}