The Audio Unit and its callbacks run in a completely separate real-time thread from any other thread in you app. So any commands given to an Audio Unit should be assumed to be executed asynchronously. And possibly not until many tens of milliseconds after a command is issued.To be safe, in my apps, I never free any related resources until several seconds after an audio unit is told to stop. And I never stop an audio unit if I plan to immediately (re)start that same unit. I just leave the audio units running, passing silence (zeros) in all the callbacks.
Post
Replies
Boosts
Views
Activity
A -50 error sometimes indicates that you are asking for an unsupported audio format. Try changing the requested audio unit format to use float samples, or a sample rate of 48000, or 2 channels, or some combintion of those to see what works. You can always resample data to or from another rate, and or change the number of channels or sample type somewhere within a mixer or your app's own code. e.g. Accelerate's vDSP framework includes some vector type conversion routines.
For real-time audio output, using Audio Units (RemoteIO on iOS devices) with a circular/ring buffer is likely to work more reliably than trying to schedule buffers on a playerNode. Audio Units callbacks run in a higher priority real-time thread, and schedule themselves. So you don't have to schedule, just make sure there's always something in the ring buffer to prevent glitches.
Eskimo asks:
Can you clarify this statement? 127.0.0.1 is the IPv4 localhost address. How are you getting that back from getifaddrs? And what are you doing with that address? A call to getifaddrs(&p) on macOS 10.15.7 is returning exactly 2 IPV4 addresses,
where (p->ifaaddr->safamily == AFINET)
Those 2 IPV4 addresses are:> 0.0.0.0
> 127.0.0.1
If I try a UDP broadcast to those 2 addresses, one at a time:
mysocket = socket(PFINET, SOCKDGRAM, 0);
setsockopt(mysocket, SOLSOCKET, SOBROADCAST,
(char *)&i, sizeof(i));
if ((p->ifaaddr) && p->ifaaddr->safamily == AFINET) {
strncpy(ipstr, inetntoa(bcastAddr.sinaddr), ADRSIZE);
bcastAddr.sinfamily = AFINET;
bcastAddr.sinport = htons(1024);
bcastAddr.sinaddr
= ((struct sockaddrin *)(p->ifabroadaddr))->sinaddr;
sendto(mysocket, (char *)data, 63, 0,
(const struct sockaddr *)&bcastAddr,
sizeof(bcastAddr));
The UDP broadcast to 127.0.0.1 is the one I see on my local network (UDP sniffer on a Raspberry Pi).
There is a device on the local network that responds to that UDP broadcast by replying with a UDP packet.
This code looks for the response after the above UDP broadcast:
b = recvfrom(mysocket, (char *)data, 1500, 0,
(struct sockaddr *)&recvAddr, &addrLen);
This code compiled using older versions (3 to 6 months ago) of Xcode receives a UDP response from that broadcast.
This code when compiled and run on older versions (maybe 6 months ago) of Catalina or Mohave receives a UDP response from that broadcast.
This code runs an a Raspberry Pi 4 running Buster, and receives a UDP response from that broadcast.
e.g. recvfrom() returns a positive number, and a valid recvAddr IP address for the responder.
The same code compiled with Xcode 12.0.1 and run on the current version of macOS 10.15.7 never receives any UDP data on that socket and port (1024).
The above is all clang compiled command-line C code on macOS.
But an identical new failure occurs inside an iOS Objective C app built for the current iOS with the latest Xcode SDK releases.
The UDP code used to work (receive a response) 6 months ago, both on the macOS Terminal command-line and inside an iOS app.
What changed? Is the UDP response firewalled? Or am I missing some new Network permission requirement?
Is the change in macOS and iOS (at the same time), or inside the Xcode SDK being used (stdlib, etc.)?
Hmmm... your code
err = getnameinfo( cursor->ifa_addr , ...
is printing out :
lo0 127.0.0.1
en0 10.0.1.128
but my code is using and printing out :
cursor->ifa_broadaddr , ...
Oops, I had my print pipelined in the wrong order. Here's the correct print out
bcast_Addr.sin_addr = ((struct sockaddr_in *)(p->ifa_broadaddr))->sin_addr;
strncpy(ip_printout_string, inet_ntoa(bcast_Addr.sin_addr), ADR_SIZE);
0 try ip: lo0 127.0.0.1 63
1 try ip: en0 10.0.1.255 63
So 10.0.1.255 is the broadcast address that used to work and now doesn't.
Isn't ifa_broadaddr the proper IP address to be used for UDP broadcasts?
In any case, using 10.0.1.255 causes the UDP broadcast to be seen on the local network,
and that broadcast used to get a UDP response, and after updating Catalina and Xcode, no longer does.
Oops, I had my print pipelined in the wrong order. Here's the correct print out
bcast_Addr.sin_addr = ((struct sockaddr_in *)(p->ifa_broadaddr))->sin_addr;
strncpy(ip_printout_string, inet_ntoa(bcast_Addr.sin_addr), ADR_SIZE);
0 try ip: lo0 127.0.0.1 63
1 try ip: en0 10.0.1.255 63
So 10.0.1.255 is the broadcast address that used to work and now doesn't.
I have a UDP packet sniffer on the same LAN (a Raspberry Pi 4) at 10.0.1.125 . It reliably sees the UDP broadcast packet from 10.0.1.128 (the Mac) when I run the UDP broadcast code on the Mac.
There is a UDP responder on the network at 10.0.1.122 (hidden inside an FPGA). Pinging 10.0.1.122 from the Mac (10.0.1.128) works. Pinging the Mac (10.0.1.128) from the Pi (10.0.1.125) also works. The Pi and an older Mac running identical UDP broadcast code sees the UDP response from 10.0.1.122 reliably, in response to identical UDP broadcast packets (as seen by the Pi 4 sniffer). The sender address in the UDP response packet is 10.0.1.122 (as received on the older Mac and Pi).
Sending UDP packets directly (not broadcast) from a newer updated Mac (10.0.1.128) to the responder (10.0.1.122) and receiving UDP replies works great. But the newer Mac after updating to the latest macOS 10.15.7 with Xcode 12.0.1 never sees any UDP replies to UDP broadcast packets. So the broadcast code used to work (as in receive replies), but now does not, after macOS was updated to 10.15.7 (or maybe after .5 or .6, not when the issue first started). Similar issue with recent updates to iOS. Code that used to work 4 to 6 months ago, now does not.
Here's the strange thing on the Mac updated to 10.15.7 :
These 2 binaries were built from the same source code version (C code in a git repo):
rwxr-xr-x 1 rhn staff 33980 Jun 29 10:46 hl2_tcp*
rwxr-xr-x 1 rhn staff 57344 Oct 7 15:14 hl2_tcp*
The June binary works (gets a UDP response from 10.0.1.122).
Todays build does not.
On the same Mac.
Oh. I forgot. The source code has been on GitHub:
github.com hotpaw2 hl2_tcp hl2_tcp.c
When the Raspberry Pi and the older Mac do the UDP broadcast, they see their own IP address as the destination address in the UDP reply.
Here's the trace route. from the working build on the new Mac (similar to the traceroute on an older Mac):
08:02:46.609781 IP 10.0.1.128.55446 > 10.0.1.255.1024: UDP, length 63
08:02:46.619310 IP 10.0.1.122.1024 > 10.0.1.128.55446: UDP, length 60
b = recvfrom() sees this reply. (10.0.1.128 is the new Mac, 10.0.1.122 is the FPGA).
b returns 60.
On the newly updated Mac, here's the trace route for the freshly compiled build:
08:06:03.297044 IP 10.0.1.128.51366 > 10.0.1.255.1024: UDP, length 63
08:06:03.309021 IP 10.0.1.122.1024 > 10.0.1.128.51366: UDP, length 60
b = recvfrom() times out. (identical C source code!)
b returns -1 after multiple retries for many mS.
So the getifaddr(), broadcast, device, and network behavior are the same. Used to work 4 months ago on Catalina and iOS.
But the newly compiled code behaves differently on the freshly updated new Mac(s) (Catalina, Big Sur beta, and iOS 14.0.1).
Is this firewalling of the UDP response from the application intentional, due to a missing new compiler or build configuration option, or a bug?
iOS does support embedding the source code of a command line tool within an apps Xcode project and compiling the tool as part of the app build.
By simply changing the name of main() and putting a prototype of the new munged main's name into the bridging header so it can be called from Swift. And redirecting stdout (etc.) to, say, a global C string buffer, where Swift can unsafely peek and poke.
So this first-party UDP broadcast command-line tool most certainly did run inside my iOS app 4 months ago. And received UDP replies. But no longer does after updating iOS and Xcode.
What changed? (not the source code of the embedded command-line tool (except for the ending print statements).
And the same thing happed to the UDP tool running on the last Catalina update.
So here's an update:
getifadders() and UDP broadcast and UDP receive of the reply works...
BUT only from an admin account on macOS Catalina 10.15.7 and Big Sur beta.
From user accounts, Big Sur seems to completely block the UDP broadcast (sendto() returns -1),
and Catalina appears to allow the UPD broadcast but blocks (firewalls) receiving any UDP replies.
Even when the Firewall is turned completely off in System Preferences : Privacy.
iOS probably recently inherited the same behavior to identical code (stuffed inside a test iOS app).
Source code for the broadcast app is here: https://github.com/hotpaw2/hl2_tcp
Source code for a fake emulator of the hardware/FPGA UDP reply (runs on a Raspberry Pi) is here: https://gist.github.com/hotpaw2/5e75e19ecd1fb2d43d6f8f6f44bd2611
Older macOS releases (and older iOS releases) allowed this UDP broadcast and UDP receive to work, even from non-admin User accounts. Even with the Firewall turned on.
Intentional (new firewall privacy/security feature)? Or a bug?
In reply: A partially specific example was posted in this thread:
https://developer.apple.com/forums/thread/662859
But the behavior of this code seems to vary with one or more of: macOS version compiled under or run under, Xcode version compiled with, account privileges the binary is run from, directory and or account the command-line binary was copied from or to.
The last is the weirdest, as I can copy a working binary out of one directory into another, and it stops working (on 10.15.7).
But when I copied that copy (command line cp -p) into an admin account, it started working.
My stats are: UDP broadcast plus reception of UDP reply always works under Mohave (after initial permission grant), works less under Catalina (depending on build, etc.), works rarely under Big Sur (but not never). 3 different Macs. Sometimes the UDP broadcast fails (isn't seen on the LAN by multiple sensors), sometimes the UDP reply is lost (never received by Mac).
Where are the owners, directory paths, and version info of the apps that the firewall or network stack permits/denies stored?
Could that permission storage be confused by dozens of binaries with the same name, but in different directories, with different owners, built with different versions of Xcode on different Macs, but all from the same source repo?
Yes, the behavior change of UDP in iOS is documented. Is there a similar documentation of behavior change for macOS?
I was an early adopter, and have an app in the Mac App Store with a maccatalyst prefixed Bundle ID.
Should I abandon it? (and all its existing customers).
And start over with a new bundle ID and an (almost) identical app? (Will App Review even allow that?)
Or is there a way to generate a provisioning profile so that I can upload bug fix updates to the App Store?
Currently I get "Code Signing failed" with Automatically Managed signing.
And "No Eligible Profiles ... Try Again" with manual signing.
Tried generating some new profiles, both Development and Distribution, but producing no change in those error messages.
Previously, signing and uploading this maccatalyst prefixed app worked just fine with Xcode 12.0 with existing profiles and automatically managed signing.
What to do?
The solution is in the forum thread titled: "Catalyst app with framework won't codesign", answered by ben-
In my old Xcode project, I selected my app from Targets. Then:
Select Build Settings.
Scroll down in Build Settings to Enable Bitcode.
Highlight the bold "Enable Bitcode" setting, and hit the delete key.
A new non-bold Enable Bitcode will auto-re-populate with the correct settings for Xcode 12.2.
I performed the above, and now Automatically Managed Signing just works (like it did before) and allows codesigning for upload to the App Store of my maccatalyst.* prefixed app with an included app extension.
See "Older Catalyst app with extension won't codesign".
The previous distribution profile started working again after the old build setting for Enable Bitcode was deleted.
Not sure what those two items have to do with each other...
It looks like this might be an issue with a recent update to Little Snitch on Big Sur that is blocking newly compiled command-line code from sending UDP data. I disabled Little Snitch, and UDP started working.