public int Read(byte[] buffer, int offset, int length, out Meta?meta) { meta = default; int read; var instance = ffmpegInstance; if (instance is null) { return(0); } try { read = instance.FfmpegProcess.StandardOutput.BaseStream.Read(buffer, 0, length); } catch (Exception ex) { read = 0; Log.Debug(ex, "Can't read ffmpeg"); } if (read == 0) { AssertNotMainScheduler(); var(ret, triggerEndSafe) = instance.IsIcyStream ? OnReadEmptyIcy(instance) : OnReadEmpty(instance); if (ret) { return(0); } if (instance.FfmpegProcess.HasExitedSafe()) { Log.Trace("Ffmpeg has exited"); AudioStop(); triggerEndSafe = true; } if (triggerEndSafe) { OnSongEnd?.Invoke(this, EventArgs.Empty); return(0); } } instance.HasTriedToReconnect = false; instance.AudioTimer.PushBytes(read); return(read); }
private void ParseData(string input) { var splits = input.Split(new[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Split(new[] { ' ' }, 2)); var typeKVP = splits.FirstOrDefault(); if (typeKVP == null) { throw new InvalidOperationException("Empty response"); } splits = splits.Skip(1); switch (typeKVP[0]) { case "error": Log.Write(Log.Level.Warning, "Erroneous answer: {0}", typeKVP[1]); break; case "answer": switch (typeKVP[1]) { case "music": musicInfoWaiter.Notify(CurrentMusicInfo = ParseMusicData(splits)); break; case "audio": break; case "end_event": break; default: throw new NotSupportedException("Answer not recognized"); } break; case "callback": switch (typeKVP[1]) { // Error during decoding (can be ignored) case "musicdecodeerror": break; // Fatal error, song cannot be started/continued case "musicreaderror": // song has finished case "musicfinished": OnSongEnd?.Invoke(this, new EventArgs()); break; default: throw new NotSupportedException("Callback not recognized"); } break; case "pong": Log.Write(Log.Level.Debug, "Alrighty then!"); break; default: throw new NotSupportedException("Response not recognized"); } }
void Update() { Alive = Source.time + Range / Speed; while (Box < Boxes.Count && Boxes[Box].Timestamp <= Alive) { GameObject NewCube = Instantiate(Cube, transform); NewCube.name = Boxes[Box].Timestamp.ToString(); float Width = Boxes[Box].Position.x, Height = Boxes[Box].Position.y; NewCube.transform.localPosition = new Vector3(Width * PathWidth, Height * PathHeight, 0); NewCube.transform.localScale = Size; Material NewMat = new Material(CubeMat); NewMat.SetColor("_Color", Boxes[Box].Tint); NewMat.SetColor("_Edge", Boxes[Box].Edge); NewCube.GetComponent <Renderer>().material = NewMat; Cubes.Add(NewCube); ++Box; } foreach (GameObject MovingCube in Cubes) { if (!MovingCube || MovingCube.transform.localPosition.z < -Overrun) { Destroyables.Enqueue(MovingCube); } else { Vector3 CurrentPos = MovingCube.transform.localPosition; float Distance = (float.Parse(MovingCube.name) - Alive) * Speed + Range; MovingCube.transform.localPosition = new Vector3(CurrentPos.x, CurrentPos.y, Distance); } } while (Destroyables.Count != 0) { GameObject Target = Destroyables.Dequeue(); Cubes.Remove(Target); if (Target) { Destroy(Target.GetComponent <Renderer>().material); Destroy(Target); } } if (PlayState != Source.IsPlaying) { PlayState = Source.IsPlaying; OnSongEnd?.Invoke(); } }
public int Read(byte[] buffer, int offset, int length, out Meta?meta) { var stream = InStream; if (stream is null) { meta = default; return(0); } var read = stream.Read(buffer, offset, length, out meta); if (read == 0 && !hasFired) { hasFired = true; OnSongEnd?.Invoke(this, EventArgs.Empty); return(0); } return(read); }
void AttendTile(uint tileID) { if (isPlayingSong) { if (targetSquence.Count > 0) { if (targetSquence.Peek() == tileID) { targetSquence.Dequeue(); if (targetSquence.Count <= 0) { isPlayingSong = false; channel.clip = songClips[targetSong]; channel.Play(); OnSongEnd.Invoke(targetSong); } } } } }
private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.RemainingBufferDuration < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { // check for premature connection drop if (ffmpegProcess.HasExited && !hasTriedToReconnectAudio) { var expectedStopLength = GetCurrentSongLength(); if (expectedStopLength != TimeSpan.Zero) { var actualStopPosition = audioTimer.SongPosition; if (actualStopPosition + retryOnDropBeforeEnd < expectedStopLength) { Log.Write(Log.Level.Debug, "Connection to song lost, retrying at {0}", actualStopPosition); hasTriedToReconnectAudio = true; Position = actualStopPosition; return; } } } if (ffmpegProcess.HasExited && audioTimer.RemainingBufferDuration < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } hasTriedToReconnectAudio = false; audioTimer.PushBytes(read); bool doSend = true; switch (SendMode) { case TargetSendMode.None: doSend = false; break; case TargetSendMode.Voice: break; case TargetSendMode.Whisper: case TargetSendMode.WhisperGroup: if (isStall) { if (++stallCount % StallCountInterval == 0) { stallNoErrorCount++; if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; } } else { doSend = false; } } if (SendMode == TargetSendMode.Whisper) { doSend &= channelSubscriptionsCache.Length > 0 || clientSubscriptionsCache.Length > 0; } break; default: throw new InvalidOperationException(); } // Save cpu when we know there is noone to send to if (!doSend) { break; } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPcmAudio(audioBuffer, read); while (encoder.HasPacket) { var packet = encoder.GetPacket(); switch (SendMode) { case TargetSendMode.Voice: tsFullClient.SendAudio(packet.Array, packet.Length, encoder.Codec); break; case TargetSendMode.Whisper: tsFullClient.SendAudioWhisper(packet.Array, packet.Length, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); break; case TargetSendMode.WhisperGroup: tsFullClient.SendAudioGroupWhisper(packet.Array, packet.Length, encoder.Codec, GroupWhisperType, GroupWhisperTarget); break; } encoder.ReturnPacket(packet.Array); } } } }
private void TriggerSongEnd(object o, EventArgs e) => OnSongEnd?.Invoke(this, EventArgs.Empty);
private void TriggerSongEnd(object?o, EventArgs e) => scheduler.InvokeAsync(() => OnSongEnd.InvokeAsync(this, EventArgs.Empty));
private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.RemainingBufferDuration < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { // check for premature connection drop if (ffmpegProcess.HasExited && !hasTriedToReconnectAudio) { var expectedStopLength = GetCurrentSongLength(); if (expectedStopLength != TimeSpan.Zero) { var actualStopPosition = audioTimer.SongPosition; if (actualStopPosition + retryOnDropBeforeEnd < expectedStopLength) { Log.Write(Log.Level.Debug, "Connection to song lost, retrying at {0}", actualStopPosition); hasTriedToReconnectAudio = true; Position = actualStopPosition; return; } } } if (ffmpegProcess.HasExited && audioTimer.RemainingBufferDuration < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } hasTriedToReconnectAudio = false; audioTimer.PushBytes(read); if (isStall) { stallCount++; if (stallCount % StallCountInterval == 0) { stallNoErrorCount++; } if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; break; } } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPCMAudio(audioBuffer, read); Tuple <byte[], int> encodedArr; while ((encodedArr = encoder.GetPacket()) != null) { if (channelSubscriptionsCache.Length == 0 && clientSubscriptionsCache.Length == 0) { tsFullClient.SendAudio(encodedArr.Item1, encodedArr.Item2, encoder.Codec); } else { tsFullClient.SendAudioWhisper(encodedArr.Item1, encodedArr.Item2, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); } } } } }
private void AudioSend() { lock (ffmpegLock) { if (ffmpegProcess == null) { return; } if (audioBuffer == null || audioBuffer.Length < encoder.OptimalPacketSize) { audioBuffer = new byte[encoder.OptimalPacketSize]; } UpdatedSubscriptionCache(); while (audioTimer.BufferLength < audioBufferLength) { int read = ffmpegProcess.StandardOutput.BaseStream.Read(audioBuffer, 0, encoder.OptimalPacketSize); if (read == 0) { if (!ffmpegProcess.HasExited) { return; } if (audioTimer.BufferLength < TimeSpan.Zero && !encoder.HasPacket) { AudioStop(); OnSongEnd?.Invoke(this, new EventArgs()); } return; } audioTimer.PushBytes(read); if (isStall) { stallCount++; if (stallCount % StallCountInterval == 0) { stallNoErrorCount++; } if (stallNoErrorCount > StallNoErrorCountMax) { stallCount = 0; isStall = false; break; } } AudioModifier.AdjustVolume(audioBuffer, read, volume); encoder.PushPCMAudio(audioBuffer, read); Tuple <byte[], int> encodedArr; while ((encodedArr = encoder.GetPacket()) != null) { if (channelSubscriptionsCache.Length == 0 && clientSubscriptionsCache.Length == 0) { tsFullClient.SendAudio(encodedArr.Item1, encodedArr.Item2, encoder.Codec); } else { tsFullClient.SendAudioWhisper(encodedArr.Item1, encodedArr.Item2, encoder.Codec, channelSubscriptionsCache, clientSubscriptionsCache); } } } } }