xamarin/xamarin-macios

Missing enum entry for AVCaptureDeviceTypeExternal (AVCaptureDeviceType.External)

Closed this issue · 6 comments

Apple platform

iOS, Mac Catalyst

Framework version

net8.0-*

Affected platform version

Mac Catalyst 17.5.8020, iOS etc.

Description

It's not possible to open an external camera on iPadOS because the external device type is not present in AVCaptureDeviceType enum:

https://developer.apple.com/documentation/avfoundation/avcapturedevicetypeexternal

Steps to Reproduce

The following will not compile:

var session = AVCaptureDeviceDiscoverySession.Create([AVCaptureDeviceType.External], AVMediaTypes.Video, AVCaptureDevicePosition.Unspecified);

Did you find any workaround?

No response

Relevant log output

No response

@rolfbjarne Thanks so much for picking this up so quickly. It is, however, extremely concerning to learn about the bindings release being tied to XCode releases. Is there a technical reason for that, or is it due to some other policy? Although I tried to de-risk as much as I could as early as possible, I only just got started doing some more serious implementation work with the Apple API bindings (having been focused on Windows first for other deadlines), and almost immediately encountered what appears to be a release blocker.

AFAIK even if this issue were closed, it's not possible release apps built with pre-release XCode versions, and it can be months between XCode releases - a factor that's both beyond my control and hard to predict. So, what's the expectation here for developers in this situation? Although I was able to build the project OK using the instructions from the wiki, I couldn't find much on how to consume the results in order to ship with a MAUI project for example. Is there any guidance you could provide there (maybe I've overlooked some documentation on the matter)? The only thing I can think of is perhaps construct the desired AVCaptureDeviceDiscoverySession in Objective-C and then use ObjCRuntime.Runtime.GetNSObject or call the protected managed constructor via reflection (but I don't have much/any Apple development experience, so it would take me a while to test that theory out).

With respect to the bindings themselves, it feels like the problem has been excacerbated by the decision to use enums that are attributed with their respective platform strings. I'm curious as to what the reasoning is/was there, or maybe it's an oversight (other overloads sometimes have both)? From my perspective, this has caused a simple missing enum value to escalate into a potentially multi-month long release blocker, where it seems like it should have had a trivial workaround.

@rolfbjarne I'm just finishing for the day, but I have at least been able to show that the absence of this particular constant isn't a blocker for Catalyst. I'll continue to check iPad OS tomorrow and then look to de-risk the rest of the required API surface for there, but it would still be nice to get a better handle on what our options are if other blockers turn up.

It is, however, extremely concerning to learn about the bindings release being tied to XCode releases. Is there a technical reason for that, or is it due to some other policy?

It's a side effect of how we version or NuGets.

The technical reason why adding APIs is a problem it's this:

  1. Say we release NuGet iOS v18.0 next month with Xcode 18.0 support.
  2. In a service update, we add more APIs (for whatever reason), but keep the NuGet at v18.0.
  3. Someone creates another NuGet that references our iOS NuGet v18.0, and uses the new APIs we added in point 2.
  4. Someone else consumes that other NuGet, but has only our iOS v18.0 NuGet installed.
  5. Their build breaks with weird errors.

There are a few ways to get around this, but they all have their own problems, so we chose this route.

With respect to the bindings themselves, it feels like the problem has been excacerbated by the decision to use enums that are attributed with their respective platform strings. I'm curious as to what the reasoning is/was there, or maybe it's an oversight (other overloads sometimes have both)? From my perspective, this has caused a simple missing enum value to escalate into a potentially multi-month long release blocker, where it seems like it should have had a trivial workaround.

The reason the API is designed this way is to make it discoverable and easier to use from C#. An enum where Intellisense will give you the valid values is more easier to use than an API that takes a constant string, where you have to read through documentation to figure out which string to pass and where to find it.

I agree on the point that having a string overload would be a good backup option; we haven't always done this.

From my perspective, this has caused a simple missing enum value to escalate into a potentially multi-month long release blocker, where it seems like it should have had a trivial workaround.

For urgent needs we're happy to provide workarounds (this typically means binding the native API manually, where you can just copy the code we provide into your project).

I'm just finishing for the day, but I have at least been able to show that the absence of this particular constant isn't a blocker for Catalyst.

Let me know if you need a manual binding for this API.

If there's any other APIs you're missing, please open a separate issue for each (the issues can be very simple, just mention exactly which native API you need, and we'll get back to you with a solution).

@rolfbjarne That's awesome, thanks so much for the rapid support, it certainly alleviates some of the concern!

If I understood correclty, it sounds like the release policy was chosen as more of a consequency of NuGet's dependency resolution rules, but I can understand the desire to avoid confusing breakages.

I saw that XCode 16 went to RC yesterday and the release date looks like it will be the 16th. I'll try and complete as much proof of concept work as I can over the next few days. I'm guessing you guys are probably aiming for roughly same-day support and even if I find and report something, it might already be too late to land a proper upstream fix in time for the corresponding xamarin-macios release?

I'm happy so long as I know that a workaround is available/feasible. I've made bindings for various other languages and frameworks previously, so I'll see if I can also investigate that path along with the proof of concept work to verify the rest of the API surface we require. FWIW, the bindings for the other APIs I've looked into were pretty straightforward to use/verify, and the setup and build process for the project was pretty smooth and well documented, so nice job and thanks for that!

I saw that XCode 16 went to RC yesterday and the release date looks like it will be the 16th. I'll try and complete as much proof of concept work as I can over the next few days. I'm guessing you guys are probably aiming for roughly same-day support and even if I find and report something, it might already be too late to land a proper upstream fix in time for the corresponding xamarin-macios release?

The current release plan with regards to Xcode 16 is in the comments here: #20802 (short version: it will be released together with .NET 9 in November).

This means there's plenty of time to get additional API fixes / additions in.

I'm happy so long as I know that a workaround is available/feasible. I've made bindings for various other languages and frameworks previously, so I'll see if I can also investigate that path along with the proof of concept work to verify the rest of the API surface we require. FWIW, the bindings for the other APIs I've looked into were pretty straightforward to use/verify, and the setup and build process for the project was pretty smooth and well documented, so nice job and thanks for that!

Thanks!

That's great news, thanks!