前回に続いてPhoto Gallery Publishing Plug-in Platformについてです。サンプルとしてLiveフォト ギャラリーなどで使える はてなフォトライフへ写真をアップロードするプラグインを作ります。今回は実際にプラグインのコードの記述しアップロードができるところまで作成します。
プラグインの処理
コードを書く前に、プラグインが行う処理を確認しておきましょう。Liveアプリケーション上でひとつ以上の動画像を選択した状態で、アップロードメニュー[1]からアップロード先を選択すると、対象のプラグインの処理が実行されます。アップロード先の選択からアップロード完了までに、Liveアプリケーションとプラグインとの間では複数回のやり取りをしています。あるアップロードに対して行われるこの一連のやり取りを、本記事中ではセッションと記載しています。
1. 設定ウィンドウの表示
プラグインは最初に設定ウィンドウを表示します。ウィンドウ表示は必須ではありませんが、通常はアップロードするサービスへの認証処理やアップロード確認などのために利用します。Flickrへのアップロードの場合は図1のようなウィンドウが用意されています。
この段階でのプラグインが、Liveアプリケーションとのやり取りによって可能な処理は以下の通りです。
- プラグイン固有の設定の参照・保存
- アップロード対象の動画像情報の参照
- セッションに必要な情報の保存
「セッションに必要な情報の保存」とは、プラグイン自身がこの後の処理に必要とする情報を保存しておくという意味です。「アップロード対象の動画像情報の参照」と「セッションに必要な情報の保存」はどちらもセッション情報の参照・編集として考えることができます。
必要な処理を終えた後、セッションの続行または中断をLiveアプリケーションに通知し次のステップへ進み(または終了し)ます。
2. 動画像のアップロード
続いて、ユーザーが選択した動画像のアップロード処理を行います。アップロード中には、図2のように進行を示すウィンドウが表示されます。このウィンドウはLiveアプリケーションが用意したものです。
この段階でのプラグインは、Liveアプリケーションとのやり取りにより以下の処理が可能です。
- アップロード対象の動画像情報の参照
- セッションに必要な情報の参照・編集・保存
- 動画像のストリームの参照
- 進行状況の通知
- ユーザーによるアップロードのキャンセル通知の受信
- ウィンドウの表示
上のふたつは設定ウィンドウ表示のときと同じくセッション情報の参照と編集です。
この処理は、アップロード対象の動画像の個数分だけ繰り返することになります。セッション内の動画像ごとにアップロードの成功・失敗をLiveアプリケーションに通知し、すべて完了すると次のステップに進みます。
3. 結果ウィンドウの表示
図3のようなアップロードの結果を示すウィンドウが最後に表示されて一連の処理は終了です。
表示されるウィンドウはLiveアプリケーションが用意したものですが、ウィンドウ中の「表示」ボタンと「詳細情報」リンクはプラグインの設定により表示・非表示が決まります。
ここでのやり取りにより可能な処理は以下の通りです。
- アップロード対象の動画像情報の参照
- セッションに必要な情報の参照
- 表示ボタン・詳細情報リンクの表示とクリック時の処理
表示ボタンと詳細情報リンクは以下の違いがあります。
- 詳細情報リンク
Liveアプリケーションを親ウィンドウとしてプラグインが用意したウィンドウを表示することができます。結果ウィンドウだけでは何枚中何枚がアップロードに成功したことのみしかユーザーはわかりません。これを補うために使用することができます。
- 表示ボタン
表示ボタンをクリックすると結果ウィンドウは閉じられます。アップロード先のサービスのWebページへ移動するために使用することが想定されています。
プロジェクトの作成
それではプラグインを作成していきましょう。プラグインは.NET Frameworkのクラスライブラリとして作成します。本連載では Visual Studio 2008とVisual Basicを使用しています。
プロジェクトの新規作成
まずはWindowsのクラスライブラリのプロジェクトを新規に作成します(図4)。
参照の追加
続いて必要な参照をふたつ追加します。ソリューションプロパティからプロジェクトを右クリックして表示されるメニューから追加が可能です。
参照の追加ウィンドウの参照タブを選択し、Live フォト ギャラリーがインストールされている場所[2]から「Microsoft.WindowsLive.PublishPlugins」を追加します(図5)。
この中にプラグインが実装すべきInterfaceの情報があります。
.NETタブから「System.Windows.Forms」も追加します。
Interfaceの実装
IPublishPluginというInterfaceを通してプラグインとLiveアプリケーションはやり取りを行います。プラグインはこのInterfaceを実装する必要があります。プロジェクトにあるクラスファイルを適当な名前に変更しInterfaceを実装しましょう。コードは次のようになります。
本記事ではクラス名を「HatenaFotolifePlugin」としています。クラスに「Implements IPublishPlugin」を入力すると、Visual Studioが上記のメソッドを自動で挿入します。これらのメソッドの処理を記述していくとプラグインの完成です。
プラグインの登録
まだ何もメソッドの処理を記述していませんが、Liveアプリケーションがプラグインを認識するための条件は既に満たしています。デバッグにも必要になるので、この時点でビルドしたアセンブリ(DLLファイル)をLiveアプリケーションが参照できるように登録してみましょう。
プラグインの登録はレジストリを編集する必要があります。ここでは直接レジストリエディタ[3]を使用して以下のキーと値を追加してください(図6)。
値(いずれも文字列値)
名前 |
値 |
AssemblyPath |
DLLファイルへの絶対パス(ファイル名を含む) |
ClassName |
名前空間を含めたプラグインのクラス名 |
FriendlyName |
Liveアプリケーションのメニューに表示される名前 |
追加した後、Live フォト ギャラリーを起動するとアップロードメニューに追加した項目が表示されていると思います。
デバッグに関してですが、Visual Stuidoからデバッグを行う場合はプロジェクトのプロパティのデバッグタブにある開始動作から「外部プログラムの開始」を選択し、Live フォト ギャラリー(WLXPhotoGallery.exe)を選択します。そうするとデバッグ実行時にLive フォト ギャラリーが起動し、ブレークポイントの使用や変数の参照などが可能です。
はてなフォトライフAPIの利用
はてなフォトライフに写真をアップロードするコードは前回の記事中に書いています。前回のコードに少し変更を加えてプラグインクラスに追加します。
前回作成したメソッドは次の3個でした。
- CreateWsseHeaderValue
- GetPostUri
- PostPhoto
そして、XMLを使用するためにImportsステートメントで次のように名前空間を指定していました。
プラグインでもXMLを扱うためデフォルトの名前空間を次のように変更します。
この変更に併せてGetPostUriメソッドの以下の部分を変更します。
PostPhotoメソッドは少し引数が多くなりますが、写真の名前とContent Type(image/jpegnなど)のStringおよびSystem.IO.Streamを引数に加えます。そして、引数の値を使用するようにコードを変更します。写真のバイトデータは引数のStreamから取得し、サーバーへ渡す<entry>要素も以下のコードのように記述します。メソッドの全文を示します。
作成するプラグインではアップロード先のフォルダを指定しませんので、<dc:subject>要素は前回のコードから削除しています。
CreateWsseHeaderValueメソッドは変更せずに使用します。
設定ウィンドウの表示
それではInterfaceのメソッドを実装していきましょう。まず、設定ウィンドウの表示処理を実装します。設定ウィンドウの表示等を行うメソッドはShowConfigurationSettingsです。
今回作成するプラグインでは最低限必要なものとしてユーザー名とパスワードをユーザーが入力するウィンドウを作成します。ユーザー名は一度入力されたものはプラグイン固有の設定として保存しておき、次回のアップロード時に入力が省けるよう設計します。パスワードは保存せずに毎回入力するものとします。
ShowConfigurationSettingsメソッド内部で次の処理を順に行います。
- プラグイン設定から以前入力したユーザー名情報を取得
- 設定ウィンドウの表示(ユーザー名とパスワードの入力)
- 入力された情報から、はてなフォトライフPostURIの取得
- ユーザー名をプラグイン設定として保存
- PostURI・ユーザー名・パスワードをセッション情報として保存
ウィンドウの作成
プロジェクトにユーザー名等を入力するためのWindowsフォームを追加します。作成するウィンドウを図7に示します。図7を参考にコントロールを配置してください。オレンジ色の文字は記事中で使用しているコントロール名です。
Windows フォーム内のコードを以下に示します。
ポイントは、ユーザー名をコンストラクタ引数で受け取る部分と、入力した値はプロパティとして参照できるようにしている部分です。
メソッドの引数と戻り値
ShowConfigurationSettingsメソッドには以下の引数があります。
引数名 |
説明 |
parentWindow |
Liveアプリケーションのウィンドウハンドル。設定ウィンドウを表示する際に親ウィンドウと指定するために使用します。 |
sessionXml |
アップロード対象の動画像情報のXML文書。プラグインが使用する一時的な情報はこのXML文書を書き換えて保持します。 |
persistXml |
プラグイン固有の設定保存用のXML文書。プラグインは自由に形式を決定し使用できます。 |
publishProperties |
動画像の関連データへアクセスするためのIPublishPropertiesというInterfaceのオブジェクト。 |
引数にあるようにLiveアプリケーションとプラグインと情報のやり取りにXML文書(XmlDocumentオブジェクト)が利用されています。加えてIPublishProperties Interfaceによりメタデータへアクセスが可能です。sessionXmlとpersistXmlについては後述しています。publishPropertiesは今回使用していません。
メソッドの戻り値はBoolean型です。処理を続ける場合にはTrueを、中断する場合はFalseを返します。
メソッドの実装
ShowConfigurationSettingsメソッドに処理を追記します。
引数のpersistXmlについてですが、これを使用してプラグインの設定を保存します。ここではユーザー名を保存するため次の書式で使用することにします。
初めてプラグインが実行されたとき、persistXmlは何も記述されていないXML文書になっています。
PostURIを取得するところまで書いてみましょう。コードは次のように書くことができます。
次は、この後の処理で使用するために取得したPostURI・ユーザー名・パスワードをsessionXmlへ追記します。次の書式になるよう要素を追加します。
コードは次のようになります。コードの最後では、persistXmlへユーザー名を、sessionXmlへセッション情報を反映させています。
上記のコードでは引数のXmlDocumentオブジェクトからXDocumentオブジェクトへ変換してVisual BasicのXMLリテラルを使用してXMLの操作をしています。編集内容を反映させるため最後にXmlDocumentオブジェクトへ戻しています。
Session XMLとPersist XML
既に設定ウィンドウ表示処理に出てきたようにLiveアプリケーションとプラグインとのやり取りにはXLM文書(XmlDocumentオブジェクト)が利用されています。ここでは各メソッドの引数にあるpersistXmlとsessionXmlについて説明します。
Session XML
Session XMLはユーザーが選択した動画像の情報を参照するためと、アップロード処理にプラグインが必要な情報を一時的に保持するために使用します。プラグインが使用する情報の保持はSession XMLを使用せず、プラグインクラスのプロパティやPrivate変数として値を保持したほうがスマートのように思えますが、Photo Gallery Publishing Plug-in Platformによる投稿プラグインではプラグインのメソッド呼び出し時に同じインスタンスが使用されるとは限りません。そのため、必要な情報は一度Session XMLを通してLiveアプリケーションに渡し、再度Liveアプリケーションから受け取る必要があります。
Session XMLの例を以下に示します。
<ItemSet>要素内に選択された動画像の数だけ<Item>要素があり、各動画像の情報が記載されていることがわかります。動画と画像の判別は<Item>要素内にある<PerceivedType>要素の値(imageまたはvideo)により可能です。また、<Item>要素内には<Keyword>要素と<PersonRegion>要素があり、Live フォト ギャラリーでユーザーが付けたタグおよび人物タグの情報の取得も可能となっています。
プラグインが使用するセッション中の情報は、ユーザーや動画像に関するパラメータは<PublishParameters>要素以下に要素を追加し、成功・失敗などのログはXML文書の最後に要素を追加して利用することが想定されているようです。
Persist XML
Persist XMLはプラグイン固有の設定を保存するために使用します。XML文書の内容はプラグインが自由に決定でき、ShowConfigurationSettingsメソッド呼び出し時にLiveアプリケーションから渡されます。変更した内容の保存は、ShowConfigurationSettingsメソッドの戻り値をTrueとしたときのみLiveアプリケーションにより行われます。
Persist XMLはプラグインの全般的な設定を保存するために用意されているもので、ユーザーパスワードなど重要な情報の保存に使用してはいけません。本記事で作成するプラグインではユーザー名の保存に使用しています。
動画像のアップロード
アップロード処理を行うメソッドはPublishItemです。ユーザーが選択した動画像の個数の回数だけメソッドが呼ばれます。作成するプラグインでは、1回の呼び出しに対して以下の処理を行います。
- Session XMLから画像の情報を取得(画像形式、ファイル名、タイトルなど)
- 同様に PostURI・ユーザー名・パスワードを取得
- はてなフォトライフへ画像をアップロード
メソッドの引数と戻り値
PublishItemメソッドには以下の引数があります。
引数名 |
説明 |
parentWindow |
Liveアプリケーションのウィンドウハンドル。各アップロード処理に何かしらのウィンドウ表示が可能です。 |
mediaObjectId |
Liveアプリケーションが付けた動画像のID。Session XMLの<Item>要素id属性と一致しています。 |
stream |
アップロードする動画像のバイナリストリーム。 |
sessionXml |
ShowConfigurationSettingsメソッド内で編集されたSession XML。 |
publishProperties |
IPublishPropertiesオブジェクト。 |
callback |
進行状況の通知およびユーザーによるキャンセル検出のためのIPublishProgressCallbackというInterfaceのオブジェクト。 |
cancelEvent |
ユーザーによるキャンセル検出するためのEventWaitHandleオブジェクト。 |
publishProperties、callback、cancelEventは今回使用しません。
戻り値はShowConfigurationSettingsメソッドと同じくBoolean型です。アップロードが成功した場合はTrueを返し、失敗した場合はFalseを返すようにします。Falseを返した場合もセッションのキャンセルにはならず、さらに動画像がある場合は続けてPublishItemメソッドが呼び出されます。
メソッドの実装
まず、引数のsessionXmlとmediaObjectIdから対象となる動画像の情報を参照します。sessionXmlの<Item>要素のid属性の値がmediaObjectIdと一致している要素がアップロードの対象です。ここでは<Item>要素の情報を使用して以下の処理を行います。
- 動画・画像の判別
- 拡張子からContent Type文字列の作成
- タイトルまたはファイル名から写真名の決定
動画が選択されていた場合は処理を終了し、Content Type文字列は拡張子をみて決定することにします。また、アップロードする写真の名前はLive フォト ギャラリー上でタイトルが付けられていた場合それを利用し、ない場合はファイル名とします。
以上のコードは次のように書くことができます。
画像自体のデータはStreamで渡されていますので、Session XMLからPostURI・ユーザー名・パスワードを取得して、それらを作成済みの
はてなフォトライフへアップロードするメソッドに渡せば処理は完了です。続きのコードは以下のようになります。
結果ウィンドウの表示
最後に結果ウィンドウの表示です。結果ウィンドウ自体はLiveアプリケーションが表示しますので、表示ボタンと詳細情報リンクの実装となります。今回は、表示ボタンのみ有効にし、クリックすると はてなフォトライフのWebページへ移動するようにします。
表示ボタンと詳細情報リンクの有効化はHasPublishResultsメソッドとHasSummaryInformationメソッドの戻り値の設定により行います。どちらのメソッドも戻り値がBoolean型で、Trueの場合対象のボタンまたはリンクが有効になります。
表示ボタンクリック時の動作はLaunchPublishResultsメソッドに記述します。引数はSession XMLです。
詳細情報リンククリック時の動作はShowSummaryInformationメソッドに記述します。ウィンドウの表示が想定されているため引数には、Session XMLに加えIWin32Windowオブジェクトがあります。HasSummaryInformationメソッドでFalseを返すと、このメソッドが呼ばれることはありません。
プラグインの実行
以上でLive フォト ギャラリーからはてなフォトライフへ写真のアップロードが可能になりました。実際に動かしてみましょう(図8)。うまく動いたでしょうか?
もしセッション中に例外がスローされた場合はLiveアプリケーション側で吸収され詳細はわかりません。処理を細かく切り分けて失敗している原因を探すとよいでしょう。
次回もPhoto Gallery Publishing Plug-in Platformを利用したプラグイン作成の予定です。