by

Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Activity
    Paul McClernan
    @PaulMcClernan
    @montegoulding I'm taking a different approach now, getting the MIDIObject referenced in the message and then getting it's properties, the lines where I was trying to get a string from the CFSStringRef element have been commented out:
    https://github.com/PaulMcClernan/LCB_CoreMIDI/blob/master/LCB_CoreMIDI_0.6.1.lcb#L247-L281
    Monte Goulding
    @montegoulding
    Hi @PaulMcClernan for future reference then:
    • Do not use CFBridgingRelease as we don’t use ARC
    • The following should work:
      variable tNSStringObj as ObjcObject
      put PointerToObjcObject(tCFStringRef) into tNSStringObj
      variable tString as String
      put StringFromNSString(tNSStringObj) into tString
    Paul McClernan
    @PaulMcClernan
    @montegoulding ah, so no au
    Automagic Ref count stuff, good to know, I was basically trying whatever I could find to try.
    It seems there's not a lot of people even bothering to fully parse these messages...in any language.
    I'm pretty sure even Apple doesn't bother, at least not in GarageBand (it just pops up an alert that includes the count of ins / outs)
    Paul McClernan
    @PaulMcClernan
    The reason I'm trying to parse as much as I can is because I'm receiving a 1 callback for each active MIDI Object on my system, so for example of I remove Network MIDI from Apples Audio-MIDI serup when
    Setup app, I get maybe 5 callbacks instead of just one.
    Sorry, I'm on mobile in my car
    Monte Goulding
    @montegoulding
    hopefully not driving!
    Paul McClernan
    @PaulMcClernan
    :-D no sitting outside of my work on dinner break
    Monte Goulding
    @montegoulding
    I guess the lunch room is to be avoided right now
    Paul McClernan
    @PaulMcClernan
    ✓ yeah, hard to eat with a mask on, I wish I could avoid physically being here altogether, but apparently I'm a sacrificial..er essential worker
    I work for a company that makes labels for,,among other things, soaps and sanitizers which are pretty essential products right now. We're actually extremely busy.
    Monte Goulding
    @montegoulding
    oh
    definitely essential then I guess
    was all in such short supply down here that all the small gin distilleries started making it
    Paul McClernan
    @PaulMcClernan
    We're making our own Santizer here at work, we already had alcohol for pressroom (not sure what they do with it), we just added in 30% aloe vera gel. But I can't buy Lysol spray anywhere. My wife and two college age sons work in hospitals, they're stripping down in the garage and we were spraying down and bagging shoes with Lysol, but I altrady went through two big cans over the last month and it's sold out everywhere. It's crazy, I'm a wreck, trying to keep my mind off of it with coding and otherwise staying busy.
    Paul McClernan
    @PaulMcClernan
    if element 1 of tMIDINotificationIDnSize = 4 then
    PointerToMIDIObjectPropertyChangeNotification(tMIDIObjectPropertyChangeNotification,pMIDINotifyStructPtr, element 2 of tMIDINotificationIDnSize )
          put element 5 of tMIDIObjectPropertyChangeNotification into tCFStringRef
          put PointerToObjcObject(tCFStringRef) into tNSStringObj
          put StringFromNSString(tNSStringObj) into tString
    That works! but I swear that I already tried PointerToObjcObject(tCFStringRef) into tNSStringObj
    Paul McClernan
    @PaulMcClernan
    Actually I'm not sure that it is working, but it's not crashing, OR maybe there is nothing in the CFString to get, as in null...
    Monte Goulding
    @montegoulding
    @PaulMcClernan yes it doesn’t look good over there. Fairly sure you would be getting a crash if either tCFStringRef or tNSStringObj were null. Is it possible they are empty strings?
    Paul McClernan
    @PaulMcClernan
    Hmm, it didn't crash on my Mac at work running Mohave 10.14.6, but it does crash on my laptop at home running Sierra 10.12.6, same code.
    Crashed Thread:        0  Dispatch queue: com.apple.main-thread
    Exception Type:        EXC_BAD_ACCESS (SIGSEGV)
    Exception Codes:       KERN_INVALID_ADDRESS at 0x00006f436e696780
    Exception Note:        EXC_CORPSE_NOTIFY
    
    VM Regions Near 0x6f436e696780:
        MALLOC_LARGE_REUSABLE  0000000118d64000-000000011a806000 [ 26.6M] rw-/rwx SM=PRV  
    --> 
        STACK GUARD            000070000a8f3000-000070000a8f4000 [    4K] ---/rwx SM=NUL  stack guard for thread 7
    
    Application Specific Information:
    objc_msgSend() selector name: retain
    
    
    Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
    0   libobjc.A.dylib                   0x00007fff9ce4f05d objc_msgSend + 29
    1   com.runrev.livecode               0x0000000105e91b5d MCObjcObjectCreateWithId + 61
    2   com.runrev.livecode               0x0000000105eecf04 ffi_call_unix64 + 76
    3   com.runrev.livecode               0x0000000105eed75b 0x105e50000 + 644955
    4   com.runrev.livecode               0x0000000105ef9980 0x105e50000 + 694656
    5   com.runrev.livecode               0x0000000105ef93c1 0x105e50000 + 693185
    Monte Goulding
    @montegoulding
    Hmm… are you sure it’s a CFStringRef you are passing to PointerToObjcObject
    Paul McClernan
    @PaulMcClernan
    I just noticed that in the Swift version it lists it as Unmanaged<CFString> vs. CFStringRef in Objective C
    Trevor DeVore
    @trevordevore
    @PaulMcClernan have you tried checking to see that the element is not nothing before converting? What happens in a test if you pass a variable that is “nothing” to PointerToObjcObject? Does it crash?
    Paul McClernan
    @PaulMcClernan
    @trevordevore
    the element is a 'something' after the memcpy, it logs as a foreign pointer (because I typed it with "r")
    here is the log of tMIDIObjectPropertyChangeNotification elements: [4, 20, 6225980, 2, <foreign pointer 0x7fff375ae130>] all of the other elements appear to be working correct. Testing for null before StringFromNSString makes no difference, if I comment out put PointerToObjcObject(tCFStringRef) into tNSStringObj it doesn't crash.
    Paul McClernan
    @PaulMcClernan
    put PointerToObjcObject(nothing) into tNSStringObj does not cause a crash
    Paul McClernan
    @PaulMcClernan
    I think it might have something to do with that Unmanaged<CFString> thing. Reading this: https://nshipster.com/unmanaged/
    Monte Goulding
    @montegoulding
    @PaulMcClernan I’m perplexed by this. The only thing I can think of is the stringref is already released somehow.
    Paul McClernan
    @PaulMcClernan
    I've moved on to the next, and most important callback procedure I need for my library to receive MIDI data (so far it's been send via virtual source only)...
    I think the difficulties I've been having with blocks are in part due to lack of error feedback for code within a block, when things go wrong within the block's context they either crash the engine (and then at least there's some feedback from macOS crash log) or fail silently.
    Paul McClernan
    @PaulMcClernan
    I'm happy to anounce I have MIDI-in working! ...well at least somewhat, the only problem is that after I send it a bunch of note messages, which I can see logging in the extension console, it crashes with this message in the crash log:
    *** error for object 0x7f8d24b029e0: pointer being freed was not allocated
    it seems to be crashing mostly when I flood it noteon/noteoff messages being sent rapidly
    Brian Milby
    @bwmilby
    That’s cool (the working part, not the crashing part)
    Paul McClernan
    @PaulMcClernan
    So what this ReadProc receives is a pointer to MIDIPacketList which is a struct that is: 1 x Uint32 (that is number of MIDIpackets that follow it) and then an open ended C-array of packets: a packet is 1xUint64 (a Delta MIDITimeStamp, most of the time it will probably be 0 meaning 'right now'), 1xUint16 (num of MIDIMsg bytes in packet ), and then the actual MIDIMsg Bytes; usually 3 or 4 bytes (for non-SysEx messages) but a single MIDIPacket is pre-defined (for Swift) as 8+2+256+2x'padding' (the 2 padding is probably because it has to be 4 byte aligned for ARM/iOS) in the MIDIServices.h
    I'm not sure how to iterate through this PacketList, I used memcpy as before to put the data into a ForeignType of UInt32 followed by 272 Uint8, which gives me the packet count (so far always 1) and the first packet (as a ton of 1 byte elements of a list)...
    One problem is there seems to be null separator bytes in between the elements, I'm having trouble shoe-horning them into the appropriate types (for example there seems to be an extra null byte between the Uint64 TimeStamp and the Uint16 byte count, and then a null byte and then the 3 bytes of actual MIDIMsg bytes).
    Is this how arrays are actually stored in memory, I mean elements are separated by null bytes?
    I think If I could just get a new pointer to the memory starting at the first packet (original pointer's position + 4 bytes, so right after the Uint32 packet count) then I could use CoreMIDI's MIDIPacketNext to iterate through the packets.
    Paul McClernan
    @PaulMcClernan
    I when I make the second value of my ForeignType string anything that is 8 bytes length (should be a Uint64), it fails silently and no input gets logged, but if I substitute two 4 byte values (two Uint32) I get input logging (but of course if that Uint64 becomes a value other than zero "now" I'm going to want it to be the TimeStamp that it should be)
    Paul McClernan
    @PaulMcClernan

    Here's an example of what is getting logged:

    [1, 0, 0, 3, 144, 74, 127, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

    element [1] is Uint32 (packet count), [2]Uint32,[3]Uint32 (2&3 should be Uint64 TimeStamp), [4] Uint16 byte count of MIDIMessage - 3 bytes that follow, [5] Uint8 144 is NoteOn Channel 1, [6] Uint8 is NoteNum 74 (E5 I think), [7] Uint8 is Velocity ... the rest are where the next packet would be if the first value was 2.

    Paul McClernan
    @PaulMcClernan
    So now I have another handler called from the ReadProcBlock that Posts back to the engine, passing an LCS handler in the Stack Script the MIDIMsg bytes... The problem is that it only fires it once when sending data from another app (a Virtual MIDI Piano App) UNLESS I bring my stack to the front again and then switch back to the Piano App then it fires only once again... my sTarget ScriptObject in LCB is set to whatever "this stack" resolves to when the MIDIClient object is create (which is the first thing that needs to be done to use CoreMIDI)... So my question is are ScriptObjects variables in LCB dynamic? What I mean is will the "this stack" sTarget ScriptObject later point to a different stack that I might open after the stack that created the MIDIClient? How can I ensure that the stack that created the MIDIClient gets sent the messages, even if the stack is running in the background or not the front window?
    Paul McClernan
    @PaulMcClernan

    Trying to send data back to the engine is still making me bonkers, the only thing that really works (except for the crashes when I send a bunch of messages in a row, which I think is a threading or sync issue) is logging the data, which isn't very useful.
    I noticed that in the Dictionary both Execute Script and Send Script have this note:

    Note: An error is thrown if this syntax is used in a context where access to script objects is not allowed.

    but there's no examples of "context where access to script objects is not allowed"
    I also notice there is a "stream" LCB module now that has WriteToStream
    'write Buffer to Destination'
    that sounds like it could be useful for what I'm trying to achieve.
    Paul McClernan
    @PaulMcClernan
    So I tried making a buffer that I can pull waiting messages from in a "send in time" loop in LCS. Here's a video of it in action, until it crashes:
    https://www.youtube.com/watch?v=Eq-ptIlOB8Q
    Paul McClernan
    @PaulMcClernan
    OK I've filed a bug report and moved passed it because I'm fairly convinced there is nothing I can do in my LCB code to work passed that crashing.
    Now I'm looking for a method to coerce one variable type to another. I need to convert a 4 byte/4 Char code into a Uint32 (in Motorola byte order, so reversed) for use in several areas of CoreMIDI/CoreAudio.
    Monte Goulding
    @montegoulding
    @PaulMcClernan the code of byte N of Data would be your freind there I think
    Paul McClernan
    @PaulMcClernan
    @montegoulding I know I can get the integer value of each of the 4 chars but then how do I combine those 4 bytes and shove it into a Uint32?
    I want to go from "MCAggregateTypeInfo: hhhh" (4 Uint8s) or "MCAggregateTypeInfo: bbbb" (4 CChar) to a single UInt32.
    I can actually get the Uint32 value very easily in LCS with binaryDecode("I",pFourChars,rOutNum) but I'd rather handle it within my LCB library.
    Paul McClernan
    @PaulMcClernan
    I wound up just doing it the old fashion way, doing the math
    public handler getIntegerFromFourCharCode(in pStr as String) returns optional any
       variable tUint32 as Uint32
       put (the code of char 4 of pStr) * 256 * 256 * 256 into tUint32
       put tUint32 + ((the code of char 3 of pStr) * 256 * 256) into tUint32
       put tUint32 + ((the code of char 2 of pStr) * 256 ) into tUint32
       put tUint32 + (the code of char 1 of pStr) into tUint32
       return tUint32
    end handler