Rustでeguiを使ってwindowsの音を鳴らす

先日初めてcrates.ioに[crateを登録](https://crates.io/crates/windows_audio)してみました。
案外簡単に登録できて便利だったので記念に記事も書こうかと思って今回書いてみました。
次の人には参考になるかもしれません。

* プログラム言語Rustを使ってwindows環境でプログラムを書いてみたい人
* [egui](https://crates.io/crates/egui)を使ってGUIを作ってみたい人
* windowsのシステム音を手軽に鳴らしたい人

## Rustのインストール
* [公式の手順](https://www.rust-lang.org/ja/tools/install)に従ってRustをインストールしてください。特に迷う箇所はないと思います。
## プロジェクトの作成 → VSCodeを起動
* 適当なフォルダで、パスに`cmd`と入力してコマンドプロンプトを起動後↓を実行
```
cargo new windows_audio
cd windows_audio
cargo run --release
code .
```
※ windows_audioはプロジェクト名です。

※ VScodeはインストールされている前提で進めます。
## VSCodeの設定(ビルド設定が面倒な人向け)
* VSCodeが起動したら ターミナル → タスクの実行 → タスクの構成 → テンプレートからtask.jsonを設定 → Others と移動して↓に設定してください
```
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "echo",
            "type": "shell",
            "command": "cargo run --release",
            "group":{
                "kind": "build",
                "isDefault": true
            }
        }
    ]
}
```
* ctrl + s で上書き保存してください。
* これで ctrl + shift + b で cargo run --release コマンドが実行されます。
## Cargo.tomlに使うクレートを記入
* Cargo.tomlファイルの[dependencies]に eframe と windows_audio を追加してください。
```
[dependencies]
eframe = "0.20.1"
windows_audio = "0.1.7"
```
## main.rsファイル
* src → main.rsを↓に変更してください。
```

#![cfg_attr(not(release_assertions), windows_subsystem = "windows")]
use eframe::{egui, App};
use egui::{FontFamily, FontId, TextStyle};
fn main() {
    set_ui(); 
}

fn set_ui(){
    let options = eframe::NativeOptions{
        ..Default::default()
    };
    eframe::run_native(
        "windows_audio", 
        options, 
        Box::new(|cc| Box::new(MyApp::new(cc))),
    );
}
pub struct MyApp{
    audio: windows_audio::Audio,
    volume: f32,
}
impl Default for MyApp{
    fn default() -> Self{
        Self{audio: windows_audio::Audio::new(), volume: 1.0}
    }
}

impl MyApp{
    pub fn new(cc: &eframe::CreationContext<'_>) -> Self{
        let mut style = (*cc.egui_ctx.style()).clone();
        style.text_styles = [
            (TextStyle::Heading, FontId::new(16.0, FontFamily::Proportional)),
            (TextStyle::Body, FontId::new(12.0, FontFamily::Proportional)),
            (TextStyle::Monospace, FontId::new(12.0, FontFamily::Proportional)),
            (TextStyle::Button, FontId::new(12.0, FontFamily::Proportional)),
            (TextStyle::Small, FontId::new(12.0, FontFamily::Proportional)),
        ]
        .into();
        cc.egui_ctx.set_style(style);
        let mut fonts = egui::FontDefinitions::default();
        fonts.font_data.insert(
            "my_font".to_owned(),
            egui::FontData::from_static(include_bytes!("C:/Windows/Fonts/Meiryo.ttc")),
        );
        fonts
            .families
            .entry(egui::FontFamily::Proportional)
            .or_default()
            .insert(0, "my_font".to_owned());
        cc.egui_ctx.set_fonts(fonts);
        cc.egui_ctx.set_visuals(egui::Visuals::dark());
        MyApp::default()
    }
}


impl App for MyApp {
    fn on_exit(&mut self, _gl: Option<&eframe::glow::Context>) {}

    fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
        let Self { audio, volume } = self;
        eframe::egui::CentralPanel::default().show(ctx, |ui|{
            let tmp = *volume;
            ui.vertical_centered_justified(|ui|{
                ui.horizontal(|ui|{
                    ui.label("音量:");
                    let sd = egui::Slider::new(volume, (0.1)..=(20.0))
                        .logarithmic(true)
                        .show_value(true)
                        .text("");
                    ui.add(sd);
                });
            });
            if tmp != *volume{ audio.volume = *volume; }//volume変数が変更時のみ音量を変更
            egui::ScrollArea::both().show(ui, |ui| {
                for a in audio.get_audios(){
                    ui.vertical_centered_justified(|ui|{
                        let btn = egui::Button::new(&a.name);
                        if ui.add(btn).on_hover_text_at_pointer(&a.path).clicked(){
                            audio.play(&a.name);
                        }
                    });
                }
            });
        });
    }
}
```
ctrl + shift + b でビルドするとexeが起動すると思います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/139073/1b10e40d-10b8-b906-24a6-116b0394fe05.png)
ボタンを押すと音が鳴ります。