Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src/CoreAudio: update CoreAudio API, remove deprecated API calls. #4254

Merged
merged 2 commits into from
Jun 7, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 58 additions & 61 deletions src/mumble/CoreAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,41 +7,12 @@

#include "User.h"

#include <Carbon/Carbon.h>

// We define a global macro called 'g'. This can lead to issues when included code uses 'g' as a type or parameter name (like protobuf 3.7 does). As such, for now, we have to make this our last include.
#include "Global.h"

// Ignore deprecation warnings for the whole file, for now.
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"

class CoreAudioInputRegistrar : public AudioInputRegistrar {
public:
CoreAudioInputRegistrar();
virtual AudioInput *create();
virtual const QList<audioDevice> getDeviceChoices();
virtual void setDeviceChoice(const QVariant &, Settings &);
virtual bool canEcho(const QString &) const;
};

class CoreAudioOutputRegistrar : public AudioOutputRegistrar {
public:
CoreAudioOutputRegistrar();
virtual AudioOutput *create();
virtual const QList<audioDevice> getDeviceChoices();
virtual void setDeviceChoice(const QVariant &, Settings &);
bool canMuteOthers() const;
};

class CoreAudioInit : public DeferInit {
CoreAudioInputRegistrar *cairReg;
CoreAudioOutputRegistrar *caorReg;
public:
CoreAudioInit() : cairReg(NULL), caorReg(NULL) {}
void initialize();
void destroy();
};

static CoreAudioInit cainit;

void CoreAudioInit::initialize() {
Expand Down Expand Up @@ -84,33 +55,42 @@ const QHash<QString, QString> CoreAudioSystem::getDevices(bool input) {
UInt32 len, ndevs;
OSStatus err;

err = AudioHardwareGetPropertyInfo(kAudioHardwarePropertyDevices, &len, NULL);
AudioObjectPropertyAddress propertyAddress = {
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};

err = AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len);
if (err != noErr)
return qhReturn;

ndevs = len / sizeof(AudioDeviceID);
AudioDeviceID devs[ndevs];

err = AudioHardwareGetProperty(kAudioHardwarePropertyDevices, &len, devs);
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len, devs);
if (err != noErr)
return qhReturn;

propertyAddress.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;

for (UInt32 i = 0; i < ndevs; i++) {
QString qsDeviceName;
QString qsDeviceIdentifier;
char buf[4096];

/* Get number of channels, to determine whether we're an input or an output... */
AudioBufferList *bufs = NULL;

err = AudioDeviceGetPropertyInfo(devs[i], 0, input, kAudioDevicePropertyStreamConfiguration, &len, NULL);
AudioBufferList *bufs = nullptr;
propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
err = AudioObjectGetPropertyDataSize(devs[i], &propertyAddress, 0, nullptr, &len);
if (err != noErr) {
qWarning("CoreAudioSystem: Failed to get length of AudioStreamConfiguration. Unable to allocate.");
continue;
}

bufs = reinterpret_cast<AudioBufferList *>(malloc(len));
err = AudioDeviceGetProperty(devs[i], 0, input, kAudioDevicePropertyStreamConfiguration, &len, bufs);
propertyAddress.mSelector = kAudioDevicePropertyStreamConfiguration;
err = AudioObjectGetPropertyData(devs[i], &propertyAddress, 0, nullptr, &len, bufs);
if (! bufs || err != noErr) {
qWarning("CoreAudioSystem: Failed to get AudioStreamConfiguration from device.");
free(bufs);
Expand All @@ -129,8 +109,9 @@ const QHash<QString, QString> CoreAudioSystem::getDevices(bool input) {

/* Get device name. */
len = sizeof(CFStringRef);
CFStringRef devName = NULL;
err = AudioDeviceGetProperty(devs[i], 0, 0, kAudioDevicePropertyDeviceNameCFString, &len, &devName);
CFStringRef devName = nullptr;
propertyAddress.mSelector = kAudioDevicePropertyDeviceNameCFString;
err = AudioObjectGetPropertyData(devs[i], &propertyAddress, 0, nullptr, &len, &devName);
if (! devName || err != noErr) {
qWarning("CoreAudioSystem: Failed to get device name. Skipping device.");
}
Expand All @@ -139,8 +120,9 @@ const QHash<QString, QString> CoreAudioSystem::getDevices(bool input) {
CFRelease(devName);

/* Device UID. */
CFStringRef devUid = NULL;
err = AudioDeviceGetProperty(devs[i], 0, 0, kAudioDevicePropertyDeviceUID, &len, &devUid);
CFStringRef devUid = nullptr;
propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
err = AudioObjectGetPropertyData(devs[i], &propertyAddress, 0, nullptr, &len, &devUid);
if (! devUid || err != noErr) {
qWarning("CoreAudioSystem: Failed to get device UID. Skipping device.");
}
Expand All @@ -154,8 +136,6 @@ const QHash<QString, QString> CoreAudioSystem::getDevices(bool input) {
return qhReturn;
}

CoreAudioInputRegistrar::CoreAudioInputRegistrar() : AudioInputRegistrar(QLatin1String("CoreAudio"), 10) {
}

AudioInput *CoreAudioInputRegistrar::create() {
return new CoreAudioInput();
Expand All @@ -175,9 +155,6 @@ bool CoreAudioInputRegistrar::canEcho(const QString &outputsys) const {
return false;
}

CoreAudioOutputRegistrar::CoreAudioOutputRegistrar() : AudioOutputRegistrar(QLatin1String("CoreAudio"), 10) {
}

AudioOutput *CoreAudioOutputRegistrar::create() {
return new CoreAudioOutput();
}
Expand All @@ -198,8 +175,13 @@ CoreAudioInput::CoreAudioInput() {
OSStatus err;
AudioStreamBasicDescription fmt;
AudioDeviceID devId = 0;
CFStringRef devUid = NULL;
CFStringRef devUid = nullptr;
UInt32 val, len;
AudioObjectPropertyAddress propertyAddress = {
0,
kAudioDevicePropertyScopeInput,
kAudioObjectPropertyElementMaster
};

memset(&buflist, 0, sizeof(AudioBufferList));

Expand All @@ -214,7 +196,8 @@ CoreAudioInput::CoreAudioInput() {
avt.mOutputDataSize = sizeof(AudioDeviceID);

len = sizeof(AudioValueTranslation);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &len, &avt);
propertyAddress.mSelector = kAudioHardwarePropertyDeviceForUID;
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len, &avt);
if (err != noErr) {
qWarning("CoreAudioInput: Unable to query for AudioDeviceID.");
return;
Expand All @@ -223,14 +206,16 @@ CoreAudioInput::CoreAudioInput() {
qWarning("CoreAudioInput: Set device to 'Default Device'.");

len = sizeof(AudioDeviceID);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultInputDevice, &len, &devId);
propertyAddress.mSelector = kAudioHardwarePropertyDefaultInputDevice;
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len, &devId);
if (err != noErr) {
qWarning("CoreAudioInput: Unable to query for default input AudioDeviceID.");
return;
}

len = sizeof(CFStringRef);
err = AudioDeviceGetProperty(devId, 0, true, kAudioDevicePropertyDeviceUID, &len, &devUid);
propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
err = AudioObjectGetPropertyData(devId, &propertyAddress, 0, nullptr, &len, &devUid);
if (err != noErr) {
qWarning("CoreAudioInput: Unable to get default device UID.");
return;
Expand All @@ -246,8 +231,8 @@ CoreAudioInput::CoreAudioInput() {
desc.componentFlags = 0;
desc.componentFlagsMask = 0;

comp = FindNextComponent(NULL, &desc);
if (comp == NULL) {
comp = FindNextComponent(nullptr, &desc);
if (!comp) {
qWarning("CoreAudioInput: Unable to find AudioUnit.");
return;
}
Expand Down Expand Up @@ -345,7 +330,8 @@ CoreAudioInput::CoreAudioInput() {

AudioValueRange range;
len = sizeof(AudioValueRange);
err = AudioDeviceGetProperty(devId, 0, true, kAudioDevicePropertyBufferFrameSizeRange, &len, &range);
propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
err = AudioObjectGetPropertyData(devId, &propertyAddress, 0, nullptr, &len, &range);
if (err != noErr) {
qWarning("CoreAudioInput: Unable to query for allowed buffer size ranges.");
} else {
Expand All @@ -354,7 +340,8 @@ CoreAudioInput::CoreAudioInput() {

int iActualBufferLength = iMicLength;
val = iMicLength;
err = AudioDeviceSetProperty(devId, NULL, 0, true, kAudioDevicePropertyBufferFrameSize, sizeof(UInt32), &val);
propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
err = AudioObjectSetPropertyData(devId, &propertyAddress, 0, nullptr, sizeof(UInt32), &val);
if (err != noErr) {
qWarning("CoreAudioInput: Unable to set preferred buffer size on device. Querying for device default.");
len = sizeof(UInt32);
Expand All @@ -380,7 +367,7 @@ CoreAudioInput::CoreAudioInput() {
}

bRunning = true;
};
}

CoreAudioInput::~CoreAudioInput() {
OSStatus err;
Expand Down Expand Up @@ -444,8 +431,13 @@ CoreAudioOutput::CoreAudioOutput() {
AudioStreamBasicDescription fmt;
unsigned int chanmasks[32];
AudioDeviceID devId = 0;
CFStringRef devUid = NULL;
CFStringRef devUid = nullptr;
UInt32 len;
AudioObjectPropertyAddress propertyAddress = {
0,
kAudioDevicePropertyScopeOutput,
kAudioObjectPropertyElementMaster
};

if (! g.s.qsCoreAudioOutput.isEmpty()) {
devUid = CoreAudioSystem::QStringToCFString(g.s.qsCoreAudioOutput);
Expand All @@ -458,7 +450,8 @@ CoreAudioOutput::CoreAudioOutput() {
avt.mOutputDataSize = sizeof(AudioDeviceID);

len = sizeof(AudioValueTranslation);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDeviceForUID, &len, &avt);
propertyAddress.mSelector = kAudioHardwarePropertyDeviceForUID;
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len, &avt);
if (err != noErr) {
qWarning("CoreAudioOutput: Unable to query for AudioDeviceID.");
return;
Expand All @@ -467,14 +460,16 @@ CoreAudioOutput::CoreAudioOutput() {
qWarning("CoreAudioOutput: Set device to 'Default Device'.");

len = sizeof(AudioDeviceID);
err = AudioHardwareGetProperty(kAudioHardwarePropertyDefaultOutputDevice, &len, &devId);
propertyAddress.mSelector = kAudioHardwarePropertyDefaultOutputDevice;
err = AudioObjectGetPropertyData(kAudioObjectSystemObject, &propertyAddress, 0, nullptr, &len, &devId);
if (err != noErr) {
qWarning("CoreAudioOutput: Unable to query for default output AudioDeviceID");
return;
}

len = sizeof(CFStringRef);
err = AudioDeviceGetProperty(devId, 0, false, kAudioDevicePropertyDeviceUID, &len, &devUid);
propertyAddress.mSelector = kAudioDevicePropertyDeviceUID;
err = AudioObjectGetPropertyData(devId, &propertyAddress, 0, nullptr, &len, &devUid);
if (err != noErr) {
qWarning("CoreAudioOutput: Unable to get default device UID.");
return;
Expand All @@ -491,8 +486,8 @@ CoreAudioOutput::CoreAudioOutput() {
desc.componentFlags = 0;
desc.componentFlagsMask = 0;

comp = FindNextComponent(NULL, &desc);
if (comp == NULL) {
comp = FindNextComponent(nullptr, &desc);
if (!comp) {
qWarning("CoreAudioOuput: Unable to find AudioUnit.");
return;
}
Expand Down Expand Up @@ -575,15 +570,17 @@ CoreAudioOutput::CoreAudioOutput() {

AudioValueRange range;
len = sizeof(AudioValueRange);
err = AudioDeviceGetProperty(devId, 0, false, kAudioDevicePropertyBufferFrameSizeRange, &len, &range);
propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSizeRange;
err = AudioObjectGetPropertyData(devId, &propertyAddress, 0, nullptr, &len, &range);
if (err != noErr) {
qWarning("CoreAudioOutput: Unable to query for allowed buffer size ranges.");
} else {
qWarning("CoreAudioOutput: BufferFrameSizeRange = (%.2f, %.2f)", range.mMinimum, range.mMaximum);
}

UInt32 val = (iFrameSize * iMixerFreq) / SAMPLE_RATE;
err = AudioDeviceSetProperty(devId, NULL, 0, false, kAudioDevicePropertyBufferFrameSize, sizeof(UInt32), &val);
propertyAddress.mSelector = kAudioDevicePropertyBufferFrameSize;
err = AudioObjectSetPropertyData(devId, &propertyAddress, 0, nullptr, sizeof(UInt32), &val);
if (err != noErr) {
qWarning("CoreAudioOutput: Could not set requested buffer size for device. Continuing with default.");
}
Expand Down
30 changes: 30 additions & 0 deletions src/mumble/CoreAudio.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include "AudioOutput.h"

#include <AudioToolbox/AudioToolbox.h>
#include <Carbon/Carbon.h>

#include "Global.h"
Krzmbrzl marked this conversation as resolved.
Show resolved Hide resolved

class CoreAudioSystem : public QObject {
private:
Expand Down Expand Up @@ -54,6 +57,33 @@ class CoreAudioOutput : public AudioOutput {
void run() Q_DECL_OVERRIDE;
};

class CoreAudioInputRegistrar : public AudioInputRegistrar {
public:
CoreAudioInputRegistrar() : AudioInputRegistrar(QLatin1String("CoreAudio"), 10) {}
virtual AudioInput *create();
virtual const QList<audioDevice> getDeviceChoices();
virtual void setDeviceChoice(const QVariant &, Settings &);
virtual bool canEcho(const QString &) const;
};

class CoreAudioOutputRegistrar : public AudioOutputRegistrar {
public:
CoreAudioOutputRegistrar(): AudioOutputRegistrar(QLatin1String("CoreAudio"), 10) {}
virtual AudioOutput *create();
virtual const QList<audioDevice> getDeviceChoices();
virtual void setDeviceChoice(const QVariant &, Settings &);
bool canMuteOthers() const;
};

class CoreAudioInit : public DeferInit {
CoreAudioInputRegistrar *cairReg;
CoreAudioOutputRegistrar *caorReg;
public:
CoreAudioInit() : cairReg(nullptr), caorReg(nullptr) {}
void initialize();
void destroy();
};

#else
class CoreAudioSystem;
class CoreAudioInput;
Expand Down