Comments (16)
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.
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.
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.
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.
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.
I wouldn't mind also exploring a hunch I have
Just tested my theory. Looks like 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.
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.
- Link your app against the MIDIKitC package library
- Import MIDIKitC
import MIDIKitC
- Then every time
midiManager.addThruConnection
is called, add this parameter:midiManager.addThruConnection( outputs: [], inputs: [], tag: "Thru1", lifecycle: .nonPersistent, using: CMIDIThruConnectionCreateNonPersistent )
from midikit.
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.
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.
- One possible workaround is to not use thru connections at all. Instead use
addInputConnection
and feed its events to anaddOutputConnection
. It achieves the same goal, albeit less performant and less convenient. - Given some work, MIDIKit could transparently implement that workaround on platforms that have the Code MIDI bug.
from midikit.
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.
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.
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.
@NaanProphet Would you like to test main branch? Make sure you pull latest of course.
from midikit.
@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.
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.
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)
- Move bluetooth SwiftUI views/classes into MIDIKit?
- midiManager.endpoints and midiManager.devices.devices only give an empty list `[]` HOT 1
- Example: Wired USB Connection from iOS device to Mac HOT 3
- Expose inits for CoreMIDI packets and packet lists HOT 2
- MIDI 2.0 RPN/NRPN HOT 3
- MIDI Notification - Object `removed` may return empty metadata HOT 1
- Broken link in docs for Event Filters HOT 3
- MIDIEventLogger example In Advanced Examples folder won't build HOT 13
- `MIDIFile` could use `Hashable` conformance HOT 1
- Crash while parsing MIDI file HOT 1
- Translation of Note On with 0 Velocity to Note Off Should Be Opt-In (Off by Default) HOT 1
- MIDI File parse bug. HOT 4
- `MIDIFile`: Add structure validation
- MTCVideoPlayer project fails to build HOT 1
- Convert `MIDIManager` to global singleton
- MIDIKitSMF: slow parse time for very big SMF files HOT 2
- Docs: "MIDI.File" typo? HOT 3
- ProgramChange midi1RawBytes() HOT 1
- 80-90% CPU Usage For HUITest Client HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from midikit.