Post

Replies

Boosts

Views

Activity

Reply to Change the OSLog level that is written to Xcode console of a dependent library
Thanks Quinn the Eskimo! I don't like that quite as much, because then all logs from my lib will be at the same level (the one passed in by the user of the lib). The something-is-very-broken logs would be drowned out in a sea of debug logs. For example, there are debug logs that emit on each audio buffer coming from the mic, containing the sample count in the buffer. These are frequent and only meant to be 'turned on' when I'm trying to debug an issue. I'll share what I ended up doing. It makes log lines a little cumbersome for me, but thankfully users of my lib don't have to deal with that. import OSLog public enum AIProxyLogLevel: Int { case debug case info case warning case error case critical func isAtOrAboveThresholdLevel(_ threshold: AIProxyLogLevel) -> Bool { return self.rawValue >= threshold.rawValue } } internal var aiproxyCallerDesiredLogLevel = AIProxyLogLevel.warning internal let aiproxyLogger = Logger( subsystem: Bundle.main.bundleIdentifier ?? "UnknownApp", category: "AIProxy" ) // Why not create a wrapper around OSLog instead of forcing log callsites to include an `if ll(<level>)` check? // Because I like the Xcode log feature that links to the source location of the log. // If you create a wrapper, even one that is inlined, the Xcode source feature always links to the wrapper location. @inline(__always) internal func ll(_ logLevel: AIProxyLogLevel) -> Bool { return logLevel.isAtOrAboveThresholdLevel(aiproxyCallerDesiredLogLevel) } And then my lib adds log lines like so: if ll(.warning) { aiproxyLogger.warning("this is a warning log") } if ll(.debug) { aiproxyLogger.debug("this is a debug log") } ... And I expose a simple interface to the user of the lib that internally sets aiproxyCallerDesiredLogLevel. It's a little unorthodox, but it's getting the job done for me, and Xcode's link-to-log-source functionality still works. Big fan of your work. Every time I stumble on a great forum or technical note thread it always has your name on it. ps. long live macnetworkprog! Lou
2h
Reply to AudioComponentInstanceNew takes up to five seconds to complete
I am also seeing this with the AVAudioEngine APIs. @oliverpahl-mitel did you ever hear back from Apple on your feedback assistant post? At runtime here are the errors that get dumped to console (I get the KeystrokeSuppressorCore.cpp:44 ERROR, but I don't see the AggInpStreamsChanged wait failed you are getting). If I setup an input node with inputNode.setVoiceProcessingEnabled(true), here are the errors that get dumped to console: AddInstanceForFactory: No factory registered for id <CFUUID 0x60000300f780> F8BB1C28-BAE8-11D6-9C31-00039315CD46 throwing -10877 throwing -10877 vpPlatformUtil.mm:312 Cannot retrieve theDeviceBoardID string... vpPlatformUtil.mm:312 Cannot retrieve theDeviceBoardID string... AudioHardware-mac-imp.cpp:409 AudioObjectHasProperty: no object with given ID 0 AUVPAggregate.cpp:4929 Failed to get current tap stream physical format, err=2003332927 vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 vpStrategyManager.mm:486 Error code 2003332927 reported at GetPropertyInfo vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 vpStrategyManager.mm:486 Error code 2003332927 reported at GetPropertyInfo vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 vpStrategyManager.mm:486 Error code 2003332927 reported at GetPropertyInfo vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 KeystrokeSuppressorCore.cpp:44 ERROR: KeystrokeSuppressor initialization was unsuccessful. Invalid or no plist was provided. AU will be bypassed. vpSetupUplinkDSPChain.cpp:124 >vp> skip reference mixer setup because reference channel count is 0 vpStrategyManager.mm:486 Error code 2003332927 reported at GetPropertyInfo HALB_IOThread.cpp:326 HALB_IOThread::_Start: there already is a thread HALB_IOThread.cpp:326 HALB_IOThread::_Start: there already is a thread For reference, if I switch inputNode.setVoiceProcessingEnabled(false) and keep all of my surrounding code the same, the following messages are dumped to console: AddInstanceForFactory: No factory registered for id <CFUUID 0x600003ff2500> F8BB1C28-BAE8-11D6-9C31-00039315CD46 throwing -10877 throwing -10877
Dec ’24
Reply to Turning on setVoiceProcessingEnabled bumps channel count to 5
I just found something interesting. While AVAudioConverter doesn't play nicely with the five channels, it seems like AVAudioEngine's built in converters do. Because if I specify a tap like this: let desiredTapFormat = AVAudioFormat( commonFormat: .pcmFormatInt16, sampleRate: inputPCMFormat.sampleRate, channels: 1, interleaved: false ) inputNode.installTap(onBus: 0, bufferSize: 256, format: desiredTapFormat) { buffer, when in ... } I find that the buffer argument already has a single channel, and it's not silence!
Dec ’24
Reply to How to get in contact with team that manages DeviceCheck
(Post replies, not comments.) Thanks for the tip. No, what I mean is, if I, an attacker, have my own trivial app, and I collect tokens that my users send to my server (no MITM needed). Then I send those tokens to your app's API. These would return non-200s from Apple's servers when the token was validated in the server-to-server call. It's actually quite tricky to get DeviceCheck to pass in the first place. A bunch of things need to be true: An App Identifier in your developer dashboard must match the bundle identifier of your app exactly The app must be signed using a certificate from the team account that has that App Identifier A DeviceCheck secret key (used for the backend-to-backend communication) must be created from the same account as 1 and 2. The fact that it's hard to get right gave me some confidence that it was also hard to forge. Now, I'm not so sure
Dec ’24