MusicBeeのプラグイン開発
最近、MusicBeeというWindows向けのオーディオプレイヤーのプラグイン開発ばかりやってます。
本体がVer2.0辺りから.NET化したのもあって、プラグインも.NET(C#、VB.NET、C++/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
メソッドは、
内部変数about
のConfigurationPanelHeight
プロパティに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
メソッドを走らせる必要があります。
ここで割とハマりました。
こんなところですか。
本当はもっとある気がするんだけど、すぐには浮かんでこないのと、文章にとりとめがなくなりすぎてて意味不明になってしまうので。
蛇足
デザイナで編集してると気づかないうちに余計なプロパティまで変更してること、ありますよね。
DataGridViewのReadOnlyプロパティがいつの間にかtrueになっていたことに気づかず、新規行追加できねぇ!なんでだ!!って2日くらいハマってた。
— ところてん (@htsign) February 10, 2015
.NET Framework における System.String について
今年に入って初めて .NET Framework にまともに触れるようになってきたのでまだまだ勉強中です。
趣味で触るのはC#、仕事で触るのはVB.NETって感じです。
さて、だいたいどの解説サイトを見ても「C#もVB.NETもできることは同じ」というような解釈になってます。
ただ、System.String
が言語によって扱いが異なる気がしています。
あるとき、VB.NETでNullable(Of String)
と書いたときに静的エラーが出力されました。
妙だと思い調べてみると、System.String
は参照型であるというのです。
基本的な型のうち int, double, byte, char などは値型ですが、
string は「値型のように振る舞う参照型」であるというような記述を見ました。
参照型であるということは null を代入できるのか。
と思い、以下のコードを書きました。
C#
public class Program { public static void Main(string[] args) { string string1 = null; string string2 = ""; string string3 = string.Empty; Console.WriteLine("1:{0}", string1 ?? "string1 is null"); Console.WriteLine("2:{0}", string2 ?? "string2 is null"); Console.WriteLine("3:{0}", string3 ?? "string3 is null"); Console.WriteLine(string1 == string2); // null == "" Console.WriteLine(string2 == string3); // "" == string.Empty Console.WriteLine(string3 == string1); // string.Empty == null } }
VB.NET
Public Module Program Public Sub Main(args() As string) Dim string1 As String = Nothing Dim string2 As String = "" Dim string3 As String = String.Empty Console.WriteLine("1:{0}", If(string1, "string1 is Nothing")) Console.WriteLine("2:{0}", If(string2, "string2 is Nothing")) Console.WriteLine("3:{0}", If(string3, "string3 is Nothing")) Console.WriteLine(string1 = string2) ' Nothing = "" Console.WriteLine(string2 = string3) ' "" = String.Empty Console.WriteLine(string3 = string1) ' String.Empty = Nothing End Sub End Module
動作デモ*1
C# : http://rextester.com/ELTMU58022 VB.NET : http://rextester.com/IRCW50181
と、ここまで来て二つの言語間で結果が違ったことに気づきました。
これ、 ""
と String.Empty
はエイリアスの関係なので言うまでもなく同じものです。
ですから、比較したときにtrue
になるのは当然だと思います。
でも、
string string1 = null; string string2 = ""; Console.WriteLine(string1 == string2); // ==> false
Dim string1 As String = Nothing Dim string2 As String = "" Console.WriteLine(string1 = string2) ' ==> True
なのです。
VB.NETではデフォルトでOption Strict Off
であるため暗黙の型変換が行われたのかと思い、Option Strict On
を記述するも変わらず。
ちなみに、
Dim string1 As String = Nothing Dim string2 As String = "" Console.WriteLine(string2.Equals(string1)) ' ==> False
でした。
この挙動について、このエントリを書いている途中まではSystem.String
の特殊性によるものかと思っていましたが、書いている途中でそれぞれの言語の等価演算子の振る舞いの違いによるものかも?ともちょっと思っています。
どうなんですかね、これ。
何とも尻切れトンボ感あるエントリになってしまいましたが、この辺で。
追記 (2014/11/11 1:21)
どうやら、やはり等価演算子自体が違う振る舞いをするようです。
@htsign ちょい前のやつ、気になってil覗いてみたけど、演算子の実体が違うみたいやで。
— michi (@michi1129) 2014, 11月 10
*1:rextester.comは鯖が落ちていることが稀によくある
Co-opゲーが好きで対戦ゲーがあまり好きでない理由
最初に
独り言なので読む価値ないですさようなら
本題
ゲームを仕事と見る向きもありますが*1、
基本的にゲームはあくまでも暇つぶしの道具であり、遊びなので、
楽しめなければ意味がありません。
そして勝負要素のあるゲームというのは、どちらかが必ず負けるか引き分けに終わる。
たいていの人は負けると悔しい(ですよね?)ので、その苦境を楽しめるかどうかで対戦ゲーの好き好きが決まってくると思うんですが、私は苦手です。
特にFPSや二人零和有限確定完全情報ゲームなど本人のスキルに多分に左右される勝ち負けは、相手に見合う実力がなければ一方的にただ蹂躙されるだけになってしまうため、遊びとは程遠い結果に終わることが多いです。
それを楽しめる人を私は見てみたい。
一方、Co-opでは他の人と一緒にゲームを進行させて楽しみを共有できます。
共通の目的があるので一緒に達成できます。あるいは一緒に失敗できます。
失敗してもみんなと一緒にワイワイできれば楽しいんです。
そういう意味では、対戦ゲーでも多人数vs多人数なら同じチームのメンバーによっては楽しく遊べます。
勝てたらもちろん嬉しいですし、負けても楽しめます。
ただし、例えば野良で入ったチームに異常に上手い人が一人いて、その人がワンマンプレイでチームを勝利に導く場合はその限りではありません。
「勝たされている」感じがしてしまう。
せっかくチームを組むのだから協力して、その先に勝つためのきっかけを作るという、そこまでの過程に楽しみを見出すタイプです。私は。
他の人との行動が綺麗に噛み合い、その結果ものすごい成果を生み出すときに、言い知れないカタルシスを覚えます。
ちょっと話が対戦ゲー寄りの中身になりましたが、今書いたことはCo-opにも言えると思います。
協力から結果を生み出すのが好きなんです。
そういうところ、誰にだってあると思うんですが、どうでしょうか。
Xperia Z1 Compact買いました。
Expansysでセールだったので。
通常価格 \67868 のところ、なんと \41790 (カラバリ黒の場合)でした。
ちなみに7月9日22時現在、やや値上がりしてますがまだ安いです。
http://www.expansys.jp/sony-xperia-z1-compact-unlocked-lte-16gb-black-258379/
小型の端末が好きで、正直Z1 Compact(国内ではZ1 fとして知られるSO-02Fです)の4.3インチでも「やや大きいかな」と思っていたんですが、霜降りでこの価格はしばらく見られるもんじゃないと思いポチりました。
ヤマト利用で、送料1900円と関税料1900円でした。
それでも安い…!
先ほど帰宅したら届いていたのでこれから開けます。
化粧箱右下にワールドカップのロゴ入ってる。
正直どうでもいいけどなんとなくかわいい。
Visual Studio Online "Monaco" でWeb上で完結する開発環境を使えるようになるまで
最近Web上で開発できる環境って増えてきましたよね。
有名どころだと
辺りでしょうか。
プロジェクト単位でなく、ただ書いて動かすだけのサービスなら他にも
などあります。
あとCloud9はGitHub Gistで大活躍のAce editorを開発しているところでもあります。
なんでもWeb上でやっちゃう時代
さて、時代の流れなのか、最近のMicrosoftの大幅なOpen & Webへの方向転換のおかげなのか、
Visual Studioもオンラインサービス連携が強化されています。
従来のTeam Foundationに加えてGitによるプロジェクト管理も出来るようになりました。
そしてWeb上での開発をMicrosoftもサポートしていたようなので、*1 今回、環境を整えてみることにしたわけです。
ちなみに、このMicrosoft製エディタ(コードネーム: Monaco)は、TypeScript公式サイトのPlaygroundやOneDrive(旧:SkyDrive)でも利用されています。
試しにOneDriveの任意のフォルダにJavaScriptファイルなど置いてみると分かりますが、Web上で編集できます。*2
前提条件
MonacoでVisual Studio Online上のプロジェクトを編集できるようにするためには、以下の条件をすべて満たす必要があります。
- Microsoftアカウントを持っていること
- MicrosoftアカウントでVisual Studio Onlineにサインアップしていること
- MicrosoftアカウントでWindows Azureにサインアップしていること
1つ目は言わずもがなですね。
2つ目、3つ目は無料でサインアップできます。
Visual Studio Online http://go.microsoft.com/fwlink/?LinkId=307137&clcid=0x411 Windows Azure https://account.windowsazure.com/signup?offer=ms-azr-0044p
無料枠ではいろいろな制限が付きますが、とりあえず触るだけなら問題ありません。
手順
以下は前提条件をクリアしているものとして進めます。
まずプロジェクトを作ります。
Visual Studio Onlineトップページの右上にある歯車マークをクリックします。
コントロールパネルに遷移するので、ここで「Create a new team project」をクリックします。
ポップアップダイアログが表示されるので、必要事項を記入し「Create project」をクリックします。
ここで、Version controlは必ずGitにしてください。
あとでこの違いが重要になってきます。
さて、プロジェクトが作成されたらVisual Studio Onlineですることはもうありません。
作られるのに少し時間がかかります。
次にAzureでWebサイトを作ります。
画面左下の「新規」をクリックして、「コンピューティング」→「Webサイト」→「カスタム作成」と辿ります。
必要事項を入力します。
必ず「ソース管理から発行」にチェックを入れてください。
「ソースコードの位置」で「Visual Studio Online」
「接続を承認する」で自分のURIを入力して「今すぐ承認」をクリックします。
小窓が開くので「Accept」を押してあげてください。
最後に「デプロイするリポジトリの選択」で、先ほど作ったプロジェクトを選択して完了してください。
サイトが作られるまで少し時間がかかります。
出来上がったらWebサイト名をクリックして詳細画面に進みます。
メニューの「構成」をクリックしてサイトの構成編集画面を表示します。
「VISUAL STUDIO ONLINE での編集」をオンにして*3 保存します。
メニューから「ダッシュボード」に移り、「Visual Studio Online での編集」をクリックします。
ここでやっとMonacoがお目見えです。
これからプロジェクトと関連付ける作業を行います。
上部メニューにあるサイト名をクリックし、「Connect to Visual Studio Online」をクリックします。
指示に従って接続します。
勝手に元の画面に戻るので、再び上部メニューからサイト名をクリックし、今度は「Clone repository from Visual Studio Online」をクリックします。
ここで先ほど作成したプロジェクトを選択します(Version controlがGitのもののみ選択できます)
と、これでコンソール画面にずらずらっとGitの標準出力が流れて…
晴れてVisual Studio Onlineのプロジェクトに関連付けられました。
あとは好きにコードを書いてgit push
しまくりましょう。
新規でファイル作成はもちろん、ローカルからのアップロード*4 にも対応しています。
Let's enjoy!!
あ、そうそう。
git push
するにはBasic認証(Digest認証かも?)が必要です。
認証するにはVisual Studio Onlineのコントロールパネルで、右上の自分の名前部分をクリックして「My profile」をクリックします。
ポップアップダイアログが表示されるので、「CREDENTIALS」タブの「Enable alternate credentials」をクリックし、パスワードを指定してください。