Loopy Pro: Create music, your way.

What is Loopy Pro?Loopy Pro is a powerful, flexible, and intuitive live looper, sampler, clip launcher and DAW for iPhone and iPad. At its core, it allows you to record and layer sounds in real-time to create complex musical arrangements. But it doesn’t stop there—Loopy Pro offers advanced tools to customize your workflow, build dynamic performance setups, and create a seamless connection between instruments, effects, and external gear.

Use it for live looping, sequencing, arranging, mixing, and much more. Whether you're a live performer, a producer, or just experimenting with sound, Loopy Pro helps you take control of your creative process.

Download on the App Store

Loopy Pro is your all-in-one musical toolkit. Try it for free today.

Calling developers: anyone else notice some fundamental Core MIDI changes in iOS 14?

2

Comments

  • edited December 2020

    @AlanC3 said:
    0 CoreMIDI MIDI::Packetizer::add
    1 CoreMIDI MIDI::LegacyPacketList::traverse
    2 CoreMIDI MIDI::LegacyPacketList::traverse
    3 CoreMIDI MIDIProcess::WriteOutput
    4 CoreMIDI MIDISend

    I've heard Xequence user reports about "the app keyboard somehow feeling more laggy in iOS 14.2". I wonder if this conversion code maybe introduces significant latency too when using timestamps in the past (unlikely seeing that it only has to process a few bytes, but then again, who knows how many CIA security checks the MIDI packets are subjected to internally :D ) ?

    Thanks @moodscaper and @AlanC3 for the detective work. At least I've dumped an informational message into our news API so users know that if Xequence is suddenly crashing all the time, "it wasn't me" ;)

  • edited December 2020

    @moodscaper said:
    Hey @AlanC3 - been tearing my hair out on this too - crashing in same area, in my case, I'm just sending a single MIDI packet / message to reset aftertouch.

    Exactly the same trace. I guess they have some clunky code in place to convert packet lists to event lists or something like that...

    The fact that it's crashing for you on a single command and with the same stack trace is quite the coincidence, isn't it? ;)

    Nice to have confirmation that it's not some weird bug in my own code that I'd missed.

    Funnily enough, I was just about to update on this thread as I've been digging around this morning.

    I read on the JUCE forum that allegedly this issue is fixed in iOS 14.3.

    I really hope so: I'd rather not have to do the conversion to MIDI 2.0 right now.

    Core Audio team really do seem to have The Reverse Midas Touch these days don't they? :neutral:

    It's not just the Core Audio team; Core Graphics has recently developed some bizarre behaviour that wasn't there in previous releases...

  • @Samu said:
    But yea, it's getting a bit ridiculous like the timer on the Apple Watch that keeps track on how long you should wash hands, sooner or later they'll bake in a 'wank detector' with endurance exercises or some other stupid sh*t like that.

    I wonder if it will get its own ring on the fitness app...?

  • My turn for a rant:

    Just been looking at the documentation for all this. So I will ultimately need to use MIDISendEventList / MIDIReceivedEventList to send MIDIEventPackets now. What’s in one of those?

    typedef struct MIDIEventPacket {
        ...
    } MIDIEventPacket;
    

    Not exactly helpful.

    But there are helper functions to build events in MIDI 2.0 UMP format, like MIDI1UPNoteOn; how do they work?

    Function

    MIDI1UPNoteOn

    No overview available.

    Sigh.

    What’s happening on the input side? Well, MIDIInputPortCreateWithBlock has been replaced with MIDIInputPortCreateWithProtocol and it takes a MIDIReceiveBlock instead of a MIDIReadBlock.

    But MIDIReceiveBlock is listed in the Deprecated Symbols section...

    :|

    This is why I'm going back to building kids educational apps.

  • @AlanC3 - it's a crazy hot mess isn't it? And I'm pretty sure Gene De Lisa mentioned that at least one of those helpers blows-up when you call it.

    I'm guessing we're in the same boat - I've lots of code dependent on the "old" packet list and block-based port stuff in one of my apps. Significant number of iOS music makers not updating to iOS 14 yet either, and there's no way I'm coding around all this new stuff with horrendous #available blocks.

    I strongly suspect the audio team (if there is one) has zero influence on what gets released and when, so we're basically on their dev branch and we get whatever they happened to check-in on iOS update build / release day...

  • @AlanC3 said:
    This is why I'm going back to building kids educational apps.

    Wait until iOS 17 requires user permission and an "entitlement" to request touch screen access or draw pixels on the display ;)

  • I'm just taking a cursory look at the UMP specification. Is this satire?

    I mean, seriously... is this for 3 year olds?

  • edited December 2020

    @SevenSystems said:

    @Samu said:

    I'm very careful with my opinions on this stuff normally because I realize the world has been getting extremely paranoid in the past two decades or so (for my taste) -- but everyone seems to accept it all as normal. It doesn't stop with computery stuff. The "LETHAL DANGER" signposts next to every creek and puddle of mud are a symptom of the same societal illness.

    (my personal bottom line is: Life is dangerous. That's NORMAL. Absolute safety doesn't exist and if it did, it would make life miserable). But I think that's also a very oldschool attitude :) (well I'm 41, so...)

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

  • @AudioGus said:

    @SevenSystems said:

    @Samu said:

    I'm very careful with my opinions on this stuff normally because I realize the world has been getting extremely paranoid in the past two decades or so (for my taste) -- but everyone seems to accept it all as normal. It doesn't stop with computery stuff. The "LETHAL DANGER" signposts next to every creek and puddle of mud are a symptom of the same societal illness.

    (my personal bottom line is: Life is dangerous. That's NORMAL. Absolute safety doesn't exist and if it did, it would make life miserable). But I think that's also a very oldschool attitude :) (well I'm 41, so...)

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

    Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished ;)

  • @SevenSystems said:

    @AudioGus said:

    @SevenSystems said:

    @Samu said:

    I'm very careful with my opinions on this stuff normally because I realize the world has been getting extremely paranoid in the past two decades or so (for my taste) -- but everyone seems to accept it all as normal. It doesn't stop with computery stuff. The "LETHAL DANGER" signposts next to every creek and puddle of mud are a symptom of the same societal illness.

    (my personal bottom line is: Life is dangerous. That's NORMAL. Absolute safety doesn't exist and if it did, it would make life miserable). But I think that's also a very oldschool attitude :) (well I'm 41, so...)

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

    Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished ;)

    Lets just put you in charge!

  • edited December 2020

    I can confirm the other bug mentioned on the Juce Forums thread:

    https://forum.juce.com/t/ios-14-2-midi-connections-broken/42440/8

    When you call MIDIObjectGetStringProperty it may return with no error but give you a null string pointer. This was causing a crash when I was requesting the endpoint name to build a list of available MIDI devices: the function apparently succeeded, but the returned string was null causing a crash when I attempted to convert it to an NSString. My fault for not checking for null, but the endpoint name for a device should always be present.

    This is another intermittent one that I can't reproduce: I've had one crash report with this as the cause.

  • @AlanC3 makes you wonder who the hell they let loose on the Core MIDI code between 14.1 and 14.2 release...

    Luckily I escaped this other issue because of the crazy stuff I have to do when calling MIDIObjectGetStringProperty() from Swift...

  • Looking at it some more I can't be certain the pointer returned by MIDIObjectGetStringProperty was null, all I can say is that it was definitely invalid since the app crashed when copying the string contents. That said, if you've not been bitten by this from Swift with all the extra checks that involves, it being null does seem most likely.

  • @AlanC3 - yep, lots of null type checking going on in Swift, so you have to do shenanigans like this, which I guess should protect you...

    var foo: Unmanaged<CFString>?
    MIDIObjectGetStringProperty(midiObjRef, kMIDIPropertyName, &foo)
    if let bar = foo?.takeRetainedValue() {
        return bar as String
    }
    
  • @SevenSystems said:

    @AudioGus said:

    @SevenSystems said:

    @Samu said:

    I'm very careful with my opinions on this stuff normally because I realize the world has been getting extremely paranoid in the past two decades or so (for my taste) -- but everyone seems to accept it all as normal. It doesn't stop with computery stuff. The "LETHAL DANGER" signposts next to every creek and puddle of mud are a symptom of the same societal illness.

    (my personal bottom line is: Life is dangerous. That's NORMAL. Absolute safety doesn't exist and if it did, it would make life miserable). But I think that's also a very oldschool attitude :) (well I'm 41, so...)

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

    Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished ;)

    Did you just add that disclaimer when you launch Xeq2?
    I swear it wasn’t there last night when I was using it.
    😄

  • @CracklePot said:

    @SevenSystems said:

    @AudioGus said:

    @SevenSystems said:

    @Samu said:

    I'm very careful with my opinions on this stuff normally because I realize the world has been getting extremely paranoid in the past two decades or so (for my taste) -- but everyone seems to accept it all as normal. It doesn't stop with computery stuff. The "LETHAL DANGER" signposts next to every creek and puddle of mud are a symptom of the same societal illness.

    (my personal bottom line is: Life is dangerous. That's NORMAL. Absolute safety doesn't exist and if it did, it would make life miserable). But I think that's also a very oldschool attitude :) (well I'm 41, so...)

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

    Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished ;)

    Did you just add that disclaimer when you launch Xeq2?
    I swear it wasn’t there last night when I was using it.
    😄

    Yes. Is the wording too harsh? 😬

  • So I've installed iOS 14.3 which, according to the thread on the juice forum, should have stopped the MIDI problems. Assuming Apple didn't drop whatever fixes were in the betas from the final release. :o

    I can't get my own app to crash (but then I couldn't recreate the problem on 14.2) and I'm not seeing problems anywhere else, so here's hoping...

  • @AlanC3 Good to know. I think I just got my first 14.2 crash stemming from the MIDI issues

  • An additional comment Form the Auria Pro dev on Core MIDI and 14.2 found on the Auria Pro forum.

  • The crash I was getting on the call to MIDISend() seems to be fixed on 14.3

    I guess disabling CoreMIDI on 14.2 is one way of stopping the crashing! :neutral:

  • @moodscaper said:
    The crash I was getting on the call to MIDISend() seems to be fixed on 14.3

    That's good. Looks like Apple have fixed it.

  • @SevenSystems said:
    I'm just taking a cursory look at the UMP specification. Is this satire?

    I mean, seriously... is this for 3 year olds?

    I think that a number of these documents are written for various parties, and it is almost impossible to imagine how much can be misinterpreted no matter how clear the writer thinks it is. I usually find that what people is too much actually isn't enough because it misses some material. Since much of the MIDI 2.0 material hasn't been released to the general public, I don't feel comfortable using any of the MIDI 2.0 features. I'm still trying to find information on big-endian/little-endian issues that occur when 32-bit integers (presumably unsigned) are sent over byte oriented systems.

  • @moodscaper said:
    @AlanC3 - yep, lots of null type checking going on in Swift, so you have to do shenanigans like this, which I guess should protect you...

    var foo: Unmanaged<CFString>?
    MIDIObjectGetStringProperty(midiObjRef, kMIDIPropertyName, &foo)
    if let bar = foo?.takeRetainedValue() {
        return bar as String
    }
    

    When I look at https://developer.apple.com/documentation/coremidi/1495282-midiobjectgetstringproperty it says that MIDIObjectGetStringProperty returns a value of type OSStatus. The value of foo is only defined if the returned value is noErr. Frankly, I'm not familiar with Swift and became unhappy the more I read about it. What checks the returned value? The web page also explicitly states that the value of foo can be null.

    My understanding is that Swift is a wrapper around Objective-C code and I found the discussion of what happens with the wrapper to be unclear.

  • @SevenSystems said:

    @moodscaper said:
    I think I'm maybe at the point where I'm spending 30-40% of my development time fixing or working around stuff that Apple break or deprecate...

    ...you forgot dealing with IDs, certificates, provisioning profiles, "WhyDoesTheAppUseTheLocalNetwork" descriptions and entitlements 😂

    My problem is that they don't seem to be consistent on the meaning of the word deprecate. Look at https://bradleyross.github.io/ObjectiveC-Examples/Documentation/BRossTools/FunctionalArea.html The items listed under new architecture (MIDI 2.0) are only available in the latest versions of the operating systems and older versions of the operating system are still supported, the items listed under "old architecture" must still be current since that is the only way to work with older operating systems. My understanding is that is that the lifecycle is: beta, production, superseded (will be deprecated), deprecated, and removed. Also notice that the tag placed on the methods in the documentation is inconsistent with what I consider to be their actual status. I look at the documentation on the web, the contents of the header files, and then run the header files through Doxygen. At that point, I still feel like I'm throwing dice to get my answer.

    I'm one of those old curmudgeons who remember when documentation actually documented something and filled up bookcases.

  • @BradleyRoss said:

    @moodscaper said:
    @AlanC3 - yep, lots of null type checking going on in Swift, so you have to do shenanigans like this, which I guess should protect you...

    var foo: Unmanaged<CFString>?
    MIDIObjectGetStringProperty(midiObjRef, kMIDIPropertyName, &foo)
    if let bar = foo?.takeRetainedValue() {
        return bar as String
    }
    

    When I look at https://developer.apple.com/documentation/coremidi/1495282-midiobjectgetstringproperty it says that MIDIObjectGetStringProperty returns a value of type OSStatus. The value of foo is only defined if the returned value is noErr. Frankly, I'm not familiar with Swift and became unhappy the more I read about it. What checks the returned value? The web page also explicitly states that the value of foo can be null.

    My understanding is that Swift is a wrapper around Objective-C code and I found the discussion of what happens with the wrapper to be unclear.

    Swift is definitely not a wrapper around Obj-C. Many of the Obj-C libraries have direct, zero cost, bridges to the Objective-C libraries and Swift was designed to handle this, but Swift isn't wrapping Objective-C to do this.

    What you are seeing in these types of calls is older and deeper than that though. If you see "Core" in a library name, it usually means it's a C implementation at base. You end up needing to think a bit in a C way when you work directly with these libraries. Who checks the OSStatus value depends on who is calling the function. Sometimes, you are providing the implementation and you provide the status or the error. Sometimes it's the other way around.

    There were several libraries talked about at this years WWDC that won't ever have Objective-C versions. Swift with some C is the way everything is moving at Apple now. Swift isn't my favorite language in the world, but it is pretty good and you might as well start using it if you plan on doing dev work on Apple platforms.

  • edited June 2021

    @NeonSilicon is spot-on. That code snippet is ugly due to it talking essentially to an API designed for C.

    In the code, foo is declared as possibly being nil, and bar will only be assigned a non-nil value if foo isn't nil. What's missing / implied in the snippet is the else return nil, and the return type of an enclosing function being a String? optional (i.e. possibly nil :smile: )

    In the (contrived) example, I don't check the OSStatus return value because I don't care. All I care about is whether I get something back or not, and there's a test for that when takeRetainedValue() is called.

    There's all sorts of noisy code like this when you have to interact with the C-based APIs in Swift. Dealing with pointers is especially fun...

    Documentation... Well, as someone once told me, if you're taking on this particular tech-stack (especially the audio sub-set) be prepared to be 40% developer and 60% detective :wink:

  • Having dealt with a lot of messy C code in the best, I interpreted the documentation as saying that if the return value (OSStatus), is not noErr, the value of foo is undefined. That means that the value may be the right value, the wrong value, nil, or something totally inappropriate. Assuming anything else is like being a forensic scientist without a magnifying glass, fingerprint kit, or any other tools. "Undefined" is a term I became very familiar with when coding for IBM mainframes. I still shudder when I hear the hexadecimal error code 0c4. For MS-DOS programmers, the equivalent was "General Protection Fault".

  • wow, interesting thread.

  • can us non dev's help at all? can we write apple or something?

  • @SevenSystems said:

    I think a lot of this has to do with lawyers, the legal system, the industry of litigation etc.

    Then lawyers need to be banned, the legal system needs to change, and the industry of litigation has to be demolished ;)

    I see... your reaction against the profession of legal practice is conditional on a premise.
    I've already figured out you're a no government type so this is a consistent message.

    Will there be a Xequence 3 anytime soon? Just kidding. I respect your work and will pay for more MIDI focused tools.
    I think I own the whole catalog.

Sign In or Register to comment.