Lync 2013 SDK Conversation Class

Hello There,

It’s been a while, so today I’m going to share how to Establish new call, Blind and Consulted Audio Transfer using Lync 2013 SDK. Below is a class to handle such scenarios. I hope that somebody will find it useful.

using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Conversation;
using Microsoft.Lync.Model.Conversation.AudioVideo;
using Microsoft.Lync.Model.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace LyncCallTransfer
{
    public class conversationTracker
    {

        private LyncClient lyncClient = LyncClient.GetClient();
        private List<Contact> contacts;
        private AVModality _AVModality;

        public static List<Conversation> conversations { set; get; }
        public Conversation conversation { get; set; }

        public conversationTracker(List<Contact> contacts) 
        {
            conversations = new List<Conversation>();

            foreach(Conversation establishedConversation in lyncClient.ConversationManager.Conversations)
            {
                if (establishedConversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Disconnected)
                {
                    conversations.Add(establishedConversation);
                }
            }
            
            this.contacts = contacts;
        }

        public conversationTracker()
        {
            conversations = new List<Conversation>();

            foreach (Conversation establishedConversation in lyncClient.ConversationManager.Conversations)
            {
                if (establishedConversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Disconnected)
                {
                    conversations.Add(establishedConversation);
                }
            }

            this.contacts = null;
        }

        public void StartConversation() 
        {
            lyncClient.ConversationManager.ConversationAdded += ConversationManager_ConversationAdded;
            conversation = lyncClient.ConversationManager.AddConversation();
           
        }

        public void StartBlindTransfer(Contact tobeTransferedTo,Conversation thisConversation)
        {
             _AVModality = (AVModality)thisConversation.Modalities[ModalityTypes.AudioVideo];

             
            //transfers call specific contact
            try
            {
                _AVModality.BeginTransfer(tobeTransferedTo, TransferOptions.None, ModalityCallback, null);
            }
            catch (LyncClientException lyncClientException)
            {

            }
            catch (SystemException systemException)
            {

            }
        }

        public void StartConsultiveTransfer(Conversation srcConversation,Conversation dstConversation)
        {
            _AVModality = (AVModality)srcConversation.Modalities[ModalityTypes.AudioVideo];

            AsyncCallback transferCallback = ar =>
            {
                try
                {
                    ModalityState state;
                    IList<string> properties;
                    _AVModality.EndConsultativeTransfer(out state, out properties, ar);
                }
                catch (Exception ex)
                {

                    Console.Out.WriteLine(ex);
                }
            };


            try
            {
                _AVModality.BeginConsultativeTransfer(dstConversation, TransferOptions.None, transferCallback, null);
            }
            catch (LyncClientException lyncClientException)
            {
                Console.WriteLine(lyncClientException);
            }
            catch (SystemException systemException)
            {

            }
        }

        void ConversationManager_ConversationAdded(object sender, ConversationManagerEventArgs e)
        {
            if (e.Conversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Notified) 
            {
                 if (e.Conversation.CanInvoke(ConversationAction.AddParticipant))
                 {
                     e.Conversation.ParticipantAdded += Conversation_ParticipantAdded;
                    
                     foreach (Contact contact in contacts)
                     {
                         e.Conversation.AddParticipant(contact);
                     }
                 }
            }

        }

        void Conversation_ParticipantAdded(object sender, ParticipantCollectionChangedEventArgs e)
        {
            if (e.Participant.IsSelf != true && contacts.Contains(e.Participant.Contact ) ) 
            {
               if (((Conversation)sender).Modalities[ModalityTypes.AudioVideo].CanInvoke(ModalityAction.Connect))
                {
                    object[] asyncState = { ((Conversation)sender).Modalities[ModalityTypes.AudioVideo], "CONNECT" };
                    try
                    {
                        ((Conversation)sender).Modalities[ModalityTypes.AudioVideo].ModalityStateChanged += _AVModality_ModalityStateChanged;
                        ((Conversation)sender).Modalities[ModalityTypes.AudioVideo].BeginConnect(ModalityCallback, asyncState);

                    }
                    catch (Exception ce)
                    {
                        throw new Exception("Lync Platform Exception on BeginConnect: " + ce.Message);
                    }
                    finally {  }
                }
            }
        }

      


        void _AVModality_ModalityStateChanged(object sender, ModalityStateChangedEventArgs e)
        {
            switch (e.NewState)
            {
                case ModalityState.Connected:

                    if(((Modality)sender).Conversation.Modalities[ModalityTypes.AudioVideo].State != ModalityState.Disconnected)
                    {
                        conversations.Add(((Modality)sender).Conversation);
                        lyncClient.ConversationManager.ConversationAdded -= ConversationManager_ConversationAdded;
                    }
                    break;
                
                case ModalityState.Disconnected:

                   if(conversations.Contains(((Modality)sender).Conversation))
                   {
                        conversations.Remove(((Modality)sender).Conversation);
                   }
                   break;
            }
        }

        private void ModalityCallback(IAsyncResult ar)
        {
            Object[] asyncState = (Object[])ar.AsyncState;
            ModalityState state;
            IList<string> properties;

            try
            {
                if (ar.IsCompleted == true)
                {
                    if (asyncState[1].ToString() == "RETRIEVE")
                    {
                        ((AVModality)asyncState[0]).EndRetrieve(ar);
                    }
                    if (asyncState[1].ToString() == "HOLD")
                    {
                        ((AVModality)asyncState[0]).EndHold(ar);
                    }
                    if (asyncState[1].ToString() == "CONNECT")
                    {
                        ((AVModality)asyncState[0]).EndConnect(ar);
                       
                    }
                    if (asyncState[1].ToString() == "FORWARD")
                    {
                        ((AVModality)asyncState[0]).EndForward(ar);
                    }
                    if (asyncState[1].ToString() == "TRANSFER")
                    {
                        ((AVModality)asyncState[0]).EndTransfer(out state, out properties, ar);

                    }
                    
                }
            }
            catch (Exception)
            { 

            }
        }
    }
}
Posted in Programming, Technology and tagged , , , , , , , , , . Bookmark the permalink. RSS feed for this post. Leave a trackback.

2 Responses to Lync 2013 SDK Conversation Class

  1. Certainly, very useful.. Some examples using that class would be nice, but it looks easy enough to understand.

    Thanks 🙂

    • Saddam Abu Ghaida says:

      I will add some code using that class to make it look more understandable, thanks for the comment

Leave a Reply

Your email address will not be published. Required fields are marked *

Time limit is exhausted. Please reload CAPTCHA.

Swedish Greys - a WordPress theme from Nordic Themepark.