asynch song loading functional now

This commit is contained in:
Harrison Deng 2017-12-05 10:42:06 -06:00
parent 8f03c3310d
commit c41c941338
9 changed files with 106 additions and 166 deletions

View File

@ -5,6 +5,8 @@ import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.jaudiotagger.audio.exceptions.InvalidAudioFrameException;
import org.jaudiotagger.audio.exceptions.ReadOnlyFileException;
@ -56,6 +58,7 @@ public class Mp3Manager implements MusicManager {
exec = Executors.newSingleThreadExecutor();
exec.submit(() -> {
lock.lock();
Logger.getLogger("org.jaudiotagger").setLevel(Level.OFF);
try {
MP3File mp3File = new MP3File(audioFile.file());
sampleCount = MathUtils.round(Float.valueOf((float) (mp3File.getAudioHeader().getSampleRateAsNumber()*mp3File.getMP3AudioHeader().getPreciseTrackLength())));
@ -113,6 +116,7 @@ public class Mp3Manager implements MusicManager {
exec.shutdown();
try {
bitstream.close();
bitstream = null;
} catch (BitstreamException e) {
e.printStackTrace();
}
@ -160,28 +164,32 @@ public class Mp3Manager implements MusicManager {
}
public int loadNextBuffer() {
int bytesRead = 0;
try {
Header header = bitstream.readFrame();
if (header != null) {
if (bitstream != null) {
int bytesRead = 0;
try {
Header header = bitstream.readFrame();
if (header != null) {
try {
decoder.decodeFrame(header, bitstream);
} catch (ArrayIndexOutOfBoundsException | DecoderException e) {
System.out.println(e);
try {
decoder.decodeFrame(header, bitstream);
} catch (ArrayIndexOutOfBoundsException | DecoderException e) {
System.out.println(e);
}
bitstream.closeFrame();
bytesRead = sampleBuffer.reset();
currentByteSet = sampleBuffer.getBuffer();
} else {
currentByteSet = null;
}
bitstream.closeFrame();
bytesRead = sampleBuffer.reset();
currentByteSet = sampleBuffer.getBuffer();
} else {
currentByteSet = null;
} catch (BitstreamException e1) {
e1.printStackTrace();
}
} catch (BitstreamException e1) {
e1.printStackTrace();
return bytesRead;
} else {
return 0;
}
return bytesRead;
}
@Override

View File

@ -1,6 +1,8 @@
package zero1hd.rhythmbullet.audio;
import java.util.Observable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
@ -14,9 +16,12 @@ public class MusicList extends Observable {
private String searchPath;
private boolean searched;
private FileHandleAlphabeticalComparator fhac;
private ExecutorService exec;
public MusicList() {
musicList = new Array<>();
fhac = new FileHandleAlphabeticalComparator();
exec = Executors.newSingleThreadExecutor();
}
private Array<FileHandle> recursiveMusicFileList(FileHandle fileHandle) {
@ -34,8 +39,11 @@ public class MusicList extends Observable {
return musicFiles;
}
public void refresh() {
searched = true;
/**
* refreshes song list, notifies any observers of the refresh while passing no argument to the notifier.
* Blocking.
*/
public void refresh(boolean notify) {
musicList.clear();
Gdx.app.debug("SongController", "Searching path: " + searchPath);
if (Gdx.files.absolute(searchPath).exists() && Gdx.files.absolute(searchPath).isDirectory()) {
@ -47,7 +55,26 @@ public class MusicList extends Observable {
musicList.add(Gdx.files.external("RhythmBullet/Alan Walker - Spectre.mp3"));
Sort.instance().sort(musicList, fhac);
notifyObservers();
searched = true;
if (notify) {
notifyObservers();
}
}
/**
* Wrapper method that uses asynch refresh.
* Also notifies listeners that are on the main thread.
*/
public void asynchRefresh() {
searched = false;
exec.submit(() -> {
refresh(false);
Gdx.app.postRunnable(() -> {
notifyObservers();
searched = true;
Gdx.app.debug("Asynch-MusicList", "Async refresh done. Notification has been sent.");
});
});
}
public void setSearchPath(String searchPath) {

View File

@ -1,6 +1,5 @@
package zero1hd.rhythmbullet.audio;
import java.security.InvalidParameterException;
import java.util.Observable;
import java.util.Observer;
import java.util.Random;
@ -22,22 +21,24 @@ public class MusicListController extends Observable implements OnCompletionListe
public MusicListController(MusicList musicList, Preferences prefs) {
if (prefs == null) throw new NullPointerException("preferences can't be null...");
if (musicList == null) throw new NullPointerException("music list can't be null...");
if (!musicList.isSearched()) throw new InvalidParameterException("music list has to be searched already.");
musicList.addObserver(this);
this.prefs = prefs;
this.musicList = musicList;
rand = new Random();
changeMusic();
}
public void play() {
mm.play();
mm.setVolume(prefs.getFloat("music vol", 1f));
if (mm != null) {
mm.play();
mm.setVolume(prefs.getFloat("music vol", 1f));
} else {
Gdx.app.debug("MusicListController", "failed to begin playing. Load the music!!!");
}
}
public void setMusicByIndex(int index) {
this.currentPlaybackID = index;
changeMusic();
loadMusic();
}
public void skip() {
@ -45,7 +46,7 @@ public class MusicListController extends Observable implements OnCompletionListe
if (shuffle) {
shuffle(false);
}
changeMusic();
loadMusic();
}
public void previous() {
@ -53,7 +54,7 @@ public class MusicListController extends Observable implements OnCompletionListe
if (shuffle) {
shuffle(false);
}
changeMusic();
loadMusic();
}
@Override
@ -68,7 +69,7 @@ public class MusicListController extends Observable implements OnCompletionListe
} else {
currentPlaybackID++;
}
changeMusic();
loadMusic();
play();
}
}
@ -84,7 +85,7 @@ public class MusicListController extends Observable implements OnCompletionListe
currentPlaybackID = rand.nextInt(musicList.getAmountOfMusic());
}
if (load) {
changeMusic();
loadMusic();
}
}
@ -104,7 +105,11 @@ public class MusicListController extends Observable implements OnCompletionListe
return autoPlay;
}
private void changeMusic() {
/**
* Loads the current selected song.
*/
public void loadMusic() {
Gdx.app.debug("MusicListController", "music is being loaded...");
if (mm != null) {
mm.dispose();
}
@ -133,7 +138,7 @@ public class MusicListController extends Observable implements OnCompletionListe
@Override
public void update(Observable o, Object arg) {
if (o == musicList) {
changeMusic();
loadMusic();
play();
}
}

View File

@ -10,21 +10,20 @@ import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import zero1hd.rhythmbullet.audio.MusicListController;
public class MusicControls extends HorizontalGroup {
private MusicListController sc;
private ImageButton reverse, forward;
private CheckBox shuffle, play;
private float disableTimer;
public MusicControls(Skin skin, MusicListController sc) {
this.sc = sc;
reverse = new ImageButton(skin, "rewind-button");
reverse.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
boolean wasPlaying = sc.getCurrentMusicManager().isPlaying();
sc.previous();
if (wasPlaying) {
sc.play();
if (sc.getCurrentMusicManager() != null) {
boolean wasPlaying = sc.getCurrentMusicManager().isPlaying();
sc.previous();
if (wasPlaying) {
sc.play();
}
}
forward.setDisabled(true);
@ -37,17 +36,23 @@ public class MusicControls extends HorizontalGroup {
play = new CheckBox(null, skin, "play-button") {
@Override
public void act(float delta) {
play.setChecked(sc.getCurrentMusicManager().isPlaying());
if (sc.getCurrentMusicManager() != null) {
play.setChecked(sc.getCurrentMusicManager().isPlaying());
} else {
play.setChecked(false);
}
super.act(delta);
}
};
play.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
if (play.isChecked()) {
sc.getCurrentMusicManager().play();
} else {
sc.getCurrentMusicManager().pause();
if (sc.getCurrentMusicManager() != null) {
if (play.isChecked()) {
sc.getCurrentMusicManager().play();
} else {
sc.getCurrentMusicManager().pause();
}
}
}
});
@ -57,10 +62,12 @@ public class MusicControls extends HorizontalGroup {
forward.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
boolean wasPlaying = sc.getCurrentMusicManager().isPlaying();
sc.skip();
if (wasPlaying) {
sc.play();
if (sc.getCurrentMusicManager() != null) {
boolean wasPlaying = sc.getCurrentMusicManager().isPlaying();
sc.skip();
if (wasPlaying) {
sc.play();
}
}
forward.setDisabled(true);

View File

@ -46,8 +46,8 @@ public class Visualizer extends Widget implements Disposable {
public void setMM(MusicManager mm) {
if (mm != null) {
mm.dispose();
if (this.mm != null) {
this.mm.dispose();
}
this.mm = mm;
mmSet = false;

View File

@ -182,7 +182,7 @@ public class MusicSelectionPage extends Page implements Observer {
return currentlySelected.getAudioInfo();
}
public void refresh() {
public void refreshUIList() {
musicTable.clear();
selectables.clear();
musicInfoTable.clear();
@ -283,13 +283,11 @@ public class MusicSelectionPage extends Page implements Observer {
public void update(Observable o, Object arg) {
if (o == mc) {
MusicManager mm = (MusicManager) arg;
selectSong(mm);
} else if (o == mc.getMusicList()) {
refresh();
selectMusicUI(mm);
}
}
public void selectSong(MusicManager mm) {
public void selectMusicUI(MusicManager mm) {
if (currentlySelected == null || mm.getMusicFile() != currentlySelected.getMusicFile()) {
for (int i = 0; i < selectables.size; i++) {
if (selectables.get(i).getMusicFile() == mm.getMusicFile()) {
@ -309,7 +307,6 @@ public class MusicSelectionPage extends Page implements Observer {
if (currentlySelected.getMusicFile() != mc.getCurrentMusicManager().getMusicFile()) {
int index = mc.getMusicList().getMusicList().indexOf(currentlySelected.getMusicFile(), true);
mc.setMusicByIndex(index);
mc.play();
}
}

View File

@ -92,7 +92,7 @@ public class OptionsPage extends Page {
musicSearchTimer -= delta;
if (musicSearchTimer <= 0) {
sc.getMusicList().setSearchPath(directoryField.getText());
sc.getMusicList().refresh();
sc.getMusicList().asynchRefresh();
songCount.setText("Songs: " + sc.getMusicList().getAmountOfMusic());
}
}

View File

@ -1,98 +0,0 @@
package zero1hd.rhythmbullet.graphics.ui.windows;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.scenes.scene2d.Actor;
import com.badlogic.gdx.scenes.scene2d.ui.List;
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
import com.badlogic.gdx.scenes.scene2d.ui.Window;
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
import com.badlogic.gdx.utils.Array;
import zero1hd.rhythmbullet.audio.MusicManager;
import zero1hd.rhythmbullet.audio.MusicList;
import zero1hd.rhythmbullet.util.MiniEvents;
import zero1hd.rhythmbullet.util.MiniSender;
public class MusicSelector extends Window {
boolean confirmed;
boolean back;
FileHandle selectedMusic;
Array<String> fileNames;
private List<String> musicList;
private ScrollPane listScroller;
private MusicList songList;
public MiniSender miniSender;
public MusicSelector(String title, Skin skin, final String path, MusicList songList) {
super(title, skin, "tinted");
padTop(25f);
padLeft(5f);
padRight(5f);
this.songList = songList;
miniSender = new MiniSender();
setSize(Gdx.graphics.getWidth()*0.5f, Gdx.graphics.getHeight()*0.5f);
fileNames = new Array<>();
musicList = new List<String>(skin, "default");
TextButton confirmButton = new TextButton("confirm", skin, "window");
confirmButton.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
confirmed = true;
selectedMusic = Gdx.files.absolute(path+System.getProperty("file.separator")+musicList.getSelected());
miniSender.send(MiniEvents.MUSIC_SELECTED);
}
});
add(confirmButton);
TextButton regenMap = new TextButton("regen map", skin, "window");
regenMap.addListener(new ChangeListener() {
@Override
public void changed(ChangeEvent event, Actor actor) {
miniSender.send(MiniEvents.MUSIC_DATA_CLEANED);
}
});
add(regenMap);
row();
listScroller = new ScrollPane(musicList, skin);
listScroller.setScrollingDisabled(true, false);
add(listScroller).colspan(2).expand().fill().prefWidth(getWidth()-5);
}
public void refresh() {
songList.refresh();
musicList.setItems(songList.getMusicList());
}
public boolean isConfirmed() {
boolean isConfirmed = confirmed;
confirmed = false;
return isConfirmed;
}
public boolean isBack() {
boolean isBack = back;
back = false;
return isBack;
}
public MusicManager getSelectedMusic() {
if (selectedMusic != null) {
return songList.getAudioData(selectedMusic);
} else {
return null;
}
}
}

View File

@ -65,12 +65,10 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
MusicList musicList = new MusicList();
musicList.setSearchPath(core.getPrefs().getString("music dir"));
musicList.refresh();
musicList.asynchRefresh();
mlc = new MusicListController(musicList, core.getPrefs());
mlc.setAutoPlay(true);
mlc.setShuffle(true);
mlc.shuffle(true);
postTransition();
}
@ -136,9 +134,6 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
mlc.addObserver(mainPage);
mlc.addObserver(musicSelectionPage);
mlc.getMusicList().addObserver(musicSelectionPage);
musicSelectionPage.refresh();
mainPage.updateVisualsForDifferentSong(mlc.getCurrentMusicManager());
musicSelectionPage.selectSong(mlc.getCurrentMusicManager());
}
public void attemptLoadShaders() {
if (core.getPrefs().getBoolean("glow shader", true)) {
@ -216,7 +211,7 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
stage.act(delta);
if (blurlvl > 0) {
//Begin drawing a normal version of screen
// Begin drawing a normal version of screen
normalBuffer.begin();
stage.getViewport().apply();
Gdx.gl.glClearColor(0.22f, 0f, 0f, 1f);
@ -224,7 +219,7 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
stage.draw();
normalBuffer.end();
//BEGINNING NORMAL SCREEN RENDER
// BEGINNING NORMAL SCREEN RENDER
screenViewport.apply();
// Begin light filtering
@ -294,7 +289,6 @@ public class MainMenu extends ScreenAdapter implements TransitionAdapter {
@Override
public void show() {
Gdx.input.setInputProcessor(stage);
mlc.play();
calcLerpAlpha(Gdx.graphics.getWidth());
super.show();
}