mirror of
https://github.com/godotengine/godot.git
synced 2025-10-19 07:53:26 +00:00
Add permission request for Apple embedded platforms, fix microphone input
Co-Authored-By: Miguel de Icaza <miguel@gnome.org> Supersedes https://github.com/godotengine/godot/pull/107233 Fixes https://github.com/godotengine/godot-proposals/issues/12563 Fixes https://github.com/godotengine/godot/issues/33885 Superseding Miguel's PR to get it in during the beta stage.
This commit is contained in:
parent
30456ba095
commit
5a7b6b7159
5 changed files with 44 additions and 10 deletions
|
@ -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.
|
||||
</description>
|
||||
</method>
|
||||
<method name="request_permissions">
|
||||
|
|
|
@ -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<String> get_granted_permissions() const override;
|
||||
};
|
||||
|
||||
#endif // APPLE_EMBEDDED_ENABLED
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#import "drivers/apple/os_log_logger.h"
|
||||
#include "main/main.h"
|
||||
|
||||
#import <AVFoundation/AVFAudio.h>
|
||||
#import <AudioToolbox/AudioServices.h>
|
||||
#import <CoreText/CoreText.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
@ -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<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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue