Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lighthouse-client/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,4 @@ tracing-subscriber = { version = "0.3", features = ["env-filter", "std"] }
tokio = { version = "1.21", features = ["rt", "rt-multi-thread", "macros", "time"] }
clap = { version = "4.5", features = ["derive", "env"] }
dotenvy = "0.15"
midi-msg = "0.8.0"
49 changes: 49 additions & 0 deletions lighthouse-client/examples/midi_events.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use clap::Parser;
use futures::StreamExt;
use lighthouse_client::{protocol::Authentication, Lighthouse, Result, TokioWebSocket, LIGHTHOUSE_URL};
use lighthouse_protocol::InputEvent;
use midi_msg::MidiMsg;
use tracing::{info, warn};

async fn run(lh: Lighthouse<TokioWebSocket>) -> Result<()> {
info!("Connected to the Lighthouse server");

// Stream input events
let mut stream = lh.stream_input().await?;
while let Some(msg) = stream.next().await {
let event = msg?.payload;
if let InputEvent::Midi(midi) = event {
match MidiMsg::from_midi(&midi.data) {
Ok((msg, _)) => info!("Got MIDI message: {:?}", msg),
Err(e) => warn!("Could not parse MIDI message: {:?}", e),
};
}
}

Ok(())
}

#[derive(Parser)]
struct Args {
/// The username.
#[arg(short, long, env = "LIGHTHOUSE_USER")]
username: String,
/// The API token.
#[arg(short, long, env = "LIGHTHOUSE_TOKEN")]
token: String,
/// The server URL.
#[arg(long, env = "LIGHTHOUSE_URL", default_value = LIGHTHOUSE_URL)]
url: String,
}

#[tokio::main(flavor = "current_thread")]
async fn main() -> Result<()> {
tracing_subscriber::fmt().init();
_ = dotenvy::dotenv();

let args = Args::parse();
let auth = Authentication::new(&args.username, &args.token);
let lh = Lighthouse::connect_with_tokio_to(&args.url, auth).await?;

run(lh).await
}
1 change: 1 addition & 0 deletions lighthouse-protocol/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ license.workspace = true
rand = "0.8"
rmpv = { version = "1.0.1", features = ["with-serde"] }
serde = { version = "1.0", features = ["derive"] }
serde_bytes = "0.11.17"
serde_with = "3.4"

[dev-dependencies]
Expand Down
4 changes: 3 additions & 1 deletion lighthouse-protocol/src/input/input_event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize};

use crate::Direction;

use super::{EventSource, GamepadEvent, KeyEvent, MouseEvent, UnknownEvent};
use super::{EventSource, GamepadEvent, KeyEvent, MidiEvent, MouseEvent, UnknownEvent};

/// A user input event, as generated by the new frontend (LUNA).
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
Expand All @@ -11,6 +11,7 @@ pub enum InputEvent {
Key(KeyEvent),
Mouse(MouseEvent),
Gamepad(GamepadEvent),
Midi(MidiEvent),
#[serde(untagged)]
Unknown(UnknownEvent),
}
Expand All @@ -22,6 +23,7 @@ impl InputEvent {
InputEvent::Key(KeyEvent { source, .. }) => source,
InputEvent::Mouse(MouseEvent { source, .. }) => source,
InputEvent::Gamepad(GamepadEvent { source, .. }) => source,
InputEvent::Midi(MidiEvent { source, .. }) => source,
InputEvent::Unknown(UnknownEvent { source, .. }) => source,
}
}
Expand Down
35 changes: 35 additions & 0 deletions lighthouse-protocol/src/input/midi_event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use serde::{Deserialize, Serialize};

use super::EventSource;

/// A MIDI message event.
#[derive(Debug, Serialize, Deserialize, PartialEq, Clone)]
pub struct MidiEvent {
/// The client identifier. Also unique per MIDI input device.
pub source: EventSource,
/// The binary MIDI message.
///
/// The first byte is a status byte (first/most significant bit = 1), the
/// remaining bytes are data bytes (first/most significant bit = 0).
///
/// To give a simple example, pressing C5 on a MIDI keyboard would generate the
/// following message:
///
/// ```plaintext
/// [0x90, 0x48, 0x64]
/// Ch.1 Note 72 Velocity 100
/// NoteOn i.e. C5
/// ```
///
/// The note values can be looked up online:
///
/// - https://www.phys.unsw.edu.au/jw/notes.html
///
/// Same goes for a full description of the packet structure:
///
/// - https://www.w3.org/TR/webmidi/#terminology
/// - http://www.opensound.com/pguide/midi/midi5.html
/// - https://www.songstuff.com/recording/article/midi-message-format/
#[serde(with = "serde_bytes")]
pub data: Vec<u8>,
}
2 changes: 2 additions & 0 deletions lighthouse-protocol/src/input/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod input_event;
mod key_event;
mod key_modifiers;
mod legacy_input_event;
mod midi_event;
mod mouse_button;
mod mouse_event;
mod unknown_event;
Expand All @@ -22,6 +23,7 @@ pub use input_event::*;
pub use key_event::*;
pub use key_modifiers::*;
pub use legacy_input_event::*;
pub use midi_event::*;
pub use mouse_button::*;
pub use mouse_event::*;
pub use unknown_event::*;