mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2025-06-03 00:00:20 +00:00
Added permission checks for mac audio backend.
This commit is contained in:
parent
e18597f5eb
commit
0e0eb5f41f
@ -18,17 +18,18 @@
|
|||||||
|
|
||||||
define_channel_client_subsystem("audin" "mac" "")
|
define_channel_client_subsystem("audin" "mac" "")
|
||||||
FIND_LIBRARY(CORE_AUDIO CoreAudio)
|
FIND_LIBRARY(CORE_AUDIO CoreAudio)
|
||||||
|
FIND_LIBRARY(AVFOUNDATION AVFoundation)
|
||||||
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
|
FIND_LIBRARY(AUDIO_TOOL AudioToolbox)
|
||||||
FIND_LIBRARY(APP_SERVICES ApplicationServices)
|
FIND_LIBRARY(APP_SERVICES ApplicationServices)
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_SRCS
|
set(${MODULE_PREFIX}_SRCS
|
||||||
audin_mac.c)
|
audin_mac.m)
|
||||||
|
|
||||||
include_directories(..)
|
include_directories(..)
|
||||||
include_directories(${MAC_INCLUDE_DIRS})
|
include_directories(${MAC_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
add_channel_client_subsystem_library(${MODULE_PREFIX} ${MODULE_NAME} ${CHANNEL_NAME} "" TRUE "")
|
||||||
|
|
||||||
set(${MODULE_PREFIX}_LIBS freerdp ${CORE_AUDIO} ${AUDIO_TOOL} ${APP_SERVICES} winpr)
|
set(${MODULE_PREFIX}_LIBS freerdp ${AVFOUNDATION} ${CORE_AUDIO} ${AUDIO_TOOL} ${APP_SERVICES} winpr)
|
||||||
|
|
||||||
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS})
|
||||||
|
@ -33,12 +33,14 @@
|
|||||||
#include <winpr/debug.h>
|
#include <winpr/debug.h>
|
||||||
#include <winpr/cmdline.h>
|
#include <winpr/cmdline.h>
|
||||||
|
|
||||||
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
#define __COREFOUNDATION_CFPLUGINCOM__ 1
|
#define __COREFOUNDATION_CFPLUGINCOM__ 1
|
||||||
#define IUNKNOWN_C_GUTS \
|
#define IUNKNOWN_C_GUTS \
|
||||||
void* _reserved; \
|
void *_reserved; \
|
||||||
void* QueryInterface; \
|
void *QueryInterface; \
|
||||||
void* AddRef; \
|
void *AddRef; \
|
||||||
void* Release
|
void *Release
|
||||||
|
|
||||||
#include <CoreAudio/CoreAudioTypes.h>
|
#include <CoreAudio/CoreAudioTypes.h>
|
||||||
#include <CoreAudio/CoreAudio.h>
|
#include <CoreAudio/CoreAudio.h>
|
||||||
@ -72,17 +74,18 @@ typedef struct _AudinMacDevice
|
|||||||
int dev_unit;
|
int dev_unit;
|
||||||
|
|
||||||
AudinReceive receive;
|
AudinReceive receive;
|
||||||
void* user_data;
|
void *user_data;
|
||||||
|
|
||||||
rdpContext* rdpcontext;
|
rdpContext *rdpcontext;
|
||||||
|
|
||||||
|
bool isAuthorized;
|
||||||
bool isOpen;
|
bool isOpen;
|
||||||
AudioQueueRef audioQueue;
|
AudioQueueRef audioQueue;
|
||||||
AudioStreamBasicDescription audioFormat;
|
AudioStreamBasicDescription audioFormat;
|
||||||
AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS];
|
AudioQueueBufferRef audioBuffers[MAC_AUDIO_QUEUE_NUM_BUFFERS];
|
||||||
} AudinMacDevice;
|
} AudinMacDevice;
|
||||||
|
|
||||||
static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format)
|
static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT *format)
|
||||||
{
|
{
|
||||||
switch (format->wFormatTag)
|
switch (format->wFormatTag)
|
||||||
{
|
{
|
||||||
@ -94,7 +97,7 @@ static AudioFormatID audin_mac_get_format(const AUDIO_FORMAT* format)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* format)
|
static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT *format)
|
||||||
{
|
{
|
||||||
switch (format->wFormatTag)
|
switch (format->wFormatTag)
|
||||||
{
|
{
|
||||||
@ -106,10 +109,14 @@ static AudioFormatFlags audin_mac_get_flags_for_format(const AUDIO_FORMAT* forma
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT* format)
|
static BOOL audin_mac_format_supported(IAudinDevice *device, const AUDIO_FORMAT *format)
|
||||||
{
|
{
|
||||||
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
AudioFormatID req_fmt = 0;
|
AudioFormatID req_fmt = 0;
|
||||||
|
|
||||||
|
if (!mac->isAuthorized)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (device == NULL || format == NULL)
|
if (device == NULL || format == NULL)
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
@ -126,10 +133,13 @@ static BOOL audin_mac_format_supported(IAudinDevice* device, const AUDIO_FORMAT*
|
|||||||
*
|
*
|
||||||
* @return 0 on success, otherwise a Win32 error code
|
* @return 0 on success, otherwise a Win32 error code
|
||||||
*/
|
*/
|
||||||
static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* format,
|
static UINT audin_mac_set_format(IAudinDevice *device, const AUDIO_FORMAT *format,
|
||||||
UINT32 FramesPerPacket)
|
UINT32 FramesPerPacket)
|
||||||
{
|
{
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)device;
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
|
|
||||||
|
if (!mac->isAuthorized)
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (device == NULL || format == NULL)
|
if (device == NULL || format == NULL)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
@ -155,13 +165,13 @@ static UINT audin_mac_set_format(IAudinDevice* device, const AUDIO_FORMAT* forma
|
|||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
|
static void mac_audio_queue_input_cb(void *aqData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer,
|
||||||
const AudioTimeStamp* inStartTime, UInt32 inNumPackets,
|
const AudioTimeStamp *inStartTime, UInt32 inNumPackets,
|
||||||
const AudioStreamPacketDescription* inPacketDesc)
|
const AudioStreamPacketDescription *inPacketDesc)
|
||||||
{
|
{
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)aqData;
|
AudinMacDevice *mac = (AudinMacDevice *)aqData;
|
||||||
UINT error = CHANNEL_RC_OK;
|
UINT error = CHANNEL_RC_OK;
|
||||||
const BYTE* buffer = inBuffer->mAudioData;
|
const BYTE *buffer = inBuffer->mAudioData;
|
||||||
int buffer_size = inBuffer->mAudioDataByteSize;
|
int buffer_size = inBuffer->mAudioDataByteSize;
|
||||||
(void)inAQ;
|
(void)inAQ;
|
||||||
(void)inStartTime;
|
(void)inStartTime;
|
||||||
@ -180,12 +190,15 @@ static void mac_audio_queue_input_cb(void* aqData, AudioQueueRef inAQ, AudioQueu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT audin_mac_close(IAudinDevice* device)
|
static UINT audin_mac_close(IAudinDevice *device)
|
||||||
{
|
{
|
||||||
UINT errCode = CHANNEL_RC_OK;
|
UINT errCode = CHANNEL_RC_OK;
|
||||||
char errString[1024];
|
char errString[1024];
|
||||||
OSStatus devStat;
|
OSStatus devStat;
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)device;
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
|
|
||||||
|
if (!mac->isAuthorized)
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
return ERROR_INVALID_PARAMETER;
|
return ERROR_INVALID_PARAMETER;
|
||||||
@ -223,13 +236,17 @@ static UINT audin_mac_close(IAudinDevice* device)
|
|||||||
return errCode;
|
return errCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT audin_mac_open(IAudinDevice* device, AudinReceive receive, void* user_data)
|
static UINT audin_mac_open(IAudinDevice *device, AudinReceive receive, void *user_data)
|
||||||
{
|
{
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)device;
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
DWORD errCode;
|
DWORD errCode;
|
||||||
char errString[1024];
|
char errString[1024];
|
||||||
OSStatus devStat;
|
OSStatus devStat;
|
||||||
size_t index;
|
size_t index;
|
||||||
|
|
||||||
|
if (!mac->isAuthorized)
|
||||||
|
return ERROR_INTERNAL_ERROR;
|
||||||
|
|
||||||
mac->receive = receive;
|
mac->receive = receive;
|
||||||
mac->user_data = user_data;
|
mac->user_data = user_data;
|
||||||
devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL,
|
devStat = AudioQueueNewInput(&(mac->audioFormat), mac_audio_queue_input_cb, mac, NULL,
|
||||||
@ -285,9 +302,9 @@ err_out:
|
|||||||
return CHANNEL_RC_INITIALIZATION_ERROR;
|
return CHANNEL_RC_INITIALIZATION_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT audin_mac_free(IAudinDevice* device)
|
static UINT audin_mac_free(IAudinDevice *device)
|
||||||
{
|
{
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)device;
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
@ -302,19 +319,19 @@ static UINT audin_mac_free(IAudinDevice* device)
|
|||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static UINT audin_mac_parse_addin_args(AudinMacDevice* device, ADDIN_ARGV* args)
|
static UINT audin_mac_parse_addin_args(AudinMacDevice *device, ADDIN_ARGV *args)
|
||||||
{
|
{
|
||||||
DWORD errCode;
|
DWORD errCode;
|
||||||
char errString[1024];
|
char errString[1024];
|
||||||
int status;
|
int status;
|
||||||
char *str_num, *eptr;
|
char *str_num, *eptr;
|
||||||
DWORD flags;
|
DWORD flags;
|
||||||
COMMAND_LINE_ARGUMENT_A* arg;
|
COMMAND_LINE_ARGUMENT_A *arg;
|
||||||
COMMAND_LINE_ARGUMENT_A audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
|
COMMAND_LINE_ARGUMENT_A audin_mac_args[] = { { "dev", COMMAND_LINE_VALUE_REQUIRED, "<device>",
|
||||||
NULL, NULL, -1, NULL, "audio device name" },
|
NULL, NULL, -1, NULL, "audio device name" },
|
||||||
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
|
{ NULL, 0, NULL, NULL, NULL, -1, NULL, NULL } };
|
||||||
|
|
||||||
AudinMacDevice* mac = (AudinMacDevice*)device;
|
AudinMacDevice *mac = (AudinMacDevice *)device;
|
||||||
|
|
||||||
if (args->argc == 1)
|
if (args->argc == 1)
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
@ -369,10 +386,10 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
|||||||
{
|
{
|
||||||
DWORD errCode;
|
DWORD errCode;
|
||||||
char errString[1024];
|
char errString[1024];
|
||||||
ADDIN_ARGV* args;
|
ADDIN_ARGV *args;
|
||||||
AudinMacDevice* mac;
|
AudinMacDevice *mac;
|
||||||
UINT error;
|
UINT error;
|
||||||
mac = (AudinMacDevice*)calloc(1, sizeof(AudinMacDevice));
|
mac = (AudinMacDevice *)calloc(1, sizeof(AudinMacDevice));
|
||||||
|
|
||||||
if (!mac)
|
if (!mac)
|
||||||
{
|
{
|
||||||
@ -397,12 +414,40 @@ UINT freerdp_audin_client_subsystem_entry(PFREERDP_AUDIN_DEVICE_ENTRY_POINTS pEn
|
|||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice*)mac)))
|
if ((error = pEntryPoints->pRegisterAudinDevice(pEntryPoints->plugin, (IAudinDevice *)mac)))
|
||||||
{
|
{
|
||||||
WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error);
|
WLog_ERR(TAG, "RegisterAudinDevice failed with error %" PRIu32 "!", error);
|
||||||
goto error_out;
|
goto error_out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AVAuthorizationStatus status =
|
||||||
|
[AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
|
||||||
|
switch (status)
|
||||||
|
{
|
||||||
|
case AVAuthorizationStatusAuthorized:
|
||||||
|
mac->isAuthorized = TRUE;
|
||||||
|
break;
|
||||||
|
case AVAuthorizationStatusNotDetermined:
|
||||||
|
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo
|
||||||
|
completionHandler:^(BOOL granted) {
|
||||||
|
if (granted == YES)
|
||||||
|
{
|
||||||
|
mac->isAuthorized = TRUE;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
WLog_WARN(TAG, "Microphone access denied by user");
|
||||||
|
}];
|
||||||
|
break;
|
||||||
|
case AVAuthorizationStatusRestricted:
|
||||||
|
WLog_WARN(TAG, "Microphone access restricted by policy");
|
||||||
|
break;
|
||||||
|
case AVAuthorizationStatusDenied:
|
||||||
|
WLog_WARN(TAG, "Microphone access denied by policy");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
return CHANNEL_RC_OK;
|
return CHANNEL_RC_OK;
|
||||||
error_out:
|
error_out:
|
||||||
free(mac);
|
free(mac);
|
@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>This application requires camera access to redirect it to the remote host</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>This application requires microphone access to redirect it to the remote host</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>English</string>
|
<string>English</string>
|
||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
|
@ -2,6 +2,10 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>NSCameraUsageDescription</key>
|
||||||
|
<string>This application requires camera access to redirect it to the remote host</string>
|
||||||
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
|
<string>This application requires microphone access to redirect it to the remote host</string>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>en</string>
|
<string>en</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
Loading…
Reference in New Issue
Block a user