Ejemplo n.º 1
0
        public override DataTransferStatus OnMessage(ICommand command, AtemConnection connection)
        {
            if (command is DataTransferUploadContinueCommand continueCommand && continueCommand.TransferId == _id)
            {
                var toSend = new DataTransferFileDescriptionCommand()
                {
                    TransferId  = _id,
                    Name        = _name,
                    Description = _description,
                };
                connection.QueueCommand(toSend);

                // also queue data
                const int maxBodySize = 1350;

                // TODO - base chunking off of UploedMediaFrameJob
                int startPos = 0;
                while (startPos < _dataQueue.Count)
                {
                    int count = 1;
                    for (; count < _dataQueue.Count - startPos; count++)
                    {
                        int d = _dataQueue.Skip(startPos).Take(count + 1).Sum(v => v.Length);
                        if (d > maxBodySize)
                        {
                            break;
                        }
                    }

                    connection.QueueCommand(new DataTransferDataCommand()
                    {
                        TransferId = _id,
                        Body       = _dataQueue.Skip(startPos).Take(count).SelectMany(b => b).ToArray()
                    });

                    startPos += count;
                }

                return(DataTransferStatus.OK);
            }

            if (command is DataTransferCompleteCommand completeCommand && completeCommand.TransferId == _id)
            {
                _onComplete(true);
                return(DataTransferStatus.Success);
            }

            _onComplete(false);
            return(DataTransferStatus.Error);
        }
        public virtual IEnumerable <ICommand> HandleCommand(Lazy <ImmutableList <ICommand> > previousCommands, ICommand cmd)
        {
            var lockRes = LockCommandHandler(previousCommands, cmd).ToList();

            if (lockRes.Any())
            {
                foreach (LockStateChangedCommand lockCmd in lockRes.OfType <LockStateChangedCommand>())
                {
                    _locked = lockCmd.Locked;
                    // _output.WriteLine($"Locked {lockCmd.Locked}");
                }

                return(lockRes);
            }

            // _output.WriteLine($"Got cmd: {cmd.GetType().FullName}");

            var res = new List <ICommand>();

            if (cmd is DataTransferUploadRequestCommand startCmd)
            {
                Assert.Equal(_bank != 0xffff, _locked);
                Assert.False(_isComplete);
                Assert.Equal(_expectedMode, startCmd.Mode);
                if (_targetBytes > 0)
                {
                    Assert.Equal((int)_targetBytes, startCmd.Size);
                }
                Assert.Equal(_index, startCmd.TransferIndex);
                Assert.Equal((uint)_bank, startCmd.TransferStoreId);

                _transferId  = startCmd.TransferId;
                _pendingAck  = 0;
                _targetBytes = (uint)startCmd.Size;

                res.Add(new DataTransferUploadContinueCommand
                {
                    TransferId = startCmd.TransferId,
                    ChunkCount = _chunkCount,
                    ChunkSize  = _chunkSize
                });
            }
            else if (cmd is DataTransferFileDescriptionCommand descCmd)
            {
                Assert.NotEqual(0u, _transferId);
                Assert.Null(_description);
                Assert.False(_isComplete);

                Assert.Equal(_transferId, descCmd.TransferId);
                _description = descCmd;

                if (_usedBytes >= _targetBytes)
                {
                    _isComplete = true;

                    res.AddRange(Complete());
                }
                else
                {
                    res.Add(null);
                }
            }
            else if (cmd is DataTransferDataCommand dataCmd)
            {
                Assert.NotEqual(0u, _transferId);
                Assert.False(_isComplete);

                Assert.Equal(_transferId, dataCmd.TransferId);
                Assert.True(dataCmd.Body.Length <= _chunkSize);
                Tuple <int, byte[]> decoded = _decodeRle
                    ? FrameEncodingUtil.DecodeRLESegment(_targetBytes, dataCmd.Body)
                    : Tuple.Create(dataCmd.Body.Length, dataCmd.Body);

                if (!_knownTargetBytes)
                {
                    byte[] newBuffer = new byte[Buffer.Length + decoded.Item1];
                    Array.Copy(Buffer, 0, newBuffer, 0, Buffer.Length);
                    Buffer = newBuffer;
                }
                //long copyLength = Math.Min(decoded.Item1, _targetBytes - _usedBytes);
                Array.Copy(decoded.Item2, 0, Buffer, _usedBytes, decoded.Item1);
                _usedBytes += (uint)decoded.Item1;

                _pendingAck++;
                if (_pendingAck >= _chunkCount)
                {
                    //res.Add(new DataTransferAckCommand {TransferId = _transferId});
                    res.Add(new DataTransferUploadContinueCommand
                    {
                        TransferId = _transferId,
                        ChunkCount = _chunkCount,
                        ChunkSize  = _chunkSize
                    });
                    _pendingAck = 0;
                }

                // _output.WriteLine($"Now have {_usedBytes} bytes of {_targetBytes}");

                if (_usedBytes >= _targetBytes && _description != null)
                {
                    _isComplete = true;
                    res.AddRange(Complete());
                }

                if (res.Count == 0)
                {
                    res.Add(null);
                }
            }

            return(res);
        }