Export (0) Print
Expand All

Working with Presence and Groups in UCMA 3.0: Adding the Contact to the Conversation (Part 4 of 5)

Summary:   Learn how to use presence to find an available member of a Microsoft Lync 2010 contact group, and then add the contact to a multiparty group conversation.

Applies to:   Microsoft Unified Communications Managed API (UCMA) 3.0 Core SDK | Microsoft Unified Communications Managed API (UCMA) 3.0 | Microsoft Lync 2010

Published:   September 2011 | Provided by:   Mark Parker, Microsoft | About the Author

Contents

Download code   Download code

This is the fourth in a series of five articles about how to work with presence and groups in a UCMA 3.0 application.

In Working with Presence and Groups in UCMA 3.0: Finding a Contact (Part 3 of 5), an available contact in the selected group (Service Department or Sales Department) was found. The next step is to bring the contact into the conversation between the Lync 2010 user and the UCMA 3.0 application.

To bring the contact into the conversation:

  1. Join the conversation to an instant messaging multipoint control unit (MCU).

    To do this, create a ConferenceSession instance that is initialized from the ConferenceSession property on the Conversation instance. Next, call the BeginJoin method on the ConferenceSession instance.

    A join operation moves the existing calls in the conversation to the appropriate MCU. Joining a conference session does not refer to participants joining the conference session.

  2. Escalate the conversation to a conference session. The Lync 2010 terminology refers to a conference session as a group conversation.

    Escalation occurs when the BeginEscalateToConference method on the Conversation instance is called.

  3. Invite the contact into the conference session.

    For this step, create a ConferenceInvitation instance, and then deliver the invitation to the contact by calling the BeginDeliver method on the ConferenceInvitation instance.

The following example shows the declarations of global variables that are used in this article.

Note Note

The code for the application that is described in this article series appears in Working with Presence and Groups in UCMA 3.0: Code Listing and Conclusion (Part 5 of 5).

private UCMASampleHelper _helper;
private UserEndpoint _userEndpoint;
private Uri _remoteContactUri;
private InstantMessagingCall _instantMessagingCall;
private RemotePresenceView _remotePresenceView;
private bool _isFirstMessage = true;
private Conversation _incomingConversation;
private ConferenceSession _conferenceSession; 
private AutoResetEvent _waitUntilConferenceInvitationIsDelivered = new AutoResetEvent(false);
private AutoResetEvent _waitUntilConversationIsTerminated = new AutoResetEvent(false);

The following example shows the part of the application that is involved in setting up a conference session (or group conversation) that includes the contact that was previously found. The if statement guards against the possibility that no available contacts were found

InstantMessagingFlow imFlow = _instantMessagingCall.Flow;
.
.
.
if (_remoteContactUri != null)
{
  imFlow.BeginSendInstantMessage("Contact found: " + _remoteContactUri.ToString(), CallSendInstantMessageCB, _instantMessagingCall);
  // Join the conversation to the IM MCU.
  _conferenceSession = _incomingConversation.ConferenceSession;
  ConferenceJoinOptions confJoinOptions = new ConferenceJoinOptions();
  confJoinOptions.JoinMode = JoinMode.Default;
  _conferenceSession.BeginJoin(confJoinOptions, ConferenceJoinCB, _conferenceSession);
  _waitUntilConferenceInvitationIsDelivered.WaitOne();
}
else
{
  Console.WriteLine("Could not find an available contact.");
  imFlow.BeginSendInstantMessage("Could not find an available contact.\nPlease call again later.", CallSendInstantMessageCB, _instantMessagingCall);
}
// Unregister for notification of the MessageReceived event.
imFlow.MessageReceived -= new EventHandler<InstantMessageReceivedEventArgs>(IMFlow_MessageReceived);
// Cancel the subscription to the presence session by unsubscribing.
_userEndpoint.ContactGroupServices.BeginUnsubscribe(ContactGroupUnsubscribeCB, _userEndpoint.ContactGroupServices);
// Terminate the RemotePresenceView subscription.
_remotePresenceView.BeginTerminate(ViewTerminateCB, _remotePresenceView);

Following the if statement, the contact either was found or could not be found. There is no longer the need to be notified of messages that are received on the flow, so the IMFlow_MessageReceived event handler is unhooked. Presence state subscription is also no longer needed, so the BeginUnsubscribe method is called on the ContactGroupServices instance.

This section describes the callback methods that are called as a result of adding a contact to the conversation. Due to the use of callback chaining, some callback methods that appear in this section do not explicitly appear in the previous section. For more information, see Working with Presence and Groups in UCMA 3.0: Callback Chaining (Part 2 of 5).

ConferenceJoinCB Callback Method

The ConferenceJoinCB callback method completes the join proces by calling the EndJoin method on the ConferenceSession instance. Before exiting, this callback calls the BeginEscalateToConference method on the Conversation instance, _incomingConversation. This global variable is set in the InstantMessagingCall_Received delegate. For more information, see Working with Presence and Groups in UCMA 3.0: Finding a Contact (Part 3 of 5).

BeginEscalateToConference causes a noticeable effect in the Lync 2010 user interface: the title under the menu bar changes to Group Conversation, and there is a hyperlink that contains the text Join Information and Meeting Options.

This callback is an example of the use of callback chaining, which is described in Working with Presence and Groups in UCMA 3.0: Callback Chaining (Part 2 of 5).

The following example shows the definition of the ConferenceJoinCB method.

private void ConferenceJoinCB(IAsyncResult ar)
{
  ConferenceSession conferenceSession = ar.AsyncState as ConferenceSession;
  try
  {
    conferenceSession.EndJoin(ar);
    Console.WriteLine("Conversation state: " + _incomingConversation.State.ToString());
    Console.WriteLine("Conference session state: " + _conferenceSession.State.ToString());
    _incomingConversation.BeginEscalateToConference(ConferenceEscalateCB, _incomingConversation);
  }

  // A production application should have catch blocks for a number 
  // of other exceptions, including ConferenceFailureException, FailureRequestException,
  // and OperationFailureException.
  catch (RealTimeException exception)
  {
    Console.WriteLine(exception.ToString());
  }
}

ConferenceEscalateCB Callback Method

The ConferenceEscalateCB callback method completes the conversation escalation process by calling the EndEscalateToConference method on the Conversation instance. Before exiting, this callback method creates a ConferenceInvitation instance, and then calls the BeginDeliver method on the ConferenceInvitation instance to send the invitation to the contact that was previously found. Note that, exactly as in the ConferenceJoinCB callback method, callback chaining is also used in the ConferenceEscalateCB callback method.

The following example shows the definition of the ConferenceEscalateCB method.

private void ConferenceEscalateCB(IAsyncResult ar)
{
  Conversation conversation = ar.AsyncState as Conversation;
  try
  {
    conversation.EndEscalateToConference(ar);
  }

  // A production application should have catch blocks for a number 
  // of other exceptions, including OperationTimeoutException and
  // OperationFailureException.
  catch (RealTimeException exception)
  {
    Console.WriteLine(exception.ToString());
  }

  ConferenceInvitation conferenceInvite = new ConferenceInvitation(_incomingConversation);
  conferenceInvite.StateChanged += new EventHandler<ConferenceInvitationStateChangedEventArgs>(conferenceInvite_StateChanged);
  ConferenceInvitationDeliverOptions confDeliverOptions = new ConferenceInvitationDeliverOptions();
  confDeliverOptions.ToastMessage = new ToastMessage("Join the conference!");
  conferenceInvite.BeginDeliver(_remoteContactUri.ToString(), confDeliverOptions, InvitationDeliverCB, conferenceInvite);
}

InvitationDeliverCB Callback Method

The InvitationDeliverCB callback method completes the process of invitation delivery by calling the EndDeliver method on the ConferenceInvitation instance. Before exiting, this method calls the Set method on the _waitUntilConferenceInvitationIsDelivered object, which allows the main thread to resume execution. The main thread was paused by a call to WaitOne on this object, just after the call to the BeginJoin method on the _conferenceSession object.

The following example shows the definition of the InvitationDeliverCB method.

private void InvitationDeliverCB(IAsyncResult ar)
{
  ConferenceInvitation conferenceInvite = ar.AsyncState as ConferenceInvitation;
  try
  {
    conferenceInvite.EndDeliver(ar);
  }
  // A production application should have catch blocks for a number 
  // of other exceptions, including FailureResponseException, OperationTimeoutException,
  // and OperationFailureException.
  catch (RealTimeException exception)
  {
    Console.WriteLine(exception.ToString());
  }
  // Synchronize with main thread.
  _waitUntilConferenceInvitationIsDelivered.Set();
}

ContactGroupUnsubscribeCB Callback Method

The ContactGroupUnsubscribeCB callback method completes the unsubscription process by calling the EndUnsubscribe method on the ContactGroupServices instance.

The following example shows the definition of the ContactGroupUnsubscribeCB method.

private void ContactGroupUnsubscribeCB(IAsyncResult ar)
{
  ContactGroupServices services = ar.AsyncState as ContactGroupServices;
  try
  {
    services.EndUnsubscribe(ar);
  }

  // A production application should have catch blocks for a number 
  // of other exceptions, including InvalidOperationException and PublishSubscribeException.
  catch (RealTimeException exception)
  {
    Console.WriteLine("Contact Group Unsubscription failed due to exception: {0}",
            exception.ToString());
  }
}

ViewTerminateCB Callback Method

The ViewTerminateCB callback method completes the process of terminating the RemotePresenceView instance, by calling the EndTerminate method on the remote presence view.

The following example shows the definition of the ViewTerminateCB method.

// Callback method referred to in the call to BeginTerminate on the RemotePresenceView instance.
private void ViewTerminateCB(IAsyncResult ar)
{
  RemotePresenceView view = ar.AsyncState as RemotePresenceView;
  view.EndTerminate(ar);
}

After the contact has accepted the invitation to participate in the conference session with the Lync 2010 caller and the UCMA 3.0 application, the application can end. Before doing so, the application calls the BeginTerminate method on the _instantMessagingCall object. The application then calls the WaitOne method on the _waitUntilConversationIsTerminated object, which pauses the main thread. When the main thread resumes operation, following a call to the Set method on the _waitUntilConversationIsTerminated object, it unregisters the InstantMessagingCall_Received delegate and calls the ShutdownPlatform method (defined in UCMASampleHelper.cs).

The following example shows the final actions of the application.

_instantMessagingCall.BeginTerminate(CallTerminateCB, _instantMessagingCall);
_waitUntilConversationIsTerminated.WaitOne();
_userEndpoint.UnregisterForIncomingCall<InstantMessagingCall>(InstantMessagingCall_Received);

// Clean up by shutting down the platform.
_helper.ShutdownPlatform();

This section describes the callback methods that appear in the previous example.

CallTerminateCB Callback Method

The CallTerminateCB callback method completes the termination of the instant message call, by calling the EndTerminate method on the InstantMessagingCall instance. This method also unhooks the handler for the StateChanged event on the call, and calls the BeginTerminate method on the Conversation instance.

The following example shows the definition of the CallTerminateCB method.

private void CallTerminateCB(IAsyncResult ar)
{
  InstantMessagingCall instantMessagingCall = ar.AsyncState as InstantMessagingCall;

  // Finish terminating the incoming call.
  instantMessagingCall.EndTerminate(ar);

  // The call has been terminated, so remove the handler for the StateChanged event.
  _instantMessagingCall.StateChanged -= InstantMessagingCall_StateChanged;

  // Terminate the conversation.
  _instantMessagingCall.Conversation.BeginTerminate(ConversationTerminateCB,
                  _instantMessagingCall.Conversation);
}

ConversationTerminateCB Callback Method

The ConversationTerminateCB callback method completes the termination of the Conversation instance, by calling the EndTerminate method on this object. Before exiting, this method calls the Set method on the _waitUntilConversationIsTerminated object. This action allows the main thread to resume operation.

The following example shows the definition of the ConversationTerminateCB method.


private void ConversationTerminateCB(IAsyncResult ar)
{
  Conversation conversation = ar.AsyncState as Conversation;

  // Finish terminating the conversation.
  conversation.EndTerminate(ar);

  // Synchronize with main thread.
  _waitUntilConversationIsTerminated.Set();
}

Mark Parker is a programming writer at Microsoft whose current responsibility is the UCMA SDK documentation.

Show:
© 2014 Microsoft