Closed juanmalm closed 12 months ago
Thank you for your feedback. This has been routed to the support team for assistance.
@juanmalm , Thanks for reporting, I am looking into this issue. I will get back to you with an update.
@juanmalm , Apologies for the delay in response. I followed the steps and I am able to leave the meeting without any issues. The await call_.HangUpAsync(new HangUpOptions()) works properly. Only difference is that I am using Visual Studio 2019.
How frequently are you getting this issue?
In the meantime, I will try to reproduce the issue in Visual Studio 2022 as well
@juanmalm , Following up to check if you got the chance to look into my previous comment. Please let me know
Hi @MughundhanRaveendran-MSFT. My issue is reproducible 100%. It happened previously with VS2019 (I already uninstalled it) and right now it is happening with VS2022. I forgot to mention in repro steps that I'm joining to a meeting which currently has a Teams user connected with a Teams client in a MacBook Pro. I will try to reproduce it connecting with a user on a Windows client.
Later I will attach a project in which I reproduce the issue. Also if you are able to provide me an email address, I can record a video showing the issue.
Here you have the code I'm using. I can share with you the project and a video showing the issue if you provide me an email address.
MainPage.xaml.cs
using Azure.Communication.Calling;
using Azure.Communication.Identity;
using Azure.WinRT.Communication;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace poc_teams_integration
{
public sealed partial class MainPage : Page
{
private const string communicationServicesConnectionString = "USE A VALID CONNECTION STRING!!!!!!!!!!!!!";
private CommunicationIdentityClient communicationIdentityClient;
private Call call_;
private CallClient call_client;
private CallAgent call_agent;
private DeviceManager deviceManager;
private LocalVideoStream[] localVideoStream;
private Authenticator authenticator;
private string userToken;
public MainPage()
{
InitializeComponent();
InitCommunicationIdentityClient();
InitCallClientAndDeviceManager();
authenticator = new Authenticator();
}
private async void InitCallClientAndDeviceManager()
{
call_client = new CallClient();
deviceManager = await call_client.GetDeviceManager();
}
private void InitCommunicationIdentityClient()
{
communicationIdentityClient = new CommunicationIdentityClient(communicationServicesConnectionString);
}
private async void JoinButton_ClickAsync(object sender, RoutedEventArgs e)
{
if (!await ValidateInput())
{
return;
}
await CreateCallAgent();
await CreateLocalVideoStream();
await JoinTeamsMeeting();
}
private async Task CreateCallAgent()
{
try
{
if (string.IsNullOrEmpty(userToken))
{
var token = await authenticator.AcquireTokenAsync();
// https://docs.microsoft.com/en-us/azure/communication-services/quickstarts/manage-teams-identity?pivots=programming-language-csharp
var accessToken = await communicationIdentityClient.GetTokenForTeamsUserAsync(token);
userToken = accessToken.Value.Token;
}
if (call_agent is null)
{
var token_credential = new CommunicationTokenCredential(userToken);
call_agent = await call_client.CreateCallAgent(token_credential, new CallAgentOptions());
call_agent.OnCallsUpdated += Agent_OnCallsUpdated;
}
}
catch (Exception ex)
{
await new MessageDialog($"It was not possible to create call agent. Please check if token is valid:{Environment.NewLine}{ex.Message}").ShowAsync();
return;
}
}
private async Task CreateLocalVideoStream()
{
try
{
if (deviceManager.Cameras.Count > 0)
{
var videoDeviceInfo = deviceManager.Cameras[0];
localVideoStream = new LocalVideoStream[1];
localVideoStream[0] = new LocalVideoStream(videoDeviceInfo);
var localUri = await localVideoStream[0].CreateBindingAsync();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Source = localUri;
LocalVideo.Play();
});
}
}
catch (Exception ex)
{
await new MessageDialog($"Error creating local video stream:{Environment.NewLine}{ex.Message}").ShowAsync();
return;
}
}
private async Task JoinTeamsMeeting()
{
try
{
var joinCallOptions = new JoinCallOptions();
joinCallOptions.VideoOptions = new VideoOptions(localVideoStream);
var teamsMeetingLinkLocator = new TeamsMeetingLinkLocator(TeamsLinkTextBox.Text);
call_ = await call_agent.JoinAsync(teamsMeetingLinkLocator, joinCallOptions);
call_.OnStateChanged += Call_OnStateChangedAsync;
}
catch (Exception ex)
{
await new MessageDialog($"It was not possible to join the Teams meeting. Please check if Teams Link is valid:{Environment.NewLine}{ex.Message}").ShowAsync();
return;
}
}
private async void Call_OnStateChangedAsync(object sender, PropertyChangedEventArgs args)
{
try
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
CallStatusTextBlock.Text = call_.State.ToString();
});
switch (((Call)sender).State)
{
case CallState.Disconnected:
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
LocalVideo.Stop();
LocalVideo.Source = null;
RemoteVideo.Stop();
RemoteVideo.Source = null;
});
localVideoStream[0].ReleaseBinding();
localVideoStream[0] = null;
break;
default:
Debug.WriteLine(((Call)sender).State);
break;
}
}
catch (Exception ex)
{
await new MessageDialog($"Call_OnStateChangedAsync error:{Environment.NewLine}{ex.Message}").ShowAsync();
}
}
private async void LeaveButton_ClickAsync(object sender, RoutedEventArgs e)
{
try
{
if (call_ is null)
{
return;
}
await call_.StopVideo(localVideoStream[0]);
await call_.HangUpAsync(new HangUpOptions());
}
catch (Exception ex)
{
await new MessageDialog($"It was not possible to leave the Teams meeting:{Environment.NewLine}{ex.Message}").ShowAsync();
}
}
private async Task<bool> ValidateInput()
{
if (TeamsLinkTextBox.Text.Trim().Length == 0 || !TeamsLinkTextBox.Text.StartsWith("http"))
{
await new MessageDialog("Please enter Teams meeting link.").ShowAsync();
return false;
}
return true;
}
private async void Agent_OnCallsUpdated(object sender, CallsUpdatedEventArgs args)
{
foreach (var call in args.AddedCalls)
{
foreach (var remoteParticipant in call.RemoteParticipants)
{
await AddVideoStreams(remoteParticipant.VideoStreams);
remoteParticipant.OnVideoStreamsUpdated += async (s, a) => await AddVideoStreams(a.AddedRemoteVideoStreams);
}
call.OnRemoteParticipantsUpdated += Call_OnRemoteParticipantsUpdated;
call.OnStateChanged += Call_OnStateChangedAsync;
}
}
private async void Call_OnRemoteParticipantsUpdated(object sender, ParticipantsUpdatedEventArgs args)
{
foreach (var remoteParticipant in args.AddedParticipants)
{
await AddVideoStreams(remoteParticipant.VideoStreams);
remoteParticipant.OnVideoStreamsUpdated += async (s, a) => await AddVideoStreams(a.AddedRemoteVideoStreams);
}
}
private async Task AddVideoStreams(IReadOnlyList<RemoteVideoStream> streams)
{
foreach (var remoteVideoStream in streams)
{
var remoteUri = await remoteVideoStream.CreateBindingAsync();
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
RemoteVideo.Source = remoteUri;
RemoteVideo.Play();
});
remoteVideoStream.Start();
}
}
}
}
Authenticator.cs
using Microsoft.Identity.Client;
using System;
using System.Threading.Tasks;
using Windows.UI.Popups;
namespace poc_teams_integration
{
internal class Authenticator
{
private IPublicClientApplication PCA;
private string ClientID = "USE A VALID CLIENT ID!!!!!!!!!!!!!";
readonly static string[] Scopes = { "https://auth.msft.communication.azure.com/Teams.ManageCalls" };
public Authenticator()
{
PCA = PublicClientApplicationBuilder.Create(ClientID)
.WithRedirectUri($"msal{ClientID}://auth")
.Build();
}
public async Task<string> AcquireTokenAsync()
{
try
{
var authResult = await PCA.AcquireTokenInteractive(Scopes)
.ExecuteAsync();
return authResult.AccessToken;
}
catch (Exception e)
{
await new MessageDialog($"Error adquiring token: {e.Message}").ShowAsync();
return string.Empty;
}
}
}
}
Hi @MughundhanRaveendran-MSFT . Any updates on this?
@juanmalm , Apologies for the delay. I was trying to run your code however I was unable to resolve Remotevideo and Localvideo properties. Could you please provide those as well?
Sure! My fault. Here you have the missing file.
MainPage.xaml
<Page x:Class="poc_teams_integration.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="using:poc_teams_integration" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" mc:Ignorable="d">
<StackPanel>
<TextBox
x:Name="TeamsLinkTextBox"
Margin="10,10,10,10"
PlaceholderText="Please enter the Teams meeting link."
TextWrapping="Wrap" />
<StackPanel
HorizontalAlignment="Center"
Orientation="Horizontal">
<Button
x:Name="JoinButton"
Margin="10,10,10,10"
Click="JoinButton_ClickAsync"
Content="Join Teams Meeting" />
<Button
x:Name="LeaveButton"
Margin="10,10,10,10"
Click="LeaveButton_ClickAsync"
Content="Leave Meeting" />
</StackPanel>
<TextBlock
x:Name="CallStatusTextBlock"
Margin="10,10,10,10"
TextWrapping="Wrap" />
<TextBlock
x:Name="RecordingStatusTextBlock"
Margin="10,10,10,10"
TextWrapping="Wrap" />
<Grid
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<MediaElement
x:Name="LocalVideo"
Grid.Column="0"
HorizontalAlignment="Stretch"
AutoPlay="True"
Stretch="UniformToFill" />
<MediaElement
x:Name="RemoteVideo"
Grid.Column="1"
HorizontalAlignment="Stretch"
AutoPlay="True"
Stretch="UniformToFill" />
</Grid>
</StackPanel>
@juanmalm , I am able to reproduce the issue by using your latest code. The issue only occurs when a user who has joined from Mac client is already present in the Teams call. I will have a discussion internally and get back to you.
Appreciate your patience on this issue.
Thanks for the feedback! We are routing this to the appropriate team for follow-up. cc @acsdevx-msft.
Author: | juanmalm |
---|---|
Assignees: | MughundhanRaveendran-MSFT |
Labels: | `Service Attention`, `Client`, `customer-reported`, `question`, `needs-team-attention`, `Communication`, `CXP Attention` |
Milestone: | - |
Any updates?
@acsdevx-msft Could you please look into this issue and provide an update once you get a chance ?
Azure.Communication.Calling 1.0.0-beta.29 was deprecated and we have released GA versions of the SDK at https://www.nuget.org/packages/Azure.Communication.Calling.WindowsClient#versions-body-tab. We have verified this scenario is working properly.
Closing this issue for now and please file new tickets for issues discovered in your tests with our new SDK. Thanks.
Library name and version
Azure.Communication.Calling 1.0.0-beta.29
Describe the bug
Following the official quick start guide:
https://docs.microsoft.com/en-us/azure/communication-services/quickstarts/voice-video-calling/get-started-teams-interop?pivots=platform-windows
HangUpAsync does not work properly.
Expected behavior
await call_.HangUpAsync(new HangUpOptions());
works properlyActual behavior
await call_.HangUpAsync(new HangUpOptions());
never returns and the user is not disconnected properly from the callReproduction Steps
Environment
UWP Target version: Windows 10, version 2004 (10.0; Build 19041) Min version: Windows 10, version 1809 (10.0; Build 17763)
Microsoft Visual Studio Professional 2022 (64-bit) Version 17.0.4