loading doesn't cause unavoidable lag (removed excessive blocking);

switched to a blocking queue list to manage album cover loading; threads
that should be daemons are daemons now;
This commit is contained in:
Harrison Deng 2018-08-23 22:21:33 -05:00
parent 211e37866e
commit b97d772ee9
3 changed files with 77 additions and 69 deletions

View File

@ -149,6 +149,7 @@ public class MusicList extends Observable {
@Override @Override
public void run() { public void run() {
Gdx.app.debug("MusicList", "recursive async search beginning.");
Array<FileHandle> obtainedAudioFiles = recursiveMusicSearch(directory); Array<FileHandle> obtainedAudioFiles = recursiveMusicSearch(directory);
Sort.instance().sort(obtainedAudioFiles, compare); Sort.instance().sort(obtainedAudioFiles, compare);
if (work) { if (work) {
@ -164,6 +165,7 @@ public class MusicList extends Observable {
if (thread == null) { if (thread == null) {
work = true; work = true;
thread = new Thread(this, threadName); thread = new Thread(this, threadName);
thread.setDaemon(true);
thread.start(); thread.start();
return true; return true;
} else { } else {

View File

@ -40,6 +40,10 @@ public class MusicMetadataController extends Observable implements Disposable, O
} }
} }
/**
* if there is the same amount of metadata as there is music in the music list.
* @return whether or not both sizes are equal.
*/
public boolean isDone() { public boolean isDone() {
return (metadataArray.size == musicList.getMusicArray().size); return (metadataArray.size == musicList.getMusicArray().size);
} }
@ -52,15 +56,11 @@ public class MusicMetadataController extends Observable implements Disposable, O
} }
public int size() { public int size() {
synchronized (loadingThread) { return metadataArray.size;
return metadataArray.size;
}
} }
public AudioMetadata getMetadata(int index) { public AudioMetadata getMetadata(int index) {
synchronized (loadingThread) { return metadataArray.get(index);
return metadataArray.get(index);
}
} }
@ -80,28 +80,25 @@ public class MusicMetadataController extends Observable implements Disposable, O
@Override @Override
public void run() { public void run() {
Gdx.app.debug(name, "loading..."); Gdx.app.debug(name, "loading...");
clear();
searching = true; searching = true;
for (int i = 0; i < metadataArray.size; i++) { Array<AudioMetadata> tempMetadataArray = new Array<>();
metadataArray.get(i).dispose();
}
metadataArray.clear();
for (int i = 0; i < musicList.getTotal() && work; i++) { for (int i = 0; i < musicList.getTotal() && work; i++) {
FileHandle musicFile = musicList.getMusicArray().get(i); FileHandle musicFile = musicList.getMusicArray().get(i);
synchronized (this) { switch (SupportedFormats.valueOf(musicFile.extension().toUpperCase())) {
switch (SupportedFormats.valueOf(musicFile.extension().toUpperCase())) { case MP3:
case MP3: tempMetadataArray.add(new MP3Metadata(musicFile));
metadataArray.add(new MP3Metadata(musicFile)); break;
break; case WAV:
case WAV: tempMetadataArray.add(new WAVMetadata(musicFile));
metadataArray.add(new WAVMetadata(musicFile)); break;
break; default:
default: break;
break;
}
} }
} }
if (work) { if (work) {
metadataArray = tempMetadataArray;
searching = false; searching = false;
Gdx.app.debug(name, "load complete."); Gdx.app.debug(name, "load complete.");
setChanged(); setChanged();
@ -130,4 +127,11 @@ public class MusicMetadataController extends Observable implements Disposable, O
loadAudioMetadata(); loadAudioMetadata();
} }
} }
public void clear() {
for (int i = 0; i < metadataArray.size; i++) {
metadataArray.get(i).dispose();
}
metadataArray.clear();
}
} }

View File

@ -2,6 +2,7 @@ package zero1hd.rhythmbullet.desktop.screens.main;
import java.util.Observable; import java.util.Observable;
import java.util.Observer; import java.util.Observer;
import java.util.concurrent.LinkedBlockingQueue;
import com.badlogic.gdx.Gdx; import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.Input.Keys; import com.badlogic.gdx.Input.Keys;
@ -178,24 +179,27 @@ public class MusicSelectionPage extends Page implements Observer {
private synchronized void updateList(float delta) { private synchronized void updateList(float delta) {
if (mc.getMusicList().isSearched()) { if (mc.getMusicList().isSearched()) {
if (mc.getMusicList().getTotal() != 0) { if (mc.getMusicList().getTotal() != 0) {
if (selectables.size() != mmc.size()) { if (mmc.isDone() && !mmc.isSearching()) {
MusicSelectable selectable = new MusicSelectable(mmc.getMetadata(selectables.size())); if (selectables.size() != mmc.size()) {
selectables.add(selectable); MusicSelectable selectable = new MusicSelectable(mmc.getMetadata(selectables.size()));
} else if (selectables.size() != vGroup.getChildren().size) { selectables.add(selectable);
vGroup.addActor(selectables.getButtons().get(vGroup.getChildren().size)); } else if (selectables.size() != vGroup.getChildren().size) {
} else { vGroup.addActor(selectables.getButtons().get(vGroup.getChildren().size));
if (selectables.getChecked() == null) { } else {
selectables.setMinCheckCount(1); if (selectables.getChecked() == null) {
selectables.setChecked(mc.getCurrentMusicFileHandle()); selectables.setMinCheckCount(1);
scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight()); selectables.setChecked(mc.getCurrentMusicFileHandle());
} else if (selectables.getChecked().getMetadata().getFileHandle() != mc.getCurrentMusicFileHandle()) { scrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
musicSelectDelay += delta; } else if (selectables.getChecked().getMetadata().getFileHandle() != mc.getCurrentMusicFileHandle()) {
if (musicSelectDelay >= 1f) { musicSelectDelay += delta;
mc.setMusicByFileHandle(selectables.getChecked().getMetadata().getFileHandle()); if (musicSelectDelay >= 1f) {
musicSelectDelay = 0; mc.setMusicByFileHandle(selectables.getChecked().getMetadata().getFileHandle());
musicSelectDelay = 0;
}
} }
} }
} }
} else { } else {
//TODO: Error message reporting empty music list or something //TODO: Error message reporting empty music list or something
} }
@ -219,6 +223,7 @@ public class MusicSelectionPage extends Page implements Observer {
@Override @Override
public void dispose() { public void dispose() {
mc.getMusicList().deleteObserver(this); mc.getMusicList().deleteObserver(this);
selectionLoaderThread.stop();
super.dispose(); super.dispose();
} }
@ -231,13 +236,15 @@ public class MusicSelectionPage extends Page implements Observer {
selectables.setChecked(mc.getCurrentMusicFileHandle()); selectables.setChecked(mc.getCurrentMusicFileHandle());
} }
} else if (o == mc.getMusicList()) { } else if (o == mc.getMusicList()) {
synchronized (this) { if (arg == mc.getMusicList().states.LOADING) {
if (arg == mc.getMusicList().states.LOADING) { synchronized (this) {
vGroup.clear(); vGroup.clear();
selectables.clear(); selectables.clear();
musicInfoTable.setToDefault(); musicInfoTable.setToDefault();
selectionLoaderThread.clear();
} }
} }
} }
} }
@ -250,31 +257,23 @@ public class MusicSelectionPage extends Page implements Observer {
private class musicSelectionLoaderThread implements Runnable { private class musicSelectionLoaderThread implements Runnable {
private Thread thread; private Thread thread;
private Array<AudioMetadata> queueList; private String name = "Music-Selection-Loader-Thread";
private String name = "Music-Selection-Loader-Thread";
private volatile boolean work = true; private volatile boolean work = true;
private LinkedBlockingQueue<AudioMetadata> queue;
public musicSelectionLoaderThread() { public musicSelectionLoaderThread() {
queueList = new Array<>(); queue = new LinkedBlockingQueue<>();
} }
@Override @Override
public void run() { public void run() {
while (work) { while (work) {
while (queueList.size != 0) { AudioMetadata metadata;
AudioMetadata metadata; try {
synchronized (this) { metadata = queue.take();
metadata = queueList.pop(); metadata.loadAlbumCover();
metadata.loadAlbumCover(); simpleDebug("Loading " + metadata.getTitle());
simpleDebug("Loading " + metadata.getTitle()); } catch (InterruptedException e) {
} simpleDebug("Thread was interupted.");
}
synchronized (this) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
} }
} }
} }
@ -282,21 +281,25 @@ public class MusicSelectionPage extends Page implements Observer {
public boolean start() { public boolean start() {
if (thread == null) { if (thread == null) {
thread = new Thread(this, name); thread = new Thread(this, name);
thread.setDaemon(true);
thread.start(); thread.start();
return true; return true;
} else {
synchronized (this) {
notify();
}
} }
return false; return false;
} }
public void stop() {
clear();
thread.interrupt();
work = false;
}
public void clear() {
queue.clear();
}
public void queue(AudioMetadata metadata) { public void queue(AudioMetadata metadata) {
if (!queueList.contains(metadata, true)) { queue.add(metadata);
queueList.add(metadata);
start();
}
} }
} }
@ -348,7 +351,7 @@ public class MusicSelectionPage extends Page implements Observer {
actualCoords.x = getX() + getParent().getX(); actualCoords.x = getX() + getParent().getX();
actualCoords.y = getY() + getParent().getY(); actualCoords.y = getY() + getParent().getY();
if ((actualCoords.y < 0 - getHeight() || actualCoords.y > getStage().getHeight() || actualCoords.x < 0 - getWidth() || actualCoords.x > getStage().getWidth()) && selectables.getChecked() != this) { if ((actualCoords.y < 0 - getHeight() - getStage().getHeight()*1.5f || actualCoords.y > getStage().getHeight()*1.5f) && selectables.getChecked() != this) {
offScreenAct(delta); offScreenAct(delta);
} else { } else {
onScreenAct(delta); onScreenAct(delta);
@ -365,10 +368,9 @@ public class MusicSelectionPage extends Page implements Observer {
if (offScreen) { if (offScreen) {
offScreen = false; offScreen = false;
timeSinceChanged = 0; timeSinceChanged = 0;
} else if (timeSinceChanged < 0.75f) { } else if (timeSinceChanged < 0.075f) {
timeSinceChanged += delta; timeSinceChanged += delta;
} } else {
if (timeSinceChanged >= 0.75f) {
if (!frameUsed && metadata.getAlbumCover() != null && !albumArtDisplayed) { if (!frameUsed && metadata.getAlbumCover() != null && !albumArtDisplayed) {
updateAlbumArtImage(metadata.getAlbumCover()); updateAlbumArtImage(metadata.getAlbumCover());
albumArtDisplayed = true; albumArtDisplayed = true;