private static void _ReadDataNodes(XElement element, Vixen.Module.Sequence.SequenceBase sequence, Guid[] effectTable, Guid[] channelIdTable) { byte[] bytes = new byte[2 * sizeof(ushort) + sizeof(byte)]; int effectIdIndex; int channelIdIndex; int channelIdCount; Guid effectId; List <OutputChannel> channels = new List <OutputChannel>(); byte parameterCount; List <object> parameters = new List <object>(); byte[] data; long dataLength; int startTime, timeSpan; // Data is stored as a base-64 stream from a binary stream. string dataString = element.Element("Data").Value; data = Convert.FromBase64String(dataString); using (MemoryStream dataStream = new MemoryStream(data)) { dataLength = dataStream.Length; while (dataStream.Position < dataLength) { channels.Clear(); parameters.Clear(); dataStream.Read(bytes, 0, bytes.Length); // Index of the command spec id from the command table (word). effectIdIndex = BitConverter.ToUInt16(bytes, 0 * sizeof(ushort)); // Referenced channel count (word). channelIdCount = BitConverter.ToUInt16(bytes, 1 * sizeof(ushort)); // Parameter count (byte) parameterCount = bytes[2 * sizeof(ushort)]; // Start time (dword). dataStream.Read(bytes, 0, sizeof(int)); startTime = BitConverter.ToInt32(bytes, 0); // Time span (dword). dataStream.Read(bytes, 0, sizeof(int)); timeSpan = BitConverter.ToInt32(bytes, 0); // Referenced channels (index into channel table, word). var outputChannels = Vixen.Sys.Execution.Fixtures.SelectMany(x => x.Channels); OutputChannel channel; while (channelIdCount-- > 0) { dataStream.Read(bytes, 0, sizeof(ushort)); channelIdIndex = BitConverter.ToUInt16(bytes, 0); // Channel may no longer exist. //channels.Add(sequence.OutputChannels.FirstOrDefault(x => x.Id == channelIdTable[channelIdIndex])); channel = outputChannels.FirstOrDefault(x => x.Id == channelIdTable[channelIdIndex]); if (channel != null) { channels.Add(channel); } } // Parameters (various) while (parameterCount-- > 0) { parameters.Add(ParameterValue.ReadFromStream(dataStream)); } // Get the effect inserted into the sequence. if (effectIdIndex < effectTable.Length) { effectId = effectTable[effectIdIndex]; if (Modules.IsValidId(effectId)) { sequence.InsertData(channels.ToArray(), startTime, timeSpan, new Command(effectId, parameters.ToArray())); } } } } }