changed to integer state system for notifier in music controller; music
selection page rewritten making better use of framework objects. Untested (still)
This commit is contained in:
parent
45da676d0d
commit
b857ffe4bd
@ -18,14 +18,14 @@ import com.badlogic.gdx.files.FileHandle;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class MusicController extends Observable implements OnCompletionListener, Observer {
|
public class MusicController extends Observable implements OnCompletionListener, Observer {
|
||||||
public enum States {
|
public final class States {
|
||||||
Loaded, Playing;
|
public final Integer LOADED = 0, PLAYING = 1;
|
||||||
}
|
}
|
||||||
|
public final States states = new States();
|
||||||
private MusicList musicList;
|
private MusicList musicList;
|
||||||
private MinimalAudioHeader musicHeader;
|
private MinimalAudioHeader musicHeader;
|
||||||
private Music music;
|
private Music music;
|
||||||
private int currentPlaybackIndex;
|
private int currentlyPlayingIndex;
|
||||||
private boolean autoPlay;
|
private boolean autoPlay;
|
||||||
private boolean shuffle;
|
private boolean shuffle;
|
||||||
private Random rand;
|
private Random rand;
|
||||||
@ -48,7 +48,7 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
Gdx.app.debug("MusicListController", "Playing from MLC.");
|
Gdx.app.debug("MusicListController", "Playing from MLC.");
|
||||||
music.play();
|
music.play();
|
||||||
music.setVolume(prefs.getFloat("music vol", 1f));
|
music.setVolume(prefs.getFloat("music vol", 1f));
|
||||||
notifyObservers(States.Playing);
|
notifyObservers(states.PLAYING);
|
||||||
} else {
|
} else {
|
||||||
Gdx.app.debug("MusicListController", "failed to begin playing. Load the music!!!");
|
Gdx.app.debug("MusicListController", "failed to begin playing. Load the music!!!");
|
||||||
}
|
}
|
||||||
@ -68,15 +68,24 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
* @param index of music to play
|
* @param index of music to play
|
||||||
*/
|
*/
|
||||||
public void setMusicByIndex(int index) {
|
public void setMusicByIndex(int index) {
|
||||||
this.currentPlaybackIndex = index;
|
this.currentlyPlayingIndex = index;
|
||||||
loadMusic();
|
loadMusic();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads music using the given file. The given file must be found in the {@link MusicList}.
|
||||||
|
* This function gets the index of the given file within {@link MusicList} and passes that index to {@link #setMusicByIndex(index)}.
|
||||||
|
* @param fileHandle to use.
|
||||||
|
*/
|
||||||
|
public void setMusicByFileHandle(FileHandle fileHandle) {
|
||||||
|
setMusicByIndex(musicList.getMusicArray().indexOf(fileHandle, true));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Goes to the next track
|
* Goes to the next track
|
||||||
*/
|
*/
|
||||||
public void skip() {
|
public void skip() {
|
||||||
currentPlaybackIndex++;
|
currentlyPlayingIndex++;
|
||||||
if (shuffle) {
|
if (shuffle) {
|
||||||
shuffle(false);
|
shuffle(false);
|
||||||
}
|
}
|
||||||
@ -87,7 +96,7 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
* Goes to the previous track
|
* Goes to the previous track
|
||||||
*/
|
*/
|
||||||
public void previous() {
|
public void previous() {
|
||||||
currentPlaybackIndex--;
|
currentlyPlayingIndex--;
|
||||||
if (shuffle) {
|
if (shuffle) {
|
||||||
shuffle(false);
|
shuffle(false);
|
||||||
}
|
}
|
||||||
@ -100,7 +109,7 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
if (shuffle) {
|
if (shuffle) {
|
||||||
shuffle(false);
|
shuffle(false);
|
||||||
} else {
|
} else {
|
||||||
currentPlaybackIndex++;
|
currentlyPlayingIndex++;
|
||||||
}
|
}
|
||||||
loadMusic();
|
loadMusic();
|
||||||
play();
|
play();
|
||||||
@ -114,9 +123,9 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
public void shuffle(boolean load) {
|
public void shuffle(boolean load) {
|
||||||
Gdx.app.debug("MusicListController", "shuffled.");
|
Gdx.app.debug("MusicListController", "shuffled.");
|
||||||
if (musicList.getTotal() == 0) {
|
if (musicList.getTotal() == 0) {
|
||||||
currentPlaybackIndex = 0;
|
currentlyPlayingIndex = 0;
|
||||||
} else {
|
} else {
|
||||||
currentPlaybackIndex = rand.nextInt(musicList.getTotal());
|
currentlyPlayingIndex = rand.nextInt(musicList.getTotal());
|
||||||
}
|
}
|
||||||
if (load) {
|
if (load) {
|
||||||
loadMusic();
|
loadMusic();
|
||||||
@ -148,13 +157,13 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
if (music != null) {
|
if (music != null) {
|
||||||
music.dispose();
|
music.dispose();
|
||||||
}
|
}
|
||||||
if (currentPlaybackIndex < 0) {
|
if (currentlyPlayingIndex < 0) {
|
||||||
currentPlaybackIndex = musicList.getTotal()-1;
|
currentlyPlayingIndex = musicList.getTotal()-1;
|
||||||
}
|
}
|
||||||
if (currentPlaybackIndex >= musicList.getTotal()) {
|
if (currentlyPlayingIndex >= musicList.getTotal()) {
|
||||||
currentPlaybackIndex = 0;
|
currentlyPlayingIndex = 0;
|
||||||
}
|
}
|
||||||
this.music = Gdx.audio.newMusic(musicList.getMusicArray().get(currentPlaybackIndex));
|
this.music = Gdx.audio.newMusic(musicList.getMusicArray().get(currentlyPlayingIndex));
|
||||||
music.setOnCompletionListener(this);
|
music.setOnCompletionListener(this);
|
||||||
|
|
||||||
setChanged();
|
setChanged();
|
||||||
@ -162,7 +171,7 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
if (autoPlay) {
|
if (autoPlay) {
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
notifyObservers(States.Loaded);
|
notifyObservers(states.LOADED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MusicList getMusicList() {
|
public MusicList getMusicList() {
|
||||||
@ -170,7 +179,7 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FileHandle getCurrentMusicFileHandle() {
|
public FileHandle getCurrentMusicFileHandle() {
|
||||||
return musicList.getSongFileHandleFromIndex(currentPlaybackIndex);
|
return musicList.getSongFileHandleFromIndex(currentlyPlayingIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MinimalAudioHeader getCurrentMusicHeader() {
|
public MinimalAudioHeader getCurrentMusicHeader() {
|
||||||
@ -220,4 +229,8 @@ public class MusicController extends Observable implements OnCompletionListener,
|
|||||||
public Music getCurrentMusic() {
|
public Music getCurrentMusic() {
|
||||||
return music;
|
return music;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public int getCurrentlyPlayingIndex() {
|
||||||
|
return currentlyPlayingIndex;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -92,6 +92,11 @@ public class MusicList extends Observable {
|
|||||||
searched = true;
|
searched = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return the amount of audio files discovered.
|
||||||
|
*/
|
||||||
public int getTotal() {
|
public int getTotal() {
|
||||||
return musicList.size;
|
return musicList.size;
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,9 @@ public class MusicMetadataController extends Observable implements Disposable, O
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int size() {
|
public int size() {
|
||||||
return metadataArray.size;
|
synchronized (loadingThread) {
|
||||||
|
return metadataArray.size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public AudioMetadata getMetadata(int index) {
|
public AudioMetadata getMetadata(int index) {
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
package zero1hd.rhythmbullet.graphics.ui.components;
|
package zero1hd.rhythmbullet.graphics.ui.components;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
|
import com.badlogic.gdx.graphics.g2d.Batch;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
||||||
import com.badlogic.gdx.math.Vector2;
|
import com.badlogic.gdx.math.Vector2;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
import com.badlogic.gdx.scenes.scene2d.ui.Button;
|
||||||
@ -9,6 +11,7 @@ import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
|||||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||||
|
|
||||||
@ -21,16 +24,17 @@ public class MusicSelectable extends Button {
|
|||||||
private float timeSinceOnScreen;
|
private float timeSinceOnScreen;
|
||||||
private AudioMetadata metadata;
|
private AudioMetadata metadata;
|
||||||
private Texture defaultAlbumArt;
|
private Texture defaultAlbumArt;
|
||||||
|
private Array<MusicSelectable> queueList;
|
||||||
|
|
||||||
public MusicSelectable(Skin skin, Texture defaultAlbumArt, AudioMetadata metadata) {
|
public MusicSelectable(Skin skin, Texture defaultAlbumArt, AudioMetadata metadata,
|
||||||
|
Array<MusicSelectable> queueList) {
|
||||||
super(skin, "music-selectable");
|
super(skin, "music-selectable");
|
||||||
this.metadata = metadata;
|
this.metadata = metadata;
|
||||||
this.defaultAlbumArt = defaultAlbumArt;
|
this.defaultAlbumArt = defaultAlbumArt;
|
||||||
|
this.queueList = queueList;
|
||||||
album = new Image(defaultAlbumArt);
|
album = new Image(defaultAlbumArt);
|
||||||
add(album).expand().left();
|
add(album).expand().left();
|
||||||
|
|
||||||
informationTable = new Table();
|
informationTable = new Table();
|
||||||
name = new ShortenedLabel(metadata.getTitle(), skin, "default-font", skin.getColor("default"));
|
name = new ShortenedLabel(metadata.getTitle(), skin, "default-font", skin.getColor("default"));
|
||||||
informationTable.add(name).colspan(2).expandX();
|
informationTable.add(name).colspan(2).expandX();
|
||||||
@ -41,34 +45,60 @@ public class MusicSelectable extends Button {
|
|||||||
informationTable.add(time).expandX();
|
informationTable.add(time).expandX();
|
||||||
add(informationTable).expand().fill();
|
add(informationTable).expand().fill();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void act(float delta) {
|
public void act(float delta) {
|
||||||
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()) {
|
if (actualCoords.y < 0 - getHeight() || actualCoords.y > getStage().getHeight()
|
||||||
|
|| actualCoords.x < 0 - getWidth() || actualCoords.x > getStage().getWidth()) {
|
||||||
offScreenAct(delta);
|
offScreenAct(delta);
|
||||||
} else {
|
} else {
|
||||||
onScreenAct(delta);
|
onScreenAct(delta);
|
||||||
}
|
}
|
||||||
super.act(delta);
|
super.act(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onScreenAct(float delta) {
|
@Override
|
||||||
timeSinceOnScreen = 0;
|
public void draw(Batch batch, float parentAlpha) {
|
||||||
if (metadata.getAlbumCover() == null) {
|
synchronized (album) {
|
||||||
metadata.loadAlbumCover();
|
super.draw(batch, parentAlpha);
|
||||||
album.setDrawable(new TextureRegionDrawable(new TextureRegion(metadata.getAlbumCover())));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onScreenAct(float delta) {
|
||||||
|
timeSinceOnScreen = 0;
|
||||||
|
if (!queueList.contains(this, true)) {
|
||||||
|
synchronized (queueList) {
|
||||||
|
queueList.add(this);
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void offScreenAct(float delta) {
|
public void offScreenAct(float delta) {
|
||||||
if (metadata.getAlbumCover() != null) {
|
if (metadata.getAlbumCover() != null) {
|
||||||
timeSinceOnScreen += delta;
|
timeSinceOnScreen += delta;
|
||||||
if (timeSinceOnScreen >= 2) {
|
if (timeSinceOnScreen >= 2) {
|
||||||
|
album.setDrawable(new TextureRegionDrawable(new TextureRegion(defaultAlbumArt)));
|
||||||
metadata.unloadAlbumCover();
|
metadata.unloadAlbumCover();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void loadAlbumCover() {
|
||||||
|
metadata.loadAlbumCover();
|
||||||
|
synchronized (album) {
|
||||||
|
album.setDrawable(new TextureRegionDrawable(new TextureRegion(metadata.getAlbumCover())));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public AudioMetadata getMetadata() {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
public FileHandle getFileHandle() {
|
||||||
|
return metadata.getFileHandle();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,60 @@
|
|||||||
|
package zero1hd.rhythmbullet.util;
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.ButtonGroup;
|
||||||
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
|
import zero1hd.rhythmbullet.audio.metadata.AudioMetadata;
|
||||||
|
import zero1hd.rhythmbullet.graphics.ui.components.MusicSelectable;
|
||||||
|
|
||||||
|
public class MusicSelectableButtonGroup extends ButtonGroup<MusicSelectable> {
|
||||||
|
private Array<MusicSelectable> buttons;
|
||||||
|
|
||||||
|
public MusicSelectableButtonGroup() {
|
||||||
|
buttons = getButtons();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(AudioMetadata metadata) {
|
||||||
|
if (metadata == null) throw new IllegalArgumentException("metadata can't be null.");
|
||||||
|
MusicSelectable button;
|
||||||
|
for (int i = 0; i < buttons.size; i++) {
|
||||||
|
button = buttons.get(i);
|
||||||
|
if (button.getMetadata() == metadata) {
|
||||||
|
button.setChecked(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(FileHandle fileHandle) {
|
||||||
|
if (fileHandle == null) throw new IllegalArgumentException("fileHandle can't be null.");
|
||||||
|
MusicSelectable button;
|
||||||
|
for (int i = 0; i < buttons.size; i++) {
|
||||||
|
button = buttons.get(i);
|
||||||
|
if (button.getFileHandle() == fileHandle) {
|
||||||
|
button.setChecked(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectNext() {
|
||||||
|
int index = getCheckedIndex() + 1;
|
||||||
|
if (index == buttons.size) {
|
||||||
|
index = 0;
|
||||||
|
}
|
||||||
|
buttons.get(index).setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void selectPrevious() {
|
||||||
|
int index = getCheckedIndex() - 1;
|
||||||
|
if (index == -1) {
|
||||||
|
index = buttons.size -1;
|
||||||
|
}
|
||||||
|
buttons.get(index).setChecked(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChecked(int index) {
|
||||||
|
buttons.get(index).setChecked(true);
|
||||||
|
}
|
||||||
|
}
|
@ -10,6 +10,7 @@ import java.util.Observer;
|
|||||||
import org.lwjgl.openal.AL11;
|
import org.lwjgl.openal.AL11;
|
||||||
|
|
||||||
import com.badlogic.gdx.Gdx;
|
import com.badlogic.gdx.Gdx;
|
||||||
|
import com.badlogic.gdx.assets.AssetLoaderParameters.LoadedCallback;
|
||||||
import com.badlogic.gdx.backends.lwjgl.audio.OpenALMusic;
|
import com.badlogic.gdx.backends.lwjgl.audio.OpenALMusic;
|
||||||
import com.badlogic.gdx.utils.Disposable;
|
import com.badlogic.gdx.utils.Disposable;
|
||||||
import com.badlogic.gdx.utils.TimeUtils;
|
import com.badlogic.gdx.utils.TimeUtils;
|
||||||
@ -23,7 +24,7 @@ import zero1hd.rhythmbullet.audio.visualizer.BasicFFT;
|
|||||||
public class PCMMachine implements Observer, Disposable {
|
public class PCMMachine implements Observer, Disposable {
|
||||||
private int windowSize = 1024;
|
private int windowSize = 1024;
|
||||||
private float[] PCM = new float[windowSize];
|
private float[] PCM = new float[windowSize];
|
||||||
private float[] frequencyBins = new float[windowSize/2];
|
private float[] frequencyBins = new float[windowSize / 2];
|
||||||
private BasicFFT fft = new BasicFFT(windowSize);
|
private BasicFFT fft = new BasicFFT(windowSize);
|
||||||
private ShortBuffer playingBuffer;
|
private ShortBuffer playingBuffer;
|
||||||
private ShortBuffer compareBuffer;
|
private ShortBuffer compareBuffer;
|
||||||
@ -45,76 +46,76 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
bufferField.setAccessible(true);
|
bufferField.setAccessible(true);
|
||||||
Field bufferSizeField = ClassReflection.getDeclaredField(OpenALMusic.class, "bufferSize");
|
Field bufferSizeField = ClassReflection.getDeclaredField(OpenALMusic.class, "bufferSize");
|
||||||
bufferSizeField.setAccessible(true);
|
bufferSizeField.setAccessible(true);
|
||||||
bufferSizeField.set(null, new Integer(4096*5));
|
bufferSizeField.set(null, new Integer(4096 * 5));
|
||||||
|
|
||||||
buffer = ((ByteBuffer) bufferField.get(null)).asShortBuffer().asReadOnlyBuffer();
|
buffer = ((ByteBuffer) bufferField.get(null)).asShortBuffer().asReadOnlyBuffer();
|
||||||
} catch (IllegalArgumentException | SecurityException | ReflectionException e) {
|
} catch (IllegalArgumentException | SecurityException | ReflectionException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
Gdx.app.debug("Visualizer reflection", "Failed attempt at retrieving tempBuffer field.");
|
Gdx.app.debug("Visualizer reflection", "Failed attempt at retrieving tempBuffer field.");
|
||||||
Gdx.app.exit();
|
Gdx.app.exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
streamReadThread = new BufferStreamReadThread();
|
streamReadThread = new BufferStreamReadThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
private synchronized void calcPCMData() {
|
private synchronized void calcPCMData() {
|
||||||
short chanVal;
|
short chanVal;
|
||||||
|
|
||||||
for (int sid = 0; sid < PCM.length && sid < playingBuffer.remaining(); sid++) {
|
for (int sid = 0; sid < PCM.length && sid < playingBuffer.remaining(); sid++) {
|
||||||
PCM[sid] = 0;
|
PCM[sid] = 0;
|
||||||
for (int channel = 0; channel < channelCount; channel ++) {
|
for (int channel = 0; channel < channelCount; channel++) {
|
||||||
if (PCM[sid] < (chanVal = playingBuffer.get())) {
|
if (PCM[sid] < (chanVal = playingBuffer.get())) {
|
||||||
PCM[sid] = chanVal;
|
PCM[sid] = chanVal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
PCM[sid] /= Short.MAX_VALUE+1f;
|
PCM[sid] /= Short.MAX_VALUE + 1f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Take down original buffer position so we don't need to sync again after...
|
||||||
//Take down original buffer position so we don't need to sync again after...
|
|
||||||
int originalPos = buffer.position();
|
int originalPos = buffer.position();
|
||||||
|
|
||||||
//Begin comparison
|
// Begin comparison
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
if (compareBuffer.compareTo(buffer) != 0) {
|
if (compareBuffer.compareTo(buffer) != 0) {
|
||||||
bufferChanged();
|
bufferChanged();
|
||||||
|
|
||||||
|
// Begin copying current buffer to the comparison buffer
|
||||||
//Begin copying current buffer to the comparison buffer
|
|
||||||
compareBuffer.clear();
|
compareBuffer.clear();
|
||||||
compareBuffer.put(buffer);
|
compareBuffer.put(buffer);
|
||||||
compareBuffer.flip();
|
compareBuffer.flip();
|
||||||
}
|
}
|
||||||
|
|
||||||
//Reset buffer to proper position.
|
// Reset buffer to proper position.
|
||||||
buffer.position(originalPos);
|
buffer.position(originalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void bufferChanged() {
|
private void bufferChanged() {
|
||||||
//set position to beginning to prepare for overwrite
|
// set position to beginning to prepare for overwrite
|
||||||
playingBuffer.position(0);
|
playingBuffer.position(0);
|
||||||
//if the backing playing buffer is full, we have two sections: A and B. A is the one before B, and is read from due to playback latency and offset. B is merely a buffer.
|
// if the backing playing buffer is full, we have two sections: A and B. A is
|
||||||
|
// the one before B, and is read from due to playback latency and offset. B is
|
||||||
|
// merely a buffer.
|
||||||
if (playingBuffer.limit() == playingBuffer.capacity()) {
|
if (playingBuffer.limit() == playingBuffer.capacity()) {
|
||||||
//put the second portion into the first...
|
// put the second portion into the first...
|
||||||
playingBuffer.put(playingBuffer.array(), buffer.capacity(), buffer.capacity());
|
playingBuffer.put(playingBuffer.array(), buffer.capacity(), buffer.capacity());
|
||||||
}
|
}
|
||||||
//put the new buffer into the remaining portion.
|
// put the new buffer into the remaining portion.
|
||||||
playingBuffer.put(compareBuffer);
|
playingBuffer.put(compareBuffer);
|
||||||
|
|
||||||
synchronizeBufferWithPlayback();
|
synchronizeBufferWithPlayback();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int calcBufferPosition() {
|
private int calcBufferPosition() {
|
||||||
int offset = (int) alGetSourcef(sourceID, AL11.AL_SAMPLE_OFFSET);
|
int offset = (int) alGetSourcef(sourceID, AL11.AL_SAMPLE_OFFSET);
|
||||||
offset = (offset/windowSize) * windowSize;
|
offset = (offset / windowSize) * windowSize;
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void synchronizeBufferWithPlayback() {
|
private void synchronizeBufferWithPlayback() {
|
||||||
playingBuffer.position(calcBufferPosition());
|
playingBuffer.position(calcBufferPosition());
|
||||||
windowsRead = (int) ((mc.getCurrentPosition()*sampleRate)/windowSize);
|
windowsRead = (int) ((mc.getCurrentPosition() * sampleRate) / windowSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setMusic() {
|
private void setMusic() {
|
||||||
try {
|
try {
|
||||||
Field sourceIDField = ClassReflection.getDeclaredField(OpenALMusic.class, "sourceID");
|
Field sourceIDField = ClassReflection.getDeclaredField(OpenALMusic.class, "sourceID");
|
||||||
@ -123,23 +124,23 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
} catch (ReflectionException e) {
|
} catch (ReflectionException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
channelCount = mc.getCurrentMusicHeader().getChannelCount();
|
channelCount = mc.getCurrentMusicHeader().getChannelCount();
|
||||||
sampleRate = mc.getCurrentMusicHeader().getSampleRate();
|
sampleRate = mc.getCurrentMusicHeader().getSampleRate();
|
||||||
|
|
||||||
playingBuffer = ShortBuffer.allocate(buffer.capacity()*2);
|
playingBuffer = ShortBuffer.allocate(buffer.capacity() * 2);
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
playingBuffer.put(buffer);
|
playingBuffer.put(buffer);
|
||||||
playingBuffer.flip();
|
playingBuffer.flip();
|
||||||
|
|
||||||
compareBuffer = ShortBuffer.allocate(buffer.capacity());
|
compareBuffer = ShortBuffer.allocate(buffer.capacity());
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
compareBuffer.put(buffer);
|
compareBuffer.put(buffer);
|
||||||
compareBuffer.flip();
|
compareBuffer.flip();
|
||||||
|
|
||||||
buffer.rewind();
|
buffer.rewind();
|
||||||
}
|
}
|
||||||
|
|
||||||
public float[] getFrequencyBins() {
|
public float[] getFrequencyBins() {
|
||||||
if (updated) {
|
if (updated) {
|
||||||
synchronized (PCM) {
|
synchronized (PCM) {
|
||||||
@ -149,11 +150,11 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
}
|
}
|
||||||
return frequencyBins;
|
return frequencyBins;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getWindowSize() {
|
public int getWindowSize() {
|
||||||
return windowSize;
|
return windowSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class BufferStreamReadThread implements Runnable {
|
private class BufferStreamReadThread implements Runnable {
|
||||||
private String name = "PCM-Audio-Processing";
|
private String name = "PCM-Audio-Processing";
|
||||||
private Thread thread;
|
private Thread thread;
|
||||||
@ -161,7 +162,7 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
private boolean paused;
|
private boolean paused;
|
||||||
private long timeOfLastRead;
|
private long timeOfLastRead;
|
||||||
private int waitTime;
|
private int waitTime;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while (run) {
|
while (run) {
|
||||||
@ -170,14 +171,14 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
timeOfLastRead = TimeUtils.millis();
|
timeOfLastRead = TimeUtils.millis();
|
||||||
paused = false;
|
paused = false;
|
||||||
}
|
}
|
||||||
waitTime = sampleRate/windowSize/Gdx.graphics.getFramesPerSecond();
|
waitTime = sampleRate / windowSize / Gdx.graphics.getFramesPerSecond();
|
||||||
if (TimeUtils.timeSinceMillis(timeOfLastRead) >= waitTime) {
|
if (TimeUtils.timeSinceMillis(timeOfLastRead) >= waitTime) {
|
||||||
calcPCMData();
|
calcPCMData();
|
||||||
updated = true;
|
updated = true;
|
||||||
windowsRead++;
|
windowsRead++;
|
||||||
timeOfLastRead = TimeUtils.millis();
|
timeOfLastRead = TimeUtils.millis();
|
||||||
|
|
||||||
currentPlaybackWindow = (int) ((mc.getCurrentPosition()*sampleRate)/windowSize);
|
currentPlaybackWindow = (int) ((mc.getCurrentPosition() * sampleRate) / windowSize);
|
||||||
if (windowsRead != currentPlaybackWindow) {
|
if (windowsRead != currentPlaybackWindow) {
|
||||||
synchronizeBufferWithPlayback();
|
synchronizeBufferWithPlayback();
|
||||||
}
|
}
|
||||||
@ -194,7 +195,7 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void start() {
|
public void start() {
|
||||||
if (thread == null && !thread.isAlive()) {
|
if (thread == null && !thread.isAlive()) {
|
||||||
thread = new Thread(this, name);
|
thread = new Thread(this, name);
|
||||||
@ -205,7 +206,7 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
public void stop() {
|
||||||
run = false;
|
run = false;
|
||||||
}
|
}
|
||||||
@ -214,15 +215,10 @@ public class PCMMachine implements Observer, Disposable {
|
|||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (o == mc) {
|
if (o == mc) {
|
||||||
switch ((MusicController.States) arg) {
|
if (arg == mc.states.LOADED) {
|
||||||
case Loaded:
|
|
||||||
setMusic();
|
setMusic();
|
||||||
break;
|
} else if (arg == mc.states.PLAYING) {
|
||||||
case Playing:
|
|
||||||
streamReadThread.start();
|
streamReadThread.start();
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ public class MainPage extends Page implements Observer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (o == mc && arg == MusicController.States.Loaded) {
|
if (o == mc && arg == mc.states.LOADED) {
|
||||||
scrollText.setText("Currently playing: " + mc.getCurrentSongName(), null);
|
scrollText.setText("Currently playing: " + mc.getCurrentSongName(), null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -233,7 +233,6 @@ public class MainScreen extends ScreenAdapter implements ResizeReadyScreen {
|
|||||||
ChangeListener analysisPageButtonListener = new ChangeListener() {
|
ChangeListener analysisPageButtonListener = new ChangeListener() {
|
||||||
@Override
|
@Override
|
||||||
public void changed(ChangeEvent event, Actor actor) {
|
public void changed(ChangeEvent event, Actor actor) {
|
||||||
musicSelectionPage.getSelectedMusic();
|
|
||||||
setDisplayedPage(analysisPage);
|
setDisplayedPage(analysisPage);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
package zero1hd.rhythmbullet.desktop.screens.main;
|
package zero1hd.rhythmbullet.desktop.screens.main;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Observable;
|
import java.util.Observable;
|
||||||
import java.util.Observer;
|
import java.util.Observer;
|
||||||
|
|
||||||
@ -8,23 +7,20 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.Input.Keys;
|
import com.badlogic.gdx.Input.Keys;
|
||||||
import com.badlogic.gdx.Preferences;
|
import com.badlogic.gdx.Preferences;
|
||||||
import com.badlogic.gdx.assets.AssetManager;
|
import com.badlogic.gdx.assets.AssetManager;
|
||||||
import com.badlogic.gdx.audio.Music;
|
|
||||||
import com.badlogic.gdx.files.FileHandle;
|
import com.badlogic.gdx.files.FileHandle;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.Texture;
|
import com.badlogic.gdx.graphics.Texture;
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion;
|
|
||||||
import com.badlogic.gdx.math.Vector3;
|
import com.badlogic.gdx.math.Vector3;
|
||||||
import com.badlogic.gdx.scenes.scene2d.Actor;
|
|
||||||
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
import com.badlogic.gdx.scenes.scene2d.InputEvent;
|
||||||
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
import com.badlogic.gdx.scenes.scene2d.InputListener;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
import com.badlogic.gdx.scenes.scene2d.ui.Image;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
import com.badlogic.gdx.scenes.scene2d.ui.Label;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
import com.badlogic.gdx.scenes.scene2d.ui.ScrollPane;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
|
||||||
|
import com.badlogic.gdx.scenes.scene2d.ui.Stack;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
import com.badlogic.gdx.scenes.scene2d.ui.Table;
|
||||||
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
import com.badlogic.gdx.scenes.scene2d.ui.TextButton;
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
import com.badlogic.gdx.scenes.scene2d.utils.ChangeListener;
|
||||||
import com.badlogic.gdx.scenes.scene2d.utils.TextureRegionDrawable;
|
|
||||||
import com.badlogic.gdx.utils.Array;
|
import com.badlogic.gdx.utils.Array;
|
||||||
|
|
||||||
import zero1hd.rhythmbullet.audio.MusicMetadataController;
|
import zero1hd.rhythmbullet.audio.MusicMetadataController;
|
||||||
@ -32,18 +28,21 @@ import zero1hd.rhythmbullet.audio.MusicController;
|
|||||||
import zero1hd.rhythmbullet.desktop.graphics.ui.pages.Page;
|
import zero1hd.rhythmbullet.desktop.graphics.ui.pages.Page;
|
||||||
import zero1hd.rhythmbullet.graphics.ui.components.MusicSelectable;
|
import zero1hd.rhythmbullet.graphics.ui.components.MusicSelectable;
|
||||||
import zero1hd.rhythmbullet.graphics.ui.components.ScrollText;
|
import zero1hd.rhythmbullet.graphics.ui.components.ScrollText;
|
||||||
|
import zero1hd.rhythmbullet.util.MusicSelectableButtonGroup;
|
||||||
|
|
||||||
public class MusicSelectionPage extends Page implements Observer {
|
public class MusicSelectionPage extends Page implements Observer {
|
||||||
Preferences musicFileAnnotation;
|
Preferences musicFileAnnotation;
|
||||||
|
|
||||||
private MusicController mc;
|
private MusicController mc;
|
||||||
private MusicMetadataController mmc;
|
private MusicMetadataController mmc;
|
||||||
|
private MusicSelectableButtonGroup selectables;
|
||||||
private Array<MusicSelectable> selectables;
|
private Stack stackSelectables;
|
||||||
private TextButton back;
|
private TextButton back;
|
||||||
private Table musicTable;
|
private Table musicTable;
|
||||||
private ScrollPane musicTableScrollPane;
|
private ScrollPane musicTableScrollPane;
|
||||||
|
|
||||||
|
private musicSelectionLoaderThread thread;
|
||||||
|
|
||||||
private Table musicInfoTable;
|
private Table musicInfoTable;
|
||||||
private Table musicSubInfo;
|
private Table musicSubInfo;
|
||||||
private ScrollText songTitle;
|
private ScrollText songTitle;
|
||||||
@ -54,9 +53,9 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
private Image albumCover;
|
private Image albumCover;
|
||||||
|
|
||||||
private AssetManager assets;
|
private AssetManager assets;
|
||||||
|
private Skin skin;
|
||||||
|
|
||||||
private boolean down, up;
|
private boolean down, up;
|
||||||
private int musicSelectableIndex;
|
|
||||||
|
|
||||||
private TextButton beginButton;
|
private TextButton beginButton;
|
||||||
|
|
||||||
@ -67,6 +66,9 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
this.assets = assetManager;
|
this.assets = assetManager;
|
||||||
this.mc = musicController;
|
this.mc = musicController;
|
||||||
this.mmc = musicMetadataController;
|
this.mmc = musicMetadataController;
|
||||||
|
this.skin = skin;
|
||||||
|
stackSelectables = new Stack();
|
||||||
|
selectables = new MusicSelectableButtonGroup();
|
||||||
musicFileAnnotation = Gdx.app.getPreferences("music_file_annotation");
|
musicFileAnnotation = Gdx.app.getPreferences("music_file_annotation");
|
||||||
|
|
||||||
musicTable = new Table();
|
musicTable = new Table();
|
||||||
@ -83,7 +85,7 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
back.addListener(backButtonListener);
|
back.addListener(backButtonListener);
|
||||||
addActor(back);
|
addActor(back);
|
||||||
back.toFront();
|
back.toFront();
|
||||||
|
|
||||||
addListener(new InputListener() {
|
addListener(new InputListener() {
|
||||||
@Override
|
@Override
|
||||||
public boolean keyDown(InputEvent event, int keycode) {
|
public boolean keyDown(InputEvent event, int keycode) {
|
||||||
@ -127,6 +129,10 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
|
|
||||||
beginButton = new TextButton("Begin", skin);
|
beginButton = new TextButton("Begin", skin);
|
||||||
beginButton.addListener(beginButtonListener);
|
beginButton.addListener(beginButtonListener);
|
||||||
|
|
||||||
|
mmc.addObserver(this);
|
||||||
|
|
||||||
|
thread = new musicSelectionLoaderThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -159,47 +165,51 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
if (songSelectionTimer > 0f) {
|
if (songSelectionTimer > 0f) {
|
||||||
songSelectionTimer -= delta;
|
songSelectionTimer -= delta;
|
||||||
if (songSelectionTimer <= 0f) {
|
if (songSelectionTimer <= 0f) {
|
||||||
setCurrentMusic();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (selectables.getButtons().size == mc.getMusicList().getTotal()) {
|
||||||
|
if (selectables.getButtons().size != stackSelectables.getChildren().size) {
|
||||||
|
int index = selectables.getButtons().size - stackSelectables.getChildren().size - 1;
|
||||||
|
stackSelectables.add(selectables.getButtons().get(index));
|
||||||
|
} else {
|
||||||
|
if (selectables.getChecked() == null) {
|
||||||
|
selectables.setChecked(mc.getCurrentMusicFileHandle());
|
||||||
|
} else if (selectables.getChecked().getFileHandle() != mc.getCurrentMusicFileHandle()) {
|
||||||
|
songSelectionTimer += delta;
|
||||||
|
if (songSelectionTimer > 2f) {
|
||||||
|
mc.setMusicByFileHandle(selectables.getChecked().getFileHandle());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
songSelectionTimer = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
super.act(delta);
|
super.act(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scrollDown() {
|
private void scrollDown() {
|
||||||
if ((musicSelectableIndex = (musicTable.getChildren().indexOf(currentlySelected, true) + 1)) == musicTable.getChildren().size) {
|
selectables.selectNext();
|
||||||
musicSelectableIndex = 0;
|
musicTableScrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
|
||||||
}
|
|
||||||
((MusicSelectable)musicTable.getChildren().get(musicSelectableIndex)).select();
|
|
||||||
musicTableScrollPane.scrollTo(currentlySelected.getX(), currentlySelected.getY(), currentlySelected.getWidth(), currentlySelected.getHeight());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void scrollUp() {
|
private void scrollUp() {
|
||||||
if ((musicSelectableIndex = (musicTable.getChildren().indexOf(currentlySelected, true) - 1)) < 0) {
|
selectables.selectPrevious();
|
||||||
musicSelectableIndex = musicTable.getChildren().size-1;
|
musicTableScrollPane.scrollTo(selectables.getChecked().getX(), selectables.getChecked().getY(), selectables.getChecked().getWidth(), selectables.getChecked().getHeight());
|
||||||
}
|
|
||||||
((MusicSelectable)musicTable.getChildren().get(musicSelectableIndex)).select();
|
|
||||||
musicTableScrollPane.scrollTo(currentlySelected.getX(), currentlySelected.getY(), currentlySelected.getWidth(), currentlySelected.getHeight());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileHandle getSelectedMusic() {
|
public FileHandle getSelectedMusic() {
|
||||||
if (currentlySelected != null) {
|
return selectables.getChecked().getMetadata().getFileHandle();
|
||||||
return currentlySelected.getMusicFile();
|
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void refreshUIList() {
|
public void refreshUIList() {
|
||||||
for (int i = 0; i < selectables.size; i++) {
|
selectables.clear();
|
||||||
selectables.get(i).dispose();
|
|
||||||
}
|
|
||||||
mmc.loadAudioMetadata();
|
mmc.loadAudioMetadata();
|
||||||
musicTable.clear();
|
musicTable.clear();
|
||||||
selectables.clear();
|
selectables.clear();
|
||||||
musicInfoTable.clear();
|
musicInfoTable.clear();
|
||||||
musicSubInfo.clear();
|
musicSubInfo.clear();
|
||||||
uiSongCount = 0;
|
|
||||||
uiSongInfoCount = 0;
|
|
||||||
|
|
||||||
Gdx.app.debug("MusicSelectionPage", "Refreshing...");
|
Gdx.app.debug("MusicSelectionPage", "Refreshing...");
|
||||||
|
|
||||||
@ -226,18 +236,17 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update(Observable o, Object arg) {
|
public void update(Observable o, Object arg) {
|
||||||
if (o == mc && arg == MusicController.States.Loaded) {
|
if (o == mc && arg == mc.states.LOADED) {
|
||||||
selectMusicUI(mc.getCurrentMusicFileHandle());
|
if (selectables.getChecked().getFileHandle() != mc.getCurrentMusicFileHandle()) {
|
||||||
|
selectables.setChecked(mc.getCurrentlyPlayingIndex());
|
||||||
|
}
|
||||||
|
} else if (o == mmc) {
|
||||||
|
thread.start();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void selectMusicUI(FileHandle fileHandle) {
|
|
||||||
selectables.get(mc.getMusicList().getMusicArray().indexOf(fileHandle, true)).select();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
public void setCameraPositionToPage(Vector3 cameraPosition) {
|
||||||
getStage().setKeyboardFocus(this);
|
getStage().setKeyboardFocus(this);
|
||||||
@ -245,11 +254,49 @@ public class MusicSelectionPage extends Page implements Observer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private class musicSelectionLoaderThread implements Runnable {
|
private class musicSelectionLoaderThread implements Runnable {
|
||||||
|
private Thread thread;
|
||||||
|
private Array<MusicSelectable> queueList;
|
||||||
|
private String name = "Music-Selection-Loader-Thread";
|
||||||
|
private volatile boolean work;
|
||||||
|
|
||||||
|
public musicSelectionLoaderThread() {
|
||||||
|
queueList = new Array<>();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
// TODO Auto-generated method stub
|
while (work) {
|
||||||
|
while (selectables.getButtons().size != mc.getMusicList().getTotal()) {
|
||||||
|
MusicSelectable selectable = new MusicSelectable(skin, assets.get("defaultCover.png"), mmc.getMetadata(selectables.getButtons().size), queueList);
|
||||||
|
selectables.add(selectable);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < queueList.size; i++) {
|
||||||
|
queueList.get(i).loadAlbumCover();
|
||||||
|
queueList.removeIndex(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized (queueList) {
|
||||||
|
try {
|
||||||
|
wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean start() {
|
||||||
|
if (thread == null) {
|
||||||
|
thread = new Thread(this, name);
|
||||||
|
thread.start();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
synchronized (queueList) {
|
||||||
|
notify();
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user