htsign's blog

ノンジャンルで書くつもりだけど技術系が多いんじゃないかと思います

MusicBeeのプラグイン開発

最近、MusicBeeというWindows向けのオーディオプレイヤーのプラグイン開発ばかりやってます。
本体がVer2.0辺りから.NET化したのもあって、プラグインも.NET(C#VB.NETC++/CLI)で非常に手軽に開発することができます。
コントロールはWinFormsです。
ビルドしたプラグインは主に2chのMusicBeeスレで公開していますが、
開発していくにあたっていろいろとノウハウも貯まってきたので、ここいらでいくつかご紹介します。
公式Wikiに書かれている内容もありますが、一応。

以下出てくるmbApiInterfaceという謎の変数ですが、
これはMusicBeeのAPIにアクセスするためのインターフェースのインスタンスです。
公式Wikiで配布されているプラグインソースコードをDLすると初めから宣言されています。

メインパネルで表示されている曲をすべて取得

public IEnumerable<string> GetDisplayedSongs()
{
    return GetSongs("domain=DisplayedFiles");
}

public IEnumerable<string> GetSongs(string query)
{
    if (mbApiInterface.Library_QueryFiles(query))
    {
        while (true)
        {
            string filepath = mbApiInterface.Library_QueryGetNextFile();
            if (string.IsNullOrEmpty(filepath)) yield break;
            yield return filepath;
        }
    }
}

ちなみに、ライブラリに存在する曲を丸ごとすべて、という場合には

public IEnumerable<string> GetAllSongs()
{
    return GetSongs("domain=Library");
}

とすることで可能です。

設定画面のコントロール作成をべた書きしなければいけない問題

MusicBeePlugin.PluginクラスのConfigureメソッドは、
内部変数aboutConfigurationPanelHeightプロパティに0以外を代入することによって、設定画面のPanelコントロールのハンドルをIntPtr構造体で受け取ります。
サンプルソースコードではこれに直接コーディングでコントロールを生やしていますが、
これをユーザーコントロールとして一まとめに作成したものを追加することで見通しがよくなります。
MusicBeeの設定画面で「保存」を押して閉じたときにMusicBeePlugin.PluginクラスのSaveSettingsメソッドが走るのですが、ここで編集した内容を反映させるため、私は設定を一まとめにプロパティで持ったConfigクラスを作り、そのインスタンスを作成したユーザーコントロールに参照渡ししています。

public bool Configure(IntPtr panelHandle)
{
    if (panelHandle != IntPtr.Zero)
    {
        Panel configPanel = (Panel)Control.FromHandle(panelHandle);
        var childUserControl = new MyUserControl(ref this.config);
        configPanel.Controls.Add(childUserControl);
    }
    return false;
}
追記(02/13 0:27)

Configクラスのインスタンスを参照渡しするより、シングルトンパターン使った方がスッキリしますね。

public class Config
{
    private Config() { }
    
    private static Config instance = new Config();
    public  static Config Instance { get { return Config.instance; } }
}

ファイルへのタグ書き込みが上手くいかない問題の解決

公式のフォーラムをよく読むと分かるのですが、MusicBeePlugin.Plugin.MusicBeeApiInterfaceクラスの中身を読んでいるだけでは気づけないんじゃないかと思います。

public void WriteTag(string filepath, MetaDataType type, string value)
{
    mbApiInterface.Library_SetFileTag(filepath, type, value);
    mbApiInterface.Library_CommitTagsToFile(filepath); // ここ大事
}

実はLibrary_SetFileTagメソッドはただバッファリングしているだけで、このメソッドを走らせているだけでは何重に実行しようとも実際に反映されることはありません。
反映させるためにはLibrary_CommitTagsToFileメソッドを走らせる必要があります。
ここで割とハマりました。


こんなところですか。
本当はもっとある気がするんだけど、すぐには浮かんでこないのと、文章にとりとめがなくなりすぎてて意味不明になってしまうので。

蛇足

デザイナで編集してると気づかないうちに余計なプロパティまで変更してること、ありますよね。