元ぷろぐらまあの日々

メディアライブラリI/Fの実装(コンポーネントプログラミング)

現在、私の自作コンポーネントではSQLite3のデータベースにレートや最後に再生した日時などを記録し、表示している。

当然、新規に追加した音楽ファイル用のデータは登録しなければ行けないし、変更・削除への追従も行う必要がある。その部分はコンポーネント自力でやってはおらず、Rubyスクリプトを使って行ってきた。Storeの利用もあるため、インポートはfoobar2000ではなくiTunesを使っており、全ての音楽ファイルはiTunesに登録されているため、RubyからiTunesにCOM接続してレコードを作成・更新してきた。

予定は無いが、foobar2000を使うのをやめて、iTunesに戻ることが万が一出てきた時に、コンポーネントのデータをiTunesに反映できるようなキー項目も設けている。

本題であるが、そのRubyスクリプトで現在行っている処理を、コンポーネントが自力で行うために使うのが、library_callbackクラス(の派生クラス)の実装と登録である。

このクラスには純粋仮想関数として、on_items_addes(), on_items_modified(), on_items_removed()の3つが宣言されているので、それぞれ実装すればいいことになる。英単語のまま、それぞれが、項目の新規追加、項目の変更、項目の削除に対応している。

パラメータはmetadb_handle_ptrクラスオブジェクトのlistで渡されるので、ファイルパスやID3タグなどへのアクセスは容易にできる。

私はiTunesのCOMを利用するので、COMプログラミングやiTunesオブジェクトの使用方法に手間取ったが、ファイルパスやタグからデータを作成することは比較的単純にできる。

が、一部よくわからない動きや注意すべき点が出てきたので書いておく。

最初はlibrary_callbackクラスの派生クラスとして自作のメディアライブラリ処理クラスを書いた。動きは問題が無かった。登録や変更、削除も問題なく動作していた。しかし、この実装ではfoobar2000を終了させた時に、全メディアファイルに対して削除のイベントが発生するのだ。私の実装では削除イベントではiTunesから本当に削除されたかをCOMで処理していたのと、音楽ファイルが22,000曲を超えいているため、この終了処理に2時間かかった。タスクマネージャでfoobar2000のプロセスが落ちるまで他のことをしながら眺めていたので気がついた。音楽ファイルが少ない開発環境では問題が顕在化しなかった。

デバッグ用にログファイルに発生したイベントと対象ファイル名を出力するようにして動作させたところその動きがつかめた。

解決策は、基底クラスをlibrary_callback_imple_baseクラスに変更することである。実装しなければならない内容は全く変わらないし、このクラスがlibrary_callbackの派生クラスになっているため、自作のクラス宣言で基底クラスを変更するだけでコンパイルは通る。この変更で、終了時の全ファイルに対する削除イベントの発生はなくなった。

もう一つ注意する点が、表示の更新である。表示用のデータが変更された時には、

static_api_ptr_t()->dispatch_refresh(metadb_ptr);

の呼び出しを行って最新のデータで表示を更新することができる。playback_callbackやiPodインタフェース(foo_dop SDK)使用時にはこれでデータベース更新後に表示を更新できるのを確認している。

しかし、この呼び出しをメディアライブラリの、on_items_added()とon_items_modified()で呼び出してしまうと、呼び出した対象に対して、on_items_modified()が呼び出されてしまうことがわかった。無限ループになってしまうのである。その他の処理でこの表示の更新を行ってもon_items_modified()は呼び出されているようであるが、再起にはならないので無限ループにはならない。

ただし、表示を更新しただけでファイルが更新されたときと同じ処理をすると無駄になるため、私はファイルのタイムスタンプを使って、ファイルの更新日時が更新された時だけ、実際のメディアライブラリの更新処理を行うようにしている。

まだ、SDKのこの部分はトライ&エラーで作っている途中で、デバッグ中であること、英語フォーラムでもそれほど質問がヒットしない分野でもあるので、正解が出せずに困っている。

実働環境のメディアライブラリのファイル数が多い場合、開発・テスト環境で同じ規模のライブラリを用意していないと問題が問題として出てこないパターンもあり、なかなか難しい。100ファイル程度を対象にした開発環境で動作していても、10000ファイルを超える本番環境では処理速度の低下が問題になるという部分でもあり、開発環境の用意が非常に難しい部分であると実感している。

モバイルバージョンを終了