Skip to content
Open
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
17 changes: 5 additions & 12 deletions src/mumble/AppNap.mm
Original file line number Diff line number Diff line change
Expand Up @@ -7,37 +7,30 @@

#include <Foundation/Foundation.h>

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
static bool appNapSuppressed = false;
#endif

void MUSuppressAppNap(bool suppress) {
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1070
NSProcessInfo *processInfo = [NSProcessInfo processInfo];
if (![processInfo respondsToSelector:@selector(disableAutomaticTermination:)]) {
return;
}

if (suppress == appNapSuppressed) {
qWarning("AppNap: attempt to set AppNap suppression state to %s while already in that state.", suppress ? "true" : "false");
return;
}

QString translatedReason = QApplication::tr("Mumble is currently connected to a server");
NSString *reason = const_cast<NSString *>(reinterpret_cast<const NSString *>(CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar *>(translatedReason.unicode()), translatedReason.length())));
NSString *reason = [[NSString alloc] initWithCharacters:reinterpret_cast<const unichar *>(translatedReason.unicode())
length:static_cast<NSUInteger>(translatedReason.length())];

if (suppress) {
[[NSProcessInfo processInfo] disableAutomaticTermination:reason];
[processInfo disableAutomaticTermination:reason];
qWarning("AppNap: suppressed with reason: '%s'", qPrintable(translatedReason));
} else {
[[NSProcessInfo processInfo] enableAutomaticTermination:reason];
[processInfo enableAutomaticTermination:reason];
qWarning("AppNap: re-enabled, was suppressed with reason: '%s'", qPrintable(translatedReason));
}

appNapSuppressed = suppress;

[reason release];
#else
Q_UNUSED(suppress);
#endif

}
7 changes: 3 additions & 4 deletions src/mumble/CoreAudio.mm
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
#include "CoreAudio.h"

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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above should be removed as well

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, definitely can do



namespace {
Expand Down Expand Up @@ -55,8 +55,7 @@ explicit CoreAudioException(const QString& msg) : msg_(msg) {}


CFStringRef QStringToCFString(const QString &str) {
return CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast< const UniChar * >(str.unicode()),
str.length());
return CFStringCreateWithCharacters(kCFAllocatorDefault, reinterpret_cast<const UniChar *>(str.unicode()), str.length());
}

QString GetDeviceStringProperty(AudioObjectID device_id, AudioObjectPropertySelector property_selector) {
Expand Down Expand Up @@ -717,7 +716,7 @@ static void LogAUStreamDescription(AudioUnit au) {
if (err != noErr) {
qWarning("CoreAudioInput: Unable to set preferred buffer size on device. Querying for device default.");
len = sizeof(UInt32);
CHECK_RETURN_FALSE(AudioDeviceGetProperty(inputDevId, 0, true, kAudioDevicePropertyBufferFrameSize, &len, &val),
CHECK_RETURN_FALSE(AudioObjectGetPropertyData(inputDevId, &propertyAddress, 0, nullptr, &len, &val),
"CoreAudioInput: Unable to query for device's buffer size.");

actualBufferLength = (int) val;
Expand Down
79 changes: 34 additions & 45 deletions src/mumble/GlobalShortcut_macx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -112,13 +112,13 @@
}

#ifdef USE_OVERLAY
if (forward && Global::get().ocIntercept) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
if (forward && Global::get().ocIntercept) {
@autoreleasepool {
NSEvent *evt = [[NSEvent eventWithCGEvent:event] retain];
QMetaObject::invokeMethod(gs, "forwardEvent", Qt::QueuedConnection, Q_ARG(void *, evt));
[pool release];
return nullptr;
}
return nullptr;
}
#else
// Mark forward as unused in this case
(void) forward;
Expand Down Expand Up @@ -163,10 +163,6 @@

kbdLayout = nullptr;

#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1050
# if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
if (TISCopyCurrentKeyboardInputSource && TISGetInputSourceProperty)
# endif
{
TISInputSourceRef inputSource = TISCopyCurrentKeyboardInputSource();
if (inputSource) {
Expand All @@ -175,16 +171,8 @@
kbdLayout = reinterpret_cast<UCKeyboardLayout *>(const_cast<UInt8 *>(CFDataGetBytePtr(data)));
}
}
#endif
#ifndef __LP64__
if (! kbdLayout) {
SInt16 currentKeyScript = GetScriptManagerVariable(smKeyScript);
SInt16 lastKeyLayoutID = GetScriptVariable(currentKeyScript, smScriptKeys);
Handle handle = GetResource('uchr', lastKeyLayoutID);
if (handle)
kbdLayout = reinterpret_cast<UCKeyboardLayout *>(*handle);
}
#endif


if (! kbdLayout)
qWarning("GlobalShortcutMac: No keyboard layout mapping available. Unable to perform key translation.");

Expand All @@ -203,36 +191,37 @@
}

void GlobalShortcutMac::dumpEventTaps() {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
uint32_t ntaps = 0;
CGEventTapInformation table[64];
if (CGGetEventTapList(20, table, &ntaps) == kCGErrorSuccess) {
qWarning("--- Installed Event Taps ---");
for (uint32_t i = 0; i < ntaps; i++) {
CGEventTapInformation *info = &table[i];

NSString *processName = nil;
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier: info->processBeingTapped];
if (app) {
processName = [app localizedName];
@autoreleasepool {
uint32_t ntaps = 0;
CGEventTapInformation table[64];
if (CGGetEventTapList(20, table, &ntaps) == kCGErrorSuccess) {
qWarning("--- Installed Event Taps ---");
for (uint32_t i = 0; i < ntaps; i++) {
CGEventTapInformation *info = &table[i];

NSString *processName = nil;
NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier: info->processBeingTapped];
if (app) {
processName = [app localizedName];
}

qWarning("{");
qWarning(" eventTapID: %u", info->eventTapID);
qWarning(" tapPoint: 0x%x", info->tapPoint);
qWarning(" options = 0x%x", info->options);
qWarning(" eventsOfInterest = 0x%llx", info->eventsOfInterest);
const char *processNameUtf8 = processName ? [processName UTF8String] : "unknown";
qWarning(" tappingProcess = %i (%s)", info->tappingProcess, processNameUtf8);
qWarning(" processBeingTapped = %i", info->processBeingTapped);
qWarning(" enabled = %s", info->enabled ? "true":"false");
qWarning(" minUsecLatency = %.2f", info->minUsecLatency);
qWarning(" avgUsecLatency = %.2f", info->avgUsecLatency);
qWarning(" maxUsecLatency = %.2f", info->maxUsecLatency);
qWarning("}");
}

qWarning("{");
qWarning(" eventTapID: %u", info->eventTapID);
qWarning(" tapPoint: 0x%x", info->tapPoint);
qWarning(" options = 0x%x", info->options);
qWarning(" eventsOfInterest = 0x%llx", info->eventsOfInterest);
qWarning(" tappingProcess = %i (%s)", info->tappingProcess, [processName UTF8String]);
qWarning(" processBeingTapped = %i", info->processBeingTapped);
qWarning(" enabled = %s", info->enabled ? "true":"false");
qWarning(" minUsecLatency = %.2f", info->minUsecLatency);
qWarning(" avgUsecLatency = %.2f", info->avgUsecLatency);
qWarning(" maxUsecLatency = %.2f", info->maxUsecLatency);
qWarning("}");
qWarning("--- End of Event Taps ---");
}
qWarning("--- End of Event Taps ---");
}
[pool release];
}

void GlobalShortcutMac::forwardEvent(void *evt) {
Expand Down
77 changes: 38 additions & 39 deletions src/mumble/Overlay_macx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
#include <xar/xar.h>
}

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

static NSString *MumbleOverlayLoaderBundle = @"/Library/ScriptingAdditions/MumbleOverlay.osax";
static NSString *MumbleOverlayLoaderBundleIdentifier = @"net.sourceforge.mumble.OverlayScriptingAddition";
Expand Down Expand Up @@ -80,53 +78,52 @@ - (void) dealloc {
- (void) appLaunched:(NSNotification *)notification {
if (active) {
BOOL overlayEnabled = NO;
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSDictionary *userInfo = [notification userInfo];
@autoreleasepool {
NSDictionary *userInfo = [notification userInfo];

NSString *bundleId = [userInfo objectForKey:@"NSApplicationBundleIdentifier"];
if ([bundleId isEqualToString:[[NSBundle mainBundle] bundleIdentifier]])
return;
NSString *bundleId = userInfo[@"NSApplicationBundleIdentifier"];
if ([bundleId isEqualToString:[[NSBundle mainBundle] bundleIdentifier]])
return;

QString qsBundleIdentifier = QString::fromUtf8([bundleId UTF8String]);
QString qsBundleIdentifier = QString::fromUtf8([bundleId UTF8String]);

switch (Global::get().s.os.oemOverlayExcludeMode) {
case OverlaySettings::LauncherFilterExclusionMode: {
qWarning("Overlay_macx: launcher filter mode not implemented on macOS, allowing everything");
overlayEnabled = YES;
break;
}
case OverlaySettings::WhitelistExclusionMode: {
if (Global::get().s.os.qslWhitelist.contains(qsBundleIdentifier)) {
switch (Global::get().s.os.oemOverlayExcludeMode) {
case OverlaySettings::LauncherFilterExclusionMode: {
qWarning("Overlay_macx: launcher filter mode not implemented on macOS, allowing everything");
overlayEnabled = YES;
break;
}
break;
}
case OverlaySettings::BlacklistExclusionMode: {
if (! Global::get().s.os.qslBlacklist.contains(qsBundleIdentifier)) {
overlayEnabled = YES;
case OverlaySettings::WhitelistExclusionMode: {
if (Global::get().s.os.qslWhitelist.contains(qsBundleIdentifier)) {
overlayEnabled = YES;
}
break;
}
case OverlaySettings::BlacklistExclusionMode: {
if (! Global::get().s.os.qslBlacklist.contains(qsBundleIdentifier)) {
overlayEnabled = YES;
}
break;
}
break;
}
}

if (overlayEnabled) {
pid_t pid = [[userInfo objectForKey:@"NSApplicationProcessIdentifier"] intValue];
SBApplication *app = [SBApplication applicationWithProcessIdentifier:pid];
[app setDelegate:self];
if (overlayEnabled) {
pid_t pid = [userInfo[@"NSApplicationProcessIdentifier"] intValue];
SBApplication *app = [SBApplication applicationWithProcessIdentifier:pid];
[app setDelegate:self];

// This timeout is specified in 'ticks'.
// A tick defined as: "[...] (a tick is approximately 1/60 of a second) [...]" in the
// Apple Event Manager Reference documentation:
// http://developer.apple.com/legacy/mac/library/documentation/Carbon/reference/Event_Manager/Event_Manager.pdf
[app setTimeout:10*60];
// This timeout is specified in 'ticks'.
// A tick defined as: "[...] (a tick is approximately 1/60 of a second) [...]" in the
// Apple Event Manager Reference documentation:
// http://developer.apple.com/legacy/mac/library/documentation/Carbon/reference/Event_Manager/Event_Manager.pdf
[app setTimeout:10*60];

[app setSendMode:kAEWaitReply];
[app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
[app setSendMode:kAEWaitReply];
[app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];

[app setSendMode:kAENoReply];
[app setSendMode:kAENoReply];
}
}

[pool release];
}
}

Expand Down Expand Up @@ -308,7 +305,7 @@ static bool isInstallerNewer(QString path, NSUInteger curVer) {
bool OverlayConfig::needsUpgrade() {
NSDictionary *infoPlist = [NSDictionary dictionaryWithContentsOfFile:[NSString stringWithFormat:@"%@/Contents/Info.plist", MumbleOverlayLoaderBundle]];
if (infoPlist) {
NSUInteger curVersion = [[infoPlist objectForKey:@"MumbleOverlayVersion"] unsignedIntegerValue];
NSUInteger curVersion = [infoPlist[@"MumbleOverlayVersion"] unsignedIntegerValue];

QString path = installerPath();
if (path.isEmpty())
Expand All @@ -321,10 +318,12 @@ static bool isInstallerNewer(QString path, NSUInteger curVer) {
}

static bool authExec(AuthorizationRef ref, const char **argv) {
Q_UNUSED(ref);
Q_UNUSED(argv);
OSStatus err = noErr;
int pid = 0, status = 0;

err = AuthorizationExecuteWithPrivileges(ref, argv[0], kAuthorizationFlagDefaults, const_cast<char * const *>(&argv[1]), nullptr);
// Deprecated: AuthorizationExecuteWithPrivileges removed. Consider using SMJobBless or a helper tool for privileged operations.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this effectively removes the entire functionality of authExec - in that case, we should return false (with a log message stating that this needs to be reimplemented.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of removing the functionality entirely, we can replace it with a supported approach.
From what I can gather, the main action in the uninstallFiles function is running the command

/bin/mv /Library/ScriptingAdditions/MumbleOverlay.osax /tmp/%1_Uninstalled_MumbleOverlay.osax

We can achieve the same effect using AppleScript.
NSAppleScript provides the command do shell script ... with administrator privileges. Where ... is the command we want to run. This way, we could remove the authExec function entirely and update the rest of uninstallFiles to use the modern API.

From the AppleScript documentation under do shell script:

Execute the command as the administrator. Once a script is correctly authenticated, it will not ask for authentication again for five minutes. The elevated privileges and the grace period do not extend to any other scripts or to the rest of the system.

We can use the NSAppleScript class to create the commands and execute them. This should keep the functionality the same but use the supported Apple API.

if (err == errAuthorizationSuccess) {
do {
pid = wait(&status);
Expand Down
5 changes: 1 addition & 4 deletions src/mumble/TextToSpeech_macx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -133,10 +133,7 @@ - (void)speechSynthesizer:(NSSpeechSynthesizer *)synthesizer didFinishSpeaking:(
}

void TextToSpeechPrivate::setVolume(int volume) {
// Check for setVolume: availability. It's only available on 10.5+.
if ([[m_synthesizerHelper synthesizer] respondsToSelector:@selector(setVolume:)]) {
[[m_synthesizerHelper synthesizer] setVolume:(float)volume / 100.0f];
}
[[m_synthesizerHelper synthesizer] setVolume:(float)volume / 100.0f];
}

TextToSpeech::TextToSpeech(QObject *) {
Expand Down
35 changes: 24 additions & 11 deletions src/mumble/os_macx.mm
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,30 @@
static void crashhandler_handle_crash();

void query_language() {
CFPropertyListRef cfaLangs;
CFStringRef cfsLang;
static char lang[16];

cfaLangs = CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
cfsLang = (CFStringRef) CFArrayGetValueAtIndex((CFArrayRef)cfaLangs, 0);

if (! CFStringGetCString(cfsLang, lang, 16, kCFStringEncodingUTF8))
return;

os_lang = lang;
@autoreleasepool {
CFPropertyListRef cfaLangs;
CFStringRef cfsLang;
static char lang[16];

cfaLangs = CFPreferencesCopyAppValue(CFSTR("AppleLanguages"), kCFPreferencesCurrentApplication);
if (!cfaLangs || CFGetTypeID(cfaLangs) != CFArrayGetTypeID()
|| CFArrayGetCount((CFArrayRef)cfaLangs) == 0) {
if (cfaLangs) {
CFRelease(cfaLangs);
}
return;
}

cfsLang = (CFStringRef) CFArrayGetValueAtIndex((CFArrayRef)cfaLangs, 0);

if (!CFStringGetCString(cfsLang, lang, sizeof(lang), kCFStringEncodingUTF8)) {
CFRelease(cfaLangs);
return;
}

os_lang = lang;
CFRelease(cfaLangs);
}
}

static void crashhandler_signal_handler(int signal) {
Expand Down
Loading