Skip to content

Commit

Permalink
Allow delaying the song start
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphiMC committed Jan 2, 2025
1 parent 2bfaa2f commit 734f2a8
Showing 1 changed file with 74 additions and 5 deletions.
79 changes: 74 additions & 5 deletions src/main/java/net/raphimc/noteblocklib/player/SongPlayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,18 @@ public SongPlayer(final Song song) {
this.song = song;
}

/**
* Starts playing the song from the beginning.
*/
public void start() {
this.start(0);
}

/**
* Starts playing the song from the beginning.
* @param delay The delay in milliseconds before starting the song.
*/
public void start(final int delay) {
if (this.isRunning()) this.stop();

this.ticksPerSecond = this.song.getTempoEvents().getTempo(0);
Expand All @@ -53,9 +64,12 @@ public void start() {
thread.setDaemon(true);
return thread;
});
this.createTickTask();
this.createTickTask(TimeUnit.MILLISECONDS.toNanos(delay));
}

/**
* Stops playing the song.
*/
public void stop() {
if (!this.isRunning()) return;

Expand All @@ -69,54 +83,95 @@ public void stop() {
this.paused = false;
}

/**
* @return Whether the player is in the running state (playing or paused).
*/
public boolean isRunning() {
return this.scheduler != null && !this.scheduler.isTerminated();
}

/**
* @return The song that is being played.
*/
public Song getSong() {
return this.song;
}

/**
* Sets the song that should be played.<br>
* Can be called in {@link #onFinished()}.
* @param song The song to play.
*/
protected void setSong(final Song song) {
this.song = song;
}

/**
* @return The current tempo in ticks per second.
*/
public float getCurrentTicksPerSecond() {
return this.ticksPerSecond;
}

/**
* @return The current tick.
*/
public int getTick() {
return this.tick;
}

/**
* Sets the current tick.
* @param tick The tick to set.
*/
public void setTick(final int tick) {
this.tick = tick;
}

/**
* @return The current playback position in milliseconds.
*/
public int getMillisecondPosition() {
return this.song.tickToMilliseconds(this.tick);
}

/**
* Sets the current playback position in milliseconds.
* @param milliseconds The time to set the playback position to.
*/
public void setMillisecondPosition(final int milliseconds) {
this.tick = this.song.millisecondsToTick(milliseconds);
}

/**
* @return Whether the player is paused.
*/
public boolean isPaused() {
return this.paused;
}

/**
* Pauses or resumes the player.
* @param paused Whether the player should be paused.
*/
public void setPaused(final boolean paused) {
this.paused = paused;
}

protected void createTickTask() {
/**
* Create the internal tick task.
* @param initialDelay The initial delay in nanoseconds.
*/
protected void createTickTask(final long initialDelay) {
if (this.tickTask != null) {
this.tickTask.cancel(false);
}
final long period = (long) (1_000_000_000D / this.ticksPerSecond);
this.tickTask = this.scheduler.scheduleAtFixedRate(this::tick, this.tickTask != null ? period : 0L, period, TimeUnit.NANOSECONDS);
this.tickTask = this.scheduler.scheduleAtFixedRate(this::tick, initialDelay, (long) (1_000_000_000D / this.ticksPerSecond), TimeUnit.NANOSECONDS);
}

/**
* Called every tick to play the notes.
*/
protected void tick() {
try {
if (!this.preTick()) {
Expand All @@ -137,7 +192,7 @@ protected void tick() {
}
if (this.ticksPerSecond != this.song.getTempoEvents().getEffectiveTempo(this.tick)) {
this.ticksPerSecond = this.song.getTempoEvents().getEffectiveTempo(this.tick);
this.createTickTask();
this.createTickTask((long) (1_000_000_000D / this.ticksPerSecond));
}
} finally {
this.postTick();
Expand All @@ -150,15 +205,29 @@ protected void tick() {
}
}

/**
* Called before each tick (Even when paused).
* @return Whether the tick should be executed.
*/
protected boolean preTick() {
return true;
}

/**
* Plays the notes.
* @param notes The notes to play.
*/
protected abstract void playNotes(final List<Note> notes);

/**
* Called when the song has finished playing.
*/
protected void onFinished() {
}

/**
* Called after each tick.
*/
protected void postTick() {
}

Expand Down

0 comments on commit 734f2a8

Please sign in to comment.