以前、CubaseをMCPから操作するサーバーを作ったという記事を書いた。

その後も cubase_mcp の開発を続けている。ただ、思っていたより進んでいない。

再生・停止やトランスポートの状態取得はできるようになったので、次はプロジェクトのトラック一覧を取りたい。

名前や選択状態、Mute、Soloあたりが分かれば、MCPからできることも増やせそう。そういう話だったのだけれど、今はまだ「何が、どこまで取れるのか」を調べている。

今日はその調査用のコードを整理してmainへマージした。トラック一覧取得が完成した報告ではなく、そこへ行くまでに何で詰まっているかのメモ。

トラックの名前が取れれば終わり、ではなかった

欲しいものを雑に書くと、こういう一覧になる。

トラック選択MuteSolo
Pianofalsefalsefalse
Basstruefalsefalse
Vocalfalsefalsetrue

これは説明用の例で、今のMCP Toolから返せる結果ではない。

名前と状態がいくつか取れたとしても、それをそのまま「プロジェクトのトラック一覧です」と返してよいのか、という問題がある。

非表示のトラックは含まれるのか。フォルダはどうなるのか。MixConsoleに見えるチャンネルと、プロジェクト画面にあるトラックは同じ範囲なのか。

同じ名前のトラックが二つある場合もあるし、途中で名前を変えることもある。名前をIDにすると困るし、並び順をIDにしても追加や削除でずれる。

一回それらしい一覧が出るところと、継続して使えるAPIにするところの間が結構遠い。

Mixer BankとDirectAccessを調べている

今はCubaseのMIDI Remote APIにある、Mixer BankとDirectAccessを比較している。

Mixer Bank

Mixer Bankは、一定数のチャンネルを操作用のスロットへ割り当て、バンクを切り替えながら扱う仕組み。

例えば8個のスロットを用意して、今の8個を読み、次へ進めてまた読む。これで一覧を作れないかと考えている。

ただし、手元のCubase 13.0.30に同梱された型定義では、バンクの総数や現在位置、終端を直接返すものが見当たらない。名前の通知が来なかったときに、それが空のスロットなのか、まだ通知が来ていないだけなのかも区別したい。

同じページらしきものが返ったから終わり、とすると、同名のチャンネルや通知の遅延を取り違えるかもしれない。

なので、0件、1件、バンク幅ちょうど、バンク幅を超える場合などを、実際の画面と照合して確認する手順を用意している。型定義を読んだだけで実機の挙動まで確認できたことにはしていない。

DirectAccess

DirectAccess は、実行中のホストオブジェクトをたどり、名前やIDなどの情報を取得するための低レベルなAPI。こちらならまとめて調べられそうに見える。

しかし、オブジェクトをたどれたことと、プロジェクト内のトラックを全部列挙できたことは別だった。

8月の実機試行では、広くたどる旧実装が同じオブジェクトへの参照を再び見つけ、循環・打ち切りとして停止した。その試行は成功扱いにしていない。

今の調査用実装では、MixConsole側の起点と、その直下の子だけに観測範囲を絞っている。繰り返し出てくる参照も、別のトラックが増えたように数えるのではなく、参照として記録する。

その範囲を取り切れても、ホスト全体やフォルダを含むプロジェクト全体を取り切ったとは言わない。コード上でも、これをトラック全件列挙の根拠にはしないようにしている。

このあたりの確認内容は Track APIの調査記録 にまとめている。現時点では、どちらを本番に使うかも確定していない。

名前と状態が同じタイミングで届くとは限らない

もう一つ面倒なのが、コールバックで情報が届くこと。

名前、選択状態、Mute、Soloなどの通知を受けて状態を組み立てるのだけれど、バンクを切り替えた直後に、前の情報と新しい情報を混ぜたくない。

例えば、名前は次のトラックへ変わっているのに、Muteだけ前のトラックの値が残っていたら、それらしいけれど間違った一覧になる。

そこで調査用のProbeでは、バンクの世代を管理し、各項目がどの世代で観測されたかを記録している。まだ通知がない値は、勝手にfalseや空文字列で埋めない。

スクリプトの有効化・無効化、再読み込み、Cubaseの再起動でも境界が変わる。今日の変更には、こうした切り替え時の通知順序や、残っている通知の送出を整理する修正も入っている。

ただ、これで実際のCubaseが返す遅延通知をすべて識別できると分かったわけではない。ホストが新しいハンドラへ古い通知を渡した場合など、APIから見分けられる範囲にも限界がある。そこも実測したい部分。

調べるための道具が増えてきた

APIから返ったログだけ見ていても、画面上で本当にその操作が行われたかは分からない。

別のトラックを押していたり、途中で人間の入力が混ざっていたりしたら、ログの解釈も変わる。通常の制作プロジェクトを壊したくもないので、専用の検証用プロジェクトと手順を分けている。

その結果、Cubase側で値を観測するProbe、MIDI経由で記録するcollector、記録を検査するauditorに加えて、入力ガードと画面の保存器まで作ることになった。

入力ガードはmacOSの入力カウンターやキー・マウスボタンの押下状態を見て、操作中に入力の干渉があれば検証を止めるもの。入力した文字そのものを記録するものではない。

ただし、ガードが通ったから正しい場所をクリックできた、とは言えない。操作前後の画面と、アクセシビリティ情報から対象や結果を別に確認する。

確認するための道具にも確認が必要になっていて、ここにかなり時間を使っている。なお、この入力ガードは調査用の独立したツールで、普段のMCP操作で自動起動するものではない。

メニューを開いたところで検証が止まった

9月13日のCubase 15の実機試行では、44個あるチェックポイントのうち30個まで進んだ。

そこでProjectメニューを開いた状態の画像が取得できなくなった。アクセシビリティ情報ではメニューが開いていることを確認できても、その状態に対応するスクリーンショットを保存できなかった。

今回の検証では操作前後の画面とUI情報を揃えることにしているので、画像が欠けたまま完了にはできない。別の画面の画像で埋めるわけにもいかず、その試行は採用していない。

Cubaseのトラック情報を調べたいのに、画面取得の問題で止まるのはなかなかつらい。

これは今の操作・取得経路で起きている問題で、Cubaseからメニューの画像を一切取得できないと分かったわけではない。 メニュー表示中の画像取得の問題 として切り分けている。

また、以前合格した入力ガードの校正についても、そのときの原本と今の実行条件を照合しないと再利用できない。今日確認した範囲では必要な原本一式を特定できておらず、再利用の判断は保留にしている。記録が消えたと断定したわけではない。

長い実機検証へもう一度入る前に、画像を取れるか、記録を揃えられるかを先に確認する段階になっている。

今日マージしたもの

調査コードが大きくなっていたので、入力ガード、Track調査、I/O調査の三つに分けてマージした。今日全部を一から作ったわけではなく、これまで積み上げていたものを整理してmainへ入れた形。

PR内容
#46 入力ガード、画面・UI情報の保存、校正チェック
#31 Track Probeの通知処理、取得範囲、記録の監査と検証手順
#47 既存Input / Outputを読む専用Probeと結合テスト
#49 I/O結合テストの短すぎる待ち時間を修正

I/O Probeは、既にあるInputとOutputを調べる読み取り専用のもの。バスの作成・削除やルーティングの変更はしない。名前や内部IDも別名に置き換えて扱う。

ここでも、8スロット分のデータを受け取れたことを、全バスの取得完了とは扱わない。記録の構造が正しくても、実機の画面と一致するかは別に確認する必要がある。

最後のPRは、マージ後にWindowsのCIで見つかったテストの問題だった。

JavaScriptの模擬ドライバからRustのcollectorへ応答を渡す結合テストで、検出の待ち時間を20msにしていた。これが約3ms超過して失敗した。

テストだけ短くしていた設定をやめ、通常の既定値である1000msを使うようにした。さらに模擬ドライバ側で50ms遅らせ、古い条件では落ちることを確かめてから修正した。本番コードや成功条件を変えたわけではない。

最新mainでは、 Linux・macOS・WindowsのCI はすべて通っている。ただし、模擬環境のテストが通ることと、実Cubaseでの確認が終わることは別。

まだトラック一覧取得は公開していない

現時点では、cubase.get_tracksはまだ公開していない。tracks.listも本番では利用できないまま。

次は 実機検証の開始条件 を揃えて、Cubase 13と15でMixer BankやDirectAccessの挙動を確認する。取得範囲とIDの扱いを決めてから、本番のトラック一覧取得へ進みたい。

再生と停止ができたので次は一覧、くらいに考えていたが、だいぶ長くなってしまった。

今日進んだのは、トラックを取る機能そのものというより、その結果をどこまで信用してよいか調べるための部分。地味だけれど、途中までしか取れていない一覧を全部取れたことにするわけにもいかないので、もう少し調べる。