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:
parent
eb6ebaf5af
commit
7290d6dc2f
1 changed files with 148 additions and 18 deletions
|
|
@ -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;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue