示例#1
0
        void IMCall_EstablishCompleted(IAsyncResult result)
        {
            try
            {
                InstantMessagingCall imCall = result.AsyncState as InstantMessagingCall;
                imCall.EndEstablish(result);

                Message m = new Message("InstantMessagingCall Established. Call state: " + _instantMessagingCall.State.ToString() + ". CallId: " + _instantMessagingCall.CallId + ".",
                                        _instantMessagingCall.RemoteEndpoint.Participant.DisplayName, _instantMessagingCall.RemoteEndpoint.Participant.UserAtHost,
                                        _instantMessagingCall.RemoteEndpoint.Participant.Uri,
                                        MessageType.InstantMessage, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, imCall.RemoteEndpoint);
            }
            catch (RealTimeException ex)
            {
                NonBlockingConsole.WriteLine("Error: imCall.EndEstablish failed. Exception: {0}", ex.ToString());
                // TODO: error message
            }
            finally
            {
                _state = TranscriptRecorderState.Active;
                this._waitForIMCallEstablished.Set();
            }
        }
示例#2
0
        private void InstantMessagingCallAcceptedCallBack(IAsyncResult ar)
        {
            InstantMessagingCall instantMessagingCall = ar.AsyncState as InstantMessagingCall;

            try
            {
                // Determine whether the call was accepted successfully.
                instantMessagingCall.EndAccept(ar);

                Message m = new Message("InstantMessagingCall Accepted. Call state: " + instantMessagingCall.State.ToString() + ". CallId: " + instantMessagingCall.CallId + ".",
                                        instantMessagingCall.RemoteEndpoint.Participant.DisplayName, instantMessagingCall.RemoteEndpoint.Participant.UserAtHost,
                                        instantMessagingCall.RemoteEndpoint.Participant.Uri,
                                        MessageType.InstantMessage, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, instantMessagingCall.RemoteEndpoint);
            }
            catch (RealTimeException exception)
            {
                // RealTimeException may be thrown on media or link-layer failures.
                // A production application should catch additional exceptions, such as OperationTimeoutException,
                // OperationTimeoutException, and CallOperationTimeoutException.

                NonBlockingConsole.WriteLine(exception.ToString());
            }
            finally
            {
                // Synchronize with main thread.
                _waitForIMCallAccepted.Set();
                _state = TranscriptRecorderState.Active;
            }
        }
示例#3
0
        private void AudioVideoCallAccepted(IAsyncResult ar)
        {
            Call call = ar.AsyncState as Call;

            try
            {
                // Determine whether the Call was accepted successfully.
                call.EndAccept(ar);

                NonBlockingConsole.WriteLine("Inbound AudioVideo call with Local Participant: " + call.Conversation.LocalParticipant.Uri + " and Remote Participant: " + call.RemoteEndpoint.Participant.Uri + " has been accepted.");

                Message m = new Message("AudioVideoCall Accepted. Call state: " + _audioVideoCall.State.ToString(),
                                        call.RemoteEndpoint.Participant.DisplayName, call.RemoteEndpoint.Participant.UserAtHost, call.RemoteEndpoint.Participant.Uri,
                                        MessageType.Audio, _transcriptRecorder.Conversation.Id, MessageDirection.Outgoing);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, call.RemoteEndpoint);
            }
            catch (RealTimeException exception)
            {
                // RealTimeException may be thrown on media or link-layer
                // failures.
                // TODO: Add actual error handling code here.
                NonBlockingConsole.WriteLine("Error accepting AVCall: " + exception.ToString());
            }
            finally
            {
                //Again, just to sync the completion of the code.
                _state = TranscriptRecorderState.Active;
                _waitForAudioVideoCallAccepted.Set();
            }
        }
示例#4
0
        public void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            TranscriptRecorderSessionShutdownEventArgs shutdownArgs = null;

            lock (_transcriptRecorders)
            {
                foreach (MediaTranscriptRecorder m in _transcriptRecorders)
                {
                    m.Shutdown();
                }
                _transcriptRecorders.Clear();
            }

            try
            {
                Message shutdownMessage = new Message("TranscriptRecorderSession is shutting down. SessionId: ", _sessionId.ToString());
                this.OnMessageReceived(shutdownMessage);

                shutdownArgs = new TranscriptRecorderSessionShutdownEventArgs(this);

                if (_conversation != null &&
                    ((_conversation.State != ConversationState.Terminating) || (_conversation.State != ConversationState.Terminated)))
                {
                    Message m = new Message("Conversation shutting down.", _conversation.LocalParticipant.DisplayName,
                                            _conversation.LocalParticipant.UserAtHost, _conversation.LocalParticipant.Uri, DateTime.Now,
                                            _conversation.Id, (this.Conference == null) ? "null" : this.Conference.ConferenceUri,
                                            MessageType.ConversationInfo, MessageDirection.Outgoing);
                    this.OnMessageReceived(m);

                    _conversation.BeginTerminate(EndTerminateConversation, _conversation);
                    //_waitForConversationTerminated.WaitOne();
                    _conversation = null;
                }
                else
                {
                    _waitForConversationTerminated.Set();
                }

                ShutdownConversationContext();
            }
            catch (Exception e)
            {
                NonBlockingConsole.WriteLine("TranscriptRecorderSession.Shutdown(). Exception occured during conversation shutdown: {0}",
                                             e.ToString());
            }
            finally
            {
                // Raise Shutdown event to MeetingTranscriptSessionManager
                this.RaiseTranscriptRecorderSessionShutdown(shutdownArgs);
            }
        }
示例#5
0
        //call received event handler
        public void AudioVideoCall_Received(CallReceivedEventArgs <AudioVideoCall> e)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: AVTranscriptRecorder is shutdown.");
                // TODO: Error message
                return;
            }

            if (_audioVideoCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: AVCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            _waitForAudioVideoCallTerminated.Reset();

            //Type checking was done by the platform; no risk of this being any
            // type other than the type expected.
            _audioVideoCall = e.Call;

            // Call: StateChanged: Only hooked up for logging, to show the call
            // state transitions.
            _audioVideoCall.StateChanged += new EventHandler <CallStateChangedEventArgs>(AudioVideoCall_StateChanged);

            // Subscribe for the flow configuration requested event; the flow will be used to send the media.
            // Ultimately, as a part of the callback, the media will be sent/recieved.
            _audioVideoCall.AudioVideoFlowConfigurationRequested += new EventHandler <AudioVideoFlowConfigurationRequestedEventArgs>(AudioVideoCall_FlowConfigurationRequested);

            _audioVideoCall.ConversationChanged += new EventHandler <ConversationChangedEventArgs>(AudioVideoCall_ConversationChanged);

            // Remote Participant URI represents the far end (caller) in this
            // conversation. Toast is the message set by the caller as the 'greet'
            // message for this call. In Microsoft Lync, the toast will
            // show up in the lower-right of the screen.
            // TODO: change this to preserve confidentiality in the video demo
            //NonBlockingConsole.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri + " Toast is: " + e.ToastMessage.Message);
            NonBlockingConsole.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri);
            //NonBlockingConsole.WriteLine("Call Received!");

            Message m = new Message("AudioVideoCall Received. Inbound call state: " + _audioVideoCall.State.ToString(),
                                    e.RemoteParticipant.DisplayName, e.RemoteParticipant.UserAtHost, e.RemoteParticipant.Uri,
                                    MessageType.Audio, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);

            _transcriptRecorder.OnMessageReceived(m);

            // Accept the call. Before transferring the call, it must be in the Established state.
            // Note that the docs are wrong in the state machine for the AVCall. BeginEstablish
            // should be called on outgoing calls, not incoming calls.
            _audioVideoCall.BeginAccept(AudioVideoCallAccepted, _audioVideoCall);

            // Wait for a few seconds to give time for the call to get to the Established state.
            //_waitForAudioVideoCallAccepted.WaitOne(2000);
            NonBlockingConsole.WriteLine("Inbound call state is {0}\n", _audioVideoCall.State.ToString());
        }
示例#6
0
        public void InstantMessagingCall_Received(CallReceivedEventArgs <InstantMessagingCall> e)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: IMTranscriptRecorder is shutdown.");
                // TODO: Info message
                return;
            }

            if (_instantMessagingCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: IMCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            _waitForIMCallTerminated.Reset();

            // Type checking was done by the platform; no risk of this being any
            // type other than the type expected.
            _instantMessagingCall = e.Call;

            // Call: StateChanged: Only hooked up for logging, to show the call
            // state transitions.
            _instantMessagingCall.StateChanged +=
                new EventHandler <CallStateChangedEventArgs>(InstantMessagingCall_StateChanged);

            _instantMessagingCall.InstantMessagingFlowConfigurationRequested +=
                new EventHandler <InstantMessagingFlowConfigurationRequestedEventArgs>(InstantMessagingCall_FlowConfigurationRequested);

            _instantMessagingCall.ConversationChanged += new EventHandler <ConversationChangedEventArgs>(InstantMessagingCall_ConversationChanged);

            // Remote Participant URI represents the far end (caller) in this
            // conversation. Toast is the message set by the caller as the
            // 'greet' message for this call. In Microsoft Lync, the
            // toast will show up in the lower-right of the screen.
            // TODO: Change to protect privacy
            // NonBlockingConsole.WriteLine("IMCall Received! From: " + e.RemoteParticipant.Uri + " Toast is: " + e.ToastMessage.Message);
            NonBlockingConsole.WriteLine("IMCall Received! From: " + e.RemoteParticipant.Uri);
            // Console.Writelin("IMCall Received!");

            Message m = new Message("InstantMessagingCall Received. Inbound call state: " + _instantMessagingCall.State.ToString(),
                                    e.RemoteParticipant.DisplayName, e.RemoteParticipant.UserAtHost, e.RemoteParticipant.Uri,
                                    MessageType.InstantMessage, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);

            _transcriptRecorder.OnMessageReceived(m);

            // Now, accept the call. EndAcceptCall will be raised on the
            // same thread.
            _instantMessagingCall.BeginAccept(InstantMessagingCallAcceptedCallBack, _instantMessagingCall);
        }
示例#7
0
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            TerminateCall();

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }
        public ConferenceTranscriptRecorder(TranscriptRecorderSession transcriptRecorder, Conversation conversation)
        {
            _transcriptRecorder = transcriptRecorder;
            _conversation       = conversation;

            // TODO: TranscriptRecorderSession should check if new conversation is joined to a conference and do full
            // Begin/EndJoin with an End async method in ConferenceTranscriptRecorder (as is done for Invite or Escalate)
            if (_conversation.ConferenceSession != null)
            {
                _conference = _conversation.ConferenceSession;
                _state      = TranscriptRecorderState.Active;
                _waitForInvitedConferenceJoined.Set();
                RegisterConferenceEvents();
            }
        }
        public ConferenceTranscriptRecorder(TranscriptRecorderSession transcriptRecorder, Conversation conversation)
        {
            _transcriptRecorder = transcriptRecorder;
            _conversation = conversation;

            // TODO: TranscriptRecorderSession should check if new conversation is joined to a conference and do full
            // Begin/EndJoin with an End async method in ConferenceTranscriptRecorder (as is done for Invite or Escalate)
            if (_conversation.ConferenceSession != null)
            {
                _conference = _conversation.ConferenceSession;
                _state = TranscriptRecorderState.Active;
                _waitForInvitedConferenceJoined.Set();
                RegisterConferenceEvents();
            }
        }
示例#10
0
        public void EstablishAudioVideoCall(Conversation conversation)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: AVTranscriptRecorder has already been shutdown.");
                // TODO: Error message
                return;
            }

            if (_audioVideoCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: AVCall already exists for this Conversation. Shutting down previous call...");
                // TODO: info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            _waitForAudioVideoCallTerminated.Reset();

            try
            {
                AudioVideoCall avCall = new AudioVideoCall(conversation);

                // Register for Call events
                _audioVideoCall = avCall;

                // Call: StateChanged: Only hooked up for logging, to show the call
                // state transitions.
                _audioVideoCall.StateChanged += new EventHandler <CallStateChangedEventArgs>(AudioVideoCall_StateChanged);

                // Subscribe for the flow configuration requested event; the flow will be used to send the media.
                // Ultimately, as a part of the callback, the media will be sent/recieved.
                _audioVideoCall.AudioVideoFlowConfigurationRequested += new EventHandler <AudioVideoFlowConfigurationRequestedEventArgs>(AudioVideoCall_FlowConfigurationRequested);

                _audioVideoCall.ConversationChanged += new EventHandler <ConversationChangedEventArgs>(AudioVideoCall_ConversationChanged);

                // Establish AudioVideoCall
                avCall.BeginEstablish(AudioVideoCall_EstablishCompleted, avCall);
            }
            catch (InvalidOperationException ex)
            {
                NonBlockingConsole.WriteLine("Error: avCall.BeginEstablish failed. Exception: {0}", ex.ToString());
                // TODO: Error message
            }
        }
示例#11
0
        public TranscriptRecorderSession(ConferenceInvitationReceivedEventArgs e, CancellationTokenSource cts = null)
        {
            _sessionId           = Constants.NextGuid();
            _transcriptRecorders = new List <MediaTranscriptRecorder>();
            _conversationToCallTranscriptMapping = new Dictionary <ConversationTranscriptRecorder, List <MediaTranscriptRecorder> >();
            _messages = new List <Message>();
            _state    = TranscriptRecorderState.Active;
            ConversationParticipant caller = e.RemoteParticipant;

            // Log Conference Invitation Recv
            Message m = new Message("Conference Started Invitation Recieved for ConferenceUri: ", caller.DisplayName, caller.UserAtHost, caller.Uri, DateTime.Now,
                                    "null", e.Invitation.ConferenceUri,
                                    MessageType.ConferenceInfo, MessageDirection.Outgoing);

            this.OnMessageReceived(m);

            AddIncomingInvitedConference(e);
        }
示例#12
0
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            this.TerminateCall();

            if (_speechRecognizer != null)
            {
                _speechRecognizer.Shutdown();
                _speechRecognizer = null;
            }

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }

            _state = TranscriptRecorderState.Terminated;

            // TODO: Shutdown message

            if (_conference != null)
            {
                UnregisterConferenceEvents();
            }

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }
示例#14
0
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            if (this.IsSubConversation)
            {
                _transcriptRecorder.OnSubConversationRemoved(this.Conversation, this);
            }
            else
            {
                _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
                TerminateConversation();
            }
            _transcriptRecorder = null;
        }
示例#15
0
        public void EstablishInstantMessagingCall(Conversation conversation)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: IMTranscriptRecorder is shutdown.");
                // TODO: error message
                return;
            }

            if (_instantMessagingCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: IMCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            this._waitForIMCallTerminated.Reset();

            try
            {
                InstantMessagingCall imCall = new InstantMessagingCall(conversation);

                // Register for Call events
                _instantMessagingCall = imCall;

                // Call: StateChanged: Only hooked up for logging, to show the call
                // state transitions.
                _instantMessagingCall.StateChanged +=
                    new EventHandler <CallStateChangedEventArgs>(InstantMessagingCall_StateChanged);

                _instantMessagingCall.InstantMessagingFlowConfigurationRequested +=
                    new EventHandler <InstantMessagingFlowConfigurationRequestedEventArgs>(InstantMessagingCall_FlowConfigurationRequested);

                // Establish AudioVideoCall
                imCall.BeginEstablish(IMCall_EstablishCompleted, imCall);
            }
            catch (InvalidOperationException ex)
            {
                NonBlockingConsole.WriteLine("Error: imCall.BeginEstablish failed. Exception: {0}", ex.ToString());
                // TODO: Error Message
            }
        }
示例#16
0
        public TranscriptRecorderSession(CallReceivedEventArgs <InstantMessagingCall> e, CancellationTokenSource cts = null)
        {
            _sessionId           = Constants.NextGuid();
            _transcriptRecorders = new List <MediaTranscriptRecorder>();
            _conversationToCallTranscriptMapping = new Dictionary <ConversationTranscriptRecorder, List <MediaTranscriptRecorder> >();
            _messages     = new List <Message>();
            _state        = TranscriptRecorderState.Active;
            _conversation = e.Call.Conversation;
            _conversationTranscriptRecorder = new ConversationTranscriptRecorder(this, _conversation);
            _transcriptRecorders.Add(_conversationTranscriptRecorder);
            _conversationToCallTranscriptMapping.Add(_conversationTranscriptRecorder, new List <MediaTranscriptRecorder>());
            ConversationParticipant caller = e.RemoteParticipant;

            // Log IM conversation started
            Message m = new Message("InstantMessaging Conversation/Conference Started.", caller.DisplayName, caller.UserAtHost, caller.Uri, DateTime.Now,
                                    _conversation.Id, (_conversation.ConferenceSession == null) ? "null" : _conversation.ConferenceSession.ConferenceUri,
                                    MessageType.ConferenceInfo, MessageDirection.Outgoing);

            this.OnMessageReceived(m);

            AddIMIncomingCall(e);
        }
        /// <summary>
        /// Ends the escalation to conference.
        /// </summary>
        /// <param name="argument">The argument.</param>
        /// <remarks></remarks>
        private void EndEscalateConversation(IAsyncResult argument)
        {
            Conversation conversation = argument.AsyncState as Conversation;
            Exception    exception    = null;

            try
            {
                conversation.EndEscalateToConference(argument);
                NonBlockingConsole.WriteLine("Conversation was escalated into conference");
            }
            catch (OperationFailureException operationFailureException)
            {
                // OperationFailureException: Indicates failure to connect the call to the remote party.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(operationFailureException.ToString());
                exception = operationFailureException;
            }
            catch (RealTimeException realTimeException)
            {
                // RealTimeException may be thrown on media or link-layer failures.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(realTimeException.ToString());
                exception = realTimeException;
            }
            finally
            {
                _state = TranscriptRecorderState.Active;
                _waitForConferenceEscalationCompleted.Set();

                //Again, just to sync the completion of the code.
                if (exception != null)
                {
                    string originator = string.Format("Error when escalating to conference.");
                    NonBlockingConsole.WriteLine(originator);
                }
            }
        }
        /// <summary>
        /// Occurs when bot joined the conference.
        /// </summary>
        /// <param name="result">The argument.</param>
        /// <remarks></remarks>
        public void EndJoinInvitedConference(IAsyncResult result)
        {
            ConferenceInvitation invite = result.AsyncState as ConferenceInvitation;
            Exception exception = null;
            List<String> activeMediaTypes = new List<string>();
            try
            {
                NonBlockingConsole.WriteLine("Joined the invited conference");
                activeMediaTypes = invite.AvailableMediaTypes.ToList();

                _conversation.ConferenceSession.EndJoin(result);
                _conference = _conversation.ConferenceSession;

                NonBlockingConsole.WriteLine(string.Format(
                                              "Conference Url: conf:{0}%3Fconversation-id={1}",
                                              _conversation.ConferenceSession.ConferenceUri,
                                              _conversation.ConferenceSession.Conversation.Id));

                RegisterConferenceEvents();

                // Raise event on TranscriptRecorderSession
                _transcriptRecorder.RaiseTranscriptRecorderSessionChanged(_conference);

                // Establish Calls for Conference's supported modalities
                if (activeMediaTypes.Contains(MediaType.Audio))
                {
                    _transcriptRecorder.OnActiveMediaTypeCallToEstablish(_conversation, TranscriptRecorderType.AudioVideo);
                }
                if (activeMediaTypes.Contains(MediaType.Message))
                {
                    _transcriptRecorder.OnActiveMediaTypeCallToEstablish(_conversation, TranscriptRecorderType.InstantMessage);
                }

                _waitForInvitedConferenceActiveMediaTypeCallEstablished.Set();
            }
            catch (ConferenceFailureException conferenceFailureException)
            {
                // ConferenceFailureException may be thrown on failures due to MCUs being absent or unsupported, or due to malformed parameters.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(conferenceFailureException.ToString());
                exception = conferenceFailureException;
            }
            catch (RealTimeException realTimeException)
            {
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(realTimeException.ToString());
                exception = realTimeException;
            }
            finally
            {
                // Again, for sync. reasons.
                _state = TranscriptRecorderState.Active;
                _waitForInvitedConferenceJoined.Set();

                if (exception != null)
                {
                    string originator = string.Format("Error when joining the invited conference: {0}", exception.ToString());
                    NonBlockingConsole.WriteLine(originator);
                }
            }
        }
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            if (this.IsSubConversation)
            {
                _transcriptRecorder.OnSubConversationRemoved(this.Conversation, this);
            }
            else
            {
                _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
                TerminateConversation();
            }
            _transcriptRecorder = null;
        }
        private void AudioVideoCallAccepted(IAsyncResult ar)
        {
            Call call = ar.AsyncState as Call;
            try
            {
                // Determine whether the Call was accepted successfully.
                call.EndAccept(ar);

                NonBlockingConsole.WriteLine("Inbound AudioVideo call with Local Participant: " + call.Conversation.LocalParticipant.Uri + " and Remote Participant: " + call.RemoteEndpoint.Participant.Uri + " has been accepted.");

                Message m = new Message("AudioVideoCall Accepted. Call state: " + _audioVideoCall.State.ToString(),
                    call.RemoteEndpoint.Participant.DisplayName, call.RemoteEndpoint.Participant.UserAtHost, call.RemoteEndpoint.Participant.Uri,
                    MessageType.Audio, _transcriptRecorder.Conversation.Id, MessageDirection.Outgoing);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, call.RemoteEndpoint);
            }
            catch (RealTimeException exception)
            {
                // RealTimeException may be thrown on media or link-layer 
                // failures. 
                // TODO: Add actual error handling code here.
                NonBlockingConsole.WriteLine("Error accepting AVCall: " + exception.ToString());
            }
            finally
            {
                //Again, just to sync the completion of the code.
                _state = TranscriptRecorderState.Active;
                _waitForAudioVideoCallAccepted.Set();
            }
        }
        void AudioVideoCall_EstablishCompleted(IAsyncResult result)
        {
            try
            {
                AudioVideoCall avCall = result.AsyncState as AudioVideoCall;
                avCall.EndEstablish(result);

               Message m = new Message("AudioVideoCall Established. Call state: " + _audioVideoCall.State.ToString() + ". CallId: " + _audioVideoCall.CallId + ".",
                    _audioVideoCall.RemoteEndpoint.Participant.DisplayName, _audioVideoCall.RemoteEndpoint.Participant.UserAtHost,
                    _audioVideoCall.RemoteEndpoint.Participant.Uri,
                    MessageType.Audio, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, avCall.RemoteEndpoint);
            }
            catch (RealTimeException ex)
            {
                NonBlockingConsole.WriteLine("Error: avCall.EndEstablish failed. Exception: {0}", ex.ToString());
                // TODO: Error message
            }
            finally
            {
                _state = TranscriptRecorderState.Active;
                _waitForAudioVideoCallEstablished.Set();
            }
        }
        public void EstablishAudioVideoCall(Conversation conversation)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: AVTranscriptRecorder has already been shutdown.");
                // TODO: Error message
                return;
            }

            if (_audioVideoCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: AVCall already exists for this Conversation. Shutting down previous call...");
                // TODO: info message
                TerminateCall();
            }
            
            _state = TranscriptRecorderState.Initialized;
            _waitForAudioVideoCallTerminated.Reset();

            try
            {
                AudioVideoCall avCall = new AudioVideoCall(conversation);

                // Register for Call events
                _audioVideoCall = avCall;

                // Call: StateChanged: Only hooked up for logging, to show the call 
                // state transitions.
                _audioVideoCall.StateChanged += new EventHandler<CallStateChangedEventArgs>(AudioVideoCall_StateChanged);

                // Subscribe for the flow configuration requested event; the flow will be used to send the media.
                // Ultimately, as a part of the callback, the media will be sent/recieved.
                _audioVideoCall.AudioVideoFlowConfigurationRequested += new EventHandler<AudioVideoFlowConfigurationRequestedEventArgs>(AudioVideoCall_FlowConfigurationRequested);

                _audioVideoCall.ConversationChanged += new EventHandler<ConversationChangedEventArgs>(AudioVideoCall_ConversationChanged);

                // Establish AudioVideoCall
                avCall.BeginEstablish(AudioVideoCall_EstablishCompleted, avCall);
            }
            catch (InvalidOperationException ex)
            {
                NonBlockingConsole.WriteLine("Error: avCall.BeginEstablish failed. Exception: {0}", ex.ToString());
                // TODO: Error message
            }
        }
        //call received event handler
        public void AudioVideoCall_Received(CallReceivedEventArgs<AudioVideoCall> e)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: AVTranscriptRecorder is shutdown.");
                // TODO: Error message
                return;
            }

            if (_audioVideoCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: AVCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            _waitForAudioVideoCallTerminated.Reset();

            //Type checking was done by the platform; no risk of this being any 
            // type other than the type expected.
            _audioVideoCall = e.Call;

            // Call: StateChanged: Only hooked up for logging, to show the call 
            // state transitions.
            _audioVideoCall.StateChanged += new EventHandler<CallStateChangedEventArgs>(AudioVideoCall_StateChanged);

            // Subscribe for the flow configuration requested event; the flow will be used to send the media.
            // Ultimately, as a part of the callback, the media will be sent/recieved.
            _audioVideoCall.AudioVideoFlowConfigurationRequested += new EventHandler<AudioVideoFlowConfigurationRequestedEventArgs>(AudioVideoCall_FlowConfigurationRequested);

            _audioVideoCall.ConversationChanged += new EventHandler<ConversationChangedEventArgs>(AudioVideoCall_ConversationChanged);

            // Remote Participant URI represents the far end (caller) in this 
            // conversation. Toast is the message set by the caller as the 'greet'
            // message for this call. In Microsoft Lync, the toast will 
            // show up in the lower-right of the screen.
            // TODO: change this to preserve confidentiality in the video demo
            //NonBlockingConsole.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri + " Toast is: " + e.ToastMessage.Message);
            NonBlockingConsole.WriteLine("Call Received! From: " + e.RemoteParticipant.Uri);
            //NonBlockingConsole.WriteLine("Call Received!");

            Message m = new Message("AudioVideoCall Received. Inbound call state: " + _audioVideoCall.State.ToString(),
                e.RemoteParticipant.DisplayName, e.RemoteParticipant.UserAtHost, e.RemoteParticipant.Uri,
                MessageType.Audio, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
            _transcriptRecorder.OnMessageReceived(m);

            // Accept the call. Before transferring the call, it must be in the Established state.
            // Note that the docs are wrong in the state machine for the AVCall. BeginEstablish 
            // should be called on outgoing calls, not incoming calls.
            _audioVideoCall.BeginAccept(AudioVideoCallAccepted, _audioVideoCall);

            // Wait for a few seconds to give time for the call to get to the Established state.
            //_waitForAudioVideoCallAccepted.WaitOne(2000);
            NonBlockingConsole.WriteLine("Inbound call state is {0}\n", _audioVideoCall.State.ToString());
        }
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            this.TerminateCall();

            if (_speechRecognizer != null)
            {
                _speechRecognizer.Shutdown();
                _speechRecognizer = null;
            }

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }
        /// <summary>
        /// Occurs when bot joined the conference.
        /// </summary>
        /// <param name="result">The argument.</param>
        /// <remarks></remarks>
        public void EndJoinInvitedConference(IAsyncResult result)
        {
            ConferenceInvitation invite           = result.AsyncState as ConferenceInvitation;
            Exception            exception        = null;
            List <String>        activeMediaTypes = new List <string>();

            try
            {
                NonBlockingConsole.WriteLine("Joined the invited conference");
                activeMediaTypes = invite.AvailableMediaTypes.ToList();

                _conversation.ConferenceSession.EndJoin(result);
                _conference = _conversation.ConferenceSession;

                NonBlockingConsole.WriteLine(string.Format(
                                                 "Conference Url: conf:{0}%3Fconversation-id={1}",
                                                 _conversation.ConferenceSession.ConferenceUri,
                                                 _conversation.ConferenceSession.Conversation.Id));

                RegisterConferenceEvents();

                // Raise event on TranscriptRecorderSession
                _transcriptRecorder.RaiseTranscriptRecorderSessionChanged(_conference);

                // Establish Calls for Conference's supported modalities
                if (activeMediaTypes.Contains(MediaType.Audio))
                {
                    _transcriptRecorder.OnActiveMediaTypeCallToEstablish(_conversation, TranscriptRecorderType.AudioVideo);
                }
                if (activeMediaTypes.Contains(MediaType.Message))
                {
                    _transcriptRecorder.OnActiveMediaTypeCallToEstablish(_conversation, TranscriptRecorderType.InstantMessage);
                }

                _waitForInvitedConferenceActiveMediaTypeCallEstablished.Set();
            }
            catch (ConferenceFailureException conferenceFailureException)
            {
                // ConferenceFailureException may be thrown on failures due to MCUs being absent or unsupported, or due to malformed parameters.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(conferenceFailureException.ToString());
                exception = conferenceFailureException;
            }
            catch (RealTimeException realTimeException)
            {
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(realTimeException.ToString());
                exception = realTimeException;
            }
            finally
            {
                // Again, for sync. reasons.
                _state = TranscriptRecorderState.Active;
                _waitForInvitedConferenceJoined.Set();

                if (exception != null)
                {
                    string originator = string.Format("Error when joining the invited conference: {0}", exception.ToString());
                    NonBlockingConsole.WriteLine(originator);
                }
            }
        }
        private void InstantMessagingCallAcceptedCallBack(IAsyncResult ar)
        {
            InstantMessagingCall instantMessagingCall = ar.AsyncState as InstantMessagingCall;
            try
            {
                // Determine whether the call was accepted successfully.
                instantMessagingCall.EndAccept(ar);

                Message m = new Message("InstantMessagingCall Accepted. Call state: " + instantMessagingCall.State.ToString() + ". CallId: " + instantMessagingCall.CallId + ".",
                    instantMessagingCall.RemoteEndpoint.Participant.DisplayName, instantMessagingCall.RemoteEndpoint.Participant.UserAtHost,
                    instantMessagingCall.RemoteEndpoint.Participant.Uri,
                    MessageType.InstantMessage, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
                _transcriptRecorder.OnMessageReceived(m);

                _transcriptRecorder.OnRemoteParticipantAdded(null, instantMessagingCall.RemoteEndpoint);
            }
            catch (RealTimeException exception)
            {
                // RealTimeException may be thrown on media or link-layer failures. 
                // A production application should catch additional exceptions, such as OperationTimeoutException,
                // OperationTimeoutException, and CallOperationTimeoutException.

                NonBlockingConsole.WriteLine(exception.ToString());
            }
            finally
            {
                // Synchronize with main thread.
                _waitForIMCallAccepted.Set();
                _state = TranscriptRecorderState.Active;
            }
        }
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }

            _state = TranscriptRecorderState.Terminated;

            // TODO: Shutdown message

            if (_conference != null)
            {
                UnregisterConferenceEvents();
            }

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }
        /// <summary>
        /// Ends the escalation to conference.
        /// </summary>
        /// <param name="argument">The argument.</param>
        /// <remarks></remarks>
        private void EndEscalateConversation(IAsyncResult argument)
        {
            Conversation conversation = argument.AsyncState as Conversation;
            Exception exception = null;
            try
            {
                conversation.EndEscalateToConference(argument);
                NonBlockingConsole.WriteLine("Conversation was escalated into conference");
            }
            catch (OperationFailureException operationFailureException)
            {
                // OperationFailureException: Indicates failure to connect the call to the remote party.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(operationFailureException.ToString());
                exception = operationFailureException;
            }
            catch (RealTimeException realTimeException)
            {
                // RealTimeException may be thrown on media or link-layer failures.
                // It is left to the application to perform real error handling here.
                NonBlockingConsole.WriteLine(realTimeException.ToString());
                exception = realTimeException;
            }
            finally
            {
                _state = TranscriptRecorderState.Active;
                _waitForConferenceEscalationCompleted.Set();

                //Again, just to sync the completion of the code.
                if (exception != null)
                {
                    string originator = string.Format("Error when escalating to conference.");
                    NonBlockingConsole.WriteLine(originator);
                }
            }
        }
        public TranscriptRecorderSession(CallReceivedEventArgs<InstantMessagingCall> e, CancellationTokenSource cts = null)
        {
            _sessionId = Constants.NextGuid();
            _transcriptRecorders = new List<MediaTranscriptRecorder>();
            _conversationToCallTranscriptMapping = new Dictionary<ConversationTranscriptRecorder, List<MediaTranscriptRecorder>>();
            _messages = new List<Message>();
            _state = TranscriptRecorderState.Active;
            _conversation = e.Call.Conversation;
            _conversationTranscriptRecorder = new ConversationTranscriptRecorder(this, _conversation);
            _transcriptRecorders.Add(_conversationTranscriptRecorder);
            _conversationToCallTranscriptMapping.Add(_conversationTranscriptRecorder, new List<MediaTranscriptRecorder>());
            ConversationParticipant caller = e.RemoteParticipant;

            // Log IM conversation started
            Message m = new Message("InstantMessaging Conversation/Conference Started.", caller.DisplayName, caller.UserAtHost, caller.Uri, DateTime.Now,
                _conversation.Id, (_conversation.ConferenceSession == null) ? "null" : _conversation.ConferenceSession.ConferenceUri,
                MessageType.ConferenceInfo, MessageDirection.Outgoing);
            this.OnMessageReceived(m);

            AddIMIncomingCall(e);
        }
        public void InstantMessagingCall_Received(CallReceivedEventArgs<InstantMessagingCall> e)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: IMTranscriptRecorder is shutdown.");
                // TODO: Info message
                return;
            }

            if (_instantMessagingCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: IMCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            _waitForIMCallTerminated.Reset();

            // Type checking was done by the platform; no risk of this being any 
            // type other than the type expected.
            _instantMessagingCall = e.Call;

            // Call: StateChanged: Only hooked up for logging, to show the call
            // state transitions.
            _instantMessagingCall.StateChanged +=
                new EventHandler<CallStateChangedEventArgs>(InstantMessagingCall_StateChanged);

            _instantMessagingCall.InstantMessagingFlowConfigurationRequested +=
                new EventHandler<InstantMessagingFlowConfigurationRequestedEventArgs>(InstantMessagingCall_FlowConfigurationRequested);

            _instantMessagingCall.ConversationChanged += new EventHandler<ConversationChangedEventArgs>(InstantMessagingCall_ConversationChanged);

            // Remote Participant URI represents the far end (caller) in this 
            // conversation. Toast is the message set by the caller as the 
            // 'greet' message for this call. In Microsoft Lync, the 
            // toast will show up in the lower-right of the screen.
            // TODO: Change to protect privacy
            // NonBlockingConsole.WriteLine("IMCall Received! From: " + e.RemoteParticipant.Uri + " Toast is: " + e.ToastMessage.Message);
            NonBlockingConsole.WriteLine("IMCall Received! From: " + e.RemoteParticipant.Uri);
            // Console.Writelin("IMCall Received!");

            Message m = new Message("InstantMessagingCall Received. Inbound call state: " + _instantMessagingCall.State.ToString(),
                e.RemoteParticipant.DisplayName, e.RemoteParticipant.UserAtHost, e.RemoteParticipant.Uri,
                MessageType.InstantMessage, _transcriptRecorder.Conversation.Id, MessageDirection.Incoming);
            _transcriptRecorder.OnMessageReceived(m);

            // Now, accept the call. EndAcceptCall will be raised on the 
            // same thread.
            _instantMessagingCall.BeginAccept(InstantMessagingCallAcceptedCallBack, _instantMessagingCall);
        }
        public TranscriptRecorderSession(ConferenceInvitationReceivedEventArgs e, CancellationTokenSource cts = null)
        {
            _sessionId = Constants.NextGuid();
            _transcriptRecorders = new List<MediaTranscriptRecorder>();
            _conversationToCallTranscriptMapping = new Dictionary<ConversationTranscriptRecorder, List<MediaTranscriptRecorder>>();
            _messages = new List<Message>();
            _state = TranscriptRecorderState.Active;
            ConversationParticipant caller = e.RemoteParticipant;

            // Log Conference Invitation Recv
            Message m = new Message("Conference Started Invitation Recieved for ConferenceUri: ", caller.DisplayName, caller.UserAtHost, caller.Uri, DateTime.Now,
               "null", e.Invitation.ConferenceUri,
                MessageType.ConferenceInfo, MessageDirection.Outgoing);
            this.OnMessageReceived(m);

            AddIncomingInvitedConference(e);
        }
        public void EstablishInstantMessagingCall(Conversation conversation)
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                NonBlockingConsole.WriteLine("Error: IMTranscriptRecorder is shutdown.");
                // TODO: error message
                return;
            }

            if (_instantMessagingCall != null)
            {
                NonBlockingConsole.WriteLine("Warn: IMCall already exists for this Conversation. Shutting down previous call...");
                // TODO: Info message
                TerminateCall();
            }

            _state = TranscriptRecorderState.Initialized;
            this._waitForIMCallTerminated.Reset();

            try
            {
                InstantMessagingCall imCall = new InstantMessagingCall(conversation);

                // Register for Call events
                _instantMessagingCall = imCall;

                // Call: StateChanged: Only hooked up for logging, to show the call
                // state transitions.
                _instantMessagingCall.StateChanged +=
                    new EventHandler<CallStateChangedEventArgs>(InstantMessagingCall_StateChanged);

                _instantMessagingCall.InstantMessagingFlowConfigurationRequested +=
                    new EventHandler<InstantMessagingFlowConfigurationRequestedEventArgs>(InstantMessagingCall_FlowConfigurationRequested);

                // Establish AudioVideoCall
                imCall.BeginEstablish(IMCall_EstablishCompleted, imCall);
            }
            catch (InvalidOperationException ex)
            {
                NonBlockingConsole.WriteLine("Error: imCall.BeginEstablish failed. Exception: {0}", ex.ToString());
                // TODO: Error Message
            }
        }
        public void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            TranscriptRecorderSessionShutdownEventArgs shutdownArgs = null;
            lock (_transcriptRecorders)
            {
                foreach (MediaTranscriptRecorder m in _transcriptRecorders)
                {
                    m.Shutdown();
                }
                _transcriptRecorders.Clear();
            }

            try
            {
                Message shutdownMessage = new Message("TranscriptRecorderSession is shutting down. SessionId: ", _sessionId.ToString());           
                this.OnMessageReceived(shutdownMessage);

                shutdownArgs = new TranscriptRecorderSessionShutdownEventArgs(this);

                if (_conversation != null &&
                    ((_conversation.State != ConversationState.Terminating) || (_conversation.State != ConversationState.Terminated)))
                {
                    Message m = new Message("Conversation shutting down.", _conversation.LocalParticipant.DisplayName,
                        _conversation.LocalParticipant.UserAtHost, _conversation.LocalParticipant.Uri, DateTime.Now,
                        _conversation.Id, (this.Conference == null) ? "null" : this.Conference.ConferenceUri,
                        MessageType.ConversationInfo, MessageDirection.Outgoing);
                   this.OnMessageReceived(m);

                    _conversation.BeginTerminate(EndTerminateConversation, _conversation);
                    //_waitForConversationTerminated.WaitOne();
                    _conversation = null;
                }
                else
                {
                    _waitForConversationTerminated.Set();
                }

                ShutdownConversationContext();
            }
            catch (Exception e)
            {
                NonBlockingConsole.WriteLine("TranscriptRecorderSession.Shutdown(). Exception occured during conversation shutdown: {0}",
                    e.ToString());
            }
            finally
            {
                // Raise Shutdown event to MeetingTranscriptSessionManager
                this.RaiseTranscriptRecorderSessionShutdown(shutdownArgs);
            }
        }
        public override void Shutdown()
        {
            if (_state == TranscriptRecorderState.Terminated)
            {
                return;
            }
            _state = TranscriptRecorderState.Terminated;

            TerminateCall();

            _transcriptRecorder.OnMediaTranscriptRecorderTerminated(this);
            _transcriptRecorder = null;
        }