Note: this post is part of Lync Client development series. You can find the following topics here:
- Microsoft Lync Client Development,
- Sign in and out in Microsoft Lync Client,
- Lync Controls inside Lync Client SDK,
- Starting with Lync Client’s API,
- Handling some common scenarios with Lync Conversation,
- Handling transfers in Lync Client API,
- Handling conference calls in Lync Client,
- Availability (presence) in Lync Client.
Today I’ll try to explain some of the scenarios I had in developing custom Lync application in terms of Lync Conversation.
As you know, a Conversation object is one of the most important objects within Lync Client API model. It represents any kind of communication between two or more participants. Therefore, you have on your disposal Participants list, along with the Properties list of active conversation to inquiry. You can also track changes of related properties by subcribing to StateChanged, PropertyChanged, ActionAvailabilityChanged, and ParticipantAdded (among the other events) to be able to see how conversation is going.
It is important to differentiate a ‘call’ or IM between conversation, not just because it is a broader term depicting any kind of communication, but also because it represents something conceptually different. For instance, you can start to communicate with other person by using IM chat, and then just click on Call button to start an audio call. This call can later be dropped, or transferred to another person, or even joined in a conference. All these events represents one conversation. Well, to be honest – there might be some other conversations spanning in this case, but for now, it is one logical conversation.
With this in mind, it is logical that Conversation object doesn’t have events, such as Calling, or OnHold. Rather, you have to deal with the Modalities. Modalities represents all kinds of conversation types that might occur during one logical communication. When conversation starts, you should be able to query for different modalities and their states to figure out if there is an audio/video call or IM conversation taking place:
// register for the events of this conversation
m_conversation.ParticipantAdded += new EventHandler(m_conversation_ParticipantAdded);
m_conversation.StateChanged += new EventHandler(m_conversation_StateChanged);
m_conversation.ActionAvailabilityChanged += new EventHandler(m_conversation_ActionAvailabilityChanged);
m_conversation.PropertyChanged += new EventHandler(m_conversation_PropertyChanged);
// is this an audio/video call?
if (startingConversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Disconnected)
// New audio/video call registered
// is this an instant message conversation?
if (startingConversation.Modalities[ModalityTypes.InstantMessage].State != ModalityState.Disconnected)
// New instant message registered
m_audioVideo = m_conversation.Modalities[ModalityTypes.AudioVideo] as AVModality;
m_audioVideo.ModalityStateChanged += new EventHandler(m_audioVideo_ModalityStateChanged);
m_audioVideo.ActionAvailabilityChanged += new EventHandler(m_audioVideo_ActionAvailabilityChanged);
m_audioVideo.AVModalityPropertyChanged += new EventHandler(m_audioVideo_AVModalityPropertyChanged);
m_instantMessage = m_conversation.Modalities[ModalityTypes.InstantMessage] as InstantMessageModality;
m_instantMessage.InstantMessageReceived += new EventHandler(m_instantMessage_InstantMessageReceived);
m_instantMessage.IsTypingChanged += new EventHandler(m_instantMessage_IsTypingChanged);
m_instantMessage.ModalityStateChanged += new EventHandler(m_instantMessage_ModalityStateChanged);
So, the best is to make sure in advance which modalities are on , and store their references for later use. You should also subscribe to their respective events to be able to track their state and motion (I mentioned the most useful ones).
And now with something very important. There is a certain workflow on how Lync handles conversations in terms their state change.
For example, when a conversation is started, it has no identifier and it is in state Active. As all operations are asynchronous in Lync, ConversationId comes later in stack. Therefore, if you need it, you should track changes of conversation properties, and store identifier if it gets set. To be more complicated, ConversationId has certain format – I figured out that it has a ‘fixed part’ or 30 character length and a ‘trailing part’. This trailing part is initially set to “==” (two equation signs), and later can be changed. So, it means, you actually don’t have an identifier which should identify the conversation uniquely across the server. You just have to find out another way to do it (e.g. I use GUID).
Another thing is changing state. When you are dealing with a simple conversation (i.e. an incoming/outgoing call which starts and then eventually ends), you don’t have to worry about. But, more realistic scenarios would be to hold or park the call, transfer it, or retry it if not successful. For that, you should be very careful to keep track of old and new conversation state – usually by StateChanged event. For example, if you are transferred to another call, your conversation will be inactivated, identifier will be changed, and activated again. Of course, you should check active participants, modality states, and so on. Additional issue is to track whether the conversation has been terminated during modalities still active (handlers still fire!) and be sure you covered all possible cases.
What is also evidently tricky (especially if you’re dealing mostly with audio calls), is determining whether a call (i.e. conversation’s modality AV) is incoming or outgoing, i.e. call direction. Easiest way to know it is to check whether an audio modality is started with Connecting or Notifying state. In case of Connecting, it is an outgoing call, and in case of Notified, it is an incoming call. But beware, a conversation can also be transferred to you, so you are in Connecting state first, no matter it is an incoming call to you. There are some other cases to it, but this is enough to give you an impression how Lync does it.
I’ll dive into the transferring of conversation next time. So, keep reading!