omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Obj_C struct OSType define problem.

    Pythonista
    4
    18
    10603
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • wolf71
      wolf71 last edited by wolf71

      Using objc_util call objc function,need define a struct.
      OSType is c_char_P ??

      from objc_util import *
      import ctypes
      
      AVAudioUnit=ObjCClass('AVAudioUnit')
      AVAudioUnitComponent=ObjCClass('AVAudioUnitComponent')
      AVAudioUnitComponentManager=ObjCClass('AVAudioUnitComponentManager')
      
      #
      # componentType,componentSubType,componentManufacturer is OSType
      #
      # ref:  developer.apple.com/reference/audiotoolbox/audiocomponentdescription
      #
      class AudioComponentDescription(ctypes.Structure):
      	_fields_=[('componentType',ctypes.c_char_p),('componentSubType',ctypes.c_char_p),('componentManufacturer',ctypes.c_char_p),('componentFlags',ctypes.c_uint32),('componentFlagsMask',ctypes.c_uint32)]
      	
      anyEffect = AudioComponentDescription('aufx','dcmp','appl',0,0)
      availableEffects = AVAudioUnitComponentManager.sharedAudioUnitComponentManager().componentsMatchingDescription_(anyEffect)
      
      

      Error Message:
      File "/var/containers/Bundle/Application/1E0EEE41-E357-4C4B-9564-45BDC5519D55/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/site-packages/objc_util.py", line 897, in call
      res = objc_msgSend(obj.ptr, sel(self.sel_name), *args)
      ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected AudioComponentDescription_Structure instance instead of AudioComponentDescription

      1 Reply Last reply Reply Quote 0
      • Cethric
        Cethric last edited by

        @wolf71 objc_util dynamically creates its own copy of the AudioComponentDescription hence your ArgumentError This can be resolved either by using the objc_util version (can remberer exactly how to do that) or you specify that you want to use your copy. Eg

        from objc_util import *
        import ctypes
        
        AVAudioUnit=ObjCClass('AVAudioUnit')
        AVAudioUnitComponent=ObjCClass('AVAudioUnitComponent')
        AVAudioUnitComponentManager=ObjCClass('AVAudioUnitComponentManager')
        
        #
        # componentType,componentSubType,componentManufacturer is OSType
        #
        # ref:  developer.apple.com/reference/audiotoolbox/audiocomponentdescription
        #
        class AudioComponentDescription(ctypes.Structure):
            _fields_=[('componentType',ctypes.c_char_p),('componentSubType',ctypes.c_char_p),('componentManufacturer',ctypes.c_char_p),('componentFlags',ctypes.c_uint32),('componentFlagsMask',ctypes.c_uint32)]
            
        anyEffect = AudioComponentDescription('aufx','dcmp','appl',0,0)
        availableEffects = AVAudioUnitComponentManager.sharedAudioUnitComponentManager().componentsMatchingDescription_(anyEffect, argtypes=[AudioComponentDescription])
        
        1 Reply Last reply Reply Quote 0
        • wolf71
          wolf71 last edited by

          Add argtypes=[AudioComponentDescription]

          But Same Error Message:

          availableEffects = AVAudioUnitComponentManager.sharedAudioUnitComponentManager().componentsMatchingDescription_(anyEffect,argtypes=[AudioComponentDescription])
          File "/var/containers/Bundle/Application/1E0EEE41-E357-4C4B-9564-45BDC5519D55/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/site-packages/objc_util.py", line 897, in call
          res = objc_msgSend(obj.ptr, sel(self.sel_name), *args)
          ArgumentError: argument 3: <type 'exceptions.TypeError'>: expected AudioComponentDescription_Structure instance instead of AudioComponentDescription

          1 Reply Last reply Reply Quote 0
          • JonB
            JonB last edited by JonB

            In order to override the type detection, you need to specify both restype and argtypes.

            .....(anyEffect , restype=c_void_p, argtypes=[ArgumentDescription])
            
            wolf71 1 Reply Last reply Reply Quote 0
            • wolf71
              wolf71 @JonB last edited by wolf71

              @JonB add restype, but the same error message.

              OSType using ctypes.c_char_p ??

              1 Reply Last reply Reply Quote 0
              • JonB
                JonB last edited by JonB

                Are you using the latest beta, or the app store version?
                https://github.com/omz/Pythonista-Issues/issues/68 is likely the issue. Check line 801 in objc_util.py, shuld say

                	kw = {k: kwargs[k] for k in ('restype', 'argtypes') if k in kwargs}
                

                and not

                	kw = {k: kwargs[k] for k in ('restype', 'kwargs') if k in kwargs}
                

                A workaround if you are on the app store version or an older beta would be to replace this line in an objc_util.py that you put in site packages. If you have an old beta, just upgrade to latest testflight version

                I don't understand what you were asking about OSType...is that a separate question? I did not see any code that uses it.

                1 Reply Last reply Reply Quote 0
                • JonB
                  JonB last edited by

                  ot, OSType is c_uint32, which is 4 chars (4 bytes). I forget the trick to get a b'abcd' style bytes converted to an integer..

                  1 Reply Last reply Reply Quote 0
                  • wolf71
                    wolf71 last edited by

                    App store version.

                    1 Reply Last reply Reply Quote 0
                    • JonB
                      JonB last edited by

                      For the fourcc code, you will want to use

                      ctypes.c_uint32
                      

                      then, to create such an integer you would use

                      struct.unpack('I',b'auxf')[0]
                      

                      You will neeed to patch your objc_util though, OR create an ObjCInstanceMethod manually:

                      manager=AVAudioUnitComponentManager.sharedAudioUnitComponentManager()
                      
                      availableEffects = ObjCInstanceMethod(manager,'componentsMatchingDescription_')(anyEffect, argtypes=[AudioComponentDescription],restype=c_void_p)
                      
                      wolf71 2 Replies Last reply Reply Quote 0
                      • wolf71
                        wolf71 @JonB last edited by

                        @JonB Thank you very much.

                        It's ok.

                        1 Reply Last reply Reply Quote 0
                        • wolf71
                          wolf71 @JonB last edited by wolf71

                          @JonB

                          swift

                          let anyEffect = AudioComponentDescription(componentType:kAudioUnitType_Effect,componentSubType:kAudioUnitSubType_Delay,componentManufacturer:0,componentFlags:0,componentFlagsMask:0)
                                  
                                  let availableEffects: [AVAudioUnitComponent] = AVAudioUnitComponentManager.shared().components(matching: anyEffect)
                                      
                                  AVAudioUnit.instantiate(with: availableEffects[0].audioComponentDescription, options: []) {
                                      avAudioUnit, error in
                                      guard let avAudioUnit = avAudioUnit else { return }
                                      debugPrint(avAudioUnit.audioComponentDescription)
                                      self.ae.attach(avAudioUnit)
                          
                          

                          Python:

                          def AVAudioUnitComp(self,avAudioUnit,error):
                          	self.effect = ObjCInstance(avAudioUnit)
                          	self.engine.attachNode(self.effect)
                          	
                          AVAudioUnitComp1=ObjCBlock(AVAudioUnitComp,restype=None,argtypes=[c_void_p,c_void_p,c_void_p])	
                          
                          AVAudioUnit=ObjCClass('AVAudioUnit')
                          AVAudioUnitComponent=ObjCClass('AVAudioUnitComponent')
                          AVAudioUnitComponentManager=ObjCClass('AVAudioUnitComponentManager')
                          
                          
                          class AudioComponentDescription(ctypes.Structure):
                          	_fields_=[('componentType',ctypes.c_uint32),('componentSubType',ctypes.c_uint32),('componentManufacturer',ctypes.c_uint32),('componentFlags',ctypes.c_uint32),('componentFlagsMask',ctypes.c_uint32)]
                          
                          anyEffect = AudioComponentDescription(1635083896,1684237680,0,0,0)
                          
                          manager=AVAudioUnitComponentManager.sharedAudioUnitComponentManager()
                          # Return AVAudioUnitComponent[]
                          availableEffects = ObjCInstanceMethod(manager,'componentsMatchingDescription_')(anyEffect, argtypes=[AudioComponentDescription],restype=c_void_p)
                          
                          AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(ObjCInstance(availableEffects[0].audioComponentDescription()),[],AVAudioUnitComp1)
                          
                          

                          Err Message:
                          AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(ObjCInstance(availableEffects[0].audioComponentDescription()),[],AVAudioUnitComp1)
                          File "/var/containers/Bundle/Application/14D01FBB-0800-4104-963B-7B7CEBA9B086/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/site-packages/objc_util.py", line 523, in new
                          cached_instance = _cached_instances.get(ptr)
                          File "/var/containers/Bundle/Application/14D01FBB-0800-4104-963B-7B7CEBA9B086/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/weakref.py", line 104, in get
                          wr = self.data[key]
                          TypeError: unhashable type

                          1 Reply Last reply Reply Quote 0
                          • JonB
                            JonB last edited by

                            This post is deleted!
                            1 Reply Last reply Reply Quote 0
                            • JonB
                              JonB last edited by

                              Try getting rid of the ObjCInstance() -- that method returns a structure, not an object.

                              1 Reply Last reply Reply Quote 0
                              • dgelessus
                                dgelessus last edited by

                                I think you also need to wrap availableEffects in an ObjCInstance. You've set the restype for the ObjCInstanceMethod to c_void_p, you need to wrap that in an ObjCInstance before you can call methods, access NSArray elements, etc.

                                Also, the second parameter of instantiateWithComponentDescription_options_completionHandler_ is a c_uint32. You need to pass 0, not [].

                                1 Reply Last reply Reply Quote 0
                                • JonB
                                  JonB last edited by

                                  oh right, should be ObjCInstance(availableEffects)[0] ( note the obcinstance wraps available effects, not availableeffects[0].

                                  wolf71 1 Reply Last reply Reply Quote 0
                                  • wolf71
                                    wolf71 @JonB last edited by

                                    @JonB Using this like can pass,but the next arg error

                                    AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(ObjCInstance(availableEffects[0].audioComponentDescription()),ns([]),AVAudioUnitComp1)
                                    

                                    AVAudioUnit.instantiateWithComponentDescription_options_completionHandler_(ObjCInstance(availableEffects[0].audioComponentDescription()),ns([]),AVAudioUnitComp1)
                                    File "/var/containers/Bundle/Application/1E0EEE41-E357-4C4B-9564-45BDC5519D55/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/site-packages/objc_util.py", line 523, in new
                                    cached_instance = _cached_instances.get(ptr)
                                    File "/var/containers/Bundle/Application/1E0EEE41-E357-4C4B-9564-45BDC5519D55/Pythonista3.app/Frameworks/PythonistaKit.framework/pylib/weakref.py", line 104, in get
                                    wr = self.data[key]
                                    TypeError: unhashable type

                                    1 Reply Last reply Reply Quote 0
                                    • JonB
                                      JonB last edited by

                                      Note very carefully your first argument. look at what you are passing to ObjCInstance - it is not a pointer to an object.
                                      availableEffects is probably a c_void_p. You need to convert that to a NSArray using ObjCInstance, before you try to index into it.

                                      ObjCInstance(availableEffects)[0]

                                      Then, take the resulting structure and index into it. Since that type is not a object, you won't use ObjCinstnce. Your best bet is to actually look at things in the debugger or console, so you know what you are dealing with. Also, I find it useful to break up these massive oneliners into multiple statements, so you can easier identifier your own bugs.

                                      1 Reply Last reply Reply Quote 1
                                      • dgelessus
                                        dgelessus last edited by

                                        Also, as I said above, the options argument is an integer, not an array. [] and ns([]) does not work, you need to use 0 here.

                                        1 Reply Last reply Reply Quote 0
                                        • First post
                                          Last post
                                        Powered by NodeBB Forums | Contributors