253 lines
6.2 KiB
Java
Executable File
253 lines
6.2 KiB
Java
Executable File
package zero1hd.rhythmbullet.audio;
|
|
|
|
import java.util.Observable;
|
|
import java.util.Observer;
|
|
import java.util.Random;
|
|
|
|
import com.badlogic.gdx.Gdx;
|
|
import com.badlogic.gdx.Preferences;
|
|
import com.badlogic.gdx.audio.Music;
|
|
import com.badlogic.gdx.audio.Music.OnCompletionListener;
|
|
import com.badlogic.gdx.files.FileHandle;
|
|
|
|
/**
|
|
* Manages current games music playback and does this in tandem with the {@link MusicList} by asking to retrieve files and then feeding it to LibGDX.
|
|
* Notifies observers when a new song is loaded.
|
|
* The loading model is like taking a disk and loading it into a player. It doesn't necessarily mean it'll play right away, but its ready and the only track that has a stream opened.
|
|
* @author yunya
|
|
*
|
|
*/
|
|
public class MusicController extends Observable implements OnCompletionListener, Observer {
|
|
public final class States {
|
|
public final Integer LOADED = new Integer(0), PLAYING = new Integer(1);
|
|
}
|
|
|
|
public final States states = new States();
|
|
private MusicList musicList;
|
|
private MinimalAudioHeader musicHeader;
|
|
private volatile Music music;
|
|
private int currentlyPlayingIndex;
|
|
private boolean autoPlay;
|
|
private boolean shuffle;
|
|
private Random rand;
|
|
private Preferences prefs;
|
|
|
|
public MusicController(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...");
|
|
musicList.addObserver(this);
|
|
this.prefs = prefs;
|
|
this.musicList = musicList;
|
|
rand = new Random();
|
|
}
|
|
|
|
/**
|
|
* This play method automatically sets the volume.
|
|
*/
|
|
public void play() {
|
|
if (music != null) {
|
|
Gdx.app.debug("MusicController", "Playing from MLC.");
|
|
music.play();
|
|
music.setVolume(prefs.getFloat("music vol", 1f));
|
|
setChanged();
|
|
notifyObservers(states.PLAYING);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Called to pause current song. Does nothing if no song is playing or loaded.
|
|
*/
|
|
public void pause() {
|
|
if (music != null) {
|
|
music.pause();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Loads music based on the index in the {@link MusicList}.
|
|
* @param index of music to play
|
|
*/
|
|
public void setMusicByIndex(int index) {
|
|
this.currentlyPlayingIndex = index;
|
|
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
|
|
*/
|
|
public void skip() {
|
|
currentlyPlayingIndex++;
|
|
if (shuffle) {
|
|
shuffle();
|
|
}
|
|
loadMusic();
|
|
}
|
|
|
|
/**
|
|
* Goes to the previous track
|
|
*/
|
|
public void previous() {
|
|
currentlyPlayingIndex--;
|
|
if (shuffle) {
|
|
shuffle();
|
|
}
|
|
loadMusic();
|
|
}
|
|
|
|
@Override
|
|
public void onCompletion(Music music) {
|
|
if (autoPlay) {
|
|
if (shuffle) {
|
|
shuffle();
|
|
} else {
|
|
currentlyPlayingIndex++;
|
|
}
|
|
loadMusic();
|
|
play();
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Shuffles the controller whether the shuffle boolean is true or false.
|
|
*/
|
|
public void shuffle() {
|
|
Gdx.app.debug("MusicListController", "shuffled.");
|
|
if (musicList.getTotal() == 0) {
|
|
currentlyPlayingIndex = 0;
|
|
} else {
|
|
currentlyPlayingIndex = rand.nextInt(musicList.getTotal());
|
|
}
|
|
}
|
|
|
|
public void setAutoPlay(boolean autoPlay) {
|
|
this.autoPlay = autoPlay;
|
|
}
|
|
|
|
public void setShuffle(boolean shuffle) {
|
|
this.shuffle = shuffle;
|
|
}
|
|
|
|
public boolean isShuffle() {
|
|
return shuffle;
|
|
}
|
|
|
|
public boolean isAutoPlay() {
|
|
return autoPlay;
|
|
}
|
|
|
|
/**
|
|
* Loads the current selected song.
|
|
*/
|
|
public void loadMusic() {
|
|
Gdx.app.debug("MusicListController", "music is being loaded and listeners are being notified.");
|
|
boolean playing = isPlaying();
|
|
musicHeader = null;
|
|
if (music != null) {
|
|
music.dispose();
|
|
}
|
|
if (currentlyPlayingIndex < 0) {
|
|
currentlyPlayingIndex = musicList.getTotal()-1;
|
|
}
|
|
if (currentlyPlayingIndex >= musicList.getTotal()) {
|
|
currentlyPlayingIndex = 0;
|
|
}
|
|
if (musicList.getTotal() != 0) {
|
|
this.music = Gdx.audio.newMusic(musicList.getMusicArray().get(currentlyPlayingIndex));
|
|
music.setOnCompletionListener(this);
|
|
|
|
setChanged();
|
|
|
|
notifyObservers(states.LOADED);
|
|
if (playing) {
|
|
play();
|
|
}
|
|
}
|
|
}
|
|
|
|
public MusicList getMusicList() {
|
|
return musicList;
|
|
}
|
|
|
|
public FileHandle getCurrentMusicFileHandle() {
|
|
return musicList.getSongFileHandleFromIndex(currentlyPlayingIndex);
|
|
}
|
|
|
|
public MinimalAudioHeader getCurrentMusicHeader() {
|
|
if (musicHeader != null) {
|
|
return musicHeader;
|
|
} else {
|
|
return musicHeader = musicList.newMinimalAudioHeader(getCurrentMusicFileHandle());
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void update(Observable o, Object arg) {
|
|
if (o == musicList) {
|
|
if (arg == musicList.states.LOADING) {
|
|
pause();
|
|
} else if (arg == musicList.states.COMPLETE) {
|
|
if (shuffle) {
|
|
shuffle();
|
|
}
|
|
loadMusic();
|
|
if (autoPlay) {
|
|
play();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public String getCurrentSongName() {
|
|
return getCurrentMusicFileHandle().nameWithoutExtension();
|
|
}
|
|
|
|
public float getCurrentPosition() {
|
|
if (music != null) {
|
|
return music.getPosition();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
public void setMusicPosition(float position) {
|
|
if (music != null) {
|
|
music.setPosition(position);
|
|
}
|
|
}
|
|
|
|
public boolean isPlaying() {
|
|
if (music != null) {
|
|
return music.isPlaying();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Returns the current music. In no circumstances should this be used to begin playing or it would be playing independent of the controller.
|
|
* Doing otherwise would mean you are playing the music separately of the controller.
|
|
* @return the {@link Music} that is currently "loaded" and ready to play.
|
|
*/
|
|
public Music getCurrentMusic() {
|
|
return music;
|
|
}
|
|
|
|
public int getCurrentlyPlayingIndex() {
|
|
return currentlyPlayingIndex;
|
|
}
|
|
|
|
public boolean hasSongLoaded() {
|
|
if (music != null) {
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|