[MacOS] Ask user for permission to access microphone

This is required for MacOS 10.14 and later. This also requires an explanation why
access is required in the apps Info.plist. Hence added custom Info.plist templates
for each app.
This commit is contained in:
Roland Rossgotterer
2019-05-06 16:14:24 +02:00
committed by Klaus Basan
parent 61adfefa7a
commit 5f00747d19
14 changed files with 355 additions and 30 deletions

View File

@@ -54,38 +54,13 @@ namespace BlackCore
IContextAudio(mode, runtime),
m_voice(new CVoiceVatlib())
{
//! \todo KB 2018-11 those are supposed to be Qt::QueuedConnection, but not yet changed (risk to break something)
m_channel1 = m_voice->createVoiceChannel();
connect(m_channel1.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::onConnectionStatusChanged);
connect(m_channel1.data(), &IVoiceChannel::userJoinedRoom, this, &CContextAudio::onUserJoinedRoom);
connect(m_channel1.data(), &IVoiceChannel::userLeftRoom, this, &CContextAudio::onUserLeftRoom);
m_channel2 = m_voice->createVoiceChannel();
connect(m_channel2.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::onConnectionStatusChanged);
connect(m_channel2.data(), &IVoiceChannel::userJoinedRoom, this, &CContextAudio::onUserJoinedRoom);
connect(m_channel2.data(), &IVoiceChannel::userLeftRoom, this, &CContextAudio::onUserLeftRoom);
initVoiceChannels();
initInputDevice();
initOutputDevice();
initAudioMixer();
m_voiceInputDevice = m_voice->createInputDevice();
m_voiceOutputDevice = m_voice->createOutputDevice();
m_audioMixer = m_voice->createAudioMixer();
m_voice->connectVoice(m_voiceInputDevice.get(), m_audioMixer.get(), IAudioMixer::InputMicrophone);
m_voice->connectVoice(m_channel1.data(), m_audioMixer.get(), IAudioMixer::InputVoiceChannel1);
m_voice->connectVoice(m_channel2.data(), m_audioMixer.get(), IAudioMixer::InputVoiceChannel2);
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputOutputDevice1, m_voiceOutputDevice.get());
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputVoiceChannel1, m_channel1.data());
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputVoiceChannel2, m_channel2.data());
m_audioMixer->makeMixerConnection(IAudioMixer::InputVoiceChannel1, IAudioMixer::OutputOutputDevice1);
m_audioMixer->makeMixerConnection(IAudioMixer::InputVoiceChannel2, IAudioMixer::OutputOutputDevice1);
this->setVoiceOutputVolume(90);
m_unusedVoiceChannels.push_back(m_channel1);
m_unusedVoiceChannels.push_back(m_channel2);
m_voiceChannelOutputPortMapping[m_channel1] = IAudioMixer::OutputVoiceChannel1;
m_voiceChannelOutputPortMapping[m_channel2] = IAudioMixer::OutputVoiceChannel2;
m_selcalPlayer = new CSelcalPlayer(QAudioDeviceInfo::defaultOutputDevice(), this);
this->changeDeviceSettings();
@@ -105,6 +80,69 @@ namespace BlackCore
return this;
}
void CContextAudio::initVoiceChannels()
{
//! \todo KB 2018-11 those are supposed to be Qt::QueuedConnection, but not yet changed (risk to break something)
m_channel1 = m_voice->createVoiceChannel();
connect(m_channel1.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::onConnectionStatusChanged);
connect(m_channel1.data(), &IVoiceChannel::userJoinedRoom, this, &CContextAudio::onUserJoinedRoom);
connect(m_channel1.data(), &IVoiceChannel::userLeftRoom, this, &CContextAudio::onUserLeftRoom);
m_channel2 = m_voice->createVoiceChannel();
connect(m_channel2.data(), &IVoiceChannel::connectionStatusChanged, this, &CContextAudio::onConnectionStatusChanged);
connect(m_channel2.data(), &IVoiceChannel::userJoinedRoom, this, &CContextAudio::onUserJoinedRoom);
connect(m_channel2.data(), &IVoiceChannel::userLeftRoom, this, &CContextAudio::onUserLeftRoom);
m_unusedVoiceChannels.push_back(m_channel1);
m_unusedVoiceChannels.push_back(m_channel2);
m_voiceChannelOutputPortMapping[m_channel1] = IAudioMixer::OutputVoiceChannel1;
m_voiceChannelOutputPortMapping[m_channel2] = IAudioMixer::OutputVoiceChannel2;
}
void CContextAudio::initInputDevice()
{
#ifdef Q_OS_MAC
CMacOSMicrophoneAccess::AuthorizationStatus status = m_micAccess.getAuthorizationStatus();
if (status == CMacOSMicrophoneAccess::Authorized)
{
m_voiceInputDevice = m_voice->createInputDevice();
}
else if (status == CMacOSMicrophoneAccess::NotDetermined)
{
m_voiceInputDevice.reset(new CAudioInputDeviceDummy(this));
connect(&m_micAccess, &CMacOSMicrophoneAccess::permissionRequestAnswered, this, &CContextAudio::delayedInitMicrophone);
m_micAccess.requestAccess();
}
else
{
m_voiceInputDevice.reset(new CAudioInputDeviceDummy(this));
CLogMessage(this).error(u"Microphone access not granted. Voice input will not work.");
}
#else
m_voiceInputDevice = m_voice->createInputDevice();
#endif
}
void CContextAudio::initOutputDevice()
{
m_voiceOutputDevice = m_voice->createOutputDevice();
}
void CContextAudio::initAudioMixer()
{
m_audioMixer = m_voice->createAudioMixer();
m_voice->connectVoice(m_voiceInputDevice.get(), m_audioMixer.get(), IAudioMixer::InputMicrophone);
m_voice->connectVoice(m_channel1.data(), m_audioMixer.get(), IAudioMixer::InputVoiceChannel1);
m_voice->connectVoice(m_channel2.data(), m_audioMixer.get(), IAudioMixer::InputVoiceChannel2);
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputOutputDevice1, m_voiceOutputDevice.get());
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputVoiceChannel1, m_channel1.data());
m_voice->connectVoice(m_audioMixer.get(), IAudioMixer::OutputVoiceChannel2, m_channel2.data());
m_audioMixer->makeMixerConnection(IAudioMixer::InputVoiceChannel1, IAudioMixer::OutputOutputDevice1);
m_audioMixer->makeMixerConnection(IAudioMixer::InputVoiceChannel2, IAudioMixer::OutputOutputDevice1);
}
CContextAudio::~CContextAudio()
{
this->leaveAllVoiceRooms();
@@ -643,5 +681,14 @@ namespace BlackCore
return voiceChannel;
}
#ifdef Q_OS_MAC
void CContextAudio::delayedInitMicrophone()
{
m_voiceInputDevice = m_voice->createInputDevice();
m_voice->connectVoice(m_voiceInputDevice.get(), m_audioMixer.get(), IAudioMixer::InputMicrophone);
}
#endif
} // namespace
} // namespace

View File

@@ -30,6 +30,7 @@
#include "blackmisc/network/userlist.h"
#include "blackmisc/settingscache.h"
#include "blackmisc/icons.h"
#include "blackmisc/macos/microphoneaccess.h"
#include "blacksound/selcalplayer.h"
#include "blacksound/notificationplayer.h"
@@ -120,6 +121,12 @@ namespace BlackCore
CContextAudio *registerWithDBus(BlackMisc::CDBusServer *server);
private:
void initVoiceChannels();
void initInputDevice();
void initOutputDevice();
void initAudioMixer();
void initVoiceVatlib(bool allocateInput = true);
//! \copydoc IVoice::connectionStatusChanged
//! \sa IContextAudio::changedVoiceRooms
void onConnectionStatusChanged(IVoiceChannel::ConnectionStatus oldStatus, IVoiceChannel::ConnectionStatus newStatus);
@@ -152,6 +159,11 @@ namespace BlackCore
const int MinUnmuteVolume = 20; //!< minimum volume when unmuted
int m_outVolumeBeforeMute = 90;
#ifdef Q_OS_MAC
BlackMisc::CMacOSMicrophoneAccess m_micAccess;
void delayedInitMicrophone();
#endif
// For easy access.
QSharedPointer<IVoiceChannel> m_channel1;
QSharedPointer<IVoiceChannel> m_channel2;