diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 57c1b6c7505f..cc65efcbb487 100644
--- a/doc/classes/OS.xml
+++ b/doc/classes/OS.xml
@@ -302,6 +302,7 @@
On Android devices: Returns the list of dangerous permissions that have been granted.
On macOS: Returns the list of granted permissions and user selected folders accessible to the application (sandboxed applications only). Use the native file dialog to request folder access permission.
+ On iOS, VisionOS: Returns the list of granted permissions.
@@ -781,8 +782,9 @@
- [code]OS.request_permission("android.permission.READ_EXTERNAL_STORAGE")[/code]
- [code]OS.request_permission("android.permission.POST_NOTIFICATIONS")[/code]
- [code]OS.request_permission("macos.permission.RECORD_SCREEN")[/code]
+ - [code]OS.request_permission("appleembedded.permission.AUDIO_RECORD")[/code]
[b]Note:[/b] On Android, permission must be checked during export.
- [b]Note:[/b] This method is implemented on Android and macOS.
+ [b]Note:[/b] This method is implemented on Android, macOS and visionOS platforms.
diff --git a/drivers/apple_embedded/os_apple_embedded.h b/drivers/apple_embedded/os_apple_embedded.h
index 6bbf31852315..16d1b4dafd6f 100644
--- a/drivers/apple_embedded/os_apple_embedded.h
+++ b/drivers/apple_embedded/os_apple_embedded.h
@@ -132,6 +132,9 @@ class OS_AppleEmbedded : public OS_Unix {
void on_exit_background();
virtual Rect2 calculate_boot_screen_rect(const Size2 &p_window_size, const Size2 &p_imgrect_size) const override;
+
+ virtual bool request_permission(const String &p_name) override;
+ virtual Vector get_granted_permissions() const override;
};
#endif // APPLE_EMBEDDED_ENABLED
diff --git a/drivers/apple_embedded/os_apple_embedded.mm b/drivers/apple_embedded/os_apple_embedded.mm
index fa71c96e100f..69c93ef41264 100644
--- a/drivers/apple_embedded/os_apple_embedded.mm
+++ b/drivers/apple_embedded/os_apple_embedded.mm
@@ -48,6 +48,7 @@
#import
#import
#import
+#import
#import
#include
@@ -714,4 +715,35 @@ Rect2 fit_keep_aspect_covered(const Vector2 &p_container, const Vector2 &p_rect)
}
}
+bool OS_AppleEmbedded::request_permission(const String &p_name) {
+ if (p_name == "appleembedded.permission.AUDIO_RECORD") {
+ if (@available(iOS 17.0, *)) {
+ AVAudioApplicationRecordPermission permission = [AVAudioApplication sharedInstance].recordPermission;
+ if (permission == AVAudioApplicationRecordPermissionGranted) {
+ // Permission already granted, you can start recording.
+ return true;
+ } else if (permission == AVAudioApplicationRecordPermissionDenied) {
+ // Permission denied, or not yet granted
+ return false;
+ } else {
+ // Request the permission, but for now return false as documented
+ [AVAudioApplication requestRecordPermissionWithCompletionHandler: ^(BOOL granted) {
+ get_main_loop()->emit_signal(SNAME("on_request_permissions_result"), p_name, granted);
+ }];
+ }
+ };
+ }
+ return false;
+}
+
+Vector OS_AppleEmbedded::get_granted_permissions() const {
+ Vector ret;
+
+ if (@available(iOS 17.0, *)) {
+ if ([AVAudioApplication sharedInstance].recordPermission == AVAudioApplicationRecordPermissionGranted) {
+ ret.push_back("appleembedded.permission.AUDIO_RECORD");
+ }
+ }
+ return ret;
+}
#endif // APPLE_EMBEDDED_ENABLED
diff --git a/drivers/coreaudio/audio_driver_coreaudio.mm b/drivers/coreaudio/audio_driver_coreaudio.mm
index d9efa9c658eb..fb870e4740a7 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.mm
+++ b/drivers/coreaudio/audio_driver_coreaudio.mm
@@ -241,14 +241,16 @@
AudioBufferList bufferList;
bufferList.mNumberBuffers = 1;
- bufferList.mBuffers[0].mData = ad->input_buf.ptrw();
+ bufferList.mBuffers[0].mData = nullptr;
bufferList.mBuffers[0].mNumberChannels = ad->capture_channels;
bufferList.mBuffers[0].mDataByteSize = ad->input_buf.size() * sizeof(int16_t);
OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
+ ad->input_buf.resize(inNumberFrames * ad->capture_channels);
if (result == noErr) {
+ int16_t *data = (int16_t *)bufferList.mBuffers[0].mData;
for (unsigned int i = 0; i < inNumberFrames * ad->capture_channels; i++) {
- int32_t sample = ad->input_buf[i] << 16;
+ int32_t sample = data[i] << 16;
ad->input_buffer_write(sample);
if (ad->capture_channels == 1) {
@@ -393,9 +395,6 @@
UInt32 flag = 1;
result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Input, kInputBus, &flag, sizeof(flag));
ERR_FAIL_COND_V(result != noErr, FAILED);
- flag = 0;
- result = AudioUnitSetProperty(input_unit, kAudioOutputUnitProperty_EnableIO, kAudioUnitScope_Output, kOutputBus, &flag, sizeof(flag));
- ERR_FAIL_COND_V(result != noErr, FAILED);
UInt32 size;
#ifdef MACOS_ENABLED