public static Task <IEnumerable <MediaUploadResult> > UploadMediaAsync(this IMediaClient client, string targetPath, params string[] filePaths)
        {
            Ensure.Argument.NotNull(filePaths, "filePaths");
            Ensure.Argument.Is(filePaths.Length > 0, "You must provide at least one file to upload.");

            var uploads = new List <UploadMediaCommand>();

            foreach (var file in filePaths.Select(path => new FileInfo(path)))
            {
                if (!file.Exists)
                {
                    throw new FileNotFoundException("File not found.", file.FullName);
                }

                var fileStream = new FileStream(file.FullName, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 1024, useAsync: true);
                uploads.Add(new UploadMediaCommand {
                    FileName   = file.Name,
                    FileStream = fileStream
                });
            }

            return(client.UploadMediaAsync(targetPath, uploads.ToArray()));
        }
 public static Task <IEnumerable <MediaUploadResult> > UploadMediaAsync(this IMediaClient client, params UploadMediaCommand[] commands)
 {
     return(client.UploadMediaAsync(null, commands));
 }
 public static Task <IEnumerable <MediaUploadResult> > UploadMediaAsync(this IMediaClient client, params string[] targetPaths)
 {
     return(client.UploadMediaAsync(null, targetPaths));
 }
Example #4
0
        public RopuClient(
            ProtocolSwitch protocolSwitch,
            ServingNodeClient servingNodeClient,
            IMediaClient mediaClient,
            LoadBalancerProtocol loadBalancerProtocol,
            IClientSettings clientSettings,
            IBeepPlayer beepPlayer,
            RopuWebClient webClient,
            KeysClient keysClient)
        {
            _webClient            = webClient;
            _beepPlayer           = beepPlayer;
            _clientSettings       = clientSettings;
            _loadBalancerProtocol = loadBalancerProtocol;
            _protocolSwitch       = protocolSwitch;
            _servingNodeClient    = servingNodeClient;
            _mediaClient          = mediaClient;
            _servingNodeClient.SetControllingFunctionHandler(this);
            _retryTimer = new Ropu.Shared.Timer();
            _keysClient = keysClient;

            var allEvents = (EventId[])Enum.GetValues(typeof(EventId));

            //start
            _start        = new RopuState(StateId.Start);
            _stateManager = new StateManager <StateId, EventId>(_start);
            _stateManager.AddState(_start);
            _start.AddTransitions(allEvents, () => _start);

            //registered
            _registered = new RopuState(StateId.Registered)
            {
                Entry = async token =>
                {
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    _callGroup        = IdleGroup;
                    _registeredUserId = _clientSettings.UserId.Value;
                    if (_heartbeatTask == null)
                    {
                        _heartbeatTask = Heartbeat(_heartbeatCancellationTokenSource.Token);
                    }
                    _heartbeatOnEvent.Set(); //allows the heartbeat to continue
                    await Task.Run(() => {});
                },
            };
            _stateManager.AddState(_registered);
            _registered.AddTransition(EventId.CallRequest, () => _startingCall !);
            _registered.AddTransition(EventId.PttDown, () => _startingCall !);
            _registered.AddTransition(EventId.RegistrationResponseReceived, () => _registered);
            _registered.AddTransition(EventId.CallStartFailed, () => _registered);
            _registered.AddTransition(EventId.PttUp, () => _registered);
            _registered.AddTransition(EventId.GroupSelected, () => _registered);

            //unregistered
            _noGroup      = new RopuState(StateId.NoGroup);
            _unregistered = new RopuState(StateId.Unregistered)
            {
                Entry = async token =>
                {
                    _heartbeatOnEvent.Reset(); //stops the heartbeat
                    await Register(token);
                }
            };
            _unregistered.AddTransition(EventId.RegistrationResponseReceived, () => IdleGroup == null ? _noGroup : _registered);
            _unregistered.AddTransition(EventId.FloorIdle, () => _unregistered);
            _unregistered.AddTransition(EventId.FloorTaken, () => _unregistered);
            _unregistered.AddTransition(EventId.CallEnded, () => _unregistered);
            _unregistered.AddTransition(EventId.CallRequest, () => _unregistered);
            _unregistered.AddTransition(EventId.CallStartFailed, () => _unregistered);
            _unregistered.AddTransition(EventId.HeartbeatFailed, () => _unregistered);
            _unregistered.AddTransition(EventId.PttUp, () => _unregistered);
            _unregistered.AddTransition(EventId.PttDown, () => _unregistered);
            _unregistered.AddTransition(EventId.GroupSelected, () => _unregistered);

            _stateManager.AddState(_unregistered);

            //no group
            _noGroup.AddTransition(EventId.PttUp, () => _noGroup);
            _noGroup.AddTransition(EventId.PttDown, () => _noGroup);
            _noGroup.AddTransition(EventId.GroupSelected, () => _registered);
            _noGroup.AddTransition(EventId.RegistrationResponseReceived, () => _noGroup);
            _noGroup.AddTransition(EventId.CallRequest, () => _noGroup);
            _noGroup.AddTransition(EventId.CallStartFailed, () => _noGroup);


            _stateManager.AddState(_noGroup);

            //deregistering
            _deregistering = new RopuState(StateId.Deregistering)
            {
                Entry = async token => await Deregister(token),
            };
            _deregistering.AddTransition(EventId.DeregistrationResponseReceived, () => _unregistered);
            _deregistering.AddTransitions(allEvents.Where(e => e != EventId.DeregistrationResponseReceived), () => _deregistering);
            _deregistering.AddTransition(EventId.GroupSelected, () => _deregistering);
            _stateManager.AddState(_deregistering);

            //starting call
            _startingCall = new RopuState(StateId.StartingCall)
            {
                Entry = async token => await StartCall(token),
                Exit  = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                    }
                }
            };
            _startingCall.AddTransition(EventId.CallStartFailed, () => _registered);
            _startingCall.AddTransition(EventId.PttUp, () => _startingCall);
            _startingCall.AddTransition(EventId.PttDown, () => _startingCall);
            _startingCall.AddTransition(EventId.RegistrationResponseReceived, () => _startingCall);
            _startingCall.AddTransition(EventId.CallRequest, () => _startingCall);
            _startingCall.AddTransition(EventId.GroupSelected, () => _startingCall);

            _stateManager.AddState(_startingCall);

            //in call idle
            _inCallIdle = new RopuState(StateId.InCallIdle);
            _inCallIdle.AddTransition(EventId.PttDown, () => _inCallRequestingFloor !);
            _inCallIdle.AddTransition(EventId.PttUp, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.RegistrationResponseReceived, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.CallRequest, () => _inCallIdle);
            _inCallIdle.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallIdle.AddTransition(EventId.GroupSelected, () => _inCallIdle);
            _stateManager.AddState(_inCallIdle);

            //in call receiving
            _inCallReceiveing = new RopuState(StateId.InCallReceiving);
            _inCallReceiveing.AddTransition(EventId.PttDown, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.PttUp, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.CallRequest, () => _inCallReceiveing);
            _inCallReceiveing.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallReceiveing.AddTransition(EventId.GroupSelected, () => _inCallReceiveing);
            _stateManager.AddState(_inCallReceiveing);

            //in call transmitting
            _inCallTransmitting = new RopuState(StateId.InCallTransmitting)
            {
                Entry = async token =>
                {
                    _beepPlayer.PlayGoAhead();
                    await Task.Run(() => {});
                },
                Exit = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                    }
                }
            };
            _inCallTransmitting.AddTransition(EventId.PttUp, () => _inCallReleasingFloor !);
            _inCallTransmitting.AddTransition(EventId.RegistrationResponseReceived, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.CallRequest, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.CallStartFailed, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.PttDown, () => _inCallTransmitting);
            _inCallTransmitting.AddTransition(EventId.GroupSelected, () => _inCallTransmitting);

            _stateManager.AddState(_inCallTransmitting);

            //in call requesting floor
            _inCallRequestingFloor = new RopuState(StateId.InCallRequestingFloor)
            {
                Entry = token =>
                {
                    if (_callGroup == null)
                    {
                        return(Task.CompletedTask);
                    }
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    _servingNodeClient.SendFloorRequest(_callGroup.Value, _clientSettings.UserId.Value);
                    StartSendingAudio();
                    return(Task.CompletedTask);
                },
                Exit = newState =>
                {
                    if (newState != _inCallTransmitting && newState != _inCallRequestingFloor)
                    {
                        _mediaClient.StopSendingAudio();
                        _beepPlayer.PlayDenied();
                    }
                }
            };
            _inCallRequestingFloor.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReleasingFloor !);
            _inCallRequestingFloor.AddTransition(EventId.CallRequest, () => _inCallReleasingFloor !);
            _inCallRequestingFloor.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallRequestingFloor.AddTransition(EventId.PttDown, () => _inCallRequestingFloor);
            _inCallRequestingFloor.AddTransition(EventId.PttUp, () => _inCallIdle);
            _inCallRequestingFloor.AddTransition(EventId.GroupSelected, () => _inCallRequestingFloor);
            _stateManager.AddState(_inCallRequestingFloor);

            //in call releasing floor
            _inCallReleasingFloor = new RopuState(StateId.InCallReleasingFloor)
            {
                Entry = async token =>
                {
                    if (_callGroup == null)
                    {
                        throw new InvalidOperationException("No call group");
                    }
                    if (_clientSettings.UserId == null)
                    {
                        throw new InvalidOperationException("UserId is not set");
                    }
                    while (!token.IsCancellationRequested)
                    {
                        _servingNodeClient.SendFloorReleased(_callGroup.Value, _clientSettings.UserId.Value);
                        await Task.Run(() => token.WaitHandle.WaitOne(1000));
                    }
                }
            };
            _inCallReleasingFloor.AddTransition(EventId.FloorGranted, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.RegistrationResponseReceived, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.CallRequest, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.CallStartFailed, () => _registered);
            _inCallReleasingFloor.AddTransition(EventId.PttDown, () => _inCallRequestingFloor);
            _inCallReleasingFloor.AddTransition(EventId.PttUp, () => _inCallReleasingFloor);
            _inCallReleasingFloor.AddTransition(EventId.GroupSelected, () => _inCallReleasingFloor);

            _stateManager.AddState(_inCallReleasingFloor);


            _inCallReleasingFloor.AddTransition(EventId.FloorGranted, () => _inCallReleasingFloor);


            _stateManager.StateChanged += (sender, args) =>
            {
                Console.WriteLine($"State Changed {this._stateManager.CurrentState}");
                StateChanged?.Invoke(this, args);
            };

            _stateManager.AddTransitionToAll(EventId.HeartbeatFailed, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.NotRegistered, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.CallEnded, () => _registered, stateId => stateId != StateId.Unregistered && stateId != StateId.Start && stateId != StateId.Deregistering);
            _stateManager.AddTransitionToAll(EventId.FloorIdle, () => _inCallIdle, IsRegistered);
            _stateManager.AddTransitionToAll(EventId.FloorTaken, () => _inCallReceiveing, IsRegistered);
            _stateManager.AddTransitionToAll(EventId.FloorGranted, () => _inCallTransmitting, stateId => stateId != StateId.InCallReleasingFloor);
            _stateManager.AddTransitionToAll(EventId.DeregistrationResponseReceived, () => _unregistered, stateId => true);
            _stateManager.AddTransitionToAll(EventId.GroupDeselected, () => _noGroup, stateId => true);

            _stateManager.CheckEventsAreHandledByAll((EventId[])Enum.GetValues(typeof(EventId)));
        }