public void Handle(UpdateCall update) { _call = update.Call; if (update.Call.State is CallStatePending pending) { if (update.Call.IsOutgoing && pending.IsCreated && pending.IsReceived) { if (pending.IsCreated && pending.IsReceived) { _mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_ringback.mp3")); _mediaPlayer.IsLoopingEnabled = true; _mediaPlayer.Play(); } } } if (update.Call.State is CallStateReady ready) { var user = CacheService.GetUser(update.Call.UserId); if (user == null) { return; } VoIPControllerWrapper.UpdateServerConfig(ready.Config); var logFile = Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{SessionId}", "tgvoip.logFile.txt"); var statsDumpFile = Path.Combine(ApplicationData.Current.LocalFolder.Path, $"{SessionId}", "tgvoip.statsDump.txt"); var call_packet_timeout_ms = CacheService.GetOption <OptionValueInteger>("call_packet_timeout_ms"); var call_connect_timeout_ms = CacheService.GetOption <OptionValueInteger>("call_connect_timeout_ms"); if (_controller != null) { _controller.Dispose(); _controller = null; } _controller = new VoIPControllerWrapper(); _controller.SetConfig(call_packet_timeout_ms.Value / 1000.0, call_connect_timeout_ms.Value / 1000.0, base.Settings.UseLessData, true, true, true, logFile, statsDumpFile); _controller.CallStateChanged += (s, args) => { BeginOnUIThread(() => { if (args == libtgvoip.CallState.WaitInit || args == libtgvoip.CallState.WaitInitAck) { _mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_connecting.mp3")); _mediaPlayer.IsLoopingEnabled = false; _mediaPlayer.Play(); } else if (args == libtgvoip.CallState.Established) { _mediaPlayer.Source = null; } }); }; BeginOnUIThread(() => { Show(update.Call, _controller); }); var p2p = base.Settings.PeerToPeerMode == 0 || (base.Settings.PeerToPeerMode == 1 && user.OutgoingLink is LinkStateIsContact); var endpoints = new Endpoint[ready.Connections.Count]; for (int i = 0; i < endpoints.Length; i++) { endpoints[i] = new Endpoint { id = ready.Connections[i].Id, ipv4 = ready.Connections[i].Ip, ipv6 = ready.Connections[i].Ipv6, peerTag = ready.Connections[i].PeerTag.ToArray(), port = (ushort)ready.Connections[i].Port }; } _controller.SetEncryptionKey(ready.EncryptionKey.ToArray(), update.Call.IsOutgoing); _controller.SetPublicEndpoints(endpoints, ready.Protocol.UdpP2p && p2p, 74); _controller.Start(); _controller.Connect(); } else if (update.Call.State is CallStateDiscarded discarded) { if (discarded.NeedDebugInformation) { ProtoService.Send(new SendCallDebugInformation(update.Call.Id, _controller.GetDebugLog())); } if (discarded.NeedRating) { BeginOnUIThread(async() => { var dialog = new PhoneCallRatingView(); var confirm = await dialog.ShowQueuedAsync(); if (confirm == ContentDialogResult.Primary) { ProtoService.Send(new SendCallRating(update.Call.Id, dialog.Rating + 1, dialog.Rating >= 0 && dialog.Rating <= 3 ? dialog.Comment : null)); } }); } _controller?.Dispose(); _controller = null; _call = null; } BeginOnUIThread(() => { switch (update.Call.State) { case CallStateDiscarded discarded: if (update.Call.IsOutgoing && discarded.Reason is CallDiscardReasonDeclined) { _mediaPlayer.Source = MediaSource.CreateFromUri(new Uri("ms-appx:///Assets/Audio/voip_busy.mp3")); _mediaPlayer.IsLoopingEnabled = true; _mediaPlayer.Play(); Show(update.Call, null); } else { _mediaPlayer.Source = null; Hide(); } break; case CallStateError error: Hide(); break; default: Show(update.Call, null); break; } }); }
private async void OnRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { var deferral = args.GetDeferral(); var message = args.Request.Message; try { if (message.ContainsKey("caption") && message.ContainsKey("request")) { var caption = message["caption"] as string; var buffer = message["request"] as string; var req = TLSerializationService.Current.Deserialize(buffer); if (caption.Equals("voip.getUser") && req is TLPeerUser userPeer) { var user = InMemoryCacheService.Current.GetUser(userPeer.UserId); if (user != null) { await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(user) } }); } else { await args.Request.SendResponseAsync(new ValueSet { { "error", TLSerializationService.Current.Serialize(new TLRPCError { ErrorMessage = "USER_NOT_FOUND", ErrorCode = 404 }) } }); } } else if (caption.Equals("voip.getConfig")) { var config = InMemoryCacheService.Current.GetConfig(); await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(config) } }); } else if (caption.Equals("voip.callInfo") && req is byte[] data) { using (var from = new TLBinaryReader(data)) { var tupleBase = new TLTuple <int, TLPhoneCallBase, TLUserBase, string>(from); var tuple = new TLTuple <TLPhoneCallState, TLPhoneCallBase, TLUserBase, string>((TLPhoneCallState)tupleBase.Item1, tupleBase.Item2, tupleBase.Item3, tupleBase.Item4); if (tuple.Item2 is TLPhoneCallDiscarded) { if (_phoneView != null) { var newView = _phoneView; _phoneViewExists = false; _phoneView = null; await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { newView.SetCall(tuple); newView.Dispose(); Window.Current.Close(); }); } return; } if (_phoneViewExists == false) { VoIPCallTask.Log("Creating VoIP UI", "Creating VoIP UI"); _phoneViewExists = true; PhoneCallPage newPlayer = null; CoreApplicationView newView = CoreApplication.CreateNewView(); var newViewId = 0; await newView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { newPlayer = new PhoneCallPage(); Window.Current.Content = newPlayer; Window.Current.Activate(); newViewId = ApplicationView.GetForCurrentView().Id; newPlayer.SetCall(tuple); _phoneView = newPlayer; }); await CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, async() => { if (ApiInformation.IsMethodPresent("Windows.UI.ViewManagement.ApplicationView", "IsViewModeSupported") && ApplicationView.GetForCurrentView().IsViewModeSupported(ApplicationViewMode.CompactOverlay)) { var preferences = ViewModePreferences.CreateDefault(ApplicationViewMode.CompactOverlay); preferences.CustomSize = new Size(340, 200); var viewShown = await ApplicationViewSwitcher.TryShowAsViewModeAsync(newViewId, ApplicationViewMode.CompactOverlay, preferences); } else { //await ApplicationViewSwitcher.SwitchAsync(newViewId); await ApplicationViewSwitcher.TryShowAsStandaloneAsync(newViewId); } }); } else if (_phoneView != null) { VoIPCallTask.Log("VoIP UI already exists", "VoIP UI already exists"); await _phoneView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { _phoneView.SetCall(tuple); }); } } } else if (caption.Equals("voip.signalBars") && req is byte[] data2) { using (var from = new TLBinaryReader(data2)) { var tuple = new TLTuple <int>(from); if (_phoneView != null) { await _phoneView.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => { _phoneView.SetSignalBars(tuple.Item1); }); } } } else if (caption.Equals("voip.setCallRating") && req is TLInputPhoneCall peer) { Execute.BeginOnUIThread(async() => { var dialog = new PhoneCallRatingView(); var confirm = await dialog.ShowQueuedAsync(); if (confirm == ContentDialogResult.Primary) { await MTProtoService.Current.SetCallRatingAsync(peer, dialog.Rating, dialog.Rating >= 0 && dialog.Rating <= 3 ? dialog.Comment : null); } }); } else { var response = await MTProtoService.Current.SendRequestAsync <object>(caption, req as TLObject); if (response.IsSucceeded) { await args.Request.SendResponseAsync(new ValueSet { { "result", TLSerializationService.Current.Serialize(response.Result) } }); } else { await args.Request.SendResponseAsync(new ValueSet { { "error", TLSerializationService.Current.Serialize(response.Error) } }); } } } } finally { deferral.Complete(); } }