Example #1
0
        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);
        }
Example #2
0
        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");
            }
        }
Example #3
0
 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();
     }
 }
Example #4
0
        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);
        }
Example #5
0
        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);
                        }
                    }
                }
            }
        }
Example #6
0
        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);
                    }
                }
            }
        }
Example #7
0
 private void TriggerSongEnd(object o, EventArgs e) => OnSongEnd?.Invoke(this, EventArgs.Empty);
Example #8
0
 private void TriggerSongEnd(object?o, EventArgs e) => scheduler.InvokeAsync(() => OnSongEnd.InvokeAsync(this, EventArgs.Empty));
Example #9
0
        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);
                        }
                    }
                }
            }
        }
Example #10
0
        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);
                        }
                    }
                }
            }
        }