Lync SDK のプログラム コードを使用した開発


環境 : Lync Server 2010, Lync 2010, Visual Studio 2010, Silverlight 4 開発者向けランタイム, Lync 2010 SDK

Lync 2010 クライアント開発入門

こんにちは。

Lync 2010 SDK では、UI Automatoin や単なる Lync クライアント コントロールの利用だけではなく、Lync クライアントそのものと同様の処理をコードを使って構築できます。
今回は、Lync クライアント SDK のプログラミングについて、その概念を見ていきましょう。

なお、Lync 2010 の日本語版 Bits も提供開始されましたが (MSDN Subscription でも提供されています)、ここでは、英語版をそのまま使います。。。

コードの作成 (基礎)

まず、前回と同様のアプリケーションを Lync クライアント SDK のプログラム コードを使って構築してみましょう。
今回は、サインインしている SIP ユーザーを取得し、前回同様、そのユーザーのイメージ、名前、状態情報を表示してみます。

まず、前回同様、Visual Studio で、[Silverlight アプリケーション] を新規作成します。(Silverlight 4 のアプリケーションとして新規作成します。)
さらに、Microsoft.Lync.Controls.dll、Microsoft.Lync.Controls.Framework.dll、Microsoft.Lync.Model.dll、Microsoft.Lync.Utilities.dll の各アセンブリを参照追加しておきます。
(前回 記述した、信頼済みサイトへの設定も、ちゃんと実施しておきましょう。)

さらに、前回同様、MainPage.xaml に StackPanel を挿入し、Orientation プロパティを [Horizontal] として、今回は、Image コントロールと、TextBlock コントロールを 2 つ挿入します。

では、この UserControl (MainPage.xaml) のロード時に、ログインしている Lync のユーザーを取得して、このユーザーのイメージを Image コントロールに表示してみましょう。
MainPage.xaml をマウスでダブルクリックして、下記の通り、初期化の際のコードを記述します。

. . .
using Microsoft.Lync.Model;
using System.IO;
using System.Windows.Media.Imaging;

. . .

private LyncClient cl;

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    // Lync クライアントの取得
    cl = LyncClient.GetClient();

    // ログインしていないなら何もしない
    if (cl.State != ClientState.SignedIn)
        return;

    // イメージの設定
    Stream imageStream =
        cl.Self.Contact.GetContactInformation(ContactInformationType.Photo) as Stream;
    BitmapImage imageBitmap = new BitmapImage();
    imageBitmap.SetSource(imageStream);
    image1.Source = imageBitmap;
    imageStream.Close();
}

Lync のプログラミングで最も重要なのは、LyncClient クラスです。このクラスを使用して、ログイン中のユーザー (Self オブジェクト) や、そのコンタクト情報 (Contact オブジェクト) などを取得し、これらのオブジェクトからさまざまな情報を取得することができます。

同様にして、下記 (太字) の通り、そのユーザー名や、状態情報も取得できます。

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    // Lync クライアントの取得
    cl = LyncClient.GetClient();

    // ログインしていないなら何もしない
    if (cl.State != ClientState.SignedIn)
        return;

    // イメージの設定
    Stream imageStream =
        cl.Self.Contact.GetContactInformation(ContactInformationType.Photo) as Stream;
    BitmapImage imageBitmap = new BitmapImage();
    imageBitmap.SetSource(imageStream);
    image1.Source = imageBitmap;
    imageStream.Close();

    // 名前の設定
    textBlock1.Text =
        cl.Self.Contact.GetContactInformation(ContactInformationType.DisplayName) as string;

    // 状態情報の設定
    ContactAvailability availability =
        (ContactAvailability)cl.Self.Contact.GetContactInformation(ContactInformationType.Availability);
    textBlock2.Text = availability.ToString();
}

実行結果は、下図の通りです。(ちょっと、イメージが大きすぎますが、適当にサイズを調整してください。。。)

上記は Lync にサインインしている前提でコードが組まれていますが、Lync クライアントが起動していないと、GetClient メソッドで例外が発生するので注意してください。
このため、現実の開発では、例外処理もちゃんと実装し、Lync が起動していない場合は利用者に起動を促すなど、適切な例外処理を実装しておいてください。

データの変更

上記では、データの取得をおこなっていますが、もちろん、データの更新 (変更) もおこなうことができます。

例えば、下記では、ボタンを押すと、ログイン中のユーザーの状態情報 (Free / Budy 情報) を「Busy」に変更します。
コードを見ていただくとわかるように、非同期 (Async) 呼び出しのため、更新完了後のコールバック関数の指定も必要になる点に注意してください。

private void button1_Click(object sender, RoutedEventArgs e)
{
    // 更新データの作成
    Dictionary<PublishableContactInformationType, object> data =
        new Dictionary<PublishableContactInformationType, object>();
    data.Add(PublishableContactInformationType.Availability, ContactAvailability.Busy);

    // 更新実行 !
    cl.Self.BeginPublishContactInformation(data, PublishInformationCallback, null);
}

private void PublishInformationCallback(IAsyncResult result)
{
    cl.Self.EndPublishContactInformation(result);
}

イベント処理

標準の Lync クライアントでは、ユーザーの状態情報 (Free / Budy 情報) が更新されると、クライアント上の状態情報も動的に更新されます。こうしたイベント処理もコードで実装できます。

下記では、このユーザー (ログインしているユーザー) の状態情報 (ContactAvailability オブジェクト) を動的に更新しています。Note の更新、サインイン / サインアウトの情報の更新など、さまざまな場面でこうしたイベント処理を実装できます。(サインインを検知する場合は、LyncClient の StateChanged イベントを処理します。)

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    . . .

    // ContactInformation のイベント処理 (更新処理)
    cl.Self.Contact.ContactInformationChanged += new EventHandler<ContactInformationChangedEventArgs>(Contact_ContactInformationChanged);
}

void Contact_ContactInformationChanged(object sender, ContactInformationChangedEventArgs e)
{
    if (e.ChangedContactInformation.Contains(ContactInformationType.Availability))
    {
        ContactAvailability availability =
            (ContactAvailability)cl.Self.Contact.GetContactInformation(ContactInformationType.Availability);
        textBlock2.Text = availability.ToString();
    }
}

また、Conversation (IM の対話) をイベントでキャプチャすることもできます。
下記は、IM (Instant Messaging) を受け取ったときに、その内容 (受信した IM のテキスト) を TextBlock に表示するサンプル コードです。

. . .
using Microsoft.Lync.Model;
using Microsoft.Lync.Model.Extensibility;
using Microsoft.Lync.Model.Conversation;

. . .

private LyncClient cl;   // クライアント
private Conversation con;   // Conversation
private Participant par;   // 参加者 (誰か 1 人)
private InstantMessageModality im;   // その人との IM

private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
    cl = LyncClient.GetClient();
    . . .

    // Conversation 開始時のイベント処理
    cl.ConversationManager.ConversationAdded += new EventHandler<Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs>(ConversationManager_ConversationAdded);
}

void ConversationManager_ConversationAdded(object sender, Microsoft.Lync.Model.Conversation.ConversationManagerEventArgs e)
{
    // 開始された Conversation を取得
    con = e.Conversation;

    // IM の参加者のうち、自分以外の誰か (最初の 1 人) を取得
    foreach (Participant x in con.Participants)
    {
        if (x.IsSelf == false)
        {
            par = x;
            break;
        }
    }

    // IM を取得
    im = (InstantMessageModality) par.Modalities[ModalityTypes.InstantMessage];

    // IM 受信の際のイベント処理
    im.InstantMessageReceived += new EventHandler<MessageSentEventArgs>(im_InstantMessageReceived);
}

void im_InstantMessageReceived(object sender, MessageSentEventArgs e)
{
    // 受信された IM の内容 (文字列) を TextBlock に表示
    textBlock1.Text = e.Text;
}

また、WPF アプリケーションなら、Windows の Synthesizer / Recognizer (Windows クライアントのプラットフォーム テクノロジーである Windows Speech Recognition) を使用して、IM と音声の連携をおこなうこともできます。例えば、IM の応答を音声として読み上げる場合には、上記のプログラムを以下の通り変更します。

. . .
using System.Speech.Synthesis;

. . .
private SpeechSynthesizer synthesizer;

. . .
void im_InstantMessageReceived(object sender, MessageSentEventArgs e)
{
    synthesizer = new SpeechSynthesizer();
    synthesizer.Speak(e.Text);
}

注意 :ただし、残念ながら、既定では、Windows クライアントに「日本語」の音声合成は入っていません。日本語を使用する場合には、日本語用の音声合成エンジンをインストールして、SpeechSynthesizer に以下の通り設定してください。(日本語の音声合成のインストールについては、こちら を参照してください。)

synthesizer.SelectVoice(“LH Kenji”);

なお、Silverlight アプリケーションの場合は、Code Gallery の Text-to-Speech: Accessibility Feature for Silverlight 3.0 Applications などが使用できます。

この他にも、Bing Translator と連携した翻訳機能の提供など、さまざまな応用例が考えられます。

上記の例は、Conversation Window とカスタム アプリケーションのウィンドウが別々に動作する非現実的なアプリケーションですが、Lync SDK では、Conversation を扱った さらに強力なプログラミングが可能ですので、これについては、次回以降で説明します。(次回説明しますが、Conversation Window にカスタムの機能を合体できます。)

なお、上記では、サンプルとして、コアな処理部分のみをピックアップして掲載していますので、現実の開発では、まめなイベントの Remove や、UI スレッドに配慮した Dispatch 処理、リソースの確実な解放 (using の使用) など、ちゃんと実装しておいてください。(本ブログを読まれている方には説明の必要はないと思いますが、念のため、記載しておきます。上記は、サンプルの可読性をあげるため、かなり省略して書いています。)

クライアント プログラミングにおける注意点

繰り返しになりますが、これらのプログラミングでは、Lync クライアントの起動が前提となっているという点に注意してください。

このため、例えば、Lync クライアントと同じ処理をプログラミングによってすべて構築したい場合には、以下の点に注意する必要があります。

  • 既定では、Lync のプロセスを起動すると、必ず、標準の Lync クライアントが起動します。このため、そもそも、標準の Lync クライアントを使用せず、カスタム アプリケーションだけでクライアント側の処理をおこないたい場合には、Lync クライアントを UI Suppression モードにしておく必要があります。
  • また、PrecenceIndicator コントロールや StartInstantMessagingButton コントロールなど、ツールボックスに標準で提供されているコントロールでは問題となりませんが、Lync で使用されている ConversationWindow コントロールなどでは、Window のハンドル (IntPtr) を使用するため、例えば、Silverlight アプリケーションなどに ConversationWindow コントロールを埋め込む場合には、WindowsFormsHost コントロールを使ってホストさせる必要があります。

Lync クライアントを UI Suppression モードにするには、Lync クライアントのインストール時にオプションで指定するか、レジストリーの設定を変更する必要があります。(プログラム コードで、臨機応変に変えることはできません。)
UI Suppression モード (SuppressedMode) の設定については、以下に記載されていますので参考にしてください。

[MSDN] Understanding UI Suppression in Lync SDK

http://msdn.microsoft.com/en-us/library/gg436950.aspx

また、上記の 2 番目で記載しているように、Conversation Window (IM の際に表示されるウィンドウ) では、ConversationWindow クラスの Dock メソッドを使用してドッキング (Docking) 可能ですが、この際、Window Handle が必要であるため、WindowsFormsHost コントロールを使用してホストさせる必要があります。このサンプル コードは、Lync SDK に入っていますので参考にしてください。

補足 : Web アプリケーションなど、サーバーサイドのリアルタイム コミュニケーション クライアントを開発する際には、第 1 回でも述べた UCMA を使用すると良いでしょう。(サーバー用のランタイムを使用します。)

このように、Lync SDK による Lync のクライアントサイド開発では、まず、Lync クライアントを前提として、Lync クライアントと自然に連携させることを考えると良いでしょう。(Lync クライアントと同じ処理を 1 から構築する方法は、プログラムが大きくなることに加え、環境設定なども含め、いろいろと考慮する必要があります。)
次回以降では、Lync で重要な機能の 1 つである Conversation を中心に、こうした実用的な連携プログラミングの手法を見ていきましょう。

皆様、良いお年をお迎えください (明日から休暇に入りますので、続きは来年に。。。)

 

Comments (0)

Skip to main content