Banshee
2006年03月21日
再生中のアイコンが二つ出てしまう問題
再生リストに同じ曲を二つ入れると再生中の曲に付くアイコンが二つ出てしまう、というバグを調査し、パッチを提出した。
再生中のアイコンを描くPlaylistView.TrackCellInd()に問題があった。再生リストはGtk.TreeViewから派生させたPlaylistViewとGtk.ListStoreから派生させたPlaylistModelによって作られている。TreeIter型の変数playingIterに再生中の曲がセットされる。しかしPlaylistView.TrackCellIndではplayingIterではなく曲情報を比較していた。問題のケースでは同じ曲情報を持つノードが二つあるので、二つアイコンが出てしまっていた。
最初は再生リストに曲を追加する処理に問題があるんじゃないかと思ったので、本当の原因にたどり着くのに時間がかかってしまった。しかし久々にBansheeのコードをあちこち見ることにもなった。以前クラス図を書いた時とはかなり違っている。クラス図を書き直さなければ。
2006年02月16日
ビットレートの計算がおかしい問題、パッチ再提出
前回のパッチでは、ファイルサイズを1000で割っているところとビットレート(キロビット単位)を1000で割っているところを両方とも直した。しかし間違っているのは前者だけだったようだ。以前のエントリに対して指摘をいただいた。
ビットレートを計算する際にSecondsとTotalSecondsをとりちがえている部分はOggに関してのみ既に修正されている。しかしトラック情報のダイアログに表示するときの計算が間違っているのでバグ自体は直っていない。どうも、やっつけでコードを書いていてロクにテストしていないんじゃないか、という印象がある。
2006年02月12日
一時停止中は再生位置のスライダを動かせないバグ
再生位置のスライダは音楽の再生とともに少しずつ動いていくものだが、ユーザーが動かすこともできる。マウスでドラッグすると新しい位置から再生が始まる。つまり、スライダは音楽の再生状況によって更新されると同時にユーザーの操作によっても更新される。
GstreamerやHelixなどの再生エンジンは一時停止中であっても再生状況のデータを送り続けている。マウスでスライダを動かしている最中はupdateEnginePositionというフラグがfalseになっており、再生エンジンからの情報によってスライダが動くことはないのだが、マウスを離すとフラグがtrueになってしまうので、その瞬間に再生エンジンからの情報によってスライダが動いてしまい、ユーザーの操作が無効になってしまう。
私のパッチでは、一時停止中なら再生エンジンからの情報は無視するようにした。一時停止中は再生エンジンは一切情報を送らないようにするのが正しい修正かもしれないが、どこを修正すればいいのか分からなかった。
2006年01月14日
Bansheeバグ覚え書き
Bansheeのバグをいくつか追いかけてみた。以下は覚え書き。
- Bug 324353: トラック情報のダイアログに表示されるビットレートが正しくない
ビットレートは普通は160KBあたりなのだが、ヒトケタの数字になってしまっている、という問題。パッチを書いてみた。ビットレートを計算する際にTimeSpanクラスのSecondsプロパティを参照しているが、このプロパティはトータルの秒数を保持するものではない。TotalSecondsプロパティを見るのが正しい。それと、ビットレートをキロビット単位に変換する際に1000で割っている、という問題もあった。
- Bug 325725: メニューがローカライズされない
メニューバーやメニュー項目のラベルのほとんどが英語のままになってしまう。日本語ファイルの問題だ、といったん閉じられたのだが、明らかにおかしいのであれこれ試してみた。起動時にGUIを生成する際の順番が間違っているような感じ。Bansheeはメニュー項目をグローバル変数で保持していて、それをGUIの生成前に初期化している。しかしGUIを生成してからでないとローカライズされたラベルを正しく読み込めないようだ。
- Bug 325428: MP3ファイルのアーティスト名や曲名が文字化けすることがある
MP3のID3v1型のタグには文字コードの情報は入っていない。アーティスト名や曲名は基本的にはUTF-8で入っているのだが、Shift-JISで入っていることもある。Shift-JISの場合は文字化けする。
amaroKでは、ID3v1のタグはShift-JISとして読み込む、というように設定できる。しかしこの方法は明らかに不十分だ。そうするとUTF-8で書かれているデータが全部文字化けしてしまう。日本語、韓国語、中国語、ロシア語などが混在しているケースにも対応できない。設定するなら曲ごとでなければならない。
BansheeはSQLiteで各ファイルの情報を保持していて、アーティスト名や曲名をMP3ファイルから独立に編集して保存できる。文字化けが起こったらそこだけ直せば問題ない。ただ、指定したフォルダをライブラリにインポートする際、文字コードを後から一つ一つ直すのは大変かもしれない。インポートの際に文字コードを指定できるようにするべきか。さらにMP3ファイル自体を書き換えて全データをUTF8にしてしまえば完璧。
- Bug 326291: 現在の再生位置を示す数字がおかしい
GStreamerを再生エンジンとして使っている場合、現在の再生位置(再生した時間)が正しく表示されない。GStreamerが提供しているgst_element_query()というAPIが常に同じ値を返してしまう。
Banshee 0.10.2のリリースビルドをrootで動かすと正しく動作する。同じビルドを私のアカウントで動かすとダメ。最新のソースコードをビルドするとrootでもダメ。なにかの設定が影響していると思うのだが、まだわからない。
ほかにインストールされていないBansheeを起動できない、アクセラレータが効かない、という問題も発見。前者は簡単な問題なのでパッチを出した。後者は機能自体が完全に脱落しているようだ。
2006年01月07日
Bansheeは新しもの好き
Bansheeの開発についていくのは大変だ。
CVSから取ってきたソースをビルドし、起動しようとしたら、SQL文のシンタックスエラーで異常終了してしまった。調べてみると問題のSQL文は"ALTER TABLE Tracks ADD RemoteLookupStatus INTEGER"。テーブルにカラムを追加するSQL文だ。SQLiteはこれを理解できないらしかった。バグ報告したら、SQLiteのバージョンが古い、3.2以上にしてくれ、と言われた。
yum updateでは最新は3.1.2。やむをえないのでFedora Coreのdevelopmentパッケージ(3.2.7)を拾ってきた。
あらためてBansheeをビルドしてみると、今度は「daap-sharpがない」というエラーが。どうやらMonoのパッケージらしい。tarballをダウンロードしてconfigureスクリプトを走らせると「avahi-sharpがない」。AVAHIの公式サイトからtarballを取ってきてconfigureスクリプトを走らせると「QtCoreがない」。BansheeはGTKしか使ってないのになんでQTを入れなきゃいけないんだ?と思ってさきほどのFedora Coreのdevelopmentディレクトリを見てみたらAVAHIのパッケージがあった。ところが、ビルドは成功したのだがインストールしようとするとnrpms.netのhowl-libsと依存関係が衝突してしまう。
このへんで私はもうイヤになってきた。nrpms.netはBansheeのパッケージも提供しているから、そのうちBansheeのビルドに必要なパッケージを全部用意してくれることだろう。とりあえずバグ報告。
2005年12月16日
Banshee概観
Bansheeのソースコードはとても読みやすい。複雑怪奇なMozillaとは大違い(笑)。おおざっぱなクラス図を書いてみた。
Bansheeのクラスは大きく四つに分けることができる。
- 音楽CDやiPodとのI/O
- 楽曲ライブラリ
- 楽曲再生エンジン
- ユーザーインターフェース
クラス図にあるAudioCdCore, HalCoreは音楽CDの挿入やイジェクトを管理。楽曲ライブラリ(Library)はSQLiteを使って楽曲情報を管理している。楽曲再生エンジン(IPlayerEngine)は設定によってGStreamer, HelixPlayer, VLCのいずれかを使う。GUI部分(PlayerUI)はGTKで作られている。iPodとのI/Oは調べていないのでよくわからない(iPodを持っていないので興味ナシ)。
主な動作は以下のような感じ。
- 音楽CDが挿入されるとHalCore - AudioCdCore - PlayerUIとコールバック関数が実行され、GUI上にCDの情報が出てくる。
- GUIで再生ボタンを押すと、指定されている再生エンジン(IPlayerEngine)を使って楽曲が再生される。
- トラック情報を編集し(TrackProperties)、保存ボタンを押すと、トランザクションクラス(TrackInfoSaveTransaction)のインスタンスが作成され、保存処理が実行される。トラック情報はSQLiteを使って管理されている。
クラスの構成にはあまり綺麗とは言えない部分もある。例えば楽曲の再生時。CoreクラスにIPlayerEngineクラスのインスタンスがpublic変数として定義されていて(activePlayer)、再生/一時停止ボタンが押されたときはこのactivePlayerのメンバ関数が直接呼ばれている。CoreクラスとPlayerUIクラスが互いに依存しあっている、私が毛嫌いしているパターンだ。Coreクラスがグローバル変数の集合体のようになってしまっている。クラス図には書かなかったが、BansheeCoreというクラスがPlayerUIとCoreを持ち、CoreもまたPlayerUIを持っているのも理解しにくい。
ともあれ、もう少し追いかけてみようかと思う。

