/// <param name="manager"> Audio player manager which this player is attached to </param> /// <param name="outputHook"> Hook which can intercept outgoing audio frames </param> public AudioPlayer(DefaultAudioPlayerManager manager, AudioOutputHook outputHook) { this.manager = manager; this.outputHook = outputHook; activeTrack = null; paused = new AtomicBoolean(); listeners = new IList <AudioEventListener>(); volumeLevel = new AtomicInteger(100); trackSwitchLock = new object(); }
private void handleTerminator(InternalAudioTrack track) { lock (trackSwitchLock) { if (activeTrack == track) { activeTrack = null; dispatchEvent(new TrackEndEvent(this, track, track.ActiveExecutor.failedBeforeLoad() ? AudioTrackEndReason.LOAD_FAILED : AudioTrackEndReason.FINISHED)); } } }
private void stopWithReason(AudioTrackEndReason reason) { shadowTrack = null; lock (trackSwitchLock) { InternalAudioTrack previousTrack = activeTrack; activeTrack = null; if (previousTrack != null) { previousTrack.stop(); dispatchEvent(new TrackEndEvent(this, previousTrack, reason)); } } }
private AudioFrame provideShadowFrame() { InternalAudioTrack shadow = shadowTrack; AudioFrame frame = null; if (shadow != null) { frame = shadow.provide(); if (frame != null && frame.Terminator) { shadowTrack = null; frame = null; } } return(frame); }
/// <param name="track"> The track to start playing, passing null will stop the current track and return false </param> /// <param name="noInterrupt"> Whether to only start if nothing else is playing </param> /// <returns> True if the track was started </returns> public virtual bool startTrack(AudioTrack track, bool noInterrupt) { InternalAudioTrack newTrack = (InternalAudioTrack)track; InternalAudioTrack previousTrack; lock (trackSwitchLock) { previousTrack = activeTrack; if (noInterrupt && previousTrack != null) { return(false); } } activeTrack = newTrack; lastRequestTime = DateTimeHelperClass.CurrentUnixTimeMillis(); lastReceiveTime = nanoTime(); stuckEventSent = false; if (previousTrack != null) { previousTrack.stop(); dispatchEvent(new TrackEndEvent(this, previousTrack, newTrack == null ? AudioTrackEndReason.STOPPED : AudioTrackEndReason.REPLACED)); shadowTrack = previousTrack; } if (newTrack == null) { shadowTrack = null; return(false); } dispatchEvent(new TrackStartEvent(this, newTrack)); manager.executeTrack(this, newTrack, manager.Configuration, volumeLevel); return(true); }
/// <summary> /// Provide an audio frame bypassing hooks. </summary> /// <param name="timeout"> Specifies the maximum time to wait for data. Pass 0 for non-blocking mode. </param> /// <param name="unit"> Specifies the time unit of the maximum wait time. </param> /// <returns> An audio frame if available, otherwise null </returns> public AudioFrame provideDirectly(long timeout, TimeUnit unit) { InternalAudioTrack track; lastRequestTime = DateTimeHelperClass.CurrentUnixTimeMillis(); 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 = nanoTime(); shadowTrack = null; if (frame.Terminator) { handleTerminator(track); continue; } } else if (timeout == 0) { checkStuck(track); frame = provideShadowFrame(); } return(frame); } return(null); }