Answering the Call : accepting incoming calls in Lync Client SDK
One of the things you can do with the Lync Client SDK is be notified of incoming calls, and if you wish, answer them.
Although I don’t think automatically answering would necessarily be a good idea (unless you have a dedicated machine, such as in a meeting room), you may have a Screen Pop which appears on incoming calls, and you want the user to be able to click a button to accept the call.
You’d think it would outrageously obvious to do this (and in a way it is), but it can be a bit confusing due to the terminology.
Calls & Conversations
You want to answer a Call. Specifically, you want to answer an AudioVideo (AV) call.
However (and apologies if you already know this), a call is presented to you in a container, called a Conversation. That’s because a Conversation can contain one or many Calls.
Before that starts to sound confusing, it’s important to know that trading messages in a IM session is also a type of Call : specifically a Instant Message Call.
When you start an IM session with another Lync user, a Conversation is created, with a single Call in it – the Instant Message Call. If you then add audio or video, another Call type is created within the same Conversation.
Add desktop sharing? That’s just adding a new Application Sharing Call to your Conversation.
All of this explains why you won’t find a NewAVCall event in the Lync SDK. However, you will find a new Conversation event: ConversationManager.ConversationAdded Event.
This will fire for every new conversation which gets added. This means when someone phones you, a new conversation will be added, and this will fire. However, it also means that if someone sends you an Instant Message, it will fire for that also.
Assuming you only want to accept AV calls, you need a way of separating AV calls from everything else. Within the Conversation object that gets passed from the event is a Modalities IDictionary, containing all the modalities of the conversation.
At first, I just checked in this IDictionary, and if I saw the AudioVideo modality, assumed it must be an AV call. However, this isn’t always the case. It seems that the AV modality will be included on IM-only conversations, if both the sender and receiver can support AV. Not helpful. 😉
However, there is a way to identify whether the AV modality is the one that’s active – by looking at the State of the modality. For an incoming Call the state will move through a couple of different states, but when you look at it will probably be Notified. One of the things it won’t be though is Disconnected – unless it’s an IM-only call. So, I’m checking for AV Calls using:
private bool ContainsAVCall(Conversation c)
return c.Modalities.ContainsKey(ModalityTypes.AudioVideo) && c.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Disconnected;
Once you’re happy that you want to answer the call, do so! Accepting an incoming AV Call from within a Conversation is as easy as:
Because of the way that events are fired at the beginning of a Conversation, and the way that a Conversation can contain multiple Calls, it a conversation starts on IM and is then upscaled to AV, this event won’t fire and the call won’t be picked up. You’ll have to use an alternative method to detect the change in modality/state and react accordingly. (this may become another blog post)