diff --git a/doc/classes/OS.xml b/doc/classes/OS.xml
index 018e42a6572..774ee21ed56 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 148fada9a08..e799c0a71a7 100644
--- a/drivers/apple_embedded/os_apple_embedded.h
+++ b/drivers/apple_embedded/os_apple_embedded.h
@@ -137,6 +137,9 @@ public:
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 6468c688aca..07d1f8a270c 100644
--- a/drivers/apple_embedded/os_apple_embedded.mm
+++ b/drivers/apple_embedded/os_apple_embedded.mm
@@ -43,6 +43,7 @@
#import "drivers/apple/os_log_logger.h"
#include "main/main.h"
+#import
#import
#import
#import
@@ -733,4 +734,35 @@ Rect2 OS_AppleEmbedded::calculate_boot_screen_rect(const Size2 &p_window_size, c
}
}
+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.h b/drivers/coreaudio/audio_driver_coreaudio.h
index 64c77fe97ff..36f5eee73b7 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.h
+++ b/drivers/coreaudio/audio_driver_coreaudio.h
@@ -59,7 +59,7 @@ class AudioDriverCoreAudio : public AudioDriver {
unsigned int capture_buffer_frames = 0;
Vector samples_in;
- Vector input_buf;
+ unsigned int buffer_size = 0;
#ifdef MACOS_ENABLED
PackedStringArray _get_device_list(bool capture = false);
diff --git a/drivers/coreaudio/audio_driver_coreaudio.mm b/drivers/coreaudio/audio_driver_coreaudio.mm
index d9efa9c658e..6f9f690d528 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.mm
+++ b/drivers/coreaudio/audio_driver_coreaudio.mm
@@ -241,14 +241,15 @@ OSStatus AudioDriverCoreAudio::input_callback(void *inRefCon,
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);
+ bufferList.mBuffers[0].mDataByteSize = ad->buffer_size * sizeof(int16_t);
OSStatus result = AudioUnitRender(ad->input_unit, ioActionFlags, inTimeStamp, inBusNumber, inNumberFrames, &bufferList);
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 +394,6 @@ Error AudioDriverCoreAudio::init_input_device() {
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
@@ -460,8 +458,7 @@ Error AudioDriverCoreAudio::init_input_device() {
// Sample rate is independent of channels (ref: https://stackoverflow.com/questions/11048825/audio-sample-frequency-rely-on-channels)
capture_buffer_frames = closest_power_of_2(latency * (uint32_t)capture_mix_rate / (uint32_t)1000);
- unsigned int buffer_size = capture_buffer_frames * capture_channels;
- input_buf.resize(buffer_size);
+ buffer_size = capture_buffer_frames * capture_channels;
AURenderCallbackStruct callback;
memset(&callback, 0, sizeof(AURenderCallbackStruct));