2010年4月27日火曜日

C# でオリジナルのメッセージを通知する方法

このエントリーをはてなブックマークに追加
on Mono 2.6.1, Ubuntu 9.04

デスクトップ上で、アプリまたはシステムからのメッセージ通知に使われている NotifyOSD は、Ubuntu では 9.04 以降、黒い半透明な外観を持ち、何だかカッコイイ。

メッセージ通知後、数秒で自動消滅(バブルエフェクト?)する、このメッセージをどうやって使用できるのか、淡いながらも興味を持っていたところ、次のブログ記事を読んだ。


なるほど、このように簡単に使用できるのか。

そこで、C# でも同様のことが可能と分かったので、以下にまとめてみた。

NotifySharp のインストール

NotifySharp を使用することで、NotifyOSD メッセージ通知を使用できるようになる。

標準の Mono 環境を使用しているなら、「libnotify0.4-cil」パッケージを導入すればよい(標準で導入済か)。

独自に野良インストールした Mono 環境を使用しているなら、同様に野良インストールする必要がある。

今回は “notify-sharp” package in Ubuntu にあるソース資源を使用して、インストールを行った。

インストール実行例。

$ tar -xvf notify-sharp_0.4.0~r3032.orig.tar.gz
$ cd notify-sharp-0.4.0
$ echo $MONO_HOME
/opt/mono/2.6.1
$ ./configure --prefix=$MONO_HOME
$ make
$ sudo paco -D make install

必要なアセンブリとして、NDesk.DBus(NDesk.DBus.dll)が挙げられるが、Ubuntu 9.04 では、Tomboy の依存パッケージとして「libndesk-dbus1.0-cil」が導入されているので、特に何かする必要はない。

独自に野良インストールした Mono 環境であれば、NotifySharp 同様にインストールする必要がある。もっとも、独自の Mono 環境でも Tomboy を動かすようにしているのなら、導入済みであるはずなので、特に何かする必要はない。

NotifyHello サンプル

おなじみの Hello world! である。
using System;
using Notifications;

namespace NotifyExample
{
  public class NotifyHello
  {
    public static void Main(string[] args)
    {
      Notification n = new Notification("NotifySharp", // Summary 
                                        "Hello world!", // Body
                                        "notification-message-IM"); // Icon
      n.Show();
    }
  }
}
/*
 * Build:
 *
 *   gmcs -pkg:notify-sharp notifyhello.cs
 *
 * Run:
 *
 *   mono notifyhello.exe
 *
 */


Summary にタイトル、Body にメッセージ文、Icon にアイコンファイル名(拡張子なし)または、アイコンファイルのパスを設定する。

アイコンファイルを保持するデフォルトディレクトリは「/usr/share/icons/Human/scalable/status」なので、ここにあるアイコンファイルは、ファイル名(拡張子なし)の設定で、使用することができる(notification-*.svg は NotifyOSD 用のアイコン類)。

NotifyTime サンプル

時報サンプルを試してみた。
using Notifications;
using System;
using System.Threading;

namespace NotifyExample
{
  public class NotifyTime
  {
    readonly Predicate<DateTime> _pred;

    public NotifyTime()
      : this(( (DateTime dt) => dt.Minute == 0 ))
    {
    }

    public NotifyTime(Predicate<DateTime> pred)
    {
      this._pred = pred;
    }

    public void Run()
    {
      int duetime = 60 - DateTime.Now.Second;
      using (Timer timer = new Timer(Notify, null , duetime * 1000, 60 * 1000))
      {
        Console.WriteLine("Press Enter key to exit.");
        Console.ReadLine();
      }
    }

    private void Notify(object state)
    {
      DateTime dt = DateTime.Now;
      if (_pred(dt))
      {        
        Notification n = new Notification("現在時刻のお知らせ",
                                          dt.ToString("f"),
                                          "/usr/share/icons/hicolor/scalable/apps/gnome-panel-clock.svg");
        n.Show();
      }
    }

    public static void Main(string[] args)
    {
      NotifyTime nt = new NotifyTime(); // 時報
      //NotifyTime nt = new NotifyTime(( (DateTime dt) => true )); // 分報
      /*
      NotifyTime nt = new NotifyTime(
        ( (DateTime dt) => dt.Hour   == 17 &&
                           dt.Minute == 30 )); // 任意の時刻
       */
      nt.Run();
    }
  }
}
/*
 * Build:
 *
 *   gmcs -pkg:notify-sharp notifytime.cs
 *
 * Run:
 *
 *   mono notifytime.exe
 *
 */


なかなか、うまくいかなかった。30 回程メッセージ通知を行った後、タイマーが止まってしまうのだ(System.Timers.Timer を使用しても同様)。

結局のところ、タイマーによる CallBack 呼出し間隔を 10 秒以上に設定すること、呼出し毎に、Notification クラスのインスタンスを生成することで、タイマー停止は回避できるようになった。

タイマーと相性が悪いのだろうか、GC との関係なのだろうか。正直よく分からなかった。

所感

カッコイイ NotifyOSD を使ってるオレ、カッコイイ!そんな気になるかもしれない。

参考

0 件のコメント:

コメントを投稿