1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-01-10 23:44:24 +00:00

CameraDevice: Fix deprecation warnings for iOS 17

This commit is contained in:
reuk 2024-10-28 21:26:43 +00:00
parent eb6ebaf5af
commit 7290d6dc2f
No known key found for this signature in database
GPG key ID: FCB43929F012EE5C

View file

@ -34,6 +34,55 @@
struct CameraDevice::Pimpl
{
static void applyDeviceOrientation (AVCaptureDevice*, AVCaptureVideoPreviewLayer*, AVCaptureConnection* outputConnection)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
const auto statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
const auto videoOrientation = statusBarOrientation != UIInterfaceOrientationUnknown
? (AVCaptureVideoOrientation) statusBarOrientation
: AVCaptureVideoOrientationPortrait;
outputConnection.videoOrientation = videoOrientation;
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
struct PreviewLayerAngleTrait
{
#if defined (__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0
API_AVAILABLE (ios (17))
static void newFn (AVCaptureDevice* device, AVCaptureVideoPreviewLayer* previewLayer, AVCaptureConnection* outputConnection)
{
const NSUniquePtr<AVCaptureDeviceRotationCoordinator> coordinator
{
[[AVCaptureDeviceRotationCoordinator alloc] initWithDevice: device
previewLayer: previewLayer]
};
outputConnection.videoRotationAngle = coordinator.get().videoRotationAngleForHorizonLevelPreview;
}
#endif
static constexpr auto oldFn = applyDeviceOrientation;
};
struct CaptureLayerAngleTrait
{
#if defined (__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0
API_AVAILABLE (ios (17))
static void newFn (AVCaptureDevice* device, AVCaptureVideoPreviewLayer* previewLayer, AVCaptureConnection* outputConnection)
{
const NSUniquePtr<AVCaptureDeviceRotationCoordinator> coordinator
{
[[AVCaptureDeviceRotationCoordinator alloc] initWithDevice: device
previewLayer: previewLayer]
};
outputConnection.videoRotationAngle = coordinator.get().videoRotationAngleForHorizonLevelCapture;
}
#endif
static constexpr auto oldFn = applyDeviceOrientation;
};
using InternalOpenCameraResultCallback = std::function<void (const String& /*cameraId*/, const String& /*error*/)>;
Pimpl (CameraDevice& ownerToUse, const String& cameraIdToUse, int /*index*/,
@ -423,6 +472,9 @@ private:
}
previewLayer = [AVCaptureVideoPreviewLayer layerWithSession: captureSession.get()];
updatePreviewOrientation();
return previewLayer;
}
@ -435,7 +487,7 @@ private:
return;
}
stillPictureTaker.takePicture (previewLayer.connection.videoOrientation);
stillPictureTaker.takePicture();
}
void startRecording (const File& file)
@ -455,7 +507,7 @@ private:
return;
}
videoRecorder.startRecording (file, previewLayer.connection.videoOrientation);
videoRecorder.startRecording (file);
}
void stopRecording()
@ -468,6 +520,21 @@ private:
return videoRecorder.getTimeOfFirstRecordedFrame();
}
AVCaptureDevice* getDevice() const
{
return cameraDevice;
}
AVCaptureVideoPreviewLayer* getPreviewLayer() const
{
return previewLayer;
}
void updatePreviewOrientation()
{
ifelse_17_0<PreviewLayerAngleTrait> (cameraDevice, previewLayer, previewLayer.connection);
}
JUCE_DECLARE_WEAK_REFERENCEABLE (CaptureSession)
private:
@ -554,7 +621,7 @@ private:
class StillPictureTaker
{
public:
StillPictureTaker (CaptureSession& cs)
explicit StillPictureTaker (CaptureSession& cs)
: captureSession (cs),
captureOutput (createCaptureOutput()),
photoOutputDelegate (nullptr)
@ -566,7 +633,7 @@ private:
captureSession.addOutputIfPossible (captureOutput);
}
void takePicture (AVCaptureVideoOrientation orientationToUse)
void takePicture()
{
if (takingPicture)
{
@ -583,7 +650,8 @@ private:
{
auto* photoOutput = (AVCapturePhotoOutput*) captureOutput;
auto outputConnection = [photoOutput connectionWithMediaType: AVMediaTypeVideo];
outputConnection.videoOrientation = orientationToUse;
ifelse_17_0<CaptureLayerAngleTrait> (captureSession.cameraDevice, captureSession.previewLayer, outputConnection);
[photoOutput capturePhotoWithSettings: [AVCapturePhotoSettings photoSettings]
delegate: id<AVCapturePhotoCaptureDelegate> (photoOutputDelegate.get())];
@ -844,8 +912,9 @@ private:
class VideoRecorder
{
public:
VideoRecorder (CaptureSession& session)
: movieFileOutput ([AVCaptureMovieFileOutput new]),
explicit VideoRecorder (CaptureSession& session)
: captureSession (session),
movieFileOutput ([AVCaptureMovieFileOutput new]),
delegate (nullptr)
{
static FileOutputRecordingDelegateClass cls;
@ -864,7 +933,7 @@ private:
jassert (! recordingInProgress);
}
void startRecording (const File& file, AVCaptureVideoOrientation orientationToUse)
void startRecording (const File& file)
{
printVideoOutputDebugInfo (movieFileOutput);
@ -872,7 +941,7 @@ private:
isDirectory: NO];
auto outputConnection = [movieFileOutput connectionWithMediaType: AVMediaTypeVideo];
outputConnection.videoOrientation = orientationToUse;
ifelse_17_0<CaptureLayerAngleTrait> (captureSession.cameraDevice, captureSession.previewLayer, outputConnection);
[movieFileOutput startRecordingToOutputFileURL: url recordingDelegate: delegate.get()];
}
@ -951,6 +1020,7 @@ private:
static void setOwner (id self, VideoRecorder* r) { object_setInstanceVariable (self, "owner", r); }
};
CaptureSession& captureSession;
AVCaptureMovieFileOutput* movieFileOutput;
std::unique_ptr<NSObject<AVCaptureFileOutputRecordingDelegate>, NSObjectDeleter> delegate;
bool recordingInProgress = false;
@ -1086,7 +1156,7 @@ struct CameraDevice::ViewerComponent : public UIViewComponent
//==============================================================================
struct JuceCameraDeviceViewerClass : public ObjCClass<UIView>
{
JuceCameraDeviceViewerClass() : ObjCClass<UIView> ("JuceCameraDeviceViewerClass_")
JuceCameraDeviceViewerClass() : ObjCClass ("JuceCameraDeviceViewerClass_")
{
addMethod (@selector (layoutSubviews),
[] (id self, SEL)
@ -1101,6 +1171,20 @@ struct CameraDevice::ViewerComponent : public UIViewComponent
previewLayer.frame = asUIView.bounds;
});
addMethod (@selector (observeValueForKeyPath:ofObject:change:context:),
[] (id self, SEL, NSString* keyPath, id, NSDictionary*, void* context)
{
if ([keyPath isEqualToString: @"videoRotationAngleForHorizonLevelPreview"])
{
if (auto* previewLayer = getPreviewLayer (self))
{
auto* viewer = static_cast<ViewerComponent*> (context);
auto& session = viewer->cameraDevice.pimpl->captureSession;
session.updatePreviewOrientation();
}
}
});
registerClass();
}
@ -1118,6 +1202,9 @@ struct CameraDevice::ViewerComponent : public UIViewComponent
static void updateOrientation (id self)
{
if (@available (ios 17, *))
return;
if (auto* previewLayer = getPreviewLayer (self))
{
UIDeviceOrientation o = [UIDevice currentDevice].orientation;
@ -1125,13 +1212,52 @@ struct CameraDevice::ViewerComponent : public UIViewComponent
if (UIDeviceOrientationIsPortrait (o) || UIDeviceOrientationIsLandscape (o))
{
if (previewLayer.connection != nil)
{
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
previewLayer.connection.videoOrientation = (AVCaptureVideoOrientation) o;
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
}
}
}
}
};
ViewerComponent (CameraDevice& device)
struct AddObserverTrait
{
#if defined (__IPHONE_17_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_17_0
API_AVAILABLE (ios (17))
static void newFn (ViewerComponent* self)
{
auto& session = self->cameraDevice.pimpl->captureSession;
self->coordinator.reset ([[AVCaptureDeviceRotationCoordinator alloc] initWithDevice: session.getDevice()
previewLayer: session.getPreviewLayer()]);
[self->coordinator.get() addObserver: static_cast<UIView*> (self->getView())
forKeyPath: @"videoRotationAngleForHorizonLevelPreview"
options: NSKeyValueObservingOptionNew
context: self];
}
#endif
static void oldFn (ViewerComponent*) {}
};
struct RemoveObserverTrait
{
API_AVAILABLE (ios (17))
static void newFn (ViewerComponent* self)
{
if (self->coordinator != nullptr)
{
[self->coordinator.get() removeObserver: static_cast<UIView*> (self->getView())
forKeyPath: @"videoRotationAngleForHorizonLevelPreview"];
}
}
static void oldFn (ViewerComponent*) {}
};
explicit ViewerComponent (CameraDevice& device)
: cameraDevice (device)
{
static JuceCameraDeviceViewerClass cls;
@ -1144,15 +1270,19 @@ struct CameraDevice::ViewerComponent : public UIViewComponent
auto* previewLayer = device.pimpl->captureSession.createPreviewLayer();
previewLayer.frame = view.bounds;
UIInterfaceOrientation statusBarOrientation = [UIApplication sharedApplication].statusBarOrientation;
AVCaptureVideoOrientation videoOrientation = statusBarOrientation != UIInterfaceOrientationUnknown
? (AVCaptureVideoOrientation) statusBarOrientation
: AVCaptureVideoOrientationPortrait;
previewLayer.connection.videoOrientation = videoOrientation;
[view.layer addSublayer: previewLayer];
ifelse_17_0<AddObserverTrait> (this);
}
~ViewerComponent() override
{
ifelse_17_0<RemoveObserverTrait> (this);
}
CameraDevice& cameraDevice;
NSUniquePtr<NSObject> coordinator;
};
//==============================================================================