From ea255b22c43b6037b35189db81193808d1af6009 Mon Sep 17 00:00:00 2001 From: zumorica Date: Mon, 18 May 2020 13:29:31 +0200 Subject: [PATCH] Attempt at queueing midi messages --- .../Instruments/InstrumentComponent.cs | 63 +++++++++++++++++-- .../EntitySystems/InstrumentSystem.cs | 25 ++++++++ .../Instruments/SharedInstrumentComponent.cs | 6 +- 3 files changed, 86 insertions(+), 8 deletions(-) create mode 100644 Content.Client/GameObjects/EntitySystems/InstrumentSystem.cs diff --git a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs index db85f689e1..7d06a4d41f 100644 --- a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -5,7 +5,6 @@ using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Client.Audio.Midi; using Robust.Shared.Audio.Midi; -using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.Network; using Robust.Shared.Interfaces.Timing; using Robust.Shared.IoC; @@ -20,6 +19,8 @@ namespace Content.Client.GameObjects.Components.Instruments [RegisterComponent] public class InstrumentComponent : SharedInstrumentComponent { + public const float TimeBetweenNetMessages = 1f; + /// /// Called when a midi song stops playing. /// @@ -27,13 +28,19 @@ namespace Content.Client.GameObjects.Components.Instruments #pragma warning disable 649 [Dependency] private IMidiManager _midiManager; - [Dependency] private readonly IGameTiming _timing; + [Dependency] private readonly IGameTiming _gameTiming; #pragma warning restore 649 [CanBeNull] private IMidiRenderer _renderer; private int _instrumentProgram = 1; + [ViewVariables] + private readonly Queue> _midiQueue = new Queue<(MidiEvent, double)>(); + + [ViewVariables] + private float _timer = 0f; + /// /// A queue of MidiEvents to be sent to the server. /// @@ -124,8 +131,14 @@ namespace Content.Client.GameObjects.Components.Instruments case InstrumentMidiEventMessage midiEventMessage: // If we're the ones sending the MidiEvents, we ignore this message. if (IsInputOpen || IsMidiOpen) break; - Timer.Spawn((int) (500 + _timing.CurTime.TotalMilliseconds - midiEventMessage.Timestamp), - () => _renderer.SendMidiEvent(midiEventMessage.MidiEvent)); + for (var i = 0; i < midiEventMessage.MidiEvent.Length; i++) + { + //_midiQueue.Enqueue((midiEventMessage.MidiEvent[i], (i == 0 ? 0 : 0) + _gameTiming.CurTime.TotalSeconds - midiEventMessage.Timestamp[i])); + + var j = i; + Timer.Spawn((int) ((TimeBetweenNetMessages)*1.5f + _gameTiming.CurTime.TotalSeconds - midiEventMessage.Timestamp[i])*1000, + () => _renderer.SendMidiEvent(midiEventMessage.MidiEvent[j])); + } break; case InstrumentStopMidiMessage _: @@ -190,7 +203,47 @@ namespace Content.Client.GameObjects.Components.Instruments /// The received midi event private void RendererOnMidiEvent(MidiEvent midiEvent) { - SendNetworkMessage(new InstrumentMidiEventMessage(midiEvent, _timing.CurTime.TotalMilliseconds)); + _midiQueue.Enqueue((midiEvent, _gameTiming.CurTime.TotalSeconds)); + } + + public void Update(float delta) + { + _timer -= delta; + + if (_timer > 0f) return; + + if (!IsMidiOpen && !IsInputOpen) + { + //UpdatePlaying(delta); + return; + } + + SendAllMidiMessages(); + _timer = TimeBetweenNetMessages; + } + + private void UpdatePlaying(float delta) + { + if(_renderer == null || _midiQueue.Count == 0) return; + var (midiEvent, timestamp) = _midiQueue.Dequeue(); + _renderer.SendMidiEvent(midiEvent); + _timer = _midiQueue.Count != 0 ? (float) (_midiQueue.Peek().Item2) : 0; + } + + private void SendAllMidiMessages() + { + var count = _midiQueue.Count; + var events = new MidiEvent[count]; + var timestamps = new double[count]; + + for (var i = 0; i < count; i++) + { + var (midiEvent, timestamp) = _midiQueue.Dequeue(); + events[i] = midiEvent; + timestamps[i] = timestamp; + } + + SendNetworkMessage(new InstrumentMidiEventMessage(events, timestamps)); } } } diff --git a/Content.Client/GameObjects/EntitySystems/InstrumentSystem.cs b/Content.Client/GameObjects/EntitySystems/InstrumentSystem.cs new file mode 100644 index 0000000000..6303475c30 --- /dev/null +++ b/Content.Client/GameObjects/EntitySystems/InstrumentSystem.cs @@ -0,0 +1,25 @@ +using Content.Client.GameObjects.Components.Instruments; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Client.GameObjects.EntitySystems +{ + public class InstrumentSystem : EntitySystem + { + public override void Initialize() + { + base.Initialize(); + EntityQuery = new TypeEntityQuery(typeof(InstrumentComponent)); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + foreach (var entity in RelevantEntities) + { + entity.GetComponent().Update(frameTime); + } + } + } +} diff --git a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs index aef625a057..9734425b3c 100644 --- a/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs +++ b/Content.Shared/GameObjects/Components/Instruments/SharedInstrumentComponent.cs @@ -26,10 +26,10 @@ namespace Content.Shared.GameObjects.Components.Instruments [Serializable, NetSerializable] public class InstrumentMidiEventMessage : ComponentMessage { - public MidiEvent MidiEvent; - public double Timestamp; + public MidiEvent[] MidiEvent; + public double[] Timestamp; - public InstrumentMidiEventMessage(MidiEvent midiEvent, double timestamp) + public InstrumentMidiEventMessage(MidiEvent[] midiEvent, double[] timestamp) { MidiEvent = midiEvent; Timestamp = timestamp;