mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Merge pull request #5786 from vitor-k/macos-perms
Request Camera Permission on MacOS
This commit is contained in:
		
						commit
						e3804a4c06
					
				
					 9 changed files with 220 additions and 5 deletions
				
			
		|  | @ -236,6 +236,10 @@ if (APPLE) | |||
|     target_sources(citra-qt PRIVATE ${MACOSX_ICON}) | ||||
|     set_target_properties(citra-qt PROPERTIES MACOSX_BUNDLE TRUE) | ||||
|     set_target_properties(citra-qt PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist) | ||||
|     target_sources(citra-qt PRIVATE | ||||
|         macos_authorization.h | ||||
|         macos_authorization.mm | ||||
|     ) | ||||
| elseif(WIN32) | ||||
|     # compile as a win32 gui application instead of a console application | ||||
|     target_link_libraries(citra-qt PRIVATE Qt5::WinMain) | ||||
|  |  | |||
|  | @ -36,5 +36,9 @@ | |||
| 	<string>NSApplication</string> | ||||
| 	<key>NSHighResolutionCapable</key> | ||||
| 	<string>True</string> | ||||
| 	<key>NSCameraUsageDescription</key> | ||||
| 	<string>This app requires camera access to emulate the 3DS's cameras.</string> | ||||
| 	<key>NSMicrophoneUsageDescription</key> | ||||
| 	<string>This app requires microphone access to emulate the 3DS's microphone.</string> | ||||
| </dict> | ||||
| </plist> | ||||
|  |  | |||
|  | @ -10,6 +10,10 @@ | |||
| #include "citra_qt/camera/qt_multimedia_camera.h" | ||||
| #include "citra_qt/main.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
| #include "citra_qt/macos_authorization.h" | ||||
| #endif | ||||
| 
 | ||||
| namespace Camera { | ||||
| 
 | ||||
| QList<QVideoFrame::PixelFormat> QtCameraSurface::supportedPixelFormats([ | ||||
|  | @ -187,6 +191,12 @@ void QtMultimediaCameraHandler::StopCamera() { | |||
| } | ||||
| 
 | ||||
| void QtMultimediaCameraHandler::StartCamera() { | ||||
| #if defined(__APPLE__) | ||||
|     if (!AppleAuthorization::CheckAuthorizationForCamera()) { | ||||
|         LOG_ERROR(Service_CAM, "Unable to start camera due to lack of authorization"); | ||||
|         return; | ||||
|     } | ||||
| #endif | ||||
|     camera->setViewfinderSettings(settings); | ||||
|     camera->start(); | ||||
|     started = true; | ||||
|  |  | |||
|  | @ -15,6 +15,10 @@ | |||
| #include "core/settings.h" | ||||
| #include "ui_configure_audio.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
| #include "citra_qt/macos_authorization.h" | ||||
| #endif | ||||
| 
 | ||||
| constexpr int DEFAULT_INPUT_DEVICE_INDEX = 0; | ||||
| 
 | ||||
| ConfigureAudio::ConfigureAudio(QWidget* parent) | ||||
|  | @ -148,6 +152,11 @@ void ConfigureAudio::UpdateAudioOutputDevices(int sink_index) { | |||
| } | ||||
| 
 | ||||
| void ConfigureAudio::UpdateAudioInputDevices(int index) { | ||||
| #if defined(__APPLE__) | ||||
|     if (index == 1) { | ||||
|         AppleAuthorization::CheckAuthorizationForMicrophone(); | ||||
|     } | ||||
| #endif | ||||
|     if (Settings::values.mic_input_device != Frontend::Mic::default_device_name) { | ||||
|         ui->input_device_combo_box->setCurrentText( | ||||
|             QString::fromStdString(Settings::values.mic_input_device)); | ||||
|  |  | |||
|  | @ -17,6 +17,10 @@ | |||
| #include "core/settings.h" | ||||
| #include "ui_configure_camera.h" | ||||
| 
 | ||||
| #if defined(__APPLE__) | ||||
| #include "citra_qt/macos_authorization.h" | ||||
| #endif | ||||
| 
 | ||||
| const std::array<std::string, 3> ConfigureCamera::Implementations = { | ||||
|     "blank", /* Blank */ | ||||
|     "image", /* Image */ | ||||
|  | @ -46,9 +50,15 @@ ConfigureCamera::~ConfigureCamera() { | |||
| 
 | ||||
| void ConfigureCamera::ConnectEvents() { | ||||
|     connect(ui->image_source, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, | ||||
|             [this](int index) { | ||||
|                 StopPreviewing(); | ||||
|                 UpdateImageSourceUI(); | ||||
| #if defined(__APPLE__) | ||||
|                 if (index == 2) { | ||||
|                     AppleAuthorization::CheckAuthorizationForCamera(); | ||||
|                 } | ||||
| #endif | ||||
|             }); | ||||
|     connect(ui->camera_selection, | ||||
|             static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, [this] { | ||||
|  |  | |||
							
								
								
									
										12
									
								
								src/citra_qt/macos_authorization.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/citra_qt/macos_authorization.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,12 @@ | |||
| // Copyright 2020 Citra Emulator Project
 | ||||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| namespace AppleAuthorization { | ||||
| 
 | ||||
| bool CheckAuthorizationForCamera(); | ||||
| bool CheckAuthorizationForMicrophone(); | ||||
| 
 | ||||
| } // namespace AppleAuthorization
 | ||||
							
								
								
									
										81
									
								
								src/citra_qt/macos_authorization.mm
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/citra_qt/macos_authorization.mm
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,81 @@ | |||
| // Copyright 2020 Citra Emulator Project | ||||
| // Licensed under GPLv2 or any later version | ||||
| // Refer to the license.txt file included. | ||||
| 
 | ||||
| #import <AVFoundation/AVFoundation.h> | ||||
| 
 | ||||
| #include "citra_qt/macos_authorization.h" | ||||
| #include "common/logging/log.h" | ||||
| 
 | ||||
| namespace AppleAuthorization { | ||||
| 
 | ||||
| static bool authorized = false; | ||||
| 
 | ||||
| enum class AuthMediaType { Camera, Microphone }; | ||||
| 
 | ||||
| // Based on | ||||
| // https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos | ||||
| void CheckAuthorization(AuthMediaType type) { | ||||
|     if (@available(macOS 10.14, *)) { | ||||
|         NSString* media_type; | ||||
|         if (type == AuthMediaType::Camera) { | ||||
|             media_type = AVMediaTypeVideo; | ||||
|         } else { | ||||
|             media_type = AVMediaTypeAudio; | ||||
|         } | ||||
| 
 | ||||
|         // Request permission to access the camera and microphone. | ||||
|         switch ([AVCaptureDevice authorizationStatusForMediaType:media_type]) { | ||||
|         case AVAuthorizationStatusAuthorized: | ||||
|             // The user has previously granted access to the camera. | ||||
|             authorized = true; | ||||
|             break; | ||||
|         case AVAuthorizationStatusNotDetermined: { | ||||
|             // The app hasn't yet asked the user for camera access. | ||||
|             [AVCaptureDevice requestAccessForMediaType:media_type | ||||
|                                      completionHandler:^(BOOL granted) { | ||||
|                                        authorized = granted; | ||||
|                                      }]; | ||||
|             if (type == AuthMediaType::Camera) { | ||||
|                 LOG_INFO(Frontend, "Camera access requested."); | ||||
|             } else { // AuthMediaType::Microphone | ||||
|                 LOG_INFO(Frontend, "Microphone access requested."); | ||||
|             } | ||||
|             break; | ||||
|         } | ||||
|         case AVAuthorizationStatusDenied: { | ||||
|             // The user has previously denied access. | ||||
|             authorized = false; | ||||
|             if (type == AuthMediaType::Camera) { | ||||
|                 LOG_WARNING(Frontend, "Camera access denied. To change this you may modify the " | ||||
|                                       "macOS system permission settings " | ||||
|                                       "for Citra at 'System Preferences -> Security & Privacy'"); | ||||
|             } else { // AuthMediaType::Microphone | ||||
|                 LOG_WARNING(Frontend, "Microphone access denied. To change this you may modify the " | ||||
|                                       "macOS system permission settings " | ||||
|                                       "for Citra at 'System Preferences -> Security & Privacy'"); | ||||
|             } | ||||
|             return; | ||||
|         } | ||||
|         case AVAuthorizationStatusRestricted: { | ||||
|             // The user can't grant access due to restrictions. | ||||
|             authorized = false; | ||||
|             return; | ||||
|         } | ||||
|         } | ||||
|     } else { | ||||
|         authorized = true; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| bool CheckAuthorizationForCamera() { | ||||
|     CheckAuthorization(AuthMediaType::Camera); | ||||
|     return authorized; | ||||
| } | ||||
| 
 | ||||
| bool CheckAuthorizationForMicrophone() { | ||||
|     CheckAuthorization(AuthMediaType::Microphone); | ||||
|     return authorized; | ||||
| } | ||||
| 
 | ||||
| } // AppleAuthorization | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue