🎵
Tauri上でSpotifyの再生中の曲情報をリアルタイムで取得し表示する
導入
今回は、Tauriを使用してSpotifyから再生中の曲情報をリアルタイムで取得する方法を紹介します。環境はmacOSです、悪しからず。
フロントのフレームワークはReactです。
AppleScriptを使ったSpotifyトラック情報の取得
macOSでは、Spotify APIを使わずともAppleScriptを使用してSpotifyから現在再生中の曲情報を取得することができます。以下のようなAppleScriptを作成し、Rustのコードから呼び出します。
tell application "Spotify"
if player state is playing then
set trackName to name of current track
set artistName to artist of current track
return trackName & " by " & artistName
else
return "Spotify is not playing."
end if
end tell
AppleScript普段書かないので勉強になりました。
-
tell application "Spotify":
これはSpotifyアプリケーションに対してコマンドを実行することを示します。 -
if player state is playing then:
現在Spotifyで音楽が再生中かどうかを確認します。 -
set trackName to name of current track:
現在再生中のトラックの名前を取得します。 -
set artistName to artist of current track:
現在再生中のトラックのアーティスト名を取得します。 -
return trackName & " by " & artistName:
トラック名とアーティスト名を結合して返します。 -
else return "Spotify is not playing.":
音楽が再生されていない場合のメッセージを返します。
Spotifyが再生中かどうかをチェックし、再生中であればその曲のタイトルとアーティスト名を取得します
これをRustから実行するために、以下のコードを実装します。
名前はspotify_info.rsとでもしておきましょう。
get_spotify_track_info関数を実装します。
spotify_info.rs
use std::process::Command;
#[tauri::command]
pub fn get_spotify_track_info() -> Result<String, String> {
let script = r#"
tell application "Spotify"
if player state is playing then
set trackName to name of current track
set artistName to artist of current track
return trackName & " by " & artistName
else
return "Spotify is not playing."
end if
end tell
"#;
let output = Command::new("osascript")
.arg("-e")
.arg(script)
.output()
.map_err(|e| e.to_string())?;
if output.status.success() {
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
Ok(result)
} else {
Err(String::from_utf8_lossy(&output.stderr).trim().to_string())
}
}
-
let script = r#"...";:
ここでは、AppleScriptのコードをRustの文字列として定義しています。r#"...";の形式を使うことで、文字列内に特別なエスケープシーケンスなしで"などを含めることができます。 -
Command::new("osascript").arg("-e").arg(script).output():
これはosascriptコマンドを呼び出してAppleScriptを実行し、その結果を取得します。osascriptはmacOSのコマンドで、AppleScriptを実行するために使用されます。 - 試験的に取得できるかターミナルで叩く場合
osascript -e 'tell application "Spotify" to name of current track & " by " & artist of current track'
みたいなコマンドです。 -
.map_err(|e| e.to_string())?:
コマンドの実行が失敗した場合、そのエラーを文字列に変換して返します。 -
if output.status.success():
コマンドが成功したかどうかをチェックします。成功した場合は、出力をUTF-8として読み取り、その結果を返します。失敗した場合は、標準エラー出力を取得してエラーメッセージとして返します。
コマンドを実装
次に、TauriでAppleScriptを実行するコマンドを実装します。main.rsに新しいコマンドを追加し、Reactコンポーネントから呼び出せるように設定します。
main.rs
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
mod system_info;
mod window_events;
mod spotify_info; //追加
use system_info::get_system_info;
use window_events::setup_window_event_listeners;
use spotify_info::get_spotify_track_info; //追加
use tauri::Manager;
fn main() {
tauri::Builder::default()
.setup(|app| {
let window = app.get_window("main").unwrap();
setup_window_event_listeners(window);
Ok(())
})
.invoke_handler(tauri::generate_handler![get_system_info, get_spotify_track_info]) //ここに追加
.run(tauri::generate_context!())
.expect("error while running tauri application");
}
Reactを使ったリアルタイム更新
Reactコンポーネントを作成し、Spotifyの曲情報を定期的に取得するロジックを実装します。ポーリングで、数秒ごとに情報を更新します。
App.tsx
const [spotityTrackInfo, setSpotityTrackInfo] = useState<string>("");
const fetchSpotifyTrackInfo = async () => {
try {
const trackInfo: string = await invoke("get_spotify_track_info");
setSpotityTrackInfo(trackInfo);
} catch (error) {
console.error("Spotifyの情報を取得できません:", error);
}
};
useEffect(() => {
fetchSpotifyTrackInfo();
const intervalId = setInterval(fetchSpotifyTrackInfo, 5000); // 5秒ごとに更新
return () => clearInterval(intervalId);
}, []);
...
<Marquee gradient={false} speed={40} delay={2}>
{"♪"} {spotityTrackInfo}
</Marquee>
感想
- Tauri上でのフロントとネイティブコマンドの実行の相性が良すぎるし、簡単
- Linux、Windowsは知らん
Discussion