-
-
Notifications
You must be signed in to change notification settings - Fork 23.8k
Implement permission request for Apple embedded platforms, fix microphone input #107233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -302,6 +302,7 @@ | |||||
| <description> | ||||||
| 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. | ||||||
| </description> | ||||||
| </method> | ||||||
| <method name="get_keycode_string" qualifiers="const"> | ||||||
|
|
@@ -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. | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
Please use Oxford comma. |
||||||
| </description> | ||||||
| </method> | ||||||
| <method name="request_permissions"> | ||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
|
|
@@ -48,6 +48,7 @@ | |||||
| #import <AudioToolbox/AudioServices.h> | ||||||
| #import <CoreText/CoreText.h> | ||||||
| #import <UIKit/UIKit.h> | ||||||
| #import <AVFoundation/AVFAudio.h> | ||||||
| #import <dlfcn.h> | ||||||
| #include <sys/sysctl.h> | ||||||
|
|
||||||
|
|
@@ -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); | ||||||
| }]; | ||||||
| } | ||||||
| }; | ||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
| } | ||||||
| return false; | ||||||
| } | ||||||
|
|
||||||
| Vector<String> OS_AppleEmbedded::get_granted_permissions() const { | ||||||
| Vector<String> ret; | ||||||
|
|
||||||
| if (@available(iOS 17.0, *)) { | ||||||
| if ([AVAudioApplication sharedInstance].recordPermission == AVAudioApplicationRecordPermissionGranted) { | ||||||
| ret.push_back("appleembedded.permission.AUDIO_RECORD"); | ||||||
| } | ||||||
| } | ||||||
| return ret; | ||||||
| } | ||||||
| #endif // APPLE_EMBEDDED_ENABLED | ||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
diff --git a/drivers/coreaudio/audio_driver_coreaudio.h b/drivers/coreaudio/audio_driver_coreaudio.h
index 64c77fe97f..36f5eee73b 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<int32_t> samples_in;
- Vector<int16_t> 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 fb870e4740..8763a1b933 100644
--- a/drivers/coreaudio/audio_driver_coreaudio.mm
+++ b/drivers/coreaudio/audio_driver_coreaudio.mm
@@ -243,10 +243,9 @@
bufferList.mNumberBuffers = 1;
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);
- 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++) {
@@ -459,8 +458,7 @@
// 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)); |
||
| 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 | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.