diff --git a/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java b/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java index 8184f2f..237825e 100755 --- a/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java +++ b/core/src/zero1hd/rhythmbullet/audio/Mp3Manager.java @@ -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) { - - try { - decoder.decodeFrame(header, bitstream); - } catch (ArrayIndexOutOfBoundsException | DecoderException e) { - System.out.println(e); + 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); + } + + 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 diff --git a/core/src/zero1hd/rhythmbullet/audio/MusicList.java b/core/src/zero1hd/rhythmbullet/audio/MusicList.java index ca1bb99..30eab11 100755 --- a/core/src/zero1hd/rhythmbullet/audio/MusicList.java +++ b/core/src/zero1hd/rhythmbullet/audio/MusicList.java @@ -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 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) { diff --git a/core/src/zero1hd/rhythmbullet/audio/MusicListController.java b/core/src/zero1hd/rhythmbullet/audio/MusicListController.java index cde7968..dea54a3 100755 --- a/core/src/zero1hd/rhythmbullet/audio/MusicListController.java +++ b/core/src/zero1hd/rhythmbullet/audio/MusicListController.java @@ -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(); } } diff --git a/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java b/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java index ae7b287..5756675 100755 --- a/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java +++ b/core/src/zero1hd/rhythmbullet/graphics/ui/components/MusicControls.java @@ -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); diff --git a/core/src/zero1hd/rhythmbullet/graphics/ui/components/Visualizer.java b/core/src/zero1hd/rhythmbullet/graphics/ui/components/Visualizer.java index dab655a..d105ddc 100755 --- a/core/src/zero1hd/rhythmbullet/graphics/ui/components/Visualizer.java +++ b/core/src/zero1hd/rhythmbullet/graphics/ui/components/Visualizer.java @@ -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; diff --git a/core/src/zero1hd/rhythmbullet/graphics/ui/pages/MusicSelectionPage.java b/core/src/zero1hd/rhythmbullet/graphics/ui/pages/MusicSelectionPage.java index 9bf6ec0..f497d68 100755 --- a/core/src/zero1hd/rhythmbullet/graphics/ui/pages/MusicSelectionPage.java +++ b/core/src/zero1hd/rhythmbullet/graphics/ui/pages/MusicSelectionPage.java @@ -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(); } } diff --git a/core/src/zero1hd/rhythmbullet/graphics/ui/pages/OptionsPage.java b/core/src/zero1hd/rhythmbullet/graphics/ui/pages/OptionsPage.java index ebfafc1..d379552 100755 --- a/core/src/zero1hd/rhythmbullet/graphics/ui/pages/OptionsPage.java +++ b/core/src/zero1hd/rhythmbullet/graphics/ui/pages/OptionsPage.java @@ -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()); } } diff --git a/core/src/zero1hd/rhythmbullet/graphics/ui/windows/MusicSelector.java b/core/src/zero1hd/rhythmbullet/graphics/ui/windows/MusicSelector.java deleted file mode 100755 index fd3589b..0000000 --- a/core/src/zero1hd/rhythmbullet/graphics/ui/windows/MusicSelector.java +++ /dev/null @@ -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 fileNames; - private List 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(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; - } - } -} diff --git a/core/src/zero1hd/rhythmbullet/screens/MainMenu.java b/core/src/zero1hd/rhythmbullet/screens/MainMenu.java index 1f8a991..efdc20a 100755 --- a/core/src/zero1hd/rhythmbullet/screens/MainMenu.java +++ b/core/src/zero1hd/rhythmbullet/screens/MainMenu.java @@ -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(); }