diff --git a/Content.Client/Instruments/InstrumentSystem.MidiParsing.cs b/Content.Client/Instruments/InstrumentSystem.MidiParsing.cs
deleted file mode 100644
index 16aed930f6..0000000000
--- a/Content.Client/Instruments/InstrumentSystem.MidiParsing.cs
+++ /dev/null
@@ -1,54 +0,0 @@
-using System.Linq;
-using Content.Shared.Instruments;
-using Robust.Shared.Audio.Midi;
-
-namespace Content.Client.Instruments;
-
-public sealed partial class InstrumentSystem
-{
- ///
- /// Tries to parse the input data as a midi and set the channel names respectively.
- ///
- ///
- /// Thank you to http://www.somascape.org/midi/tech/mfile.html for providing an awesome resource for midi files.
- ///
- ///
- /// This method has exception tolerance and does not throw, even if the midi file is invalid.
- ///
- private bool TrySetChannels(EntityUid uid, byte[] data)
- {
- if (!MidiParser.MidiParser.TryGetMidiTracks(data, out var tracks, out var error))
- {
- Log.Error(error);
- return false;
- }
-
- var resolvedTracks = new List();
- for (var index = 0; index < tracks.Length; index++)
- {
- var midiTrack = tracks[index];
- if (midiTrack is { TrackName: null, ProgramName: null, InstrumentName: null})
- continue;
-
- switch (midiTrack)
- {
- case { TrackName: not null, ProgramName: not null }:
- case { TrackName: not null, InstrumentName: not null }:
- case { TrackName: not null }:
- case { ProgramName: not null }:
- resolvedTracks.Add(midiTrack);
- break;
- default:
- resolvedTracks.Add(null); // Used so the channel still displays as MIDI Channel X and doesn't just take the next valid one in the UI
- break;
- }
-
- Log.Debug($"Channel name: {resolvedTracks.Last()}");
- }
-
- RaiseNetworkEvent(new InstrumentSetChannelsEvent(GetNetEntity(uid), resolvedTracks.Take(RobustMidiEvent.MaxChannels).ToArray()));
- Log.Debug($"Resolved {resolvedTracks.Count} channels.");
-
- return true;
- }
-}
diff --git a/Content.Client/Instruments/InstrumentSystem.cs b/Content.Client/Instruments/InstrumentSystem.cs
index d861f4163b..abc3fa8210 100644
--- a/Content.Client/Instruments/InstrumentSystem.cs
+++ b/Content.Client/Instruments/InstrumentSystem.cs
@@ -1,4 +1,3 @@
-using System.IO;
using System.Linq;
using Content.Shared.CCVar;
using Content.Shared.Instruments;
@@ -13,7 +12,7 @@ using Robust.Shared.Timing;
namespace Content.Client.Instruments;
-public sealed partial class InstrumentSystem : SharedInstrumentSystem
+public sealed class InstrumentSystem : SharedInstrumentSystem
{
[Dependency] private readonly IClientNetManager _netManager = default!;
[Dependency] private readonly IMidiManager _midiManager = default!;
@@ -24,8 +23,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
public int MaxMidiEventsPerBatch { get; private set; }
public int MaxMidiEventsPerSecond { get; private set; }
- public event Action? OnChannelsUpdated;
-
public override void Initialize()
{
base.Initialize();
@@ -41,26 +38,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
SubscribeLocalEvent(OnShutdown);
SubscribeLocalEvent(OnHandleState);
- SubscribeLocalEvent(OnActiveInstrumentAfterHandleState);
- }
-
- private bool _isUpdateQueued = false;
-
- private void OnActiveInstrumentAfterHandleState(Entity ent, ref AfterAutoHandleStateEvent args)
- {
- // Called in the update loop so that the components update client side for resolving them in TryComps.
- _isUpdateQueued = true;
- }
-
- public override void FrameUpdate(float frameTime)
- {
- base.FrameUpdate(frameTime);
-
- if (!_isUpdateQueued)
- return;
-
- _isUpdateQueued = false;
- OnChannelsUpdated?.Invoke();
}
private void OnHandleState(EntityUid uid, SharedInstrumentComponent component, ref ComponentHandleState args)
@@ -275,13 +252,7 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
}
- [Obsolete("Use overload that takes in byte[] instead.")]
public bool OpenMidi(EntityUid uid, ReadOnlySpan data, InstrumentComponent? instrument = null)
- {
- return OpenMidi(uid, data.ToArray(), instrument);
- }
-
- public bool OpenMidi(EntityUid uid, byte[] data, InstrumentComponent? instrument = null)
{
if (!Resolve(uid, ref instrument))
return false;
@@ -292,8 +263,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
return false;
SetMaster(uid, null);
- TrySetChannels(uid, data);
-
instrument.MidiEventBuffer.Clear();
instrument.Renderer.OnMidiEvent += instrument.MidiEventBuffer.Add;
return true;
diff --git a/Content.Client/Instruments/MidiParser/MidiInstrument.cs b/Content.Client/Instruments/MidiParser/MidiInstrument.cs
deleted file mode 100644
index 93946496eb..0000000000
--- a/Content.Client/Instruments/MidiParser/MidiInstrument.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-using Robust.Shared.Utility;
-
-namespace Content.Client.Instruments.MidiParser;
-
-// This file was autogenerated. Based on https://www.ccarh.org/courses/253/handout/gminstruments/
-public enum MidiInstrument : byte
-{
- AcousticGrandPiano = 0,
- BrightAcousticPiano = 1,
- ElectricGrandPiano = 2,
- HonkyTonkPiano = 3,
- RhodesPiano = 4,
- ChorusedPiano = 5,
- Harpsichord = 6,
- Clavinet = 7,
- Celesta = 8,
- Glockenspiel = 9,
- MusicBox = 10,
- Vibraphone = 11,
- Marimba = 12,
- Xylophone = 13,
- TubularBells = 14,
- Dulcimer = 15,
- HammondOrgan = 16,
- PercussiveOrgan = 17,
- RockOrgan = 18,
- ChurchOrgan = 19,
- ReedOrgan = 20,
- Accordion = 21,
- Harmonica = 22,
- TangoAccordion = 23,
- AcousticNylonGuitar = 24,
- AcousticSteelGuitar = 25,
- ElectricJazzGuitar = 26,
- ElectricCleanGuitar = 27,
- ElectricMutedGuitar = 28,
- OverdrivenGuitar = 29,
- DistortionGuitar = 30,
- GuitarHarmonics = 31,
- AcousticBass = 32,
- FingeredElectricBass = 33,
- PluckedElectricBass = 34,
- FretlessBass = 35,
- SlapBass1 = 36,
- SlapBass2 = 37,
- SynthBass1 = 38,
- SynthBass2 = 39,
- Violin = 40,
- Viola = 41,
- Cello = 42,
- Contrabass = 43,
- TremoloStrings = 44,
- PizzicatoStrings = 45,
- OrchestralHarp = 46,
- Timpani = 47,
- StringEnsemble1 = 48,
- StringEnsemble2 = 49,
- SynthStrings1 = 50,
- SynthStrings2 = 51,
- ChoirAah = 52,
- VoiceOoh = 53,
- SynthChoir = 54,
- OrchestraHit = 55,
- Trumpet = 56,
- Trombone = 57,
- Tuba = 58,
- MutedTrumpet = 59,
- FrenchHorn = 60,
- BrassSection = 61,
- SynthBrass1 = 62,
- SynthBrass2 = 63,
- SopranoSax = 64,
- AltoSax = 65,
- TenorSax = 66,
- BaritoneSax = 67,
- Oboe = 68,
- EnglishHorn = 69,
- Bassoon = 70,
- Clarinet = 71,
- Piccolo = 72,
- Flute = 73,
- Recorder = 74,
- PanFlute = 75,
- BottleBlow = 76,
- Shakuhachi = 77,
- Whistle = 78,
- Ocarina = 79,
- SquareWaveLead = 80,
- SawtoothWaveLead = 81,
- CalliopeLead = 82,
- ChiffLead = 83,
- CharangLead = 84,
- VoiceLead = 85,
- FithsLead = 86,
- BassLead = 87,
- NewAgePad = 88,
- WarmPad = 89,
- PolysynthPad = 90,
- ChoirPad = 91,
- BowedPad = 92,
- MetallicPad = 93,
- HaloPad = 94,
- SweepPad = 95,
- RainEffect = 96,
- SoundtrackEffect = 97,
- CrystalEffect = 98,
- AtmosphereEffect = 99,
- BrightnessEffect = 100,
- GoblinsEffect = 101,
- EchoesEffect = 102,
- SciFiEffect = 103,
- Sitar = 104,
- Banjo = 105,
- Shamisen = 106,
- Koto = 107,
- Kalimba = 108,
- Bagpipe = 109,
- Fiddle = 110,
- Shanai = 111,
- TinkleBell = 112,
- Agogo = 113,
- SteelDrums = 114,
- Woodblock = 115,
- TaikoDrum = 116,
- MelodicTom = 117,
- SynthDrum = 118,
- ReverseCymbal = 119,
- GuitarFretNoise = 120,
- BreathNoise = 121,
- Seashore = 122,
- BirdTweet = 123,
- TelephoneRing = 124,
- Helicopter = 125,
- Applause = 126,
- Gunshot = 127,
-}
-
-public static class MidiInstrumentExt
-{
- ///
- /// Turns the given enum value into it's string representation to be used in localization.
- ///
- public static string GetStringRep(this MidiInstrument instrument)
- {
- return CaseConversion.PascalToKebab(instrument.ToString());
- }
-}
diff --git a/Content.Client/Instruments/MidiParser/MidiParser.cs b/Content.Client/Instruments/MidiParser/MidiParser.cs
deleted file mode 100644
index 937384e439..0000000000
--- a/Content.Client/Instruments/MidiParser/MidiParser.cs
+++ /dev/null
@@ -1,184 +0,0 @@
-using System.Diagnostics.CodeAnalysis;
-using System.Text;
-using Content.Shared.Instruments;
-
-namespace Content.Client.Instruments.MidiParser;
-
-public static class MidiParser
-{
- // Thanks again to http://www.somascape.org/midi/tech/mfile.html
- public static bool TryGetMidiTracks(
- byte[] data,
- [NotNullWhen(true)] out MidiTrack[]? tracks,
- [NotNullWhen(false)] out string? error)
- {
- tracks = null;
- error = null;
-
- var stream = new MidiStreamWrapper(data);
-
- if (stream.ReadString(4) != "MThd")
- {
- error = "Invalid file header";
- return false;
- }
-
- var headerLength = stream.ReadUInt32();
- // MIDI specs define that the header is 6 bytes, we only look at the 6 bytes, if its more, we skip ahead.
-
- stream.Skip(2); // format
- var trackCount = stream.ReadUInt16();
- stream.Skip(2); // time div
-
- // We now skip ahead if we still have any header length left
- stream.Skip((int)(headerLength - 6));
-
- var parsedTracks = new List();
-
- for (var i = 0; i < trackCount; i++)
- {
- if (stream.ReadString(4) != "MTrk")
- {
- tracks = null;
- error = "Track contains invalid header";
- return false;
- }
-
- var track = new MidiTrack();
-
- var trackLength = stream.ReadUInt32();
- var trackEnd = stream.StreamPosition + trackLength;
- var hasMidiEvent = false;
- byte? lastStatusByte = null;
-
- while (stream.StreamPosition < trackEnd)
- {
- stream.ReadVariableLengthQuantity();
-
- /*
- * If the first (status) byte is less than 128 (hex 80), this implies that running status is in effect,
- * and that this byte is actually the first data byte (the status carrying over from the previous MIDI event).
- * This can only be the case if the immediately previous event was also a MIDI event,
- * i.e. SysEx and Meta events interrupt (clear) running status.
- * See http://www.somascape.org/midi/tech/mfile.html#events
- */
-
- var firstByte = stream.ReadByte();
- if (firstByte >= 0x80)
- {
- lastStatusByte = firstByte;
- }
- else
- {
- // Running status: push byte back for reading as data
- stream.Skip(-1);
- }
-
- // The first event in each MTrk chunk must specify status.
- if (lastStatusByte == null)
- {
- tracks = null;
- error = "Track data not valid, expected status byte, got nothing.";
- return false;
- }
-
- var eventType = (byte)(lastStatusByte & 0xF0);
-
- switch (lastStatusByte)
- {
- // Meta events
- case 0xFF:
- {
- var metaType = stream.ReadByte();
- var metaLength = stream.ReadVariableLengthQuantity();
- var metaData = stream.ReadBytes((int)metaLength);
- if (metaType == 0x00) // SequenceNumber event
- continue;
-
- // Meta event types 01 through 0F are reserved for text and all follow the basic FF 01 len text format
- if (metaType is < 0x01 or > 0x0F)
- break;
-
- // 0x03 is TrackName,
- // 0x04 is InstrumentName
-
- var text = Encoding.ASCII.GetString(metaData, 0, (int)metaLength);
- switch (metaType)
- {
- case 0x03 when track.TrackName == null:
- track.TrackName = text;
- break;
- case 0x04 when track.InstrumentName == null:
- track.InstrumentName = text;
- break;
- }
-
- // still here? then we dont care about the event
- break;
- }
-
- // SysEx events
- case 0xF0:
- case 0xF7:
- {
- var sysexLength = stream.ReadVariableLengthQuantity();
- stream.Skip((int)sysexLength);
- // Sysex events and meta-events cancel any running status which was in effect.
- // Running status does not apply to and may not be used for these messages.
- lastStatusByte = null;
- break;
- }
-
-
- default:
- switch (eventType)
- {
- // Program Change
- case 0xC0:
- {
- var programNumber = stream.ReadByte();
- if (track.ProgramName == null)
- {
- if (programNumber < Enum.GetValues().Length)
- track.ProgramName = Loc.GetString($"instruments-component-menu-midi-channel-{((MidiInstrument)programNumber).GetStringRep()}");
- }
- break;
- }
-
- case 0x80: // Note Off
- case 0x90: // Note On
- case 0xA0: // Polyphonic Key Pressure
- case 0xB0: // Control Change
- case 0xE0: // Pitch Bend
- {
- hasMidiEvent = true;
- stream.Skip(2);
- break;
- }
-
- case 0xD0: // Channel Pressure
- {
- hasMidiEvent = true;
- stream.Skip(1);
- break;
- }
-
- default:
- error = $"Unknown MIDI event type {lastStatusByte:X2}";
- tracks = null;
- return false;
- }
- break;
- }
- }
-
-
- if (hasMidiEvent)
- parsedTracks.Add(track);
- }
-
- tracks = parsedTracks.ToArray();
-
- return true;
- }
-}
diff --git a/Content.Client/Instruments/MidiParser/MidiStreamWrapper.cs b/Content.Client/Instruments/MidiParser/MidiStreamWrapper.cs
deleted file mode 100644
index 1886417a56..0000000000
--- a/Content.Client/Instruments/MidiParser/MidiStreamWrapper.cs
+++ /dev/null
@@ -1,103 +0,0 @@
-using System.IO;
-using System.Text;
-
-namespace Content.Client.Instruments.MidiParser;
-
-public sealed class MidiStreamWrapper
-{
- private readonly MemoryStream _stream;
- private byte[] _buffer;
-
- public long StreamPosition => _stream.Position;
-
- public MidiStreamWrapper(byte[] data)
- {
- _stream = new MemoryStream(data, writable: false);
- _buffer = new byte[4];
- }
-
- ///
- /// Skips X number of bytes in the stream.
- ///
- /// The number of bytes to skip. If 0, no operations on the stream are performed.
- public void Skip(int count)
- {
- if (count == 0)
- return;
-
- _stream.Seek(count, SeekOrigin.Current);
- }
-
- public byte ReadByte()
- {
- var b = _stream.ReadByte();
- if (b == -1)
- throw new Exception("Unexpected end of stream");
-
- return (byte)b;
- }
-
- ///
- /// Reads N bytes using the buffer.
- ///
- public byte[] ReadBytes(int count)
- {
- if (_buffer.Length < count)
- {
- Array.Resize(ref _buffer, count);
- }
-
- var read = _stream.Read(_buffer, 0, count);
- if (read != count)
- throw new Exception("Unexpected end of stream");
-
- return _buffer;
- }
-
- ///
- /// Reads a 4 byte big-endian uint.
- ///
- public uint ReadUInt32()
- {
- var bytes = ReadBytes(4);
- return (uint)((bytes[0] << 24) |
- (bytes[1] << 16) |
- (bytes[2] << 8) |
- (bytes[3]));
- }
-
- ///
- /// Reads a 2 byte big-endian ushort.
- ///
- public ushort ReadUInt16()
- {
- var bytes = ReadBytes(2);
- return (ushort)((bytes[0] << 8) | bytes[1]);
- }
-
- public string ReadString(int count)
- {
- var bytes = ReadBytes(count);
- return Encoding.UTF8.GetString(bytes, 0, count);
- }
-
- public uint ReadVariableLengthQuantity()
- {
- uint value = 0;
-
- // variable-length-quantities encode ints using 7 bits per byte
- // the highest bit (7) is used for a continuation flag. We read until the high bit is 0
-
- while (true)
- {
- var b = ReadByte();
- value = (value << 7) | (uint)(b & 0x7f); // Shift current value and add 7 bits
- // value << 7, make room for the next 7 bits
- // b & 0x7F mask out the high bit to just get the 7 bit payload
- if ((b & 0x80) == 0)
- break; // This was the last bit.
- }
-
- return value;
- }
-}
diff --git a/Content.Client/Instruments/UI/ChannelsMenu.xaml b/Content.Client/Instruments/UI/ChannelsMenu.xaml
index 20e4a3e923..1bf4647609 100644
--- a/Content.Client/Instruments/UI/ChannelsMenu.xaml
+++ b/Content.Client/Instruments/UI/ChannelsMenu.xaml
@@ -7,7 +7,5 @@
-
diff --git a/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs b/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs
index da164a633c..c175e67842 100644
--- a/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs
+++ b/Content.Client/Instruments/UI/ChannelsMenu.xaml.cs
@@ -1,56 +1,26 @@
-using Content.Shared.Instruments;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Audio.Midi;
-using Robust.Shared.Utility;
+using Robust.Shared.Timing;
namespace Content.Client.Instruments.UI;
[GenerateTypedNameReferences]
public sealed partial class ChannelsMenu : DefaultWindow
{
- [Dependency] private readonly IEntityManager _entityManager = null!;
-
private readonly InstrumentBoundUserInterface _owner;
public ChannelsMenu(InstrumentBoundUserInterface owner) : base()
{
RobustXamlLoader.Load(this);
- IoCManager.InjectDependencies(this);
_owner = owner;
ChannelList.OnItemSelected += OnItemSelected;
ChannelList.OnItemDeselected += OnItemDeselected;
AllButton.OnPressed += OnAllPressed;
ClearButton.OnPressed += OnClearPressed;
- DisplayTrackNames.OnPressed += OnDisplayTrackNamesPressed;
- }
-
- protected override void EnteredTree()
- {
- base.EnteredTree();
-
- _owner.Instruments.OnChannelsUpdated += UpdateChannelList;
- }
-
- private void OnDisplayTrackNamesPressed(BaseButton.ButtonEventArgs obj)
- {
- DisplayTrackNames.SetClickPressed(!DisplayTrackNames.Pressed);
- Populate();
- }
-
- private void UpdateChannelList()
- {
- Populate(); // This is kind of in-efficent because we don't filter for which instrument updated its channels, but idc
- }
-
- protected override void ExitedTree()
- {
- base.ExitedTree();
-
- _owner.Instruments.OnChannelsUpdated -= UpdateChannelList;
}
private void OnItemSelected(ItemList.ItemListSelectedEventArgs args)
@@ -81,71 +51,15 @@ public sealed partial class ChannelsMenu : DefaultWindow
}
}
- ///
- /// Walks up the tree of instrument masters to find the truest master of them all.
- ///
- private ActiveInstrumentComponent ResolveActiveInstrument(InstrumentComponent? comp)
- {
- comp ??= _entityManager.GetComponent(_owner.Owner);
-
- var instrument = new Entity(_owner.Owner, comp);
-
- while (true)
- {
- if (instrument.Comp.Master == null)
- break;
-
- instrument = new Entity((EntityUid)instrument.Comp.Master,
- _entityManager.GetComponent((EntityUid)instrument.Comp.Master));
- }
-
- return _entityManager.GetComponent(instrument.Owner);
- }
-
- public void Populate()
+ public void Populate(InstrumentComponent? instrument)
{
ChannelList.Clear();
- var instrument = _entityManager.GetComponent(_owner.Owner);
- var activeInstrument = ResolveActiveInstrument(instrument);
for (int i = 0; i < RobustMidiEvent.MaxChannels; i++)
{
- var label = _owner.Loc.GetString("instrument-component-channel-name",
- ("number", i));
- if (activeInstrument != null
- && activeInstrument.Tracks.TryGetValue(i, out var resolvedMidiChannel)
- && resolvedMidiChannel != null)
- {
- if (DisplayTrackNames.Pressed)
- {
- label = resolvedMidiChannel switch
- {
- { TrackName: not null, InstrumentName: not null } =>
- Loc.GetString("instruments-component-channels-multi",
- ("channel", i),
- ("name", resolvedMidiChannel.TrackName),
- ("other", resolvedMidiChannel.InstrumentName)),
- { TrackName: not null } =>
- Loc.GetString("instruments-component-channels-single",
- ("channel", i),
- ("name", resolvedMidiChannel.TrackName)),
- _ => label,
- };
- }
- else
- {
- label = resolvedMidiChannel switch
- {
- { ProgramName: not null } =>
- Loc.GetString("instruments-component-channels-single",
- ("channel", i),
- ("name", resolvedMidiChannel.ProgramName)),
- _ => label,
- };
- }
- }
+ var item = ChannelList.AddItem(_owner.Loc.GetString("instrument-component-channel-name",
+ ("number", i)), null, true, i);
- var item = ChannelList.AddItem(label, null, true, i);
item.Selected = !instrument?.FilteredChannels[i] ?? false;
}
diff --git a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs
index ffdb67f626..e511cb8654 100644
--- a/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs
+++ b/Content.Client/Instruments/UI/InstrumentBoundUserInterface.cs
@@ -1,5 +1,4 @@
using Content.Shared.ActionBlocker;
-using Content.Shared.Instruments;
using Content.Shared.Instruments.UI;
using Content.Shared.Interaction;
using Robust.Client.Audio.Midi;
@@ -102,7 +101,9 @@ namespace Content.Client.Instruments.UI
public void OpenChannelsMenu()
{
_channelsMenu ??= new ChannelsMenu(this);
- _channelsMenu.Populate();
+ EntMan.TryGetComponent(Owner, out InstrumentComponent? instrument);
+
+ _channelsMenu.Populate(instrument);
_channelsMenu.OpenCenteredRight();
}
diff --git a/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs b/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs
index 4a29478a9c..9b14e01fb5 100644
--- a/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs
+++ b/Content.Client/Instruments/UI/InstrumentMenu.xaml.cs
@@ -11,7 +11,6 @@ using Robust.Client.UserInterface.XAML;
using Robust.Shared.Containers;
using Robust.Shared.Input;
using Robust.Shared.Timing;
-using Robust.Shared.Utility;
using static Robust.Client.UserInterface.Controls.BaseButton;
using Range = Robust.Client.UserInterface.Controls.Range;
@@ -146,6 +145,10 @@ namespace Content.Client.Instruments.UI
if (!PlayCheck())
return;
+ await using var memStream = new MemoryStream((int) file.Length);
+
+ await file.CopyToAsync(memStream);
+
if (!_entManager.TryGetComponent(Entity, out var instrument))
{
return;
@@ -153,7 +156,7 @@ namespace Content.Client.Instruments.UI
if (!_entManager.System()
.OpenMidi(Entity,
- file.CopyToArray(),
+ memStream.GetBuffer().AsSpan(0, (int) memStream.Length),
instrument))
{
return;
diff --git a/Content.Server/Instruments/InstrumentSystem.cs b/Content.Server/Instruments/InstrumentSystem.cs
index a347d7ea41..2539db7a6f 100644
--- a/Content.Server/Instruments/InstrumentSystem.cs
+++ b/Content.Server/Instruments/InstrumentSystem.cs
@@ -1,12 +1,8 @@
-using System.Linq;
using Content.Server.Administration;
-using Content.Server.Administration.Logs;
using Content.Server.Interaction;
using Content.Server.Popups;
using Content.Server.Stunnable;
using Content.Shared.Administration;
-using Content.Shared.CCVar;
-using Content.Shared.Database;
using Content.Shared.Examine;
using Content.Shared.Instruments;
using Content.Shared.Instruments.UI;
@@ -21,7 +17,6 @@ using Robust.Shared.Console;
using Robust.Shared.GameStates;
using Robust.Shared.Player;
using Robust.Shared.Timing;
-using Robust.Shared.Utility;
namespace Content.Server.Instruments;
@@ -36,7 +31,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly TransformSystem _transform = default!;
[Dependency] private readonly ExamineSystemShared _examineSystem = default!;
- [Dependency] private readonly IAdminLogManager _admingLogSystem = default!;
private const float MaxInstrumentBandRange = 10f;
@@ -56,7 +50,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
SubscribeNetworkEvent(OnMidiStop);
SubscribeNetworkEvent(OnMidiSetMaster);
SubscribeNetworkEvent(OnMidiSetFilteredChannel);
- SubscribeNetworkEvent(OnMidiSetChannels);
Subs.BuiEvents(InstrumentUiKey.Key, subs =>
{
@@ -139,44 +132,6 @@ public sealed partial class InstrumentSystem : SharedInstrumentSystem
Clean(uid, instrument);
}
-
- private void OnMidiSetChannels(InstrumentSetChannelsEvent msg, EntitySessionEventArgs args)
- {
- var uid = GetEntity(msg.Uid);
-
- if (!TryComp(uid, out InstrumentComponent? instrument) || !TryComp(uid, out ActiveInstrumentComponent? activeInstrument))
- return;
-
- if (args.SenderSession.AttachedEntity != instrument.InstrumentPlayer)
- return;
-
- if (msg.Tracks.Length > RobustMidiEvent.MaxChannels)
- {
- Log.Warning($"{args.SenderSession.UserId.ToString()} - Tried to send tracks over the limit! Received: {msg.Tracks.Length}; Limit: {RobustMidiEvent.MaxChannels}");
- return;
- }
-
- var tracksString = string.Join("\n",
- msg.Tracks
- .Where(t => t != null)
- .Select(t => t!.ToString()));
-
- _admingLogSystem.Add(
- LogType.Instrument,
- LogImpact.Low,
- $"{ToPrettyString(args.SenderSession.AttachedEntity)} set the midi channels for {ToPrettyString(uid)} to {tracksString}");
-
- // Truncate any track names too long.
- foreach (var t in msg.Tracks)
- {
- t?.TruncateFields(_cfg.GetCVar(CCVars.MidiMaxChannelNameLength));
- }
-
- activeInstrument.Tracks = msg.Tracks;
-
- Dirty(uid, activeInstrument);
- }
-
private void OnMidiSetMaster(InstrumentSetMasterEvent msg, EntitySessionEventArgs args)
{
var uid = GetEntity(msg.Uid);
diff --git a/Content.Shared.Database/LogType.cs b/Content.Shared.Database/LogType.cs
index fa2304dc87..88634f327b 100644
--- a/Content.Shared.Database/LogType.cs
+++ b/Content.Shared.Database/LogType.cs
@@ -475,10 +475,5 @@ public enum LogType
///
/// Damaging grid collision has occurred.
///
- ShuttleImpact = 102,
-
- ///
- /// Events relating to midi playback.
- ///
- Instrument = 103,
+ ShuttleImpact = 102
}
diff --git a/Content.Shared/CCVar/CCVars.Midi.cs b/Content.Shared/CCVar/CCVars.Midi.cs
index 806bcc2b52..4ca4bfd6f8 100644
--- a/Content.Shared/CCVar/CCVars.Midi.cs
+++ b/Content.Shared/CCVar/CCVars.Midi.cs
@@ -15,10 +15,4 @@ public sealed partial class CCVars
public static readonly CVarDef MaxMidiLaggedBatches =
CVarDef.Create("midi.max_lagged_batches", 8, CVar.SERVERONLY);
-
- ///
- /// Defines the max amount of characters to allow in the "Midi channel selector".
- ///
- public static readonly CVarDef MidiMaxChannelNameLength =
- CVarDef.Create("midi.max_channel_name_length", 64, CVar.SERVERONLY);
}
diff --git a/Content.Shared/Instruments/SharedInstrumentComponent.cs b/Content.Shared/Instruments/SharedInstrumentComponent.cs
index 97eef752eb..73500f3869 100644
--- a/Content.Shared/Instruments/SharedInstrumentComponent.cs
+++ b/Content.Shared/Instruments/SharedInstrumentComponent.cs
@@ -34,18 +34,6 @@ public abstract partial class SharedInstrumentComponent : Component
public BitArray FilteredChannels { get; set; } = new(RobustMidiEvent.MaxChannels, true);
}
-///
-/// Component that indicates that musical instrument was activated (ui opened).
-///
-[RegisterComponent, NetworkedComponent]
-[AutoGenerateComponentState(true)]
-public sealed partial class ActiveInstrumentComponent : Component
-{
- [DataField]
- [AutoNetworkedField]
- public MidiTrack?[] Tracks = [];
-}
-
[Serializable, NetSerializable]
public sealed class InstrumentComponentState : ComponentState
{
@@ -150,72 +138,3 @@ public enum InstrumentUiKey
{
Key,
}
-
-///
-/// Sets the MIDI channels on an instrument.
-///
-[Serializable, NetSerializable]
-public sealed class InstrumentSetChannelsEvent : EntityEventArgs
-{
- public NetEntity Uid { get; }
- public MidiTrack?[] Tracks { get; set; }
-
- public InstrumentSetChannelsEvent(NetEntity uid, MidiTrack?[] tracks)
- {
- Uid = uid;
- Tracks = tracks;
- }
-}
-
-///
-/// Represents a single midi track with the track name, instrument name and bank instrument name extracted.
-///
-[Serializable, NetSerializable]
-public sealed class MidiTrack
-{
- ///
- /// The first specified Track Name
- ///
- public string? TrackName;
- ///
- /// The first specified instrument name
- ///
- public string? InstrumentName;
-
- ///
- /// The first program change resolved to the name.
- ///
- public string? ProgramName;
-
- public override string ToString()
- {
- return $"Track Name: {TrackName}; Instrument Name: {InstrumentName}; Program Name: {ProgramName}";
- }
-
- ///
- /// Truncates the fields based on the limit inputted into this method.
- ///
- public void TruncateFields(int limit)
- {
- if (InstrumentName != null)
- InstrumentName = Truncate(InstrumentName, limit);
-
- if (TrackName != null)
- TrackName = Truncate(TrackName, limit);
-
- if (ProgramName != null)
- ProgramName = Truncate(ProgramName, limit);
- }
-
- private const string Postfix = "…";
- // TODO: Make a general method to use in RT? idk if we have that.
- private string Truncate(string input, int limit)
- {
- if (string.IsNullOrEmpty(input) || limit <= 0 || input.Length <= limit)
- return input;
-
- var truncatedLength = limit - Postfix.Length;
-
- return input.Substring(0, truncatedLength) + Postfix;
- }
-}
diff --git a/Resources/Locale/en-US/instruments/instruments-component.ftl b/Resources/Locale/en-US/instruments/instruments-component.ftl
index 76cfb28166..f0e0c1b3a9 100644
--- a/Resources/Locale/en-US/instruments/instruments-component.ftl
+++ b/Resources/Locale/en-US/instruments/instruments-component.ftl
@@ -19,139 +19,6 @@ instruments-component-channels-menu = MIDI Channel Selection
instrument-component-channel-name = MIDI Channel {$number}
instruments-component-channels-all-button = All
instruments-component-channels-clear-button = Clear
-instruments-component-channels-track-names-toggle = Show Track Names
-instruments-component-channels-single = {$channel} {$name}
-instruments-component-channels-multi = {$channel} {$name} ({$other})
-
# SwappableInstrumentComponent
swappable-instrument-component-style-set = Style set to "{$style}"
-
-instruments-component-menu-midi-channel-acoustic-grand-piano = Acoustic Grand Piano
-instruments-component-menu-midi-channel-bright-acoustic-piano = Bright Acoustic Piano
-instruments-component-menu-midi-channel-electric-grand-piano = Electric Grand Piano
-instruments-component-menu-midi-channel-honky-tonk-piano = Honky-tonk Piano
-instruments-component-menu-midi-channel-rhodes-piano = Rhodes Piano
-instruments-component-menu-midi-channel-chorused-piano = Chorused Piano
-instruments-component-menu-midi-channel-harpsichord = Harpsichord
-instruments-component-menu-midi-channel-clavinet = Clavinet
-instruments-component-menu-midi-channel-celesta = Celesta
-instruments-component-menu-midi-channel-glockenspiel = Glockenspiel
-instruments-component-menu-midi-channel-music-box = Music Box
-instruments-component-menu-midi-channel-vibraphone = Vibraphone
-instruments-component-menu-midi-channel-marimba = Marimba
-instruments-component-menu-midi-channel-xylophone = Xylophone
-instruments-component-menu-midi-channel-tubular-bells = Tubular Bells
-instruments-component-menu-midi-channel-dulcimer = Dulcimer
-instruments-component-menu-midi-channel-hammond-organ = Hammond Organ
-instruments-component-menu-midi-channel-percussive-organ = Percussive Organ
-instruments-component-menu-midi-channel-rock-organ = Rock Organ
-instruments-component-menu-midi-channel-church-organ = Church Organ
-instruments-component-menu-midi-channel-reed-organ = Reed Organ
-instruments-component-menu-midi-channel-accordion = Accordion
-instruments-component-menu-midi-channel-harmonica = Harmonica
-instruments-component-menu-midi-channel-tango-accordion = Tango Accordion
-instruments-component-menu-midi-channel-acoustic-nylon-guitar = Acoustic Nylon Guitar
-instruments-component-menu-midi-channel-acoustic-steel-guitar = Acoustic Steel Guitar
-instruments-component-menu-midi-channel-electric-jazz-guitar = Electric Jazz Guitar
-instruments-component-menu-midi-channel-electric-clean-guitar = Electric Clean Guitar
-instruments-component-menu-midi-channel-electric-muted-guitar = Electric Muted Guitar
-instruments-component-menu-midi-channel-overdriven-guitar = Overdriven Guitar
-instruments-component-menu-midi-channel-distortion-guitar = Distortion Guitar
-instruments-component-menu-midi-channel-guitar-harmonics = Guitar Harmonics
-instruments-component-menu-midi-channel-acoustic-bass = Acoustic Bass
-instruments-component-menu-midi-channel-fingered-electric-bass = Fingered Electric Bass
-instruments-component-menu-midi-channel-plucked-electric-bass = Plucked Electric Bass
-instruments-component-menu-midi-channel-fretless-bass = Fretless Bass
-instruments-component-menu-midi-channel-slap-bass1 = Slap Bass 1
-instruments-component-menu-midi-channel-slap-bass2 = Slap Bass 2
-instruments-component-menu-midi-channel-synth-bass1 = Synth Bass 1
-instruments-component-menu-midi-channel-synth-bass2 = Synth Bass 2
-instruments-component-menu-midi-channel-violin = Violin
-instruments-component-menu-midi-channel-viola = Viola
-instruments-component-menu-midi-channel-cello = Cello
-instruments-component-menu-midi-channel-contrabass = Contrabass
-instruments-component-menu-midi-channel-tremolo-strings = Tremolo Strings
-instruments-component-menu-midi-channel-pizzicato-strings = Pizzicato Strings
-instruments-component-menu-midi-channel-orchestral-harp = Orchestral Harp
-instruments-component-menu-midi-channel-timpani = Timpani
-instruments-component-menu-midi-channel-string-ensemble1 = String Ensemble 1
-instruments-component-menu-midi-channel-string-ensemble2 = String Ensemble 2
-instruments-component-menu-midi-channel-synth-strings1 = Synth Strings 1
-instruments-component-menu-midi-channel-synth-strings2 = Synth Strings 2
-instruments-component-menu-midi-channel-choir-aah = Choir "Aah"
-instruments-component-menu-midi-channel-voice-ooh = Voice "Ooh"
-instruments-component-menu-midi-channel-synth-choir = Synth Choir
-instruments-component-menu-midi-channel-orchestra-hit = Orchestra Hit
-instruments-component-menu-midi-channel-trumpet = Trumpet
-instruments-component-menu-midi-channel-trombone = Trombone
-instruments-component-menu-midi-channel-tuba = Tuba
-instruments-component-menu-midi-channel-muted-trumpet = Muted Trumpet
-instruments-component-menu-midi-channel-french-horn = French Horn
-instruments-component-menu-midi-channel-brass-section = Brass Section
-instruments-component-menu-midi-channel-synth-brass1 = Synth Brass 1
-instruments-component-menu-midi-channel-synth-brass2 = Synth Brass 2
-instruments-component-menu-midi-channel-soprano-sax = Soprano Sax
-instruments-component-menu-midi-channel-alto-sax = Alto Sax
-instruments-component-menu-midi-channel-tenor-sax = Tenor Sax
-instruments-component-menu-midi-channel-baritone-sax = Baritone Sax
-instruments-component-menu-midi-channel-oboe = Oboe
-instruments-component-menu-midi-channel-english-horn = English Horn
-instruments-component-menu-midi-channel-bassoon = Bassoon
-instruments-component-menu-midi-channel-clarinet = Clarinet
-instruments-component-menu-midi-channel-piccolo = Piccolo
-instruments-component-menu-midi-channel-flute = Flute
-instruments-component-menu-midi-channel-recorder = Recorder
-instruments-component-menu-midi-channel-pan-flute = Pan Flute
-instruments-component-menu-midi-channel-bottle-blow = Bottle Blow
-instruments-component-menu-midi-channel-shakuhachi = Shakuhachi
-instruments-component-menu-midi-channel-whistle = Whistle
-instruments-component-menu-midi-channel-ocarina = Ocarina
-instruments-component-menu-midi-channel-square-wave-lead = Square Wave Lead
-instruments-component-menu-midi-channel-sawtooth-wave-lead = Sawtooth Wave Lead
-instruments-component-menu-midi-channel-calliope-lead = Calliope Lead
-instruments-component-menu-midi-channel-chiff-lead = Chiff Lead
-instruments-component-menu-midi-channel-charang-lead = Charang Lead
-instruments-component-menu-midi-channel-voice-lead = Voice Lead
-instruments-component-menu-midi-channel-fiths-lead = Fiths Lead
-instruments-component-menu-midi-channel-bass-lead = Bass Lead
-instruments-component-menu-midi-channel-new-age-pad = New Age Pad
-instruments-component-menu-midi-channel-warm-pad = Warm Pad
-instruments-component-menu-midi-channel-polysynth-pad = Polysynth Pad
-instruments-component-menu-midi-channel-choir-pad = Choir Pad
-instruments-component-menu-midi-channel-bowed-pad = Bowed Pad
-instruments-component-menu-midi-channel-metallic-pad = Metallic Pad
-instruments-component-menu-midi-channel-halo-pad = Halo Pad
-instruments-component-menu-midi-channel-sweep-pad = Sweep Pad
-instruments-component-menu-midi-channel-rain-effect = Rain Effect
-instruments-component-menu-midi-channel-soundtrack-effect = Soundtrack Effect
-instruments-component-menu-midi-channel-crystal-effect = Crystal Effect
-instruments-component-menu-midi-channel-atmosphere-effect = Atmosphere Effect
-instruments-component-menu-midi-channel-brightness-effect = Brightness Effect
-instruments-component-menu-midi-channel-goblins-effect = Goblins Effect
-instruments-component-menu-midi-channel-echoes-effect = Echoes Effect
-instruments-component-menu-midi-channel-sci-fi-effect = Sci-Fi Effect
-instruments-component-menu-midi-channel-sitar = Sitar
-instruments-component-menu-midi-channel-banjo = Banjo
-instruments-component-menu-midi-channel-shamisen = Shamisen
-instruments-component-menu-midi-channel-koto = Koto
-instruments-component-menu-midi-channel-kalimba = Kalimba
-instruments-component-menu-midi-channel-bagpipe = Bagpipe
-instruments-component-menu-midi-channel-fiddle = Fiddle
-instruments-component-menu-midi-channel-shanai = Shanai
-instruments-component-menu-midi-channel-tinkle-bell = Tinkle Bell
-instruments-component-menu-midi-channel-agogo = Agogo
-instruments-component-menu-midi-channel-steel-drums = Steel Drums
-instruments-component-menu-midi-channel-woodblock = Woodblock
-instruments-component-menu-midi-channel-taiko-drum = Taiko Drum
-instruments-component-menu-midi-channel-melodic-tom = Melodic Tom
-instruments-component-menu-midi-channel-synth-drum = Synth Drum
-instruments-component-menu-midi-channel-reverse-cymbal = Reverse Cymbal
-instruments-component-menu-midi-channel-guitar-fret-noise = Guitar Fret Noise
-instruments-component-menu-midi-channel-breath-noise = Breath Noise
-instruments-component-menu-midi-channel-seashore = Seashore
-instruments-component-menu-midi-channel-bird-tweet = Bird Tweet
-instruments-component-menu-midi-channel-telephone-ring = Telephone Ring
-instruments-component-menu-midi-channel-helicopter = Helicopter
-instruments-component-menu-midi-channel-applause = Applause
-instruments-component-menu-midi-channel-gunshot = Gunshot