RustでWindows Runtimeを利用する
PC上で鳴っている音楽をタイマーで一定時間経過後に止めたい衝動に駆られたので、Rustで実装してみようと思い立ちました。
とりあえず、他のアプリ等で再生した音楽をどうにかしてRustで作ったプログラムから停止させる必要があります。
いろいろググったりChatGPTと熱い協議を重ねた結果、Windows Runtimeを利用するのがよさそうでした。
調べたこと
Rustで音声を扱うクレートには以下がありました。
cpalはローレベルなオーディオの入出力を扱うクレートで、rodioはそれを利用した音声再生用のクレートみたいです。cpalはクロスプラットフォームかつpure Rustなので利用したかったのですが、APIを一通り触ってみた結果、どうやら無理そうということが分かりました。オーディオデバイスの情報を取得したり、新規に音声を再生することはできそうなのですが、他のアプリで再生し音楽を止める方法がなさそうでした。
Windows Runtimeで音楽を止める
上記方法がだめだったので、Windows Runtime(WinRT)のAPIを叩くことにしました。
WinRTは幸いにも、Rustから簡単に実行する方法が公式で用意されています。
クレートとしてはwindowsという名前で公開されています。
Cargo.toml
に依存クレートとして書く際は、以下のようにします。
まず、今回使いたいのはGlobalSystemMediaTransportControlsSessionManager
構造体なので、こちらのドキュメントを見ると、
Required features: "Media_Control"
という記載があります。これをwindows crateのfeatureとして記載することで、構造体を利用できるようになります。
具体的には、以下のように記載します。"Foundation"はこの後のコードで使うRequestAsync()
メソッドで必要だったため付け足してます。
[dependencies.windows]
version = "0.44.0"
features = [
"Foundation",
"Media_Control"
]
あとは、通常のcrateと同様にuseすればOKでした。(適当にunwrapしてますが目を瞑ってください……。)
use windows::Media::Control::GlobalSystemMediaTransportControlsSessionManager;
fn main() {
let manager = GlobalSystemMediaTransportControlsSessionManager::RequestAsync().unwrap();
let session = manager.get().unwrap().GetCurrentSession().unwrap();
session.TryPauseAsync();
println!("stop");
}
上記を実行すると、音楽が停止します。
まとめ
RustからWinRTを比較的簡単に利用できることが分かりました。
次回はタイマーの機能を作ってみたいと思います。
Discussion