diff --git a/BGMApp/BGMApp/BGMAudioDeviceManager.mm b/BGMApp/BGMApp/BGMAudioDeviceManager.mm index be6a3f9..2be6ed1 100644 --- a/BGMApp/BGMApp/BGMAudioDeviceManager.mm +++ b/BGMApp/BGMApp/BGMAudioDeviceManager.mm @@ -440,8 +440,7 @@ "early with kBGMErrorCode_ReturningEarly."); err = kBGMErrorCode_ReturningEarly; - // TODO: The QOS_CLASS_USER_INTERACTIVE constant isn't available on OS X 10.9. - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{ + dispatch_async(BGMGetDispatchQueue_PriorityUserInteractive(), ^{ @try { [stateLock lock]; diff --git a/BGMApp/BGMApp/BGMDeviceControlsList.cpp b/BGMApp/BGMApp/BGMDeviceControlsList.cpp index 44f42dc..8e34856 100644 --- a/BGMApp/BGMApp/BGMDeviceControlsList.cpp +++ b/BGMApp/BGMApp/BGMDeviceControlsList.cpp @@ -333,9 +333,12 @@ void BGMDeviceControlsList::InitDeviceToggling() // Changing the default device too quickly after enabling the Null Device // seems to cause problems with some programs. Not sure why. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kToggleDeviceInitialDelay), dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), mDeviceToggleBlock); +#pragma clang diagnostic pop } break; @@ -384,9 +387,12 @@ void BGMDeviceControlsList::ToggleDefaultDevice() mDeviceToggleBackBlock = CreateDeviceToggleBackBlock(); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kToggleDeviceBackDelay), dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), mDeviceToggleBackBlock); +#pragma clang diagnostic pop } void BGMDeviceControlsList::SetNullDeviceEnabled(bool inEnabled) @@ -409,12 +415,12 @@ void BGMDeviceControlsList::SetNullDeviceEnabled(bool inEnabled) (inEnabled ? kCFBooleanTrue : kCFBooleanFalse)); } -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wpartial-availability" - dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBlock() { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" return dispatch_block_create((dispatch_block_flags_t)0, ^{ +#pragma clang diagnostic pop CAMutex::Locker locker(mMutex); if(mDeviceToggleState == ToggleState::SettingNullDeviceAsDefault) @@ -429,7 +435,10 @@ dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBlock() dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBackBlock() { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" return dispatch_block_create((dispatch_block_flags_t)0, ^{ +#pragma clang diagnostic pop CAMutex::Locker locker(mMutex); if(mDeviceToggleState != ToggleState::SettingBGMDeviceAsDefault) @@ -450,15 +459,21 @@ dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBackBlock() mDisableNullDeviceBlock = CreateDisableNullDeviceBlock(); +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kDisableNullDeviceDelay), dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), mDisableNullDeviceBlock); +#pragma clang diagnostic pop }); } dispatch_block_t BGMDeviceControlsList::CreateDisableNullDeviceBlock() { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" return dispatch_block_create((dispatch_block_flags_t)0, ^{ +#pragma clang diagnostic pop CAMutex::Locker locker(mMutex); if(mDeviceToggleState != ToggleState::DisablingNullDevice) @@ -486,6 +501,8 @@ void BGMDeviceControlsList::DestroyBlock(dispatch_block_t __nullable & block) return; } +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" dispatch_block_t& blockNN = (dispatch_block_t&)block; if(!dispatch_block_testcancel(blockNN)) { @@ -502,9 +519,8 @@ void BGMDeviceControlsList::DestroyBlock(dispatch_block_t __nullable & block) Block_release(block); block = nullptr; } +#pragma clang diagnostic pop } -#pragma clang diagnostic pop /* -Wpartial-availability */ - #pragma clang assume_nonnull end diff --git a/BGMApp/BGMApp/BGMOutputVolumeMenuItem.mm b/BGMApp/BGMApp/BGMOutputVolumeMenuItem.mm index 5353073..204795c 100644 --- a/BGMApp/BGMApp/BGMOutputVolumeMenuItem.mm +++ b/BGMApp/BGMApp/BGMOutputVolumeMenuItem.mm @@ -110,13 +110,13 @@ const UInt32 CHANNEL = kMasterChannel; // somewhere else. audioDevices.bgmDevice.AddPropertyListenerBlock( CAPropertyAddress(kAudioDevicePropertyVolumeScalar, SCOPE), - dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), updateSlider); // Register the same listener for mute/unmute. audioDevices.bgmDevice.AddPropertyListenerBlock( CAPropertyAddress(kAudioDevicePropertyMute, SCOPE), - dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), updateSlider); } diff --git a/BGMApp/BGMApp/BGMPlayThrough.cpp b/BGMApp/BGMApp/BGMPlayThrough.cpp index dc755cf..445bc95 100644 --- a/BGMApp/BGMApp/BGMPlayThrough.cpp +++ b/BGMApp/BGMApp/BGMPlayThrough.cpp @@ -748,7 +748,7 @@ void BGMPlayThrough::StopIfIdle() "queuedAt=", queuedAt); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, waitNsec), - dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), + dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // Check the BGMPlayThrough instance hasn't been destructed since it queued this block if(mActive) @@ -843,7 +843,7 @@ void BGMPlayThrough::HandleBGMDeviceIsRunning(BGMPlayThrough* refCon) // // TODO: We should find a way to do this without dispatching because dispatching isn't actually // real-time safe. - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INTERACTIVE, 0), ^{ + dispatch_async(BGMGetDispatchQueue_PriorityUserInteractive(), ^{ if(refCon->mActive) { CAMutex::Locker stateLocker(refCon->mStateMutex); @@ -883,7 +883,7 @@ void BGMPlayThrough::HandleBGMDeviceIsRunningSomewhereOtherThanBGMApp(BGMPlay DebugMsg("BGMPlayThrough::HandleBGMDeviceIsRunningSomewhereOtherThanBGMApp: Got notification"); // These notifications don't need to be handled quickly, so we can always dispatch. - dispatch_async(dispatch_get_global_queue(QOS_CLASS_DEFAULT, 0), ^{ + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ // TODO: Handle expected exceptions (mostly CAExceptions from PublicUtility classes) in StopIfIdle. BGMLogUnexpectedExceptions("HandleBGMDeviceIsRunningSomewhereOtherThanBGMApp", [&refCon]() { if(refCon->mActive) diff --git a/BGMApp/BGMApp/Preferences/BGMAboutPanel.m b/BGMApp/BGMApp/Preferences/BGMAboutPanel.m index 26ce9ab..0178cb2 100644 --- a/BGMApp/BGMApp/Preferences/BGMAboutPanel.m +++ b/BGMApp/BGMApp/Preferences/BGMAboutPanel.m @@ -93,10 +93,11 @@ static NSInteger const kProjectWebsiteLabelTag = 3; websiteLabel.allowsEditingTextAttributes = YES; NSString* projectURL = [NSString stringWithUTF8String:kBGMProjectURL]; + NSFont* linkFont = websiteLabel.font ? websiteLabel.font : [NSFont labelFontOfSize:0.0]; websiteLabel.attributedStringValue = [[NSAttributedString alloc] initWithString:projectURL attributes:@{ NSLinkAttributeName: projectURL, - NSFontAttributeName: websiteLabel.font }]; + NSFontAttributeName: linkFont }]; // Load the text of the license into the text view NSString* __nullable licensePath = [bundle pathForResource:@"LICENSE" ofType:nil]; @@ -112,7 +113,7 @@ static NSInteger const kProjectWebsiteLabelTag = 3; licenseStr = @"Error: could not open license file."; } - licenseView.string = licenseStr; + licenseView.string = (NSString*)licenseStr; NSFont* __nullable font = [NSFont fontWithName:@"Andale Mono" size:0.0]; if (font) { diff --git a/BGMApp/BGMApp/Preferences/BGMOutputDevicePrefs.mm b/BGMApp/BGMApp/Preferences/BGMOutputDevicePrefs.mm index db42f45..18684a6 100644 --- a/BGMApp/BGMApp/Preferences/BGMOutputDevicePrefs.mm +++ b/BGMApp/BGMApp/Preferences/BGMOutputDevicePrefs.mm @@ -17,7 +17,7 @@ // BGMOutputDevicePrefs.mm // BGMApp // -// Copyright © 2016 Kyle Neideck +// Copyright © 2016, 2017 Kyle Neideck // // Self Include @@ -216,10 +216,10 @@ static NSInteger const kOutputDeviceMenuItemTag = 2; menuItem.toolTip ? [NSString stringWithFormat:@"%@ (%@)", menuItem.title, menuItem.toolTip] : menuItem.title; - - // Dispatched because it usually blocks. (Note that we're using QOS_CLASS_USER_INITIATED - // rather than QOS_CLASS_USER_INTERACTIVE.) - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + + // Dispatched because it usually blocks. (Note that we're using + // DISPATCH_QUEUE_PRIORITY_HIGH, which is the second highest priority.) + dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{ [self changeToOutputDevice:newDeviceID newDataSource:newDataSourceID deviceName:deviceName]; diff --git a/SharedSource/BGM_Utils.cpp b/SharedSource/BGM_Utils.cpp index 08287e0..d21909a 100644 --- a/SharedSource/BGM_Utils.cpp +++ b/SharedSource/BGM_Utils.cpp @@ -17,7 +17,7 @@ // BGM_Utils.cpp // SharedSource // -// Copyright © 2016 Kyle Neideck +// Copyright © 2016, 2017 Kyle Neideck // // Self Include @@ -29,10 +29,35 @@ // System Includes #include #include +#include // For kCFCoreFoundationVersionNumber #pragma clang assume_nonnull begin +dispatch_queue_t BGMGetDispatchQueue_PriorityUserInteractive() +{ + long queueClass; + + // Compile-time check that QOS_CLASS_USER_INTERACTIVE can be used. It was added in 10.10. +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 // MAC_OS_X_VERSION_10_10 + // Runtime check for the same. + if(floor(kCFCoreFoundationVersionNumber) > kCFCoreFoundationVersionNumber10_9) + { +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wpartial-availability" + queueClass = QOS_CLASS_USER_INTERACTIVE; +#pragma clang diagnostic pop + } + else +#endif + { + // Fallback for older versions. + queueClass = DISPATCH_QUEUE_PRIORITY_HIGH; + } + + return dispatch_get_global_queue(queueClass, 0); +} + namespace BGM_Utils { // Forward declarations diff --git a/SharedSource/BGM_Utils.h b/SharedSource/BGM_Utils.h index 86a96de..93eaeca 100644 --- a/SharedSource/BGM_Utils.h +++ b/SharedSource/BGM_Utils.h @@ -25,10 +25,11 @@ // PublicUtility Includes #include "CADebugMacros.h" -#include "CAException.h" #if defined(__cplusplus) +#include "CAException.h" + // STL Includes #include @@ -36,6 +37,7 @@ // System Includes #include +#include #pragma mark Macros @@ -127,6 +129,10 @@ #pragma clang assume_nonnull begin +#pragma mark C Utility Functions + +dispatch_queue_t BGMGetDispatchQueue_PriorityUserInteractive(); + #if defined(__cplusplus) #pragma mark C++ Utility Functions