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.
-
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 -
@wolf71
objc_util
dynamically creates its own copy of theAudioComponentDescription
hence yourArgumentError
This can be resolved either by using theobjc_util
version (can remberer exactly how to do that) or you specify that you want to use your copy. Egfrom 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])
-
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 -
In order to override the type detection, you need to specify both restype and argtypes.
.....(anyEffect , restype=c_void_p, argtypes=[ArgumentDescription])
-
@JonB add restype, but the same error message.
OSType using ctypes.c_char_p ??
-
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 saykw = {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.
-
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..
-
App store version.
-
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)
-
@JonB Thank you very much.
It's ok.
-
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 -
This post is deleted! -
Try getting rid of the ObjCInstance() -- that method returns a structure, not an object.
-
I think you also need to wrap
availableEffects
in anObjCInstance
. You've set therestype
for theObjCInstanceMethod
toc_void_p
, you need to wrap that in anObjCInstance
before you can call methods, accessNSArray
elements, etc.Also, the second parameter of
instantiateWithComponentDescription_options_completionHandler_
is ac_uint32
. You need to pass0
, not[]
. -
oh right, should be ObjCInstance(availableEffects)[0] ( note the obcinstance wraps available effects, not availableeffects[0].
-
@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 -
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.
-
Also, as I said above, the options argument is an integer, not an array.
[]
andns([])
does not work, you need to use0
here.