diff --git a/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java b/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java index ad0004c..15bca8a 100755 --- a/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java +++ b/core/src/zero1hd/rhythmbullet/audio/AudioMetadataController.java @@ -16,7 +16,7 @@ import zero1hd.rhythmbullet.audio.metadata.WAVMetadata; public class AudioMetadataController extends Observable implements Disposable, Observer { private MusicList musicList; - private Array metadataArray; + private volatile Array metadataArray; private MetadataLoadingThread loadingThread; private volatile boolean searching; private Comparator metadataComparer; @@ -54,7 +54,7 @@ public class AudioMetadataController extends Observable implements Disposable, O * @return whether or not both sizes are equal. */ public boolean isSameSizeMusicList() { - return (metadataArray.size == musicList.getMusicArray().size); + return (metadataArray.size == musicList.getTotal()); } @Override @@ -79,7 +79,7 @@ public class AudioMetadataController extends Observable implements Disposable, O return metadataArray.get(i); } } - return null; + throw new IllegalArgumentException("Couldn't find file " + filehandle.name()); } public boolean isSearching() { @@ -88,17 +88,25 @@ public class AudioMetadataController extends Observable implements Disposable, O private class MetadataLoadingThread implements Runnable { private Thread thread; - private String name = "Metadata-Load"; + private String name = "AudioMetadata-Load"; private volatile boolean work = true; @Override public void run() { Gdx.app.debug(name, "loading..."); clear(); + synchronized (this) { + try { + wait(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } searching = true; Array tempMetadataArray = new Array<>(); for (int i = 0; i < musicList.getTotal() && work; i++) { - FileHandle musicFile = musicList.getMusicArray().get(i); + FileHandle musicFile = musicList.getAudioFileHandle(i); + if (musicFile == null) return; switch (SupportedFormats.valueOf(musicFile.extension().toUpperCase())) { case MP3: tempMetadataArray.add(new MP3Metadata(musicFile)); @@ -145,9 +153,14 @@ public class AudioMetadataController extends Observable implements Disposable, O } public void clear() { - for (int i = 0; i < metadataArray.size; i++) { - metadataArray.get(i).dispose(); - } - metadataArray.clear(); + Gdx.app.postRunnable(() -> { + for (int i = 0; i < metadataArray.size; i++) { + metadataArray.get(i).dispose(); + } + metadataArray.clear(); + synchronized (loadingThread) { + loadingThread.notify(); + } + }); } } diff --git a/core/src/zero1hd/rhythmbullet/audio/MusicController.java b/core/src/zero1hd/rhythmbullet/audio/MusicController.java index d89f9ea..4dc4bea 100755 --- a/core/src/zero1hd/rhythmbullet/audio/MusicController.java +++ b/core/src/zero1hd/rhythmbullet/audio/MusicController.java @@ -46,11 +46,14 @@ public class MusicController extends Observable implements OnCompletionListener, */ public void play() { if (music != null) { - Gdx.app.debug("MusicController", "Playing from MLC."); + Gdx.app.debug("MusicController", "Playing from controller."); music.play(); music.setVolume(prefs.getFloat("music vol", 1f)); setChanged(); notifyObservers(states.PLAYING); + } else { + Gdx.app.debug("MusicController", "Music isn't loaded!"); + Thread.dumpStack(); } } @@ -78,7 +81,7 @@ public class MusicController extends Observable implements OnCompletionListener, * @param fileHandle to use. */ public void setMusicByFileHandle(FileHandle fileHandle) { - setMusicByIndex(musicList.getMusicArray().indexOf(fileHandle, true)); + setMusicByIndex(musicList.getIndexOfFileHandle(fileHandle)); } /** @@ -148,7 +151,7 @@ public class MusicController extends Observable implements OnCompletionListener, * Loads the current selected song. */ public void loadMusic() { - Gdx.app.debug("MusicListController", "music is being loaded and listeners are being notified."); + Gdx.app.debug("MusicListController", "music is being loaded from music list with " + musicList.getTotal() + " songs."); boolean playing = isPlaying(); musicHeader = null; if (music != null) { @@ -161,13 +164,15 @@ public class MusicController extends Observable implements OnCompletionListener, currentlyPlayingIndex = 0; } if (musicList.getTotal() != 0) { - this.music = Gdx.audio.newMusic(musicList.getMusicArray().get(currentlyPlayingIndex)); + FileHandle musicFile = musicList.getAudioFileHandle(currentlyPlayingIndex); + if (musicFile == null) return; + this.music = Gdx.audio.newMusic(musicFile); music.setOnCompletionListener(this); setChanged(); notifyObservers(states.LOADED); - if (playing) { + if (playing || autoPlay) { play(); } } @@ -199,9 +204,6 @@ public class MusicController extends Observable implements OnCompletionListener, shuffle(); } loadMusic(); - if (autoPlay) { - play(); - } } } } diff --git a/core/src/zero1hd/rhythmbullet/audio/MusicList.java b/core/src/zero1hd/rhythmbullet/audio/MusicList.java index b94fa0e..d75eb21 100755 --- a/core/src/zero1hd/rhythmbullet/audio/MusicList.java +++ b/core/src/zero1hd/rhythmbullet/audio/MusicList.java @@ -68,8 +68,9 @@ public class MusicList extends Observable { } public void setSearchPath(String searchPath) { - setChanged(); + if (this.searchPath != null && this.searchPath.equals(searchPath)) return; this.searchPath = searchPath; + setChanged(); } /** @@ -120,8 +121,19 @@ public class MusicList extends Observable { return musicList.get(index); } - public Array getMusicArray() { - return musicList; + public FileHandle getAudioFileHandle(int index) { + FileHandle file = musicList.get(index); + if (file != null) { + return file; + } + + asyncSearch(true); + + return null; + } + + public int getIndexOfFileHandle(FileHandle file) { + return musicList.indexOf(file, true); } public boolean isSearched() { diff --git a/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java b/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java index b2f49a0..345455c 100755 --- a/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java +++ b/core/src/zero1hd/rhythmbullet/audio/metadata/AudioMetadata.java @@ -18,6 +18,7 @@ public interface AudioMetadata extends Disposable { /** * Unloads album art from memory. + * Requires OpenGL context. */ public void unloadAlbumCover(); diff --git a/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java b/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java index dca5cdc..1884291 100755 --- a/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java +++ b/core/src/zero1hd/rhythmbullet/audio/visualizer/DoubleHorizontalVisualizer.java @@ -81,13 +81,13 @@ public class DoubleHorizontalVisualizer implements Disposable { pixelsMoved = MathUtils.floor(difference*targetDelta*barChangeRate); if (pixelsMoved >= 0) { if (barHeights[bar] + pixelsMoved > amplitudes[bar]) { - barHeights[bar] = (int) amplitudes[bar]; + barHeights[bar] += MathUtils.round(difference*targetDelta); } else { barHeights[bar] += pixelsMoved; } } else { if (barHeights[bar] + pixelsMoved < amplitudes[bar]) { - barHeights[bar] = (int) amplitudes[bar]; + barHeights[bar] += MathUtils.round(difference*targetDelta); } else { barHeights[bar] += pixelsMoved; } diff --git a/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java b/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java index 30c482b..aee9141 100755 --- a/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java +++ b/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MainPage.java @@ -28,7 +28,7 @@ import zero1hd.rhythmbullet.util.ScreenConfiguration; public class MainPage extends Page implements Observer { private MusicController mc; - private AudioMetadataController mmc; + private AudioMetadataController amc; private Label versionLabel; private Image title; @@ -47,8 +47,8 @@ public class MainPage extends Page implements Observer { super(0, 0); this.mc = musicController; this.mc.addObserver(this); - this.mmc = mmc; - this.mmc.addObserver(this); + this.amc = mmc; + this.amc.addObserver(this); dhv = new DoubleHorizontalVisualizer((int) getWidth(), (int) 0, getHeight(), 0, screenConfiguration.getTargetFramesPerSecond(), mc, new PCMObtainer(mc)); dhv.setPosition(0, (int) ((getHeight() - dhv.getHeight())/2f)); @@ -122,13 +122,15 @@ public class MainPage extends Page implements Observer { @Override public void update(Observable o, Object arg) { if (o == mc) { - if (mmc.isSameSizeMusicList()) { - scrollText.setText("Currently playing: " + mmc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null); + if (amc.isSameSizeMusicList()) { + scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null); } else { scrollText.setText("Currently playing: " + mc.getCurrentMusicFileHandle().nameWithoutExtension().replace('_', ' '), null); } - } else if (o == mmc) { - scrollText.setText("Currently playing: " + mmc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null); + } else if (o == amc) { + if (amc.size() != 0) { + scrollText.setText("Currently playing: " + amc.getAudioMetadata(mc.getCurrentMusicFileHandle()).getTitle(), null); + } } } } diff --git a/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java b/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java index 7490c2e..0ff635e 100755 --- a/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java +++ b/desktop/src/zero1hd/rhythmbullet/desktop/screens/main/MusicSelectionPage.java @@ -230,8 +230,9 @@ public class MusicSelectionPage extends Page implements Observer { if (o == mmc) { selectionLoaderThread.start(); } else if (o == mc) { - if (mc.getMusicList().getTotal() == selectables.size() && mc.getCurrentMusicFileHandle() != selectables.getChecked().getMetadata().getFileHandle()) { + if (selectables.getChecked() != null && mc.getMusicList().getTotal() == selectables.size() && mc.getCurrentMusicFileHandle() != selectables.getChecked().getMetadata().getFileHandle()) { selectables.setChecked(mc.getCurrentMusicFileHandle()); + scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight()); } } else if (o == mc.getMusicList()) { if (arg == mc.getMusicList().states.LOADING) {