示例#1
0
        /// <summary>
        ///     Discovers device on specific IP address and port.
        /// </summary>
        /// <param name="remoteEp">Remote IP address and port.</param>
        /// <returns>An observable sequence containing device information.</returns>
        private static IObservable <DiscoverResult> DiscoverOnSinglecast(IPEndPoint remoteEp) => Observable.Create <DiscoverResult>(async(observer, cancelToken) => {
            var disposables = new CompositeDisposable();
            var udpClient   = new UdpClient();
            disposables.Add(udpClient);
            try {
                udpClient.Connect(remoteEp);

                UdpReceiveResult received;
                try {
                    // send SW_ID_FindSw
                    var timeout = new CancellationTokenSource(InternalConfiguration.NetworkTimeoutMsec);
                    disposables.Add(timeout);
                    var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancelToken);
                    disposables.Add(linkedCancel);
                    var cmd = new SwApiCommand {
                        Cmd = SwApiId.FindSw
                    }.ToBytes();
                    if (await udpClient.SendAsync(cmd, cmd.Length).WithCancellation(linkedCancel.Token) != 4)
                    {
                        // cannot send.
                        observer.OnCompleted();
                        return;
                    }
                    // receive SW_ID_FindSwAck
                    timeout = new CancellationTokenSource(InternalConfiguration.NetworkTimeoutMsec);
                    disposables.Add(timeout);
                    linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancelToken);
                    disposables.Add(linkedCancel);
                    received = await udpClient.ReceiveAsync().WithCancellation(linkedCancel.Token);
                } catch (OperationCanceledException) {
                    // no results.
                    observer.OnCompleted();
                    return;
                }

                var ack = ParseFindSwAck(received.Buffer, received.RemoteEndPoint);
                if (ack != null)
                {
                    // found device
                    observer.OnNext(ack);
                }
                observer.OnCompleted();
            } catch (Exception ex) {
                observer.OnError(ex);
            } finally {
                disposables.Dispose();
            }
        });
示例#2
0
        /// <summary>
        ///     Discovers devices on specific network interface.
        /// </summary>
        /// <param name="remoteEp">Multicast address and port.</param>
        /// <param name="localAddress">Local IP address.</param>
        /// <returns>An observable sequence containing device information.</returns>
        private static IObservable <DiscoverResult> DiscoverOnMulticast(IPEndPoint remoteEp, IPAddress localAddress) => Observable.Create <DiscoverResult>(async(observer, cancelToken) => {
            var disposables = new CompositeDisposable();
            var udpClient   = new UdpClient(new IPEndPoint(localAddress, remoteEp.Port));
            disposables.Add(udpClient);
            try {
                udpClient.MulticastLoopback = false;
                udpClient.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
                udpClient.JoinMulticastGroup(remoteEp.Address, localAddress);

                // send SW_ID_FindSw
                var cmd = new SwApiCommand {
                    Cmd = SwApiId.FindSw
                }.ToBytes();
                await udpClient.SendAsync(cmd, cmd.Length, remoteEp);

                // receive SW_ID_FindSwAck
                while (true)
                {
                    if (cancelToken.IsCancellationRequested)
                    {
                        return;
                    }
                    var timeout = new CancellationTokenSource(InternalConfiguration.NetworkTimeoutMsec);
                    disposables.Add(timeout);
                    var linkedCancel = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, cancelToken);
                    disposables.Add(linkedCancel);
                    try {
                        var received = await udpClient.ReceiveAsync().WithCancellation(linkedCancel.Token);
                        var ack      = ParseFindSwAck(received.Buffer, received.RemoteEndPoint);
                        if (ack != null)
                        {
                            // found device
                            observer.OnNext(ack);
                        }
                    } catch (OperationCanceledException) {
                        // no more results.
                        break;
                    }
                }
                observer.OnCompleted();
            } catch (Exception ex) {
                observer.OnError(ex);
            } finally {
                udpClient.DropMulticastGroup(remoteEp.Address);
                disposables.Dispose();
            }
        });
示例#3
0
        public async Task SendControlCommand(SwApiCommand cmd)
        {
            if (!_controlUdp.Client.Connected)
            {
                throw new InvalidOperationException();
            }

            var buf = cmd.ToBytes();

            await _sendControlLock.WaitAsync();

            try {
                await _controlUdp.SendAsync(buf, buf.Length);
            } finally {
                _sendControlLock.Release();
            }
        }
示例#4
0
        public async Task SendGeneralCommand(SwApiCommand cmd)
        {
            if (_generalTcpStream == null)
            {
                throw new InvalidOperationException();
            }

            var payload = cmd.ToBytes();
            var buf     = BitConverter.GetBytes((uint)payload.Length).Concat(payload).ToArray();

            await _sendGeneralLock.WaitAsync();

            try {
                await _generalTcpStream.WriteAsync(buf, 0, buf.Length);
            } finally {
                _sendGeneralLock.Release();
            }
        }
示例#5
0
        private static DiscoverResult ParseFindSwAck(byte[] buf, IPEndPoint remoteEp)
        {
            if (SwApiCommand.GetApiId(buf) != SwApiId.FindSwAck)
            {
                return(null);
            }
            var ack = SwApiCommand.FromBytes <SwApiFindSwAck>(buf);

            if (ack == null)
            {
                return(null);
            }

            var result = new DiscoverResult {
                FindSwAck         = ack,
                DisplayNameString = Encoding.UTF8.GetString(ack.DisplayName).TrimEnd('\0'),
                Address           = remoteEp.Address
            };

            Debug.WriteLine($"Device found. Name='{result.DisplayNameString}' IP={result.Address} PreviewPort={result.FindSwAck.Preview} ControlPort={result.FindSwAck.Command} GeneralPort={result.FindSwAck.Tcp}");
            return(result);
        }
示例#6
0
        private static SwApiCommand ParseGeneralCommand(byte[] buf)
        {
            var apiId = SwApiCommand.GetApiId(buf);

            switch (apiId)
            {
            case SwApiId.SwBasicInfo:
                // SwApi_SwBasicInfo
                return(SwApiCommand.FromBytes <SwApiSwBasicInfo>(buf));

            case SwApiId.FileList:
                // SwApi_FileList
                return(SwApiCommand.FromBytes <SwApiFileList>(buf));

            case SwApiId.ChromaPreviewResult:
                // SwApi_ChromaPreviewResult
                return(SwApiCommand.FromBytes <SwApiChromaPreviewResult>(buf));

            case SwApiId.LiveBroadcastStateResult:
                // SwApi_LiveBroadcastState
                return(SwApiCommand.FromBytes <SwApiLiveBroadcastState>(buf));

            case SwApiId.UploadFileResult:
                // SwApi_UploadFileResult
                return(SwApiCommand.FromBytes <SwApiUploadFileResult>(buf));

            case SwApiId.ExternalStorageInputStateResult:
                // SwApi_ExternalStorageInputStateResult
                return(SwApiCommand.FromBytes <SwApiExternalStorageInputStateResult>(buf));

            case SwApiId.EthernetSettingResult:
            case SwApiId.WiFiNetworkSettingResult:
            case SwApiId.ApSettingResult:
                // SwApi_NetworkSettingResult
                return(SwApiCommand.FromBytes <SwApiNetworkSettingResult>(buf));

            case SwApiId.MountNotify:
                // SwApi_MountNotify
                return(SwApiCommand.FromBytes <SwApiMountNotify>(buf));

            case SwApiId.RecordingResult:
                // SwApi_RecordingState
                return(SwApiCommand.FromBytes <SwApiRecordingState>(buf));

            case SwApiId.RecordSetting:
            case SwApiId.PreviewSetting:
                // SwApi_CameraSetting
                return(SwApiCommand.FromBytes <SwApiCameraSetting>(buf));

            case SwApiId.FirmwareUpdateResult:
                // SwApi_DoFirmwareUpdateResult
                return(SwApiCommand.FromBytes <SwApiDoFirmwareUpdateResult>(buf));

            case SwApiId.StatusNetworkAddress:
                // SwApi_NetworkAddress
                return(SwApiCommand.FromBytes <SwApiNetworkAddress>(buf));

            case SwApiId.File:
            case SwApiId.ChangeProgramOutSetting:
            case SwApiId.TcpHeartBeat:
            case SwApiId.SetTimeResult:
            case SwApiId.ChangePreviewOutOsd:
            case SwApiId.ChangePreviewOutFormat:
            case SwApiId.GetFileError:
                // Do nothing
                return(null);

            default:
                Debug.WriteLine($"Unsupported GeneralCommand({apiId})");
                return(null);
            }
        }
示例#7
0
        private static SwApiCommand ParseControlCommand(byte[] buf)
        {
            var apiId = SwApiCommand.GetApiId(buf);

            switch (apiId)
            {
            case SwApiId.StateMode:
                // SwApi_State_Mode
                return(SwApiCommand.FromBytes <SwApiStateMode>(buf));

            case SwApiId.StateRecording:
                // SwApi_State_Recording
                return(SwApiCommand.FromBytes <SwApiStateRecording>(buf));

            case SwApiId.StateFadeToDefaultColor:
                // SwApi_State_FadeToDefaultColor
                return(SwApiCommand.FromBytes <SwApiStateFadeToDefaultColor>(buf));

            case SwApiId.StateExternalInput:
                // SwApi_State_ExternalInput
                return(SwApiCommand.FromBytes <SwApiStateExternalInput>(buf));

            case SwApiId.StateProgramOut:
                // SwApi_State_ProgramOut
                return(SwApiCommand.FromBytes <SwApiStateProgramOut>(buf));

            case SwApiId.StatePreviewOut:
                // SwApi_State_PreviewOut
                return(SwApiCommand.FromBytes <SwApiStatePreviewOut>(buf));

            case SwApiId.StateDefaultBackgroundColor:
                // SwApi_State_DefaultBackgroundColor
                return(SwApiCommand.FromBytes <SwApiStateDefaultBackgroundColor>(buf));

            case SwApiId.StateExternalStorage:
                // SwApi_State_ExternalStorage
                return(SwApiCommand.FromBytes <SwApiStateExternalStorage>(buf));

            case SwApiId.StatePreviewMode:
                // SwApi_State_PreviewMode
                return(SwApiCommand.FromBytes <SwApiStatePreviewMode>(buf));

            case SwApiId.StateTcpConnected:
                // no payload
                return(SwApiCommand.FromBytes <SwApiCommand>(buf));

            case SwApiId.StatusAudioMixer:
                // SwApi_ChangeAudioMixer
                return(SwApiCommand.FromBytes <SwApiChangeAudioMixer>(buf));

            case SwApiId.StatusAudioMixerAll:
                // SwApi_ChangeAudioMixerAll
                return(SwApiCommand.FromBytes <SwApiChangeAudioMixerAll>(buf));

            case SwApiId.StatusAudioPeak:
                // SwApi_Status_AudioPeak
                return(SwApiCommand.FromBytes <SwApiStatusAudioPeak>(buf));

            case SwApiId.StatusVideoSwitcher:
                // SwApi_VideoSwitcherStatus
                return(SwApiCommand.FromBytes <SwApiVideoSwitcherStatus>(buf));

            case SwApiId.StatusVideoSwitcherAuto:
                // SwApi_VideoSwitcherStatus
                return(SwApiCommand.FromBytes <SwApiVideoSwitcherStatus>(buf));

            case SwApiId.StatusSetPinpGeometry:
                // SwApi_VideoSetPinpGeometry
                return(SwApiCommand.FromBytes <SwApiVideoSetPinpGeometry>(buf));

            case SwApiId.StatusSetPinpBorder:
                // SwApi_VideoSetBorder
                return(SwApiCommand.FromBytes <SwApiVideoSetBorder>(buf));

            case SwApiId.StatusSetChromaRange:
                // SwApi_VideoSetChromaRange
                return(SwApiCommand.FromBytes <SwApiVideoSetChromaRange>(buf));

            case SwApiId.StatusSetSubMode:
                // SwApi_VideoSetSubMode
                return(SwApiCommand.FromBytes <SwApiVideoSetSubMode>(buf));

            case SwApiId.StatusNetworkAddress:
                // SwApi_NetworkAddress
                return(SwApiCommand.FromBytes <SwApiNetworkAddress>(buf));

            case SwApiId.StatusUpdater:
                // SwApi_DoFirmwareUpdateResult
                return(SwApiCommand.FromBytes <SwApiDoFirmwareUpdateResult>(buf));

            case SwApiId.EthernetSettingResult:
            case SwApiId.ApSettingResult:
            case SwApiId.WiFiNetworkSettingResult:
                // SwApi_NetworkSettingResult
                return(SwApiCommand.FromBytes <SwApiNetworkSettingResult>(buf));

            case SwApiId.MountNotify:
                // SwApi_MountNotify
                return(SwApiCommand.FromBytes <SwApiMountNotify>(buf));

            case SwApiId.LiveBroadcastStateResult:
                // SwApi_LiveBroadcastState
                return(SwApiCommand.FromBytes <SwApiLiveBroadcastState>(buf));

            default:
                Debug.WriteLine($"Unsupported ControlCommand({apiId})");
                return(null);
            }
        }