なんというか、音を出せたからそれで満足って、するわけないじゃないですか!!
ここはもう、「みくみくにしてやんよー」まで言わせましょう!!
要約:Rustでは、コンパイル時のエラーメッセージはしっかり見よう
- Rustの場合、問題解決策がエラーメッセージにでていることもある。
- 試行錯誤も重要だけど、ここらへんは経験が必要だなあ、、、と。
参考文献
基本的には、こちらのQiita投稿されたものを、Rustへ移植?(と呼べるのか… 申し訳ないです)となります。
rawmidiの制御に関しては、下記も参考にしています。
どうすれば、ポケットミクを制御できるのか?
ALSAには、rawmidi interfaceがあるので、これを使えば直接やり取りできそう。というところまでは、昨日5/4には見つけていた。
Rust Alsa にもあるし、これは楽勝なのでは?(と、このときはそう思っていました)
完成品
とりあえず試行錯誤のものを出してから、何で苦しんだかをまとめておく。
main.rs
extern crate alsa;
use std::error;
use std::ffi::CString;
use std::thread::sleep;
use std::time::Duration;
use std::io::Write;
fn sing() -> Result<alsa::rawmidi::Rawmidi, Box<dyn error::Error> > {
let cstr = CString::new("hw:1")?;
let miku = alsa::rawmidi::Rawmidi::open( &cstr, alsa::Direction::Playback, false ) ?;
let mut init_lyric: [u8; 18] =
[
0xF0u8, 0x43u8, 0x79u8, 0x09u8, 0x11u8,
0x0Au8,
0x01u8,
101u8, // み
7u8, // く
101u8, // み
7u8, // く
64u8, // に
32u8, // し
44u8, // て
108u8, // や
125u8, // ん
110u8, // よ
0xF7u8,
];
let mut next_lyric: [u8; 19] =
[
0xF0u8, 0x43u8, 0x79u8, 0x09u8, 0x11u8,
0x0Du8, // Direct Command
0x09u8, 0x05u8, 0x00u8, 0x00u8,
0x08u8, 0x01u8, 0x00u8, 0x00u8,
0x09u8, 0x01u8, 0x00u8, 0x00u8,
0xF7u8,
];
let mut buf_note_on: [u8;11] =
[
0xF0u8, 0x43u8, 0x79u8, 0x09u8, 0x11u8,
0x0Du8,
0x08u8,
0x09u8,
0x29u8,
0x00u8,
0xF7u8,
];
let mut buf_note_off: [u8;11] =
[
0xF0u8, 0x43u8, 0x79u8, 0x09u8, 0x11u8,
0x0Du8,
0x08u8,
0x08u8,
0x00u8,
0x00u8,
0xF7u8,
];
let durations : [ u64; 11 ] = [
100,
300,
100,
300,
200,
300,
300,
100,
300,
300,
300,
];
miku.io().write(&mut init_lyric )?;
// note off
miku.io().write(&mut buf_note_off );
for duration in &durations {
// note on
miku.io().write(&mut buf_note_on );
// Wait
sleep ( Duration::from_millis( *duration ) );
// note off
miku.io().write(&mut buf_note_off );
// goto next
miku.io().write(&mut next_lyric )?;
}
Ok(miku)
}
fn main() {
sing();
}
初期化方法は大体わかった
初期化してインスタンス作るところまでは、そんなに苦労せずにできた。
let cstr = CString::new("hw:1")?;
let miku = alsa::rawmidi::Rawmidi::open( &cstr, alsa::Direction::Playback, false ) ?;
データを書き込み方が分からない、どうなってんだろう?
NG
✕ miku.write( &mut init_lyric );
✕ miku.Write( &mut init_lyric );
✕ miku.IO().write( &mut init_lyric );
✕ miku.IO().Write( &mut init_lyric );
などでもだめだめでどうすればいいんだー、と
rust-alsaのドキュメントやソースコードをいったりきたり。
で、ふとエラーを確認したところ・・・あれ?直し方も書いてる?
コンパイル時のエラー
[kmtr@localhost rust-alsa-raw]$ cargo build
Compiling rust-alsa v0.1.0 (/home/kmtr/work/rust-alsa-raw)
error[E0599]: no method named `write` found for struct `alsa::rawmidi::IO<'_>` in the current scope
--> src/main.rs:76:12
|
76 | miku.io().write(&mut init_lyric )?;
| ^^^^^ method not found in `alsa::rawmidi::IO<'_>`
|
= help: items from traits can only be used if the trait is in scope
help: the following trait is implemented but not in scope; perhaps add a `use` for it:
|
3 | use std::io::Write;
|
ということで、下記行を追加したところ無事にコンパイルが通りました、と。
use std::io::Write;
以上になります。