Stream: platform development

Topic: Advice for returning Rust a complex struct?


view this post on Zulip jan kili (Nov 21 2024 at 01:05):

I've started making a new platform as the foundation of a music project I'm working on: https://gitlab.com/JanCVanB/roc-on

Ideally, I could have my Roc main function return a Rust struct representation of a MIDI file (a multi-tracked series of MIDI messages), but I expect that to be very complicated to implement, due to memory mapping / boxing / whatever else I haven't learned yet about advanced platform interfaces.

I've started by cheating and just writing/reading a JSON to/from disk as my app-platform interface. However, doing that with serde_json and roc-json seems to not naively scale, currently because I can't figure out how to map tags to enums.

I'm open to any input on how to best proceed! What's the most straightforward way today for passing complex data to a platform? Will I be able to avoid implementing the MIDI bytes spec from scratch in a Roc library? Do you recommend avoiding midly (over the similar midi-msg crate) because of its exotic u7s and u15s, or is that a useful exercise for Roc to face?

view this post on Zulip Luke Boswell (Nov 21 2024 at 01:11):

Cool. I think you could have Roc return one of these... or at least something close and then write something like impl From<roc::Midi> for midly::Smf ...

view this post on Zulip Luke Boswell (Nov 21 2024 at 01:11):

So you can do

let midi : midly::Smf = rocMain().into();

view this post on Zulip Luke Boswell (Nov 21 2024 at 01:12):

What can you do with a midly once you have it? does it integrate well with other libraries?

view this post on Zulip jan kili (Nov 21 2024 at 01:14):

I'm currently accepting that for my use cases it makes sense to write my own midly consumer to iterate the message tracks and populate the fundsp sequencers with timed events (and possibly also forward messages to external hardware).

view this post on Zulip jan kili (Nov 21 2024 at 01:17):

The big benefit of using a (hopefully) complete/well-maintained MIDI representation crate is that I can use it as the common protocol between a variety of senders and receivers that I may plug into this system.

view this post on Zulip jan kili (Nov 21 2024 at 01:20):

Do you know of any complete examples I can adapt for the From<roc::ComplexDeeplyNestedStructRecordWithEnumTags> part?

view this post on Zulip jan kili (Nov 21 2024 at 01:23):

I'm expecting that will require a Roc library with a record type alias that looks like Smf (which I hope can leverage very-idiomatic Roc tags) and a pile of for loops in the Rust impl.

view this post on Zulip Luke Boswell (Nov 21 2024 at 05:07):

@JanCVanB I got carried away and build a minimal e2e demo that calls into roc and returns a midly:Smf struct. It doesn't do much with it, just debug prints to stdio for now. But all the parts are there and look to be working ok.

https://github.com/lukewilliamboswell/roc-on-simple

app [main] { pf: platform "../platform/main.roc" }

main = \{} -> {
    header: {
        format: SingleTrack,
        timing: Metrical 10,
    },
    tracks: [
        [
            { delta: 1, kind: Escape [] },
            { delta: 2, kind: Midi { channel: 1, message: NoteOn { key: 1, vel: 2 } } },
            { delta: 3, kind: Meta EndOfTrack },
        ],
    ],
}
$ cargo run
   Compiling roc-on-simple v0.1.0 (/Users/luke/Documents/GitHub/roc-on-simple)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.36s
     Running `target/debug/roc-on-simple`
Smf { header: Header { format: SingleTrack, timing: Metrical(u15(10)) }, tracks: [[TrackEvent { delta: u28(1), kind: Escape([]) }, TrackEvent { delta: u28(2), kind: Midi { channel: u4(1), message: NoteOn { key: u7(1), vel: u7(2) } } }, TrackEvent { delta: u28(3), kind: Meta(EndOfTrack) }]] }

view this post on Zulip Luke Boswell (Nov 21 2024 at 05:11):

Note, it's dynamically linking the roc app... I need to dig in and fix our --no-link build pipeline if you want to make a static executable instead.

view this post on Zulip Luke Boswell (Nov 21 2024 at 10:45):

Luke Boswell said:

Note, it's dynamically linking the roc app... I need to dig in and fix our --no-link build pipeline if you want to make a static executable instead.

Done :smiley:

view this post on Zulip jan kili (Nov 21 2024 at 16:10):

OH WOW LUKE YOU ROC

view this post on Zulip jan kili (Nov 21 2024 at 16:11):

Thank you for getting carried away, I'm excited to dig into this today :heart_eyes:


Last updated: Jul 05 2025 at 12:14 UTC