-
Notifications
You must be signed in to change notification settings - Fork 20
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
use shared midi-types and midi-convert #11
Conversation
I'm a bit confused, in the PR description you say:
But as far as I can tell, the Yamaha convention is Middle C = C3 (ie. C3 is note 60), which is what This PR does work on my setup however 😄 (unlike #10) I think it might be worth highlighting the octave change though, since this is arguably a breaking change for applications which already use |
My understanding is that the Yamaha convention is Middle C (note 60) = C4. I haven't found any authoritative source for this info though |
yeah.. the whole PR would be a breaking change but I think you're right that it should get highlighted somehow, any ideas how to do that? |
fair enough lol
I'm not entirely sure since there's no GitHub releases or any other real place for a changelog in this repo. I think I would be pretty confused if I upgraded this crate and every note was an octave higher, even if it's a major version increment. maybe a note in the README? |
I'm happy with this. Though the breaking change is just the bit to communicate. Could you had a https://keepachangelog.com/en/1.0.0/ with the 'unreleased bit' filled out. That should be good enough to communicate the breaking change part. For the original types, I just ended up picking one of two. In hindsight, it probably makes sense to have two types on the convention, with a trait of 'into u8' so that users can pick which makes sense, but I'd consider that an improvement in the upstream crate (to support both) so that won't stop this one. |
@btrepp good idea on the changelog, I just pushed something, how does that look? |
text from @132ikl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly looks good, only other general thought is that the crate could use a cargo fmt
, there's some inconsistency between the code style of this crate and the PR
@@ -1,3 +1 @@ | |||
pub mod u7; | |||
pub mod u4; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe u4
should be moved into midi-types
as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
midi-types
has Channel
so doesn't need u4
..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think I was mixing up CableNumber
and Channel
@@ -66,7 +62,7 @@ impl TryFrom<&[u8]> for UsbMidiEventPacket { | |||
None => return Err(MidiPacketParsingError::MissingDataPacket) | |||
}; | |||
|
|||
let message = Message::try_from(message_body)?; | |||
let message = MidiMessage::try_parse_slice(message_body).map_err(|_| MidiPacketParsingError::MissingDataPacket)?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This shouldn't always be mapped to MissingDataPacket
; the error doesn't make sense if try_parse_slice
is given a valid packet with with invalid event. Maybe this should be something like:
let message = match MidiMessage::try_parse_slice(message_body) {
Ok(message) => message,
Err(ParseError::MessageNotFound) => return Err(MidiPacketParsingError::InvalidEventType),
Err(_) => return Err(MidiPacketParsingError::MissingDataPacket),
};
Right now InvalidEventType
has a field for the invalid event value since Message::try_from
included that with the error, but MidiMessage::try_parse_slice
doesn't. I see a couple options:
- Remove the
u8
fromInvalidEventType
, lose out on potentially useful debugging info - Keep it, and add the value to
ParseError::MessageNotFound
as well - Re-parse the message here in order to figure out the event type (this one seems a bit silly)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I realized that the cable number parse can never fail and so I added a MissingCableNumber
and also simply just forward the parse error... I cleaned up the errors a bit with that.
use crate::data::midi::notes::Note; | ||
use crate::data::byte::u7::U7; | ||
use crate::data::midi::message::Message; | ||
use crate::midi_types::{Channel, MidiMessage, Value7, Value14, Note, Program, Control}; | ||
use crate::data::usb_midi::cable_number::CableNumber::{Cable0,Cable1}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe CableNumber
could be moved to midi-types
? I'm not sure how useful they would be outside of the context of usbd-midi, but it could avoid duplication if a different project implements USB MIDI (maybe a usb
feature could be added to midi-types
?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I could see that being a TODO
in case anything ever wanted it but if nothing ever does, it doesn't have any value for other non usb midi work so, I figure, no rush?
I've intentionally disabled |
cable_number can never fail, 0xFF >> 4 is always less than 16 propagate parse error
Hi Guys, I am interested in using this library in my next project, but wanted to check the status of merging this PR. I am exploring creating libraries that make use common representation of notes, so having a standard language for usbd-midi would be very useful! |
I forked over to https://github.com/rust-midi/usbd-midi but I need to do a little bit of debugging |
Hi I am interested in this PR. Is there anything that needs to be done or I could help? For example do some testing? |
I would like to close this PR without merging in favour of not having an additional dependency that has to be maintained. As I explained in #5 my preferred solution would be just to do the transport-related tasks in this crate and leave it up to the user which crate he wants to use for converting the raw data to specific types and do fancy calculations on them. Otherwise, this crate would have to be updated everytime when a new version of I'll leave this PR open for some comments for a few days. I'm aware that a good amount of work went into it and it's disappointing to have it discarded. |
I see a lot of value in having shared types that we can use within an embedded rust ecosystem. It feels to me like that value outweighs some speculative idea of the |
I think we need to find a nice way to connect this crate with So the main challenge is probably to find a good solution for dealing with SysEx data, or do you see some other aspects that require internal parsing? |
You do have to generate what this library calls the I can totally see ripping out all of the MIDI specific stuff from this library and simply provide a raw u8 slice/array interface that lets users manage the encode/decoding to/from some other representation (like with that and pub enum Packet<'a> {
Midi(&'a [u8]),
SysexStart(&'a [u8]),
SysexContinue(&'a [u8]),
SysexEnd(&'a [u8])
} on the output, maybe just a method that takes a slice and generates the needed packets.. like |
So for my 2c. I did spent a bit of effort in the design of types here to follow Domain Driven Design, to make it so the functions are expecting valid data. A MidiNote doesn't have the same overlapping domain as a u8, so if the user sends you invalid data, how do we then handle it in the crate?. Clamp it?, Mask it?, either way is unexpected, so the idea is if you are parsing from a u8, you need to define what happens in your library if it's not a valid midi note. You can even see MidiNote is fairly easy to go into u8s and u7s, I think the time the TryFrom trait wasn't stable, I believe a TryFrom trait and impl could help without changing the types too much. I suspect you wouldn't even need TryFrom from u7 just From (it probably just wasn't implemented yet), as iirc a midi notes space is similar to a u7 That being said, a core, complete definition of a midi note in a nostd crate is probably better to use. It didn't exist at the time so I created a minimal one, however if the definition in another crate is just the data types, and doesn't bring in std-reps which would make the crate less portable, I see no reason to not share + use other dependencies. On the Yamaha vs Common one. It probably makes sense for midi-types to have both definitions, with the From conversions to change between them, and maybe some Into's that. Oh and one whether bits are used or not in practice, the aim of this implementation was to be truthful to the usb-midi specification. lots of annoying time was spent to make sure the domains were covered, to make it useful in contexts I didn't predict, so at the moment we are decently true to the spec (I believe) even with its annoying inconsistencies!. Granted there might be gaps, but the library tries to be truthful to the spec, so that if a consumer needs the cable number it is faithfully there. even if a heap of other software ignores it |
That's quite similar to what I had in mind,maybe even better. I will open a new branch for this to be implemented and tested. |
@btrepp I can see your points and they are all valid. The dependency issue is a real problem though, it doesn't strike the crate maintainer but the end user when there are conflicting versions in the whole dependency tree. We can, of course, leave all the checks in that you've implemented, so the user can't just send garbage data. But ideally, when using |
Btw. if you really want to have |
I think the idea of removing all the types and focusing on the transport, providing a simple way of getting data in and out and letting the user decide what they use to encode/decode (if they want that at all), makes a lot of sense. I'll close this issue. @btrepp's notes make sense but that could really apply to |
It took me a bit to get back to it but here is a PR that simply replaces the
usbd-midi
bespoke midi types with the types and conversion functions from the sharedmidi-types
andmidi-convert
crates. This allows users to share data directly betweenusbd-midi
and embedded_midi or any other crate that might use those same shared types.The only minor cleanup I did was to remove the unused types and expand
CodeIndexNumber
The test data changed a little bit because
midi-types
uses the more common -2..8 octave range for 12-tone english note names whereusbd-midi
was using the yamaha convention.