/** * @param trackInfo Information of the track this executor is used with */ public PrimordialAudioTrackExecutor(AudioTrackInfo trackInfo) { this.trackInfo = trackInfo; this.markerTracker = new TrackMarkerTracker(); }
@Override public void setPosition(long timecode) { position = timecode; markerTracker.checkSeekTimecode(timecode); }
@Override public void setMarker(TrackMarker marker) { markerTracker.set(marker, position); }
/** * Detach the currently active listener, so no useless reference would be kept and no events would be sent there. */ public void detach() { activeListener = null; markerTracker.trigger(ENDED); }
private void processProvidedFrame(AudioFrame frame) { if (frame != null && !frame.isTerminator()) { lastFrameTimecode.set(frame.getTimecode()); if (pendingSeek.get() == NO_SEEK && !frameBuffer.hasClearOnInsert()) { markerTracker.checkPlaybackTimecode(frame.getTimecode()); } } }
/** * Apply the position and loop state that had been set on this executor to an actual executor. * @param executor The executor to apply the state to */ public void applyStateToExecutor(AudioTrackExecutor executor) { if (position != 0) { executor.setPosition(position); } executor.setMarker(markerTracker.remove()); } }
/** * Check a timecode which was reached by seeking, trigger BYPASSED if necessary. * @param timecode Timecode which was reached by seeking. */ public void checkSeekTimecode(long timecode) { TrackMarker marker = current.get(); if (marker != null && timecode >= marker.timecode) { trigger(marker, BYPASSED); } }
private void processProvidedFrame(AudioFrame frame) { if (frame != null && !frame.isTerminator()) { if (!isPerformingSeek()) { markerTracker.checkPlaybackTimecode(frame.getTimecode()); } lastFrameTimecode.set(frame.getTimecode()); } }
/** * Check a timecode which was reached by normal playback, trigger REACHED if necessary. * @param timecode Timecode which was reached by normal playback. */ public void checkPlaybackTimecode(long timecode) { TrackMarker marker = current.get(); if (marker != null && timecode >= marker.timecode) { trigger(marker, REACHED); } }
/** * Clear the current seeking if its position matches the specified position * @param position The position to compare with */ public void clearSeek(long position) { if (position != NO_SEEK) { frameBuffer.setClearOnInsert(); if (pendingSeek.compareAndSet(position, NO_SEEK)) { markerTracker.checkSeekTimecode(position); } } }
@Override public void setMarker(TrackMarker marker) { markerTracker.set(marker, getPosition()); }
/** * Set a new track position marker. * @param marker Marker * @param currentTimecode Current timecode of the track when this marker is set */ public void set(TrackMarker marker, long currentTimecode) { TrackMarker previous = current.getAndSet(marker); if (previous != null) { previous.handler.handle(marker != null ? OVERWRITTEN : REMOVED); } if (marker != null && currentTimecode >= marker.timecode) { trigger(marker, LATE); } }
private void applySeekState(long seekPosition) { state.set(AudioTrackState.SEEKING); if (useSeekGhosting) { frameBuffer.setClearOnInsert(); } else { frameBuffer.clear(); } queuedSeek.set(-1); markerTracker.checkSeekTimecode(seekPosition); }
@Override public void setMarker(TrackMarker marker) { markerTracker.set(marker, getPosition()); }
private boolean handlePlaybackInterrupt(InterruptedException interruption, SeekExecutor seekExecutor) { Thread.interrupted(); if (checkStopped()) { markerTracker.trigger(STOPPED); return false; } SeekResult seekResult = checkPendingSeek(seekExecutor); if (seekResult != SeekResult.NO_SEEK) { // Double-check, might have received a stop request while seeking if (checkStopped()) { markerTracker.trigger(STOPPED); return false; } else { return seekResult == SeekResult.INTERNAL_SEEK; } } else if (interruption != null) { Thread.currentThread().interrupt(); throw new FriendlyException("The track was unexpectedly terminated.", SUSPICIOUS, interruption); } else { return true; } }
@Override public void stop() { frameBuffer.lockBuffer(); frameBuffer.setTerminateOnEmpty(); frameBuffer.clear(); markerTracker.trigger(STOPPED); remoteNodeManager.onTrackEnd(null, track, AudioTrackEndReason.STOPPED); }
markerTracker.trigger(ENDED); state.set(AudioTrackState.FINISHED);