Skip to content

midi output example help #1

@boonier

Description

@boonier

Hi there, I'm a bit new to Rust and most probably struggling with the fundamentals of the language, but I'm trying to wire something up in the Tauri backend to handle sending midi output generated from the JS frontend.

Just wondering if you would be able to help me?

I've based my code on what you've provided here, except swapping the MidiInput* stuff with MidiOutput*.

I have the midi events coming through from the f/e fine and the handler on Rust b/e is getting the messages fine, but where I'm struggling is with the MidiState struct, specifically getting access to the output property (sidenote: as I understand it, the reference to the MidiOutputConnection is put into a Mutex in the struct so that it can be accessed in other functions).

Here is my version of open_midi_connection fn that I've adapted:

#[tauri::command]
fn open_midi_connection(
  midi_state: tauri::State<'_, MidiState>,
  _window: Window<Wry>,
  output_idx: usize
) {
  // let handle = Arc::new(window).clone();
  let midi_out = MidiOutput::new("orca-midi-outputs").unwrap();
  let out_ports = midi_out.ports();

  let out_port: &MidiOutputPort = match out_ports.len() {
      // 0 => return Err(e)"no output port found".into()).unwrap(),
      // 0 => Err(e) => {
      //   println!("no output port found")
      // },
      1 => {
          println!("Choosing the only available output port: {}", midi_out.port_name(&out_ports[0]).unwrap());
          &out_ports[0]
      },
      _ => {
          println!("\nAvailable output ports:");
          for (i, p) in out_ports.iter().enumerate() {
              println!("{}: {}", i, midi_out.port_name(p).unwrap_or("There was a problem\n".to_string()));
          }

          out_ports.get(output_idx)
                    .ok_or("invalid output port selected").unwrap()
      }

    };
    
    println!("\nOpening connection");
    let conn_out = midi_out.connect(out_port, "midi_out_connected");
    *midi_state.output.lock().unwrap() = Some(conn_out.unwrap());
    println!("Connection open. Listen!");
}

So the conn_out holds the connection, and the next line stuffs it into the midi_state data structure (I deduce).

I then have another function trigger_note, which is called from the JS:

#[tauri::command]
fn trigger_note(
  c: u8, 
  n: u8,
  v: u8, 
  midi_state: tauri::State<'_, MidiState>
) {
  println!("Hello {}, {}, {}", c,n,v);

  // get the output connection from the mutex blahblah
  let out_port = midi_state.output.try_lock().unwrap();

  const NOTE_ON_MSG: u8 = 0x90;
  const NOTE_OFF_MSG: u8 = 0x80;
  const VELOCITY: u8 = 0x64;
  
  let _ = out_port.unwrap().send(&[NOTE_ON_MSG, n, VELOCITY]);
} 

This line let _ = out_port.unwrap().send(&[NOTE_ON_MSG, n, VELOCITY]); is where I have the problem; it doesn't compile because of some borrowing error, which I can't seem to pin down.

error[E0507]: cannot move out of dereference of `MutexGuard<'_, std::option::Option<MidiOutputConnection>>`
   --> src/main.rs:134:11
    |
134 |   let _ = out_port.unwrap().send(&[NOTE_ON_MSG, n, VELOCITY]);
    |           ^^^^^^^^^^^^^^^^^ move occurs because value has type `std::option::Option<MidiOutputConnection>`, which does not implement the `Copy` trait
    |
help: consider borrowing the `Option`'s content
    |
134 |   let _ = out_port.unwrap().as_ref().send(&[NOTE_ON_MSG, n, VELOCITY]);

Then on the compiler's advice, I add as_ref():

error[E0599]: no method named `as_ref` found for struct `MidiOutputConnection` in the current scope
   --> src/main.rs:134:29
    |
134 |   let _ = out_port.unwrap().as_ref().send(&[NOTE_ON_MSG, n, VELOCITY]);
    |                             ^^^^^^ method not found in `MidiOutputConnection`

So, I can understand as_ref() is not found in MidiOutputConnection. But why does it ask me to add it in the first place? It ,must be something that I'm not comprehending about the Mutex stuff.

My apologies for the length of this issue, I'm hoping you might be able to give me some pointers? (pun not intended!)

Many thanks

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions