Ubuntu Weekly Recipe

第209回Unityでニコニコ動画を検索する

第204回でも紹介したように、Unityは「Lens」を追加することでさまざまな検索インターフェースを追加することができます。

そこで今回は、ニコニコ動画のタグ検索を行うLensを作ってみましょう。

UnityとDashとLensのおさらい

今一度、Unityのシステムについておさらいしておきましょう。

UnityとLens

UnityはUbuntu 11.04から標準で採用されているデスクトップインターフェースです。アプリケーションドックであるLauncher、アプリケーションのメニューを表示するGlobalMenu、個々のソフトウェアの通知領域となるIndicatorなどのコンポーネントから成り立っています。

その中でも重要な位置を占めるのが、統合的な検索インターフェースであるDashです。Superキー(Windowsキー)を押すことで表示されるDashは、ユーザーに統一的な検索インターフェースを提供します。

LensはDash内部に検索条件や結果を表示するためのインターフェースとなります。何かを検索するときに特定の条件を付加したいことがあります。例えばファイルだったら「最終アクセス日時⁠⁠、音楽ファイルなら「ジャンル」といった具合に、検索対象ごとによく使われる条件は異なりますし、動画だったらサムネイル、アプリケーションだったらアイコンのように、検索結果に表示したい画像もカテゴリーごとに異なります。このように、結果のインターフェースを柔軟に変更するのがLensの目的です。

Ubuntu 11.10の初期状態では検索できるのが、アプリケーション[1]⁠、ファイルとフォルダー、音楽ファイルに限られますが、第204回で紹介したLensをアドオン的に追加することで、さまざまなデータをDashから検索できるようになります。

ScopeとD-Bus

ユーザーが意識することはあまりありませんが、もう一つScopeという概念があります。これはLens内部[2]で呼び出す検索システムそのものです。

YouTube LensならYouTubeのAPIを使って、Wikipedia LensならWikipediaのAPIを使って検索する必要があるため、これらはそれぞれ独立したScopeとして実装されます。また、複数のScopeを持ったLensを実装することも可能ですし、あるLensが、別のLensが作成したScopeを流用するといった実装も可能です。

Unity、Lens、Scopeはそれぞれ別プロセスとして起動します。このためプロセス間通信としてD-Busを使用します。

Lensのファイル構造

Lensのファイル構成は非常にシンプルです。したがってちょっとしたプログラミング経験がある人なら誰でも簡単にLensを作ることができます。

幸い、Unityと各種Lensの開発者であるDavid CalleとMichal Hrubyが、先日行われたUbuntu Developer Weekのセッション用に、Pythonを使ったサンプルライブラリを作ってくれたので、これをベースに説明しましょう。

Lensの作成方法や概念については一通りUbuntu Wikiでも詳細に説明されているので、そちらも参照してください。

ちなみに今回はPythonで記述しますが、Lens自体はCにVala、あとまだ試験的ではありますがJavaScriptでも記述できます。

サンプルコードの構造

実際にサンプルコードをブランチしてみましょう。

$ bzr branch lp:~unity-team/unity-lens-sample/python-4.0

Ubuntu 11.10で作成する場合は、Unity 4系のAPIを使う必要があるので、python-4.0をブランチします。UnityのTesting PPAを有効にしている場合や、Preciseを使用している場合はUnity 5系になるので上記のリポジトリをpython-5.0に変更してください[3]⁠。

以下の3つのファイルが重要になります。

python.lens
UnityにLensとD-Bus通信を行うための各種情報を伝えるためのファイルです。ファイル名は個々のLensで一意なIDである必要があります。
phtyon-lens.svg
Dashの下部に表示するためのアイコンです。.lensファイルのIconでこのファイル名を指定します。
unity-lens-python.py
Lensの本体(Lensデーモン)です。検索結果のレイアウトや、フィルターはすべてここに記述します。このサンプルの場合、Scopeも内部に内包しています。

サンプルのインストールと実行

上記ファイルをREADMEに書かれている手順で適切な場所に保存することで、サンプルを試すことができます。

$ sudo mkdir /usr/share/unity/lenses/python
$ sudo cp python-lens.svg /usr/share/unity/lenses/python/
$ sudo cp python.lens /usr/share/unity/lenses/python/

すべてのLensファイルは、/usr/share/unity/lenses/"LensID"/というディレクトリに保存します。この"LensID"は、.lensファイル名として設定した"LensID"と一致しなければならないことに注意してください。

今回の場合、python.lensなのでLensIDは"python"になります。

次にLensを起動します。

$ ./unity-lens-python.py

Dashから適切なLensを開いたら、UnityはD-Busを使ってLensと通信を行い。ユーザーが入力したデータをLensに渡します。このため、LensはUnityが起動している間は常にバックエンドで動いている必要があります。

最後に、Unityを再起動します。

$ setsid unity

Unityの再起動は.lensが更新されたときのみ必要です。Lensデーモン側(つまりunity-lens-python.py)を変更した場合は、Lensを止めて再起動するだけで有効になりますので、Unityの再起動は必要ありません[4]⁠。

これにより、サンプルLensが使えるようになりました。Super+pキーを押して、サンプルLensを起動してみてください図1⁠。ちなみにこのショートカットは、.lensファイルの中で設定しています。

このサンプルはユーザーが入力した文字を大文字、小文字、数字に区分けして一文字ずつLensの中に表示します。また、Lensの中に表示されたアイコンを選択すると、各文字ごとのWikipediaのページがブラウザで表示されます。

図1 サンプルで「Ubuntu 11.10」と入力した例
図1 サンプルで「Ubuntu 11.10」と入力した例

新たにLensを作る

今度はサンプルをベースに新規にLensを作ってみましょう。

冒頭でも述べたように、Dashに入力した単語を使って、ニコニコ動画のタグ検索を行い、その結果のタイトル・サムネイル・概要を表示するLensを作ります。

なお、実際のコードを以下に公開していますので、興味のある方はご覧ください。

$ bzr branch lp:~cosmos-door/+junk/nicolens

LensIDを決める

まず最初に以下の3つを決める必要があります。

LensID
前述のとおり、.lensファイルのファイル名に使用します。すべてのLensにおいて一意である必要があります。
DBusName
D-Busデーモンがそのプロセスを特定するために使う名前です。値は任意ではありますが、システム全体に渡って一意である必要があります。"net.launchpad.Lens.LensID"にしておけば、かぶることはないでしょう。
DBusPath
Unityなど別プロセスのアプリケーションが、D-Bus経由でLensオブジェクトにアクセスするために必要なパス名です。これもDBusName同様、システム全体で一意なら任意な値でかまいません。

上記が決まったら、.lensファイルを修正します。今回はニコニコ動画のLensなので、nicolensというLensIDにしました。それにあわせてD-Bus変数も変更したので、nicolens.lensの中身は以下のようになります。

[Lens]
DBusName=net.launchpad.Lens.NicoLens
DBusPath=/net/launchpad/lens/nicolens
Name=NicoNico Video Lens
Icon=/usr/share/unity/lenses/nicolens/nicolens.svg
Description=NicoNico Video search lens
SearchHint=Search NicoNico video
Shortcut=n

[Desktop Entry]
X-Ubuntu-Gettext-Domain=unity-lens-nicolens

ショートカットもなんとなく"Super+n"に変更し、アイコンファイルはnicolens.svgにリネームしています。

Lens本体を修正する

.lensファイルの内容にあわせて、Lens本体であるunity-lens-python.pyも修正します。ファイル名はサンプルと同じでもいいのですが、統一性をもたせるために、unity-lens-nicolens.pyに変更しました。

unity-lens-nicolens.pyの中で、変数BUS_NAMEに、.lensファイルに指定したDBusNameを指定します。さらに、Lensインスタンス生成時にDBusPathとLensIDを指定します。

変更した箇所だけ抜粋すると以下のようになります。

BUS_NAME = "net.launchpad.Lens.NicoLens"
self._lens = Unity.Lens.new ("/net/launchpad/lens/nicolens", "nicolens")
self._scope = Unity.Scope.new ("/net/launchpad/lens/nicolens/scope")

最後はScopeのDBusPathです。今回はScopeを外部プロセス化しないのであまり関係ありません。

この時点で、サンプルと同様に動作するか試してみるといいでしょう。インストールと実行方法は前述の「サンプルのインストールと実行」と変わりありません。ただし、ファイル名とインストール先が/usr/share/unity/lenses/nicolensになることだけ注意してください。

これ以降はLensデーモンの修正だけなので、Unityの再起動は必要ありません。デーモンであるPythonスクリプトだけ変更する度に停止、再起動してください。結果が反映されないようであれば、Unityも再起動してみてください。

カテゴリーを設定する

サンプルを実行すると、文字の入力結果が"lowercase Letters"や"UPPERCASE letters"といった風にカテゴリーにわけて表示されます図1⁠。これを設定するのがLensデーモンにある、"Populate categories"の行です。

cats.append (Unity.Category.new ("lowercase Letters",
                                 Gio.ThemedIcon.new("keyboard"),
                                 Unity.CategoryRenderer.VERTICAL_TILE))

引数の一つ目がカテゴリータイトル、二つ目がカテゴリーアイコンパス、三つ目が検索結果のタイトルなどの表示方法です。

VERTICAL_TILEはアプリケーションLensのようにアイコンの下にタイトルがくるタイプです。今回はタイトルだけではなく概要も表示したかったため、アイコンの横にタイトルを表示するHORIZONTAL_TILEを使いました。また、カテゴリーを一つだけにしています。

cats.append (Unity.Category.new ("ニコニコ動画",
                                 Gio.ThemedIcon.new("browser"),
                                 Unity.CategoryRenderer.HORIZONTAL_TILE))

検索ルーチンを実装する

Dashの検索ボックスに入力されたら、notify::active-searchシグナルがLensデーモンに渡されます。今回はこのシグナルがきたら、_on_search_changed()メソッドを呼び、入力された単語と動画リスト取得した上で、Lensのインターフェースを更新するメソッド(_update_results_model())を呼んでいます。

def _on_search_changed (self, scope, param_spec):
    tag = self.get_search_string()
    results = scope.props.results_model

    if len(tag) > 0:
        print "Search changed to: '%s'" % tag
        search = self.search_tag(tag)
        self._update_results_model (search, results)
    self.search_finished()

search_tag()に実際に行われる検索ルーチンを実装しました。ニコニコ動画だとタグ検索なら以下のアドレスにアクセスすれば、RSS形式で取得できるので、そのパーサーをsearch_tag()に記述しています。

  • http://www.nicovideo.jp/tag/検索語?rss=2.0

また、"sort=v"で再生回数順などにソートしたものが得られるようなので、フィルター作成で使ってみるといいかもしれません。

検索結果をレイアウトする

検索結果をレイアウトするのは、_update_results_model()でやってます。

def _update_results_model (self, search, model):
    model.clear ()

    for item in search:
        model.append (item["link"],          # uri
                      item["thumbnail"],     # string formatted GIcon
                      0,                     # numeric category id
                      "text/html",           # mimetype
                      item["title"],         # display name
                      item["description"],   # comment
                      item["link"])          # DnD uri

一つ目の引数は選択時に起動するアプリケーションやファイルを指定します。今回は動画のURLです。二つ目はアイコンとして、サムネイル画像のURLを指定しました。五つ目と六つ目には、RSSから取得した動画タイトルと概要を入れています。

試してみる

ここまで設定が完了すれば、実際にニコニコ動画のタグ検索が可能です。LensデーモンをCtrl-Cで止めた上で、以下のように再起動しましょう。

$ ./unity-lens-nicolens.py

こちらで用意したnicolens.lensではショートカットをnに変更したので、Super+nを押してみてください。図2のような画像が出れば成功です。サムネイルをクリックするとブラウザが開き、動画のページが表示されます。

図2 もちろん日本語での検索も可能です
図2 もちろん日本語での検索も可能です

もし動かないようなら以下を確認してみてください。

Dashの下段にあるアイコン列に作成したLensが存在しない
D-Busのパスや名前が間違っているか、.lensファイルのインストール先がLensIDに一致していないと思われます。
Lensに検索単語を入力しても検索結果が現れない
デーモンが動いていないか、検索中に何らかの理由でエラーになった可能性があります。

Lensデーモンを自動起動する

これまではLensデーモンを手動で起動していました。しかし、Unityを起動する度に(ログインする度に)手動で起動するのは面倒です。そこでD-Busデーモンが起動するたびに自動で起動するようにしてしまいましょう。

まずはunity-lens-nicolens.serviceという名前で、D-Busサービスファイルを作成します。

[D-BUS Service]
Name=net.launchpad.Lens.NicoLens
Exec=/usr/local/lib/unity-lens-nicolens/unity-lens-nicolens.py

ここでNameは.lensファイルのDBusNameと一致させるようにしてください。LensデーモンはExecにあるような場所に保存することにしました。

このファイルを、D-Busサービスディレクトリに保存します。

$ sudo cp unity-lens-nicolens.service /usr/share/dbus-1/services/unity-lens-nicolens.service

これで次回起動時から、自動的にLensデーモンが起動します。

まとめ

このように、サンプルコードをちょっと修正するだけで、Dashを自分にとって必要なWebサービスに対応した検索ツールに修正することができます。

今回は触れませんでしたが、フィルターやScopeといった機能を使うことでさらに柔軟に絞り込みやカテゴリ分けを行うこともできます。

これを機に、Lensの作成に着手してみてはいかがでしょうか?

ちなみに、Ubuntu TVでも活躍しているMichael Hallは、さらに簡単にLensを作るためのテンプレートシステムであるSingletを開発しています。残念ながら最新のコードはPrecise/Unity 5.0でしか動作しないようです。

しかしながら、初心者向けアプリケーション開発システムであるQuicklyに統合する計画もあるので、12.04のリリース付近では、もっとお手軽にLensを作成しPyPIやPPAで公開できる仕組みが整っているかもしれません。

おすすめ記事

記事・ニュース一覧