Git Product home page Git Product logo

Comments (16)

orchetect avatar orchetect commented on September 25, 2024 1

I've just pushed an update to main branch that re-enables thru connections.

Now on supported systems they will work, otherwise it throws an error (try/catch) and no longer fatal errors.

I wouldn't mind also exploring a hunch I have. I am wondering if an Obj-C target (just for internal use) was added to the package and imported by way of #if canImport(ObjCTarget) the package could remain compatible with Swift Playgrounds while also conditionally giving me access to the Obj-C workaround that would add Big Sur / Monterey support to non-persistent thru connections.

from midikit.

NaanProphet avatar NaanProphet commented on September 25, 2024 1

I've completed work on an implementation that allows non-persistent thrus to always work on macOS as outlined above.

Very cool!

@NaanProphet Would you like to test main branch? Make sure you pull latest of course.

Pulled the latest, and thru connections are working for me as expected on Ventura.

Note On: F3 midi2(28160) 1
Note Off: F3 midi2(32768) 1
Note On: G2 midi2(27648) 1
Note Off: G2 midi2(32768) 1
Note On: C4 midi2(28160) 1
Note Off: C4 midi2(32768) 1
Note On: B2 midi2(18432) 1
Note Off: B2 midi2(32768) 1
Note On: A3 midi2(16384) 1
Note Off: A3 midi2(32768) 1

from midikit.

orchetect avatar orchetect commented on September 25, 2024

The issue started in macOS Big Sur (this is explained in the docs for midiManager.addThruConnection). It remains unresolved even in Ventura.

I have a workaround that involves using Objective-C:

OSStatus CMIDIThruConnectionCreateNonPersistent(CFDataRef inConnectionParams, MIDIThruConnectionRef *outConnection)
{
    return MIDIThruConnectionCreate(NULL, inConnectionParams, outConnection);
}

But the workaround hasn't been included in order to maintain MIDIKit as a pure Swift library, which allows it to run in Swift Playgrounds on iPad for instance.

Essentially, the Swift bridging of Core MIDI API seems to have an issue where passing nil into the first parameter of MIDIThruConnectionCreate is not interpreted as a C NULL and the connection gets created persistently no matter what. This causes all sorts of issues with orphan connections so it was safest to exempt thru-connections from being made using MIDIKit until a solution can be found.

I've had a radar open with Apple for a long time with no response. And a StackOverflow post asking for suggestions which hasn't surfaced anything new.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

I just spent a bit of time re-investigating this.

It appears the issue may be fixed in macOS Ventura. So I may conditionally allow thru connections but throw a normal error instead of a fatal error on unsupported systems (Big Sur and Monterey).

I've spent hours on many occasions trying to find a Swift-only workaround for the affected platforms. I'm not sure there is a way around that.

from midikit.

NaanProphet avatar NaanProphet commented on September 25, 2024

Thanks for shedding light on this! My bad, I missed that note in the midiManager.addThruConnection docs.

Sounds like Big Sur and Monterey would continue to be unsupported then, and Apple just moved on and fixed it in Ventura. It's a tradeoff making MIDIKit Swift-only, but it is definitely nice for the reasons you mentioned.

Hope to see the Ventura support in an upcoming release! Thanks for your reply.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

I wouldn't mind also exploring a hunch I have

Just tested my theory. Looks like no dice.

no-dice

However, I did discover that merely having an Obj-C target ("ClangTarget") in a package does not prevent Playgrounds from compiling - so long as the target is not a dependency of any Swift targets in the package.

And when adding a package as a dependency to any app (Xcode or Playgrounds, same deal), any target can be imported on its own. So an Obj-C target can be manually imported by a user of MIDIKit. And it could contain the method to work around this Core MIDI bug.

I am imagining addThruConnection could have an Obj-C target's method injected, either by reference or in a closure.

It would be a bit of manual setup which is not ideal. But there's a good chance it would work.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

The package can be structured such that an Obj-C target can be imported on Mac without affecting Swift Playgrounds support.

Basically, it involves 3 extra steps.

  1. Link your app against the MIDIKitC package library
  2. Import MIDIKitC
    import MIDIKitC
  3. Then every time midiManager.addThruConnection is called, add this parameter:
    midiManager.addThruConnection(
        outputs: [],
        inputs: [],
        tag: "Thru1",
        lifecycle: .nonPersistent,
        using: CMIDIThruConnectionCreateNonPersistent
    )

from midikit.

orchetect avatar orchetect commented on September 25, 2024

Unfortunately I've run across another issue in testing. It's possible that thru connections are simply broken entirely on Big Sur and Monterey no matter what.

I dug out some old test projects and I recall now that even in a new, pure Obj-C project without MIDIKit at all, I was unable to get thru connections to transmit data.

There was a thread (perhaps one of many) that talked about this: https://stackoverflow.com/questions/54871326/how-is-a-coremidi-thru-connection-made-in-swift-4-2

I just tested this same code on Swift 5 and OS X 12.4, and it doesn't seem to work for me. MIDIThruConnectionCreate returns noErr, but no MIDI packets seem to flow.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

Just to recap. I physically tested both persistent and non-persistent thru connections on all of these:

  • macOS 10.15 Catalina (and earlier): Both Swift and Obj-C work correctly
  • macOS 11 Big Sur: Thru connections are completely broken no matter what
  • macOS 12 Monterey: Thru connections are completely broken no matter what
  • macOS 13 Ventura: Both Swift and Obj-C work correctly

Additionally, on affected systems (Big Sur and Monty):

  • No amount of tweaking or introspection of the thru connection parameters made a difference. In fact, thru connection parameters were identical across all macOS versions (Catalina thru Ventura).
  • Absolutely nothing useful showed up in the system console log. Nothing to do with MIDI, Core MIDI, or any related errors or exceptions.

Given all of this information, there's a couple conclusions.

  1. One possible workaround is to not use thru connections at all. Instead use addInputConnection and feed its events to an addOutputConnection. It achieves the same goal, albeit less performant and less convenient.
  2. Given some work, MIDIKit could transparently implement that workaround on platforms that have the Code MIDI bug.

from midikit.

NaanProphet avatar NaanProphet commented on September 25, 2024

Unfortunately I've run across another issue in testing. It's possible that thru connections are simply broken entirely on Big Sur and Monterey no matter what.

I'm learning so much about this, thank you!

Given all of this information, there's a couple conclusions.
2. Given some work, MIDIKit could transparently implement that workaround on platforms that have the Code MIDI bug.

This is a really nice idea. Transparently providing thru connections on Big Sur and Monterey would be a nice value-add for MIDIKit compared to other libraries, and still keeps them available and performant for other OS versions.

Basically, it involves 3 extra steps.

A third option might be to provide a manual client-side workaround for Big Sur and Monterey to enable the transparent feature by doing something similar to the Objective-C workaround.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

Transparently providing thru connections on Big Sur and Monterey would be a nice value-add for MIDIKit compared to other libraries

I'll work on implementing this. It shouldn't be too difficult and would remove a lot of confusion for end users.

A third option might be to provide a manual client-side workaround for Big Sur and Monterey to enable the transparent feature by doing something similar to the Objective-C workaround.

A piece of 3rd-party software like a loopback connection router? There are options out there, yes. But I think we can do it with the above solution instead.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

I've completed work on an implementation that allows non-persistent thrus to always work on macOS as outlined above.

Persistent thrus are still irredeemably broken on Big Sur and Monterey and nothing can be done about that - they will throw an error.

I am also now testing iOS versions to see if they were affected during the same period in history.

  • iOS 13.7: No bug
  • iOS 14.5: Has bug
  • iOS 15.5: Has bug
  • iOS 16.2: No bug

As expected, iOS releases during the same time period are affected. I'll update MIDIKit internals and docs to reflect that it's macOS 11/12 and iOS 14/15.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

@NaanProphet Would you like to test main branch? Make sure you pull latest of course.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

@NaanProphet Thanks. If you have Macs with any other versions of macOS and have the opportunity to test on them that's great but no problem if not. I'm satisfied that the unit tests prove that it works as expected on different OS versions.

I will look to release a new version with the updates soon, but in the meantime you can keep using main branch.

from midikit.

orchetect avatar orchetect commented on September 25, 2024

I've pushed release 0.8.2 which includes these fixes.

It's safe to assume Apple will never go back and patch the affected platforms, so MIDIKit adapts itself as best it can on those OS versions. Nothing further can be done.

from midikit.

NaanProphet avatar NaanProphet commented on September 25, 2024

I've pushed release 0.8.2 which includes these fixes.

It's safe to assume Apple will never go back and patch the affected platforms, so MIDIKit adapts itself as best it can on those OS versions. Nothing further can be done.

Thanks very much! This is wonderful.

from midikit.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.