protected AudioPlayer constructPlayer() { return new DefaultAudioPlayer(this); }
/** * Check if the player should be "cleaned up" - stopped due to nothing using it, with the given threshold. * @param threshold Threshold in milliseconds to use */ public void checkCleanup(long threshold) { AudioTrack track = getPlayingTrack(); if (track != null && System.currentTimeMillis() - lastRequestTime >= threshold) { log.debug("Triggering cleanup on an audio player playing track {}", track); stopWithReason(CLEANUP); } } }
/** * @param track The track to start playing */ public void playTrack(AudioTrack track) { startTrack(track, false); }
@Override public AudioFrame provide(long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { InternalAudioTrack track; lastRequestTime = System.currentTimeMillis(); if (timeout == 0 && paused.get()) { return null; } while ((track = activeTrack) != null) { AudioFrame frame = timeout > 0 ? track.provide(timeout, unit) : track.provide(); if (frame != null) { lastReceiveTime = System.nanoTime(); shadowTrack = null; if (frame.isTerminator()) { handleTerminator(track); continue; } } else if (timeout == 0) { checkStuck(track); frame = provideShadowFrame(); } return frame; } return null; }
/** * @param value True to pause, false to resume */ public void setPaused(boolean value) { if (paused.compareAndSet(!value, value)) { if (value) { dispatchEvent(new PlayerPauseEvent(this)); } else { dispatchEvent(new PlayerResumeEvent(this)); lastReceiveTime = System.nanoTime(); } } }
/** * Stop currently playing track. */ public void stopTrack() { stopWithReason(STOPPED); }
/** * Destroy the player and stop playing track. */ public void destroy() { stopTrack(); }
@Override public boolean provide(MutableAudioFrame targetFrame) { try { return provide(targetFrame, 0, TimeUnit.MILLISECONDS); } catch (TimeoutException | InterruptedException e) { ExceptionTools.keepInterrupted(e); throw new RuntimeException(e); } }
@Override public boolean provide(MutableAudioFrame targetFrame, long timeout, TimeUnit unit) throws TimeoutException, InterruptedException { InternalAudioTrack track; lastRequestTime = System.currentTimeMillis(); if (timeout == 0 && paused.get()) { return false; } while ((track = activeTrack) != null) { if (timeout > 0 ? track.provide(targetFrame, timeout, unit) : track.provide(targetFrame)) { lastReceiveTime = System.nanoTime(); shadowTrack = null; if (targetFrame.isTerminator()) { handleTerminator(track); continue; } return true; } else if (timeout == 0) { checkStuck(track); return provideShadowFrame(targetFrame); } else { return false; } } return false; }
@Override public void onTrackStuck(AudioTrack track, long thresholdMs) { dispatchEvent(new TrackStuckEvent(this, track, thresholdMs)); }
@Override public void onTrackException(AudioTrack track, FriendlyException exception) { dispatchEvent(new TrackExceptionEvent(this, track, exception)); }
private void checkStuck(AudioTrack track) { if (!stuckEventSent && System.nanoTime() - lastReceiveTime > manager.getTrackStuckThresholdNanos()) { stuckEventSent = true; dispatchEvent(new TrackStuckEvent(this, track, TimeUnit.NANOSECONDS.toMillis(manager.getTrackStuckThresholdNanos()))); } }
private void stopWithReason(AudioTrackEndReason reason) { shadowTrack = null; synchronized (trackSwitchLock) { InternalAudioTrack previousTrack = activeTrack; activeTrack = null; if (previousTrack != null) { previousTrack.stop(); dispatchEvent(new TrackEndEvent(this, previousTrack, reason)); } } }
private void handleTerminator(InternalAudioTrack track) { synchronized (trackSwitchLock) { if (activeTrack == track) { activeTrack = null; dispatchEvent(new TrackEndEvent(this, track, track.getActiveExecutor().failedBeforeLoad() ? LOAD_FAILED : FINISHED)); } } }
dispatchEvent(new TrackEndEvent(this, previousTrack, newTrack == null ? STOPPED : REPLACED)); dispatchEvent(new TrackStartEvent(this, newTrack));