private bool handlePlaybackInterrupt(InterruptedException interruption, SeekExecutor seekExecutor) { java.lang.Thread.interrupted(); if (checkStopped()) { markerTracker.trigger(STOPPED); return(false); } else if (checkPendingSeek(seekExecutor)) { // Double-check, might have received a stop request while seeking if (checkStopped()) { markerTracker.trigger(STOPPED); return(false); } else { return(true); } } else if (interruption != null) { System.Threading.Thread.CurrentThread.Interrupt(); throw new FriendlyException("The track was unexpectedly terminated.", SUSPICIOUS, interruption); } else { return(true); } }
/// <summary> /// Performs a seek if it scheduled. </summary> /// <param name="seekExecutor"> Callback for performing a seek on the track </param> /// <returns> True if a seek was performed </returns> private bool checkPendingSeek(SeekExecutor seekExecutor) { if (!audioTrack.Seekable) { return(false); } long seekPosition; lock (actionSynchronizer) { seekPosition = pendingSeek.get(); if (seekPosition == -1) { return(false); } log.LogDebug("Track {} interrupted for seeking to {}.", audioTrack.Identifier, seekPosition); applySeekState(seekPosition); } try { seekExecutor.performSeek(seekPosition); } catch (System.Exception e) { throw ExceptionTools.wrapUnfriendlyExceptions("Something went wrong when seeking to a position.", FAULT, e); } return(true); }
/// <summary> /// Execute the read and seek loop for the track. </summary> /// <param name="readExecutor"> Callback for reading the track </param> /// <param name="seekExecutor"> Callback for performing a seek on the track, may be null on a non-seekable track </param> public virtual void executeProcessingLoop(ReadExecutor readExecutor, SeekExecutor seekExecutor) { bool proceed = true; checkPendingSeek(seekExecutor); while (proceed) { state.set(AudioTrackState.PLAYING); proceed = false; try { // An interrupt may have been placed while we were handling the previous one. if (java.lang.Thread.interrupted() && !handlePlaybackInterrupt(null, seekExecutor)) { break; } InterruptibleForSeek = true; readExecutor.performRead(); InterruptibleForSeek = false; // Must not finish before terminator frame has been consumed the user may still want to perform seeks until then waitOnEnd(); } catch (System.Exception e) { InterruptibleForSeek = false; InterruptedException interruption = findInterrupt(e); if (interruption != null) { proceed = handlePlaybackInterrupt(interruption, seekExecutor); } else { throw ExceptionTools.wrapUnfriendlyExceptions("Something went wrong when decoding the track.", FAULT, e); } } } }