mirror of https://github.com/procxx/kepka.git
Added support for platform-specific microphone permission in calls
This commit is contained in:
parent
500ecb464c
commit
44eac2bf07
|
@ -1403,6 +1403,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
"lng_call_rate_label" = "Please rate the quality of your call";
|
"lng_call_rate_label" = "Please rate the quality of your call";
|
||||||
"lng_call_rate_comment" = "Comment (optional)";
|
"lng_call_rate_comment" = "Comment (optional)";
|
||||||
|
|
||||||
|
"lng_no_mic_permission" = "Telegram needs access to your microphone so that you can make calls and record voice messages.";
|
||||||
|
|
||||||
"lng_player_message_today" = "Today at {time}";
|
"lng_player_message_today" = "Today at {time}";
|
||||||
"lng_player_message_yesterday" = "Yesterday at {time}";
|
"lng_player_message_yesterday" = "Yesterday at {time}";
|
||||||
"lng_player_message_date" = "{date} at {time}";
|
"lng_player_message_date" = "{date} at {time}";
|
||||||
|
|
|
@ -241,6 +241,10 @@ void Call::startIncoming() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Call::answer() {
|
void Call::answer() {
|
||||||
|
_delegate->requestMicrophonePermissionOrFail([this](){ actuallyAnswer(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void Call::actuallyAnswer() {
|
||||||
Expects(_type == Type::Incoming);
|
Expects(_type == Type::Incoming);
|
||||||
|
|
||||||
if (_state != State::Starting && _state != State::WaitingIncoming) {
|
if (_state != State::Starting && _state != State::WaitingIncoming) {
|
||||||
|
|
|
@ -46,6 +46,7 @@ public:
|
||||||
Ended,
|
Ended,
|
||||||
};
|
};
|
||||||
virtual void playSound(Sound sound) = 0;
|
virtual void playSound(Sound sound) = 0;
|
||||||
|
virtual void requestMicrophonePermissionOrFail(Fn<void()> result) = 0;
|
||||||
|
|
||||||
virtual ~Delegate();
|
virtual ~Delegate();
|
||||||
|
|
||||||
|
@ -167,6 +168,7 @@ private:
|
||||||
bool checkCallFields(const MTPDphoneCall &call);
|
bool checkCallFields(const MTPDphoneCall &call);
|
||||||
bool checkCallFields(const MTPDphoneCallAccepted &call);
|
bool checkCallFields(const MTPDphoneCallAccepted &call);
|
||||||
|
|
||||||
|
void actuallyAnswer();
|
||||||
void confirmAcceptedCall(const MTPDphoneCallAccepted &call);
|
void confirmAcceptedCall(const MTPDphoneCallAccepted &call);
|
||||||
void startConfirmedCall(const MTPDphoneCall &call);
|
void startConfirmedCall(const MTPDphoneCall &call);
|
||||||
void setState(State state);
|
void setState(State state);
|
||||||
|
|
|
@ -16,6 +16,8 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include "calls/calls_call.h"
|
#include "calls/calls_call.h"
|
||||||
#include "calls/calls_panel.h"
|
#include "calls/calls_panel.h"
|
||||||
#include "media/media_audio_track.h"
|
#include "media/media_audio_track.h"
|
||||||
|
#include "platform/platform_specific.h"
|
||||||
|
#include "mainwidget.h"
|
||||||
|
|
||||||
#include "boxes/rate_call_box.h"
|
#include "boxes/rate_call_box.h"
|
||||||
namespace Calls {
|
namespace Calls {
|
||||||
|
@ -38,7 +40,9 @@ void Instance::startOutgoingCall(not_null<UserData*> user) {
|
||||||
Ui::show(Box<InformBox>(lng_call_error_not_available(lt_user, App::peerName(user))));
|
Ui::show(Box<InformBox>(lng_call_error_not_available(lt_user, App::peerName(user))));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
createCall(user, Call::Type::Outgoing);
|
requestMicrophonePermissionOrFail([this, user](){
|
||||||
|
createCall(user, Call::Type::Outgoing);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Instance::callFinished(not_null<Call*> call) {
|
void Instance::callFinished(not_null<Call*> call) {
|
||||||
|
@ -284,6 +288,31 @@ void Instance::handleCallUpdate(const MTPPhoneCall &call) {
|
||||||
bool Instance::alreadyInCall() {
|
bool Instance::alreadyInCall() {
|
||||||
return (_currentCall && _currentCall->state() != Call::State::Busy);
|
return (_currentCall && _currentCall->state() != Call::State::Busy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Instance::requestMicrophonePermissionOrFail(Fn<void()> onSuccess) {
|
||||||
|
Platform::PermissionStatus status=Platform::GetPermissionStatus(Platform::PermissionType::Microphone);
|
||||||
|
if (status==Platform::PermissionStatus::Granted) {
|
||||||
|
onSuccess();
|
||||||
|
} else if(status==Platform::PermissionStatus::CanRequest) {
|
||||||
|
Platform::RequestPermission(Platform::PermissionType::Microphone, [this, onSuccess](Platform::PermissionStatus status){
|
||||||
|
if (status==Platform::PermissionStatus::Granted) {
|
||||||
|
crl::on_main(onSuccess);
|
||||||
|
} else {
|
||||||
|
if (_currentCall) {
|
||||||
|
_currentCall->hangup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (alreadyInCall()) {
|
||||||
|
_currentCall->hangup();
|
||||||
|
}
|
||||||
|
Ui::show(Box<ConfirmBox>(lang(lng_no_mic_permission), lang(lng_menu_settings), [](){
|
||||||
|
Platform::OpenSystemSettingsForPermission(Platform::PermissionType::Microphone);
|
||||||
|
Ui::hideLayer();
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Instance::~Instance() {
|
Instance::~Instance() {
|
||||||
for (auto panel : _pendingPanels) {
|
for (auto panel : _pendingPanels) {
|
||||||
|
|
|
@ -63,6 +63,7 @@ private:
|
||||||
void createCall(not_null<UserData*> user, Call::Type type);
|
void createCall(not_null<UserData*> user, Call::Type type);
|
||||||
void destroyCall(not_null<Call*> call);
|
void destroyCall(not_null<Call*> call);
|
||||||
void destroyCurrentPanel();
|
void destroyCurrentPanel();
|
||||||
|
void requestMicrophonePermissionOrFail(Fn<void()> onSuccess) override;
|
||||||
|
|
||||||
void refreshDhConfig();
|
void refreshDhConfig();
|
||||||
void refreshServerConfig();
|
void refreshServerConfig();
|
||||||
|
|
|
@ -433,6 +433,18 @@ void RegisterCustomScheme() {
|
||||||
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PermissionStatus GetPermissionStatus(PermissionType type){
|
||||||
|
return PermissionStatus::Granted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenSystemSettingsForPermission(PermissionType type){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
namespace ThirdParty {
|
namespace ThirdParty {
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
|
|
|
@ -26,6 +26,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
|
||||||
#include <IOKit/hidsystem/ev_keymap.h>
|
#include <IOKit/hidsystem/ev_keymap.h>
|
||||||
#include <SPMediaKeyTap.h>
|
#include <SPMediaKeyTap.h>
|
||||||
#include <mach-o/dyld.h>
|
#include <mach-o/dyld.h>
|
||||||
|
#include <AVFoundation/AVFoundation.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
@ -283,6 +284,51 @@ void RegisterCustomScheme() {
|
||||||
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// I do check for availability, just not in the exact way clang is content with
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunguarded-availability"
|
||||||
|
PermissionStatus GetPermissionStatus(PermissionType type) {
|
||||||
|
switch(type) {
|
||||||
|
case PermissionType::Microphone:
|
||||||
|
if([AVCaptureDevice respondsToSelector: @selector(authorizationStatusForMediaType:)]) { // Available starting with 10.14
|
||||||
|
switch([AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio]) {
|
||||||
|
case AVAuthorizationStatusNotDetermined:
|
||||||
|
return PermissionStatus::CanRequest;
|
||||||
|
case AVAuthorizationStatusAuthorized:
|
||||||
|
return PermissionStatus::Granted;
|
||||||
|
case AVAuthorizationStatusDenied:
|
||||||
|
case AVAuthorizationStatusRestricted:
|
||||||
|
return PermissionStatus::Denied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PermissionStatus::Granted;
|
||||||
|
}
|
||||||
|
return PermissionStatus::Granted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback) {
|
||||||
|
switch(type) {
|
||||||
|
case PermissionType::Microphone:
|
||||||
|
if([AVCaptureDevice respondsToSelector: @selector(requestAccessForMediaType:completionHandler:)]) { // Available starting with 10.14
|
||||||
|
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio completionHandler:^(BOOL granted) {
|
||||||
|
resultCallback(granted ? PermissionStatus::Granted : PermissionStatus::Denied);
|
||||||
|
}];
|
||||||
|
}else{
|
||||||
|
resultCallback(PermissionStatus::Granted);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop // -Wunguarded-availability
|
||||||
|
|
||||||
|
void OpenSystemSettingsForPermission(PermissionType type) {
|
||||||
|
switch(type) {
|
||||||
|
case PermissionType::Microphone:
|
||||||
|
[[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone"]];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
void psNewVersion() {
|
void psNewVersion() {
|
||||||
|
|
|
@ -11,6 +11,15 @@ namespace Platform {
|
||||||
|
|
||||||
void start();
|
void start();
|
||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
|
enum class PermissionStatus {
|
||||||
|
Granted,
|
||||||
|
CanRequest,
|
||||||
|
Denied,
|
||||||
|
};
|
||||||
|
enum class PermissionType {
|
||||||
|
Microphone,
|
||||||
|
};
|
||||||
|
|
||||||
void SetWatchingMediaKeys(bool watching);
|
void SetWatchingMediaKeys(bool watching);
|
||||||
bool IsApplicationActive();
|
bool IsApplicationActive();
|
||||||
|
@ -20,6 +29,9 @@ void InitOnTopPanel(QWidget *panel);
|
||||||
void DeInitOnTopPanel(QWidget *panel);
|
void DeInitOnTopPanel(QWidget *panel);
|
||||||
void ReInitOnTopPanel(QWidget *panel);
|
void ReInitOnTopPanel(QWidget *panel);
|
||||||
void RegisterCustomScheme();
|
void RegisterCustomScheme();
|
||||||
|
PermissionStatus GetPermissionStatus(PermissionType type);
|
||||||
|
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback);
|
||||||
|
void OpenSystemSettingsForPermission(PermissionType type);
|
||||||
|
|
||||||
QString SystemLanguage();
|
QString SystemLanguage();
|
||||||
QString SystemCountry();
|
QString SystemCountry();
|
||||||
|
|
|
@ -626,6 +626,37 @@ void RegisterCustomScheme() {
|
||||||
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
#endif // !TDESKTOP_DISABLE_REGISTER_CUSTOM_SCHEME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PermissionStatus GetPermissionStatus(PermissionType type) {
|
||||||
|
if(type==PermissionType::Microphone) {
|
||||||
|
PermissionStatus result=PermissionStatus::Granted;
|
||||||
|
HKEY hKey;
|
||||||
|
LSTATUS res=RegOpenKeyEx(HKEY_CURRENT_USER, L"Software\\Microsoft\\Windows\\CurrentVersion\\CapabilityAccessManager\\ConsentStore\\microphone", 0, KEY_QUERY_VALUE, &hKey);
|
||||||
|
if(res==ERROR_SUCCESS) {
|
||||||
|
wchar_t buf[20];
|
||||||
|
DWORD length=sizeof(buf);
|
||||||
|
res=RegQueryValueEx(hKey, L"Value", NULL, NULL, (LPBYTE)buf, &length);
|
||||||
|
if(res==ERROR_SUCCESS) {
|
||||||
|
if(wcscmp(buf, L"Deny")==0) {
|
||||||
|
result=PermissionStatus::Denied;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegCloseKey(hKey);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return PermissionStatus::Granted;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RequestPermission(PermissionType type, Fn<void(PermissionStatus)> resultCallback) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void OpenSystemSettingsForPermission(PermissionType type) {
|
||||||
|
if(type==PermissionType::Microphone) {
|
||||||
|
ShellExecute(NULL, L"open", L"ms-settings:privacy-microphone", NULL, NULL, SW_SHOWDEFAULT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Platform
|
} // namespace Platform
|
||||||
|
|
||||||
void psNewVersion() {
|
void psNewVersion() {
|
||||||
|
|
Loading…
Reference in New Issue