Compare commits

...

20 Commits

Author SHA1 Message Date
Kyle Neideck e655d571e0 Fix the About panel not always opening on macOS 14.4+. 2024-04-24 17:55:46 +10:00
Kyle Neideck 9257d50b15 In the About panel, link to the contributors page on GitHub.
Also, bump the patch version number and copyright years. (Should have
done that before tagging v0.4.1, so jump to v0.4.2.)
2024-04-24 13:50:53 +10:00
Kyle Neideck 3097f4b621 Fix installer failing in macOS 14.5.
`launchctl kickstart -k` is no longer permitted for `coreaudiod`. See
<https://developer.apple.com/documentation/macos-release-notes/macos-14_4-release-notes>.
(Thanks to @gchilds.)

As explained in those release notes, `kill` still works. `postinstall`
was using `killall coreaudiod` if `launchctl kickstart -k` failed, but
that was failing as well because it had to be `sudo killall coreaudiod`.

I haven't been able to reproduce this on macOS 14.4, only 14.5. Not sure
why.

See #705.
2024-04-23 15:49:13 +10:00
Kyle Neideck 73f221e423 skip-ui-tests.py: Update the path to Python as macOS dropped Python 2. 2024-03-07 08:42:01 +11:00
Kyle Neideck 7d700b3de5 build_and_install.sh: Work around build failures caused by an Xcode bug.
Fixes #712.
2024-03-07 08:42:00 +11:00
Kyle Neideck 014a6eecc8 Merge pull request #721 from mrbaloghakos/master
Fix Login Items path in README
2024-02-20 22:11:54 +11:00
Ákos Balogh 2cc3faaebb Fix Login Items path in README 2024-02-20 11:08:02 +01:00
Kyle Neideck 5000c64084 Fix build errors in XCode 15.2.
Ignore deprecation warnings in PublicUtility and drop support for macOS
10.12 and earlier.

See #712.
2024-01-23 23:44:31 +11:00
Kyle Neideck 4fc776e4a6 Merge pull request #638 from LawrenceWarren/master
Update references to `System Preferences`
2022-11-27 16:01:20 +11:00
Lawrence Warren ca3c497940 feat(docs): Update references to System Preferences
As of MacOS 13, System Preferences is known as System Settings. This
commit updates all user facing references to System Preferences, using
the new nomenclature.
2022-11-26 12:52:44 +11:00
Kyle Neideck 08837fcdca Merge pull request #622 from dnicolson/fix-menu-offset-big-sur
Fix menu alignment on macOS Big Sur and later
2022-08-31 02:07:09 +10:00
Dave Nicolson 076514c83a Fix menu alignment on macOS Big Sur and later 2022-08-29 06:42:49 +02:00
Kyle Neideck 8090f12204 Merge pull request #614 from Kache/master
Add Run / Configure instructions to README
2022-07-28 13:42:39 +10:00
Kevin C bd38207146 Add Run / Configure instructions to README
And fix whitespace

Fixes: #613
2022-07-27 01:59:19 -07:00
Kyle Neideck d92d9e6d29 README.md: Make v0.4.0 the current version. 2022-06-15 21:25:05 +10:00
Kyle Neideck d048287140 Fix slider knob sizes.
Also,
 - Update copyright years.
 - Drop support for macOS 10.9.
2022-06-12 14:36:59 +10:00
Kyle Neideck c89566d212 Merge branch 'gh-actions' 2022-06-12 13:44:12 +10:00
Kyle Neideck c68e05244c Merge branch 'gh-actions' 2022-05-13 17:20:31 +10:00
Kyle Neideck 1fdf47cd12 Merge pull request #597 from adrenalin8231/474-edge-helper
add Microsoft Edge to `ResponsibleBundleIDsOf`
2022-04-18 18:33:44 +10:00
adrenalin8231 4608f4bbac add Microsoft Edge to ResponsibleBundleIDsOf 2022-04-18 14:24:29 +09:00
28 changed files with 313 additions and 154 deletions
+1 -1
View File
@@ -22,7 +22,7 @@ assignees: ''
**Versions**
> Please complete the following information.
- Background Music: [e.g. "0.3.2" or "0.4.0-SNAPSHOT-c0ab98b". `Preferences > About Background Music`]
- Background Music: [e.g. "0.4.0" or "0.4.0-SNAPSHOT-c0ab98b". `Preferences > About Background Music`]
- macOS: [e.g. "11.3 Beta (20E5172i)" or "Big Sur". ` > About This Mac`]
**Hardware**
+3 -6
View File
@@ -1443,7 +1443,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fno-omit-frame-pointer";
@@ -1553,7 +1553,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
OTHER_CFLAGS = "-fno-omit-frame-pointer";
@@ -1635,7 +1635,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
MTL_ENABLE_DEBUG_INFO = NO;
OTHER_CFLAGS = "";
RUN_CLANG_STATIC_ANALYZER = YES;
@@ -1715,7 +1715,6 @@
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "BGMAppTests/UITests/BGMAppUITests-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.AppUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1733,7 +1732,6 @@
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "BGMAppTests/UITests/BGMAppUITests-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.AppUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1752,7 +1750,6 @@
DEVELOPMENT_TEAM = "";
INFOPLIST_FILE = "BGMAppTests/UITests/BGMAppUITests-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
MACOSX_DEPLOYMENT_TARGET = 10.11;
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.AppUITests;
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
+61
View File
@@ -26,6 +26,7 @@
// Local Includes
#import "BGM_Utils.h"
#import "BGMAppVolumes.h"
#import "BGMAppVolumesController.h"
#import "BGMAutoPauseMusic.h"
#import "BGMAutoPauseMenuItem.h"
@@ -234,6 +235,66 @@ static NSString* const kOptShowDockIcon = @"--show-dock-icon";
}
}
- (void) menuWillOpen:(NSMenu*)menu {
if (@available(macOS 10.16, *)) {
// Set menu offset and check for any active menu items
float menuOffset = 12.0;
for (NSMenuItem* menuItem in self.bgmMenu.itemArray) {
if (menuItem.state == NSControlStateValueOn && menuItem.indentationLevel == 0) {
menuOffset += 10;
break;
}
}
// Align volume output device and slider
for (NSView* subview in self.outputVolumeView.subviews) {
CGRect newSubview = subview.frame;
newSubview.origin.x = menuOffset;
subview.frame = newSubview;
}
// Align system sounds and app volumes
double appIconTitleOffset = 0;
for (NSMenuItem* menuItem in self.bgmMenu.itemArray) {
if (menuItem.view.subviews.count == 7 || menuItem.view.subviews.count == 3) {
NSTextField* appTitle;
NSImageView* appIcon;
for (NSView* subview in menuItem.view.subviews) {
if (menuItem.view.subviews.count == 3) {
// System sounds
if ([subview isKindOfClass:[NSTextField class]]) {
appTitle = (NSTextField*)subview;
}
if ([subview isKindOfClass:[NSImageView class]]) {
appIcon = (NSImageView*)subview;
}
} else if (menuItem.view.subviews.count == 7) {
// App volumes
if ([subview isKindOfClass:[BGMAVM_AppNameLabel class]]) {
appTitle = (NSTextField*)subview;
}
if ([subview isKindOfClass:[BGMAVM_AppIcon class]]) {
appIcon = (NSImageView*)subview;
}
}
}
if (appIconTitleOffset == 0) {
appIconTitleOffset = appTitle.frame.origin.x - appIcon.frame.origin.x;
}
CGRect newAppIcon = appIcon.frame;
newAppIcon.origin.x = menuOffset;
appIcon.frame = newAppIcon;
CGRect newAppTitle = appTitle.frame;
newAppTitle.origin.x = menuOffset + appIconTitleOffset;
appTitle.frame = newAppTitle;
}
}
}
}
- (void) setUpMainMenu {
autoPauseMenuItem =
[[BGMAutoPauseMenuItem alloc] initWithMenuItem:self.autoPauseMenuItemUnwrapped
+3 -1
View File
@@ -241,7 +241,9 @@ BGMBackgroundMusicDevice::ResponsibleBundleIDsOf(CACFString inParentBundleID)
// Skype
{ "com.skype.skype", { "com.skype.skype.Helper" } },
// Google Chrome
{ "com.google.Chrome", { "com.google.Chrome.helper" } }
{ "com.google.Chrome", { "com.google.Chrome.helper" } },
// Microsoft Edge
{ "com.microsoft.edgemac", { "com.microsoft.edgemac.helper" } }
};
// Parallels' VM "dock helper" apps have bundle IDs like
+82 -72
View File
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="22505" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="22505"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
@@ -85,7 +85,7 @@
<rect key="frame" x="0.0" y="0.0" width="269" height="47"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<subviews>
<textField identifier="AppName" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xmd-bg-huG" customClass="BGMAVM_AppNameLabel">
<textField identifier="AppName" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Xmd-bg-huG" customClass="BGMAVM_AppNameLabel">
<rect key="frame" x="42" y="28" width="115" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" controlSize="small" lineBreakMode="truncatingTail" allowsUndo="NO" sendsActionOnEndEditing="YES" alignment="left" title="App name here" usesSingleLineMode="YES" id="ZHF-ZW-Oqg">
@@ -102,7 +102,7 @@
<slider verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="I1l-Ci-4md" customClass="BGMAVM_VolumeSlider">
<rect key="frame" x="163" y="27" width="74" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<sliderCell key="cell" controlSize="small" continuous="YES" state="on" alignment="left" maxValue="100" doubleValue="50" tickMarkPosition="above" sliderType="linear" id="Jmg-df-9Xl"/>
<sliderCell key="cell" controlSize="mini" continuous="YES" state="on" alignment="left" maxValue="100" doubleValue="50" tickMarkPosition="above" sliderType="linear" id="Jmg-df-9Xl"/>
<accessibility description="Volume"/>
</slider>
<slider toolTip="Pan" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="2mh-uO-kOV" customClass="BGMAVM_PanSlider">
@@ -111,7 +111,7 @@
<sliderCell key="cell" controlSize="mini" continuous="YES" state="on" alignment="left" minValue="-100" maxValue="100" tickMarkPosition="below" numberOfTickMarks="1" sliderType="linear" id="ccM-Mt-93g"/>
<accessibility description="Pan"/>
</slider>
<button verticalHuggingPriority="750" fixedFrame="YES" tag="1" springLoaded="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vTG-n6-GxY" customClass="BGMAVM_ShowMoreControlsButton">
<button tag="1" springLoaded="YES" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="vTG-n6-GxY" customClass="BGMAVM_ShowMoreControlsButton">
<rect key="frame" x="243" y="27" width="16" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<contentFilters>
@@ -127,7 +127,7 @@
<font key="font" metaFont="system"/>
</buttonCell>
</button>
<textField identifier="PanLeft" toolTip="Pan" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9jc-9i-jw2">
<textField identifier="PanLeft" toolTip="Pan" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9jc-9i-jw2">
<rect key="frame" x="162" y="-1" width="12" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="L" id="hgE-7A-bez">
@@ -136,7 +136,7 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField identifier="PanRight" toolTip="Pan" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1lZ-hX-6Kl">
<textField identifier="PanRight" toolTip="Pan" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="1lZ-hX-6Kl">
<rect key="frame" x="228" y="-1" width="12" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="R" id="lzr-NO-0Na">
@@ -148,16 +148,16 @@
</subviews>
<point key="canvasLocation" x="117" y="-45"/>
</customView>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" hidesOnDeactivate="YES" visibleAtLaunch="NO" animationBehavior="default" id="Cf4-3V-gl1" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES"/>
<window allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" restorable="NO" hidesOnDeactivate="YES" releasedWhenClosed="NO" visibleAtLaunch="NO" animationBehavior="default" id="Cf4-3V-gl1" customClass="NSPanel">
<windowStyleMask key="styleMask" titled="YES" closable="YES" utility="YES" nonactivatingPanel="YES"/>
<windowPositionMask key="initialPositionMask" topStrut="YES"/>
<rect key="contentRect" x="248" y="350" width="1002" height="335"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<rect key="screenRect" x="0.0" y="0.0" width="1512" height="920"/>
<view key="contentView" id="HlB-hX-Y0Y">
<rect key="frame" x="0.0" y="0.0" width="1002" height="335"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r51-dd-LGP">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="r51-dd-LGP">
<rect key="frame" x="71" y="125" width="240" height="22"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Background Music" id="Dw2-nu-eBQ">
@@ -166,16 +166,16 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="1" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ekc-h0-I43">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="1" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ekc-h0-I43">
<rect key="frame" x="71" y="100" width="240" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Version 0.4.0" id="FDH-7l-wFf">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Version 0.4.2" id="FDH-7l-wFf">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="L5P-Lw-aCd">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="L5P-Lw-aCd">
<rect key="frame" x="413" y="298" width="270" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Licensed under GPL v2 or any later version." id="ETh-En-bzX">
@@ -188,7 +188,7 @@
<rect key="frame" x="383" y="93" width="5" height="150"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
</box>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="3" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nx6-kQ-N8Z" customClass="BGMLinkField">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="3" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nx6-kQ-N8Z" customClass="BGMLinkField">
<rect key="frame" x="36" y="50" width="310" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" tag="3" title="https://github.com/kyleneideck/BackgroundMusic" placeholderString="" id="VOb-5X-o3R">
@@ -216,11 +216,11 @@
<scrollView fixedFrame="YES" horizontalLineScroll="10" horizontalPageScroll="10" verticalLineScroll="10" verticalPageScroll="10" hasHorizontalScroller="NO" usesPredominantAxisScrolling="NO" translatesAutoresizingMaskIntoConstraints="NO" id="eqz-ap-PAC">
<rect key="frame" x="415" y="45" width="567" height="245"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" ambiguous="YES" drawsBackground="NO" id="Cdb-RA-YK0">
<clipView key="contentView" drawsBackground="NO" id="Cdb-RA-YK0">
<rect key="frame" x="1" y="1" width="565" height="243"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<textView ambiguous="YES" editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" id="LSG-PF-cl8">
<textView editable="NO" importsGraphics="NO" richText="NO" verticallyResizable="YES" id="LSG-PF-cl8">
<rect key="frame" x="-6" y="0.0" width="577" height="243"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
@@ -243,7 +243,7 @@
<autoresizingMask key="autoresizingMask"/>
</scroller>
</scrollView>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6qu-yI-r00">
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="6qu-yI-r00">
<rect key="frame" x="413" y="20" width="203" height="11"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" lineBreakMode="truncatingTail" sendsActionOnEndEditing="YES" title="The AirPlay Logo is a trademark of Apple Inc." id="lx7-k3-q16">
@@ -252,20 +252,29 @@
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="2" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vy4-dv-jQB">
<rect key="frame" x="18" y="75" width="346" height="17"/>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="2" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Vy4-dv-jQB">
<rect key="frame" x="18" y="75" width="155" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Copyright © 2016-2021 Background Music contributors" placeholderString="" id="ctF-95-uVu">
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="center" title="Copyright © 2016-2024" placeholderString="" id="ctF-95-uVu">
<font key="font" metaFont="system"/>
<color key="textColor" name="labelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" tag="4" allowsCharacterPickerTouchBarItem="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tRj-QC-GuQ" customClass="BGMLinkField">
<rect key="frame" x="168" y="75" width="194" height="16"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" alignment="left" tag="3" title="Background Music contributors" placeholderString="" allowsEditingTextAttributes="YES" usesSingleLineMode="YES" id="UC2-MX-fML">
<font key="font" metaFont="system"/>
<color key="textColor" red="0.20000000000000001" green="0.40000000000000002" blue="0.59999999999999998" alpha="1" colorSpace="calibratedRGB"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<point key="canvasLocation" x="-200" y="232.5"/>
</window>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" allowsCharacterPickerTouchBarItem="YES" id="IoN-sN-cCx">
<textField focusRingType="none" verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" setsMaxLayoutWidthAtFirstLayout="YES" allowsCharacterPickerTouchBarItem="YES" id="IoN-sN-cCx">
<rect key="frame" x="0.0" y="0.0" width="471" height="180"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" drawsBackground="YES" id="Ay8-8n-FHi">
@@ -284,10 +293,10 @@
<slider identifier="Output Volume" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="9Ru-Sc-dqC" userLabel="Output Volume Slider">
<rect key="frame" x="20" y="4" width="220" height="19"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<sliderCell key="cell" continuous="YES" state="on" alignment="left" maxValue="1" tickMarkPosition="above" sliderType="linear" id="MzM-fe-nKb"/>
<sliderCell key="cell" controlSize="small" continuous="YES" state="on" alignment="left" maxValue="1" tickMarkPosition="above" sliderType="linear" id="MzM-fe-nKb"/>
<accessibility description="Output Volume" help="Sets the volume of your audio output device." identifier="Output Volume"/>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wfC-C6-SLv">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="wfC-C6-SLv">
<rect key="frame" x="20" y="25" width="226" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Volume" id="60O-ju-B5C">
@@ -306,10 +315,10 @@
<slider identifier="System Sounds Volume" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gyd-WV-2ju" userLabel="Output Volume Slider">
<rect key="frame" x="163" y="0.0" width="74" height="15"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<sliderCell key="cell" controlSize="small" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="1" tickMarkPosition="above" sliderType="linear" id="VDn-d8-XK3"/>
<sliderCell key="cell" controlSize="mini" continuous="YES" state="on" alignment="left" maxValue="1" doubleValue="1" tickMarkPosition="above" sliderType="linear" id="VDn-d8-XK3"/>
<accessibility description="System Sounds Volume" help="Volume of alerts, notification sounds, etc. Usually short. Can be played by any app."/>
</slider>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iKs-df-Hp6">
<textField focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="iKs-df-Hp6">
<rect key="frame" x="42" y="1" width="86" height="14"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="System Sounds" id="ATK-L8-s8z">
@@ -333,53 +342,54 @@
<image name="buttonCell:IXo-C7-3uE:image" width="1" height="1">
<mutableData key="keyedArchiveRepresentation">
YnBsaXN0MDDUAQIDBAUGBwpYJHZlcnNpb25ZJGFyY2hpdmVyVCR0b3BYJG9iamVjdHMSAAGGoF8QD05T
S2V5ZWRBcmNoaXZlctEICVRyb290gAGuCwwZGh8UJCgpMDM2PD9VJG51bGzWDQ4PEBESExQVFhcYVk5T
S2V5ZWRBcmNoaXZlctEICVRyb290gAGuCwwZGh8UJCkqMTQ3PUBVJG51bGzWDQ4PEBESExQVFhcYVk5T
U2l6ZV5OU1Jlc2l6aW5nTW9kZVYkY2xhc3NcTlNJbWFnZUZsYWdzVk5TUmVwc1dOU0NvbG9ygAIQAIAN
EiDDAACAA4ALVnsxLCAxfdIbDxweWk5TLm9iamVjdHOhHYAEgArSGw8gI6IhIoAFgAaACdIlDyYnXxAU
TlNUSUZGUmVwcmVzZW50YXRpb26AB4AITxEIxE1NACoAAAAKAAAAEAEAAAMAAAABAAEAAAEBAAMAAAAB
AAEAAAECAAMAAAACAAgACAEDAAMAAAABAAEAAAEGAAMAAAABAAEAAAEKAAMAAAABAAEAAAERAAQAAAAB
AAAACAESAAMAAAABAAEAAAEVAAMAAAABAAIAAAEWAAMAAAABAAEAAAEXAAQAAAABAAAAAgEcAAMAAAAB
AAEAAAEoAAMAAAABAAIAAAFSAAMAAAABAAEAAAFTAAMAAAACAAEAAYdzAAcAAAf0AAAA0AAAAAAAAAf0
YXBwbAIgAABtbnRyR1JBWVhZWiAH0AACAA4ADAAAAABhY3NwQVBQTAAAAABub25lAAAAAAAAAAAAAAAA
AAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAVkZXNjAAAAwAAAAG9kc2NtAAABMAAABmZjcHJ0AAAHmAAAADh3dHB0AAAH0AAAABRrVFJD
AAAH5AAAAA5kZXNjAAAAAAAAABVHZW5lcmljIEdyYXkgUHJvZmlsZQAAAAAAAAAAAAAAFUdlbmVyaWMg
R3JheSBQcm9maWxlAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
bWx1YwAAAAAAAAAfAAAADHNrU0sAAAAqAAABhGVuVVMAAAAoAAABrmNhRVMAAAAsAAAB1nZpVk4AAAAs
AAACAnB0QlIAAAAqAAACLnVrVUEAAAAsAAACWGZyRlUAAAAqAAAChGh1SFUAAAAuAAACrnpoVFcAAAAQ
AAAC3G5iTk8AAAAsAAAC7GtvS1IAAAAYAAADGGNzQ1oAAAAkAAADMGhlSUwAAAAgAAADVHJvUk8AAAAk
AAADdGRlREUAAAA6AAADmGl0SVQAAAAuAAAD0nN2U0UAAAAuAAAEAHpoQ04AAAAQAAAELmphSlAAAAAW
AAAEPmVsR1IAAAAkAAAEVHB0UE8AAAA4AAAEeG5sTkwAAAAqAAAEsGVzRVMAAAAoAAAE2nRoVEgAAAAk
AAAFAnRyVFIAAAAiAAAFJmZpRkkAAAAsAAAFSGhySFIAAAA6AAAFdHBsUEwAAAA2AAAFrnJ1UlUAAAAm
AAAF5GFyRUcAAAAoAAAGCmRhREsAAAA0AAAGMgBWAWEAZQBvAGIAZQBjAG4A/QAgAHMAaQB2AP0AIABw
AHIAbwBmAGkAbABHAGUAbgBlAHIAaQBjACAARwByAGEAeQAgAFAAcgBvAGYAaQBsAGUAUABlAHIAZgBp
AGwAIABkAGUAIABnAHIAaQBzACAAZwBlAG4A6AByAGkAYwBDHqUAdQAgAGgA7ABuAGgAIABNAOAAdQAg
AHgA4QBtACAAQwBoAHUAbgBnAFAAZQByAGYAaQBsACAAQwBpAG4AegBhACAARwBlAG4A6QByAGkAYwBv
BBcEMAQzBDAEOwRMBD0EOAQ5ACAEPwRABD4ERAQwBDkEOwAgAEcAcgBhAHkAUAByAG8AZgBpAGwAIABn
AOkAbgDpAHIAaQBxAHUAZQAgAGcAcgBpAHMAwQBsAHQAYQBsAOEAbgBvAHMAIABzAHoA/AByAGsAZQAg
AHAAcgBvAGYAaQBskBp1KHBwlo6Ccl9pY8+P8ABHAGUAbgBlAHIAaQBzAGsAIABnAHIA5QB0AG8AbgBl
AHAAcgBvAGYAaQBsx3y8GAAgAEcAcgBhAHkAINUEuFzTDMd8AE8AYgBlAGMAbgD9ACABYQBlAGQA/QAg
AHAAcgBvAGYAaQBsBeQF6AXVBeQF2QXcACAARwByAGEAeQAgBdsF3AXcBdkAUAByAG8AZgBpAGwAIABn
AHIAaQAgAGcAZQBuAGUAcgBpAGMAQQBsAGwAZwBlAG0AZQBpAG4AZQBzACAARwByAGEAdQBzAHQAdQBm
AGUAbgAtAFAAcgBvAGYAaQBsAFAAcgBvAGYAaQBsAG8AIABnAHIAaQBnAGkAbwAgAGcAZQBuAGUAcgBp
AGMAbwBHAGUAbgBlAHIAaQBzAGsAIABnAHIA5QBzAGsAYQBsAGUAcAByAG8AZgBpAGxmbpAacHBepmPP
j/Blh072TgCCLDCwMOwwpDDXMO0w1TChMKQw6wOTA7UDvQO5A7oDzAAgA8ADwQO/A8YDrwO7ACADswO6
A8EDuQBQAGUAcgBmAGkAbAAgAGcAZQBuAOkAcgBpAGMAbwAgAGQAZQAgAGMAaQBuAHoAZQBuAHQAbwBz
AEEAbABnAGUAbQBlAGUAbgAgAGcAcgBpAGoAcwBwAHIAbwBmAGkAZQBsAFAAZQByAGYAaQBsACAAZwBy
AGkAcwAgAGcAZQBuAOkAcgBpAGMAbw5CDhsOIw5EDh8OJQ5MDioONQ5ADhcOMg4XDjEOSA4nDkQOGwBH
AGUAbgBlAGwAIABHAHIAaQAgAFAAcgBvAGYAaQBsAGkAWQBsAGUAaQBuAGUAbgAgAGgAYQByAG0AYQBh
AHAAcgBvAGYAaQBpAGwAaQBHAGUAbgBlAHIAaQENAGsAaQAgAHAAcgBvAGYAaQBsACAAcwBpAHYAaQBo
ACAAdABvAG4AbwB2AGEAVQBuAGkAdwBlAHIAcwBhAGwAbgB5ACAAcAByAG8AZgBpAGwAIABzAHoAYQBy
AG8BWwBjAGkEHgQxBEkEOAQ5ACAEQQQ1BEAESwQ5ACAEPwRABD4ERAQ4BDsETAZFBkQGQQAgBioGOQYx
BkoGQQAgAEcAcgBhAHkAIAYnBkQGOQYnBkUARwBlAG4AZQByAGUAbAAgAGcAcgDlAHQAbwBuAGUAYgBl
AHMAawByAGkAdgBlAGwAcwBlAAB0ZXh0AAAAAENvcHlyaWdodCAyMDA3IEFwcGxlIEluYy4sIGFsbCBy
aWdodHMgcmVzZXJ2ZWQuAFhZWiAAAAAAAADzUQABAAAAARbMY3VydgAAAAAAAAABAc0AANIqKywtWiRj
bGFzc25hbWVYJGNsYXNzZXNfEBBOU0JpdG1hcEltYWdlUmVwoywuL1pOU0ltYWdlUmVwWE5TT2JqZWN0
0iorMTJXTlNBcnJheaIxL9IqKzQ1Xk5TTXV0YWJsZUFycmF5ozQxL9M3OA85OjtXTlNXaGl0ZVxOU0Nv
bG9yU3BhY2VEMCAwABADgAzSKis9PldOU0NvbG9yoj0v0iorQEFXTlNJbWFnZaJALwAIABEAGgAkACkA
MgA3AEkATABRAFMAYgBoAHUAfACLAJIAnwCmAK4AsACyALQAuQC7AL0AxADJANQA1gDYANoA3wDiAOQA
5gDoAO0BBAEGAQgJ0AnVCeAJ6Qn8CgAKCwoUChkKIQokCikKOAo8CkMKSwpYCl0KXwphCmYKbgpxCnYK
fgAAAAAAAAIBAAAAAAAAAEIAAAAAAAAAAAAAAAAAAAqBA
EiDDAACAA4ALVnsxLCAxfdIbDxweWk5TLm9iamVjdHOhHYAEgArSGw8gI6IhIoAFgAaACdMPJSYnKBRf
EBROU1RJRkZSZXByZXNlbnRhdGlvbl8QGU5TSW50ZXJuYWxMYXlvdXREaXJlY3Rpb26ACIAHTxEIxE1N
ACoAAAAKAAAAEAEAAAMAAAABAAEAAAEBAAMAAAABAAEAAAECAAMAAAACAAgACAEDAAMAAAABAAEAAAEG
AAMAAAABAAEAAAEKAAMAAAABAAEAAAERAAQAAAABAAAACAESAAMAAAABAAEAAAEVAAMAAAABAAIAAAEW
AAMAAAABAAEAAAEXAAQAAAABAAAAAgEcAAMAAAABAAEAAAEoAAMAAAABAAIAAAFSAAMAAAABAAEAAAFT
AAMAAAACAAEAAYdzAAcAAAf0AAAA0AAAAAAAAAf0YXBwbAIgAABtbnRyR1JBWVhZWiAH0AACAA4ADAAA
AABhY3NwQVBQTAAAAABub25lAAAAAAAAAAAAAAAAAAAAAAAA9tYAAQAAAADTLWFwcGwAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAVkZXNjAAAAwAAAAG9kc2NtAAABMAAA
BmZjcHJ0AAAHmAAAADh3dHB0AAAH0AAAABRrVFJDAAAH5AAAAA5kZXNjAAAAAAAAABVHZW5lcmljIEdy
YXkgUHJvZmlsZQAAAAAAAAAAAAAAFUdlbmVyaWMgR3JheSBQcm9maWxlAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAbWx1YwAAAAAAAAAfAAAADHNrU0sAAAAqAAABhGVu
VVMAAAAoAAABrmNhRVMAAAAsAAAB1nZpVk4AAAAsAAACAnB0QlIAAAAqAAACLnVrVUEAAAAsAAACWGZy
RlUAAAAqAAAChGh1SFUAAAAuAAACrnpoVFcAAAAQAAAC3G5iTk8AAAAsAAAC7GtvS1IAAAAYAAADGGNz
Q1oAAAAkAAADMGhlSUwAAAAgAAADVHJvUk8AAAAkAAADdGRlREUAAAA6AAADmGl0SVQAAAAuAAAD0nN2
U0UAAAAuAAAEAHpoQ04AAAAQAAAELmphSlAAAAAWAAAEPmVsR1IAAAAkAAAEVHB0UE8AAAA4AAAEeG5s
TkwAAAAqAAAEsGVzRVMAAAAoAAAE2nRoVEgAAAAkAAAFAnRyVFIAAAAiAAAFJmZpRkkAAAAsAAAFSGhy
SFIAAAA6AAAFdHBsUEwAAAA2AAAFrnJ1UlUAAAAmAAAF5GFyRUcAAAAoAAAGCmRhREsAAAA0AAAGMgBW
AWEAZQBvAGIAZQBjAG4A/QAgAHMAaQB2AP0AIABwAHIAbwBmAGkAbABHAGUAbgBlAHIAaQBjACAARwBy
AGEAeQAgAFAAcgBvAGYAaQBsAGUAUABlAHIAZgBpAGwAIABkAGUAIABnAHIAaQBzACAAZwBlAG4A6ABy
AGkAYwBDHqUAdQAgAGgA7ABuAGgAIABNAOAAdQAgAHgA4QBtACAAQwBoAHUAbgBnAFAAZQByAGYAaQBs
ACAAQwBpAG4AegBhACAARwBlAG4A6QByAGkAYwBvBBcEMAQzBDAEOwRMBD0EOAQ5ACAEPwRABD4ERAQw
BDkEOwAgAEcAcgBhAHkAUAByAG8AZgBpAGwAIABnAOkAbgDpAHIAaQBxAHUAZQAgAGcAcgBpAHMAwQBs
AHQAYQBsAOEAbgBvAHMAIABzAHoA/AByAGsAZQAgAHAAcgBvAGYAaQBskBp1KHBwlo6Ccl9pY8+P8ABH
AGUAbgBlAHIAaQBzAGsAIABnAHIA5QB0AG8AbgBlAHAAcgBvAGYAaQBsx3y8GAAgAEcAcgBhAHkAINUE
uFzTDMd8AE8AYgBlAGMAbgD9ACABYQBlAGQA/QAgAHAAcgBvAGYAaQBsBeQF6AXVBeQF2QXcACAARwBy
AGEAeQAgBdsF3AXcBdkAUAByAG8AZgBpAGwAIABnAHIAaQAgAGcAZQBuAGUAcgBpAGMAQQBsAGwAZwBl
AG0AZQBpAG4AZQBzACAARwByAGEAdQBzAHQAdQBmAGUAbgAtAFAAcgBvAGYAaQBsAFAAcgBvAGYAaQBs
AG8AIABnAHIAaQBnAGkAbwAgAGcAZQBuAGUAcgBpAGMAbwBHAGUAbgBlAHIAaQBzAGsAIABnAHIA5QBz
AGsAYQBsAGUAcAByAG8AZgBpAGxmbpAacHBepmPPj/Blh072TgCCLDCwMOwwpDDXMO0w1TChMKQw6wOT
A7UDvQO5A7oDzAAgA8ADwQO/A8YDrwO7ACADswO6A8EDuQBQAGUAcgBmAGkAbAAgAGcAZQBuAOkAcgBp
AGMAbwAgAGQAZQAgAGMAaQBuAHoAZQBuAHQAbwBzAEEAbABnAGUAbQBlAGUAbgAgAGcAcgBpAGoAcwBw
AHIAbwBmAGkAZQBsAFAAZQByAGYAaQBsACAAZwByAGkAcwAgAGcAZQBuAOkAcgBpAGMAbw5CDhsOIw5E
Dh8OJQ5MDioONQ5ADhcOMg4XDjEOSA4nDkQOGwBHAGUAbgBlAGwAIABHAHIAaQAgAFAAcgBvAGYAaQBs
AGkAWQBsAGUAaQBuAGUAbgAgAGgAYQByAG0AYQBhAHAAcgBvAGYAaQBpAGwAaQBHAGUAbgBlAHIAaQEN
AGsAaQAgAHAAcgBvAGYAaQBsACAAcwBpAHYAaQBoACAAdABvAG4AbwB2AGEAVQBuAGkAdwBlAHIAcwBh
AGwAbgB5ACAAcAByAG8AZgBpAGwAIABzAHoAYQByAG8BWwBjAGkEHgQxBEkEOAQ5ACAEQQQ1BEAESwQ5
ACAEPwRABD4ERAQ4BDsETAZFBkQGQQAgBioGOQYxBkoGQQAgAEcAcgBhAHkAIAYnBkQGOQYnBkUARwBl
AG4AZQByAGUAbAAgAGcAcgDlAHQAbwBuAGUAYgBlAHMAawByAGkAdgBlAGwAcwBlAAB0ZXh0AAAAAENv
cHlyaWdodCAyMDA3IEFwcGxlIEluYy4sIGFsbCByaWdodHMgcmVzZXJ2ZWQuAFhZWiAAAAAAAADzUQAB
AAAAARbMY3VydgAAAAAAAAABAc0AANIrLC0uWiRjbGFzc25hbWVYJGNsYXNzZXNfEBBOU0JpdG1hcElt
YWdlUmVwoy0vMFpOU0ltYWdlUmVwWE5TT2JqZWN00issMjNXTlNBcnJheaIyMNIrLDU2Xk5TTXV0YWJs
ZUFycmF5ozUyMNM4OQ86OzxXTlNXaGl0ZVxOU0NvbG9yU3BhY2VEMCAwABADgAzSKyw+P1dOU0NvbG9y
oj4w0issQUJXTlNJbWFnZaJBMAAIABEAGgAkACkAMgA3AEkATABRAFMAYgBoAHUAfACLAJIAnwCmAK4A
sACyALQAuQC7AL0AxADJANQA1gDYANoA3wDiAOQA5gDoAO8BBgEiASQBJgnuCfMJ/goHChoKHgopCjIK
Nwo/CkIKRwpWCloKYQppCnYKewp9Cn8KhAqMCo8KlAqcAAAAAAAAAgEAAAAAAAAAQwAAAAAAAAAAAAAA
AAAACp8
</mutableData>
</image>
</resources>
+2 -2
View File
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.4.0</string>
<string>0.4.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -33,7 +33,7 @@
<key>NSAppleScriptEnabled</key>
<true/>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016-2021 Background Music contributors</string>
<string>Copyright © 2016-2024 Background Music contributors</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSMicrophoneUsageDescription</key>
+37 -3
View File
@@ -17,7 +17,7 @@
// BGMAboutPanel.m
// BGMApp
//
// Copyright © 2016 Kyle Neideck
// Copyright © 2016, 2024 Kyle Neideck
//
// Self Include
@@ -35,6 +35,7 @@ NS_ASSUME_NONNULL_BEGIN
static NSInteger const kVersionLabelTag = 1;
static NSInteger const kCopyrightLabelTag = 2;
static NSInteger const kProjectWebsiteLabelTag = 3;
static NSInteger const kContributorsLabelTag = 4;
@implementation BGMAboutPanel {
NSPanel* aboutPanel;
@@ -42,6 +43,7 @@ static NSInteger const kProjectWebsiteLabelTag = 3;
NSTextField* versionLabel;
NSTextField* copyrightLabel;
NSTextField* websiteLabel;
NSTextField* contributorsLabel;
NSTextView* licenseView;
}
@@ -53,6 +55,7 @@ static NSInteger const kProjectWebsiteLabelTag = 3;
versionLabel = [[aboutPanel contentView] viewWithTag:kVersionLabelTag];
copyrightLabel = [[aboutPanel contentView] viewWithTag:kCopyrightLabelTag];
websiteLabel = [[aboutPanel contentView] viewWithTag:kProjectWebsiteLabelTag];
contributorsLabel = [[aboutPanel contentView] viewWithTag:kContributorsLabelTag];
licenseView = inLicenseView;
@@ -83,7 +86,10 @@ static NSInteger const kProjectWebsiteLabelTag = 3;
[[bundle infoDictionary] objectForKey:@"NSHumanReadableCopyright"];
if (copyrightNotice) {
copyrightLabel.stringValue = (NSString*)copyrightNotice;
// Remove the part that we replace with a link.
copyrightLabel.stringValue =
[((NSString*)copyrightNotice) stringByReplacingOccurrencesOfString:contributorsLabel.stringValue
withString:@""];
}
// Project website link label
@@ -97,6 +103,18 @@ static NSInteger const kProjectWebsiteLabelTag = 3;
attributes:@{ NSLinkAttributeName: projectURL,
NSFontAttributeName: linkFont }];
// Contributors link label
// TODO: Proper credits (i.e. in the app instead of just a link)
contributorsLabel.selectable = YES;
contributorsLabel.allowsEditingTextAttributes = YES;
NSString* contributorsURL = [NSString stringWithUTF8String:kBGMContributorsURL];
NSFont* cLinkFont = contributorsLabel.font ? contributorsLabel.font : [NSFont labelFontOfSize:0.0];
contributorsLabel.attributedStringValue =
[[NSAttributedString alloc] initWithString:contributorsLabel.stringValue
attributes:@{ NSLinkAttributeName: contributorsURL,
NSFontAttributeName: cLinkFont }];
// Load the text of the license into the text view
NSString* __nullable licensePath = [bundle pathForResource:@"LICENSE" ofType:nil];
@@ -122,9 +140,25 @@ static NSInteger const kProjectWebsiteLabelTag = 3;
- (void) show {
DebugMsg("BGMAboutPanel::showAboutPanel: Opening \"About Background Music\" panel");
[NSApp activateIgnoringOtherApps:YES];
// We have to make aboutPanel visible before calling [NSApp activateIgnoringOtherApps:YES]
// or the app won't be activated the first time (not sure why it only happens the first
// time) and aboutPanel won't open. WindowServer logs this explanation:
// 0[SetFrontProcessWithInfo]: CPS: Rejecting the request for pid 1234 due to the activation count being 0; launch ts=19302059379458, current time=19314267188375, window count = 0.
[aboutPanel setIsVisible:YES];
[aboutPanel makeKeyAndOrderFront:self];
// On macOS 14.4, aboutPanel needs "Release When Closed" unchecked in MainMenu.xib. Otherwise,
// aboutPanel will never open again if you click the close button.
// This is deprecated for NSApplication.activate, but that stops aboutPanel from ever being shown.
[NSApp activateIgnoringOtherApps:YES];
DebugMsg("BGMAboutPanel::showAboutPanel: Finished opening panel. "
"aboutPanel.isVisible %d, aboutPanel.isKeyWindow %d, NSApp.isActive %d",
aboutPanel.isVisible,
aboutPanel.isKeyWindow,
NSApp.isActive);
}
@end
+1 -1
View File
@@ -153,7 +153,7 @@ sleep 3
# TODO: What if they only have one audio device?
echo ""
echo "${bold}Done! Toggle your audio output device in the Sound section of System Preferences to finish" \
echo "${bold}Done! Toggle your audio output device in the Sound section of System Settings to finish" \
"uninstalling. (Or just restart your computer.)${normal}"
+9 -8
View File
@@ -76,7 +76,7 @@
// Make the "Background Music wants to use the microphone" dialog appear every time so the test
// doesn't need logic to handle both cases.
// TODO: Commented out to check if CI builds can grant access by modifying TCC.db.
// TODO: Commented out until acceptMicrophoneAuthorizationDialog work again. See below.
// if (@available(macOS 10.15.4, *)) {
// [app resetAuthorizationStatusForResource:XCUIProtectedResourceMicrophone];
// }
@@ -84,18 +84,19 @@
// Launch BGMApp.
[app launch];
// TODO: Commented out to check if CI builds can grant access by modifying TCC.db.
// TODO: This doesn't seem to be working on macOS 12.4 (21F79). You can click OK manually for
// now.
// [self acceptMicrophoneAuthorizationDialog];
if (![icon waitForExistenceWithTimeout:20.0]) {
if (![icon waitForExistenceWithTimeout:20.0]) {
// The status bar icon/button has this type when using older versions of XCTest, so try
// both. (Actually, it might depend on the macOS or Xcode version. I'm not sure.)
XCUIElement* iconOldType =
[app.menuBars childrenMatchingType:XCUIElementTypeMenuBarItem].element;
if ([iconOldType waitForExistenceWithTimeout:20.0]) {
NSLog(@"icon = iconOldType");
icon = iconOldType;
}
[app.menuBars childrenMatchingType:XCUIElementTypeMenuBarItem].element;
if ([iconOldType waitForExistenceWithTimeout:20.0]) {
NSLog(@"icon = iconOldType");
icon = iconOldType;
}
}
// Wait for the initial elements.
+2 -2
View File
@@ -1,4 +1,4 @@
#!/usr/bin/python2.7
#!/usr/bin/env python3
# This file is part of Background Music.
#
@@ -19,7 +19,7 @@
# skip-ui-tests.py
# BGMAppUITests
#
# Copyright (c) 2017 Kyle Neideck
# Copyright (c) 2017, 2024 Kyle Neideck
#
# Disables the UI tests. This is mainly useful on CI systems that don't support UI tests.
#
+2 -2
View File
@@ -17,13 +17,13 @@
<key>CFBundlePackageType</key>
<string>XPC!</string>
<key>CFBundleShortVersionString</key>
<string>0.4.0</string>
<string>0.4.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016-2021 Background Music contributors</string>
<string>Copyright © 2016-2024 Background Music contributors</string>
<key>XPCService</key>
<dict>
<key>ServiceType</key>
+2 -2
View File
@@ -17,7 +17,7 @@
// BGMDebugLogging.c
// PublicUtility
//
// Copyright © 2020 Kyle Neideck
// Copyright © 2020, 2024 Kyle Neideck
//
// Self Include
@@ -36,7 +36,7 @@
// We don't bother synchronising accesses of gDebugLoggingIsEnabled because it isn't really
// necessary and would complicate code that accesses it on realtime threads.
int BGMDebugLoggingIsEnabled()
int BGMDebugLoggingIsEnabled(void)
{
return gDebugLoggingIsEnabled;
}
+14 -1
View File
@@ -59,13 +59,15 @@ full barrier.
#if TARGET_OS_WIN32
#include <windows.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedAnd)
#else
#include <CoreFoundation/CFBase.h>
#include <libkern/OSAtomic.h>
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
inline void CAMemoryBarrier()
{
#if TARGET_OS_WIN32
@@ -196,6 +198,8 @@ inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
#endif
}
#pragma clang diagnostic pop
// int32_t flavors -- for C++ only since we can't overload in C
// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
// this will generate redefinition error. But on Mac, CFBase.h, still includes MacTypes.h where
@@ -243,6 +247,9 @@ inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
}
#endif // __cplusplus && !__LP64__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
#if __LP64__
inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
{
@@ -259,6 +266,8 @@ inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue,
#endif
}
#pragma clang diagnostic pop
/* Spinlocks. These use memory barriers as required to synchronize access to shared
* memory protected by the lock. The lock operation spins, but employs various strategies
* to back off if the lock is held, making it immune to most priority-inversion livelocks.
@@ -273,6 +282,9 @@ bool CASpinLockTry( volatile CASpinLock *__lock );
void CASpinLockLock( volatile CASpinLock *__lock );
void CASpinLockUnlock( volatile CASpinLock *__lock );
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
inline void CASpinLockLock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
@@ -301,5 +313,6 @@ inline bool CASpinLockTry( volatile CASpinLock *__lock )
#endif
}
#pragma clang diagnostic pop
#endif // __CAAtomic_h__
+3
View File
@@ -101,6 +101,8 @@ public:
// STL Helpers
public:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
{
bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsSameAddress(inAddress1, inAddress2); }
@@ -120,6 +122,7 @@ public:
{
bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentLessThanAddress(inAddress1, inAddress2); }
};
#pragma clang diagnostic pop
};
@@ -712,7 +712,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
ONLY_ACTIVE_ARCH = YES;
RUN_CLANG_STATIC_ANALYZER = YES;
WARNING_CFLAGS = "-Wpartial-availability";
@@ -780,7 +780,7 @@
GCC_WARN_UNUSED_LABEL = YES;
GCC_WARN_UNUSED_PARAMETER = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.9;
MACOSX_DEPLOYMENT_TARGET = 10.13;
RUN_CLANG_STATIC_ANALYZER = YES;
WARNING_CFLAGS = "-Wpartial-availability";
};
+2 -2
View File
@@ -17,7 +17,7 @@
// BGM_XPCHelper.m
// BGMDriver
//
// Copyright © 2016, 2017, 2020 Kyle Neideck
// Copyright © 2016, 2017, 2020, 2024 Kyle Neideck
// Copyright © 2020 Aleksey Yurkevich
//
@@ -38,7 +38,7 @@
static const UInt64 REMOTE_CALL_DEFAULT_TIMEOUT_SECS = 30;
static NSXPCConnection* CreateXPCHelperConnection()
static NSXPCConnection* CreateXPCHelperConnection(void)
{
// Create a connection to BGMXPCHelper's Mach service. If it isn't already running, launchd will start BGMXPCHelper when we send
// a message to this connection.
+2 -2
View File
@@ -19,7 +19,7 @@
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>0.4.0</string>
<string>0.4.2</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -37,7 +37,7 @@
</array>
</dict>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2016-2021 Background Music contributors</string>
<string>Copyright © 2016-2024 Background Music contributors</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
+13 -1
View File
@@ -59,13 +59,15 @@ full barrier.
#if TARGET_OS_WIN32
#include <windows.h>
#include <intrin.h>
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedOr)
#pragma intrinsic(_InterlockedAnd)
#else
#include <CoreFoundation/CFBase.h>
#include <libkern/OSAtomic.h>
#endif
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
inline void CAMemoryBarrier()
{
#if TARGET_OS_WIN32
@@ -195,6 +197,7 @@ inline bool CAAtomicTestAndSetBarrier(int bitToSet, void* theAddress)
return OSAtomicTestAndSetBarrier(bitToSet, (volatile void *)theAddress);
#endif
}
#pragma clang diagnostic pop
// int32_t flavors -- for C++ only since we can't overload in C
// CFBase.h defines SInt32 as signed int which is similar to int32_t. If CFBase.h is included, then
@@ -243,6 +246,9 @@ inline int32_t CAAtomicDecrement32Barrier(volatile int32_t* theValue)
}
#endif // __cplusplus && !__LP64__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
#if __LP64__
inline bool CAAtomicCompareAndSwap64Barrier( int64_t __oldValue, int64_t __newValue, volatile int64_t *__theValue )
{
@@ -258,6 +264,7 @@ inline bool CAAtomicCompareAndSwapPtrBarrier(void *__oldValue, void *__newValue,
return CAAtomicCompareAndSwap32Barrier((int32_t)__oldValue, (int32_t)__newValue, (int32_t *)__theValue);
#endif
}
#pragma clang diagnostic pop
/* Spinlocks. These use memory barriers as required to synchronize access to shared
* memory protected by the lock. The lock operation spins, but employs various strategies
@@ -273,6 +280,9 @@ bool CASpinLockTry( volatile CASpinLock *__lock );
void CASpinLockLock( volatile CASpinLock *__lock );
void CASpinLockUnlock( volatile CASpinLock *__lock );
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
inline void CASpinLockLock( volatile CASpinLock *__lock )
{
#if TARGET_OS_MAC
@@ -301,5 +311,7 @@ inline bool CASpinLockTry( volatile CASpinLock *__lock )
#endif
}
#pragma clang diagnostic pop
#endif // __CAAtomic_h__
+3
View File
@@ -160,6 +160,8 @@ public:
static bool compare_and_swap(T *oldvalue, T *newvalue, T **pvalue)
{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
#if TARGET_OS_MAC
#if __LP64__
return ::OSAtomicCompareAndSwap64Barrier(int64_t(oldvalue), int64_t(newvalue), (int64_t *)pvalue);
@@ -172,6 +174,7 @@ public:
//return ::CompareAndSwap(UInt32(oldvalue), UInt32(newvalue), (UInt32 *)pvalue);
return CAAtomicCompareAndSwap32Barrier(SInt32(oldvalue), SInt32(newvalue), (SInt32*)pvalue);
#endif
#pragma clang diagnostic pop
}
protected:
@@ -101,6 +101,8 @@ public:
// STL Helpers
public:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated"
struct EqualTo : public std::binary_function<AudioObjectPropertyAddress, AudioObjectPropertyAddress, bool>
{
bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsSameAddress(inAddress1, inAddress2); }
@@ -120,6 +122,7 @@ public:
{
bool operator()(const AudioObjectPropertyAddress& inAddress1, const AudioObjectPropertyAddress& inAddress2) const { return IsCongruentLessThanAddress(inAddress1, inAddress2); }
};
#pragma clang diagnostic pop
};
+1 -1
View File
@@ -13,7 +13,7 @@ the virtual device to the real output device and a few other things. The virtual
## Summary
From the user's perspective, BGMDevice appears as one input device and one output device, both named "Background Music".
They're shown in `System Preferences > Sound` along with the real audio devices.
They're shown in `System Settings > Sound` along with the real audio devices.
When you start BGMApp, it sets BGMDevice as your system's default output device so the system (i.e. Core Audio) will
start sending all<sup id="a2">[2](#f2)</sup> your audio data to BGMDriver. BGMDriver plays that audio on BGMDevice's
+3 -2
View File
@@ -38,12 +38,13 @@
(Audio will stop working until the next step, so you might want to pause any running audio apps.)
```shell
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
sudo killall coreaudiod
```
or, if that fails
```shell
sudo killall coreaudiod
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
```
- Run `Background Music.app`.
+3 -3
View File
@@ -9,14 +9,14 @@
<sup>(Open `/Applications/Utilities/Terminal.app` and paste the following at the prompt.)</sup>
```shell
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
sudo killall coreaudiod
```
or, if that fails
```shell
sudo killall coreaudiod
sudo launchctl kickstart -kp system/com.apple.audio.coreaudiod
```
- Go to the Sound section in System Preferences and change your default output device at least once. (If you only have
- Go to the Sound section in System Settings and change your default output device at least once. (If you only have
one device now, either use `Audio MIDI Setup.app` to create a temporary aggregate device, restart any audio apps that
have stopped working or just restart your system.)
+35 -28
View File
@@ -10,13 +10,14 @@
[Overview](#overview)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Auto-pause music](#auto-pause-music)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Application volume](#application-volume)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Recording system audio](#recording-system-audio)<br/>
[Download](#download)<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;[Recording system audio](#recording-system-audio)<br/>
[Download](#download)<br/>
[Run / Configure](#run--configure)<br/>
[Build and Install](#installing-from-source-code)</br>
[Uninstall](#uninstall)<br/>
[Troubleshooting](#troubleshooting)<br/>
[Related Projects](#related-projects)<br/>
[License](#license)<br/>
[Troubleshooting](#troubleshooting)<br/>
[Related Projects](#related-projects)<br/>
[License](#license)<br/>
# Overview
@@ -40,11 +41,11 @@ The auto-pause feature currently supports following music players:
+ [Decibel](https://sbooth.org/Decibel/)
+ [Hermes](http://hermesapp.org/)
+ [Swinsian](https://swinsian.com/)
+ [GPMDP](https://www.googleplaymusicdesktopplayer.com/)
+ [GPMDP](https://www.googleplaymusicdesktopplayer.com/)
Adding support for a new music player is usually straightforward.<sup id="a1">[1](#f1)</sup> If you don't know how to program, or just don't feel
like it, feel free to [create an issue](https://github.com/kyleneideck/BackgroundMusic/issues/new). Otherwise, see
[BGMMusicPlayer.h](BGMApp/BGMApp/Music%20Players/BGMMusicPlayer.h).
[BGMMusicPlayer.h](BGMApp/BGMApp/Music%20Players/BGMMusicPlayer.h).
## Application volume
@@ -61,25 +62,22 @@ the **Background Music** device. You can create the aggregate device using the *
# Download
**Requires macOS 10.10+**.
**Requires macOS 10.13+**.
You can download the current version of **Background Music** using the following options. We also have [snapshot builds](https://github.com/kyleneideck/BackgroundMusic/releases).
| ⚠️ Version 0.3.2 doesn't work on macOS Big Sur. Try this snapshot version: [0.4.0-SNAPSHOT-b38f6dd](https://github.com/kyleneideck/BackgroundMusic/releases/tag/0.4.0-SNAPSHOT-b38f6dd) |
|------------- |
### Option 1
Download **version 0.3.2**:
Download **version 0.4.0**:
<a href="https://github.com/kyleneideck/BackgroundMusic/releases/download/v0.3.2/BackgroundMusic-0.3.2.pkg"><img
<a href="https://github.com/kyleneideck/BackgroundMusic/releases/download/v0.4.0/BackgroundMusic-0.4.0.pkg"><img
src="Images/README/pkg-icon.png" width="32" height="32" align="absmiddle" />
BackgroundMusic-0.3.2.pkg</a> (571 KB)
BackgroundMusic-0.4.0.pkg</a> (895 KB)
> <sub>MD5: 7f34d9e6595566f3ba14e7afc89c86a2</sub><br/>
> <sub>SHA256: 0cd7b488b5ab97a1ecb496e484a6c209c29f35ab503e6f73b45e56719a7aba18</sub><br/>
> <sub>MD5: 0fc3c839939b1b55b799f3e00755d949</sub><br/>
> <sub>SHA256: f170957702c48f96c0fa9706b72f6d6048bcc87be393eb1d01289c20e1111325</sub><br/>
> <sub>PGP:
> [sig](https://github.com/kyleneideck/BackgroundMusic/releases/download/v0.3.2/BackgroundMusic-0.3.2.pkg.asc),
> [sig](https://github.com/kyleneideck/BackgroundMusic/releases/download/v0.4.0/BackgroundMusic-0.4.0.pkg.asc),
> [key (0595DF814E41A6F69334C5E2CAA8D9B8E39EC18C)](https://bearisdriving.com/kyle-neideck.gpg)</sub>
### Option 2
@@ -90,17 +88,26 @@ Install using [Homebrew](https://brew.sh/) by running the following command in *
brew install --cask background-music
```
If you want the snapshot version, run:
If you want the latest snapshot version, run:
```bash
brew tap homebrew/cask-versions
brew install --cask background-music-pre
```
# Run / Configure
Just run `Applications > Background Music.app`! **Background Music** sets itself as your default output device under
`System Settings > Sound` when it starts up (and sets it back on Quit).
### Launch at Startup (Optional)
Add **Background Music** to `System Settings > General > Login Items`.
# Installing from Source Code
**Background Music** usually takes less than a minute to build. You need [Xcode](https://developer.apple.com/xcode/download/) version
8 or higher.
**Background Music** usually takes less than a minute to build. You need [Xcode](https://developer.apple.com/xcode/download/) version
10 or higher.
### Option 1
@@ -147,12 +154,12 @@ To manually uninstall, see [MANUAL_UNINSTALL.md](https://github.com/kyleneideck/
# Troubleshooting
If Background Music crashes and your audio stops working, open `System Preferences > Sound` and change your
If Background Music crashes and your audio stops working, open `System Settings > Sound` and change your
system's default output device to something other than the **Background Music device**. If it already is, then
change the default device and then change it back again.
Make sure you allow "microphone access" when you first run Background Music. If you denied it, go to
`System Preferences > Security & Privacy > Privacy > Microphone`, find Background Music in the list
`System Settings > Security & Privacy > Privacy > Microphone`, find Background Music in the list
and check the box next to it. Background Music doesn't actually listen to your microphone. It needs
the permission because it gets your system audio from its virtual input device, which macOS counts
as a microphone. (We're working on it in [#177](/../../issues/177).)
@@ -169,16 +176,16 @@ meeting volume.
- **Only 2-channel (stereo) audio devices are currently supported for output.**
- **VLC pauses iTunes or Spotify when playing, and stops Background Music from unpausing your music afterward.**
- **VLC pauses iTunes or Spotify when playing, and stops Background Music from unpausing your music afterward.**
- Under VLC's preferences, select **Show All**. Navigate to **Interface > Main interfaces > macosx** and change *Control external music players* to either *Do nothing* or *Pause and resume iTunes/Spotify*.
- Under VLC's preferences, select **Show All**. Navigate to **Interface > Main interfaces > macosx** and change *Control external music players* to either *Do nothing* or *Pause and resume iTunes/Spotify*.
- **Skype pauses iTunes during calls.**
- **Skype pauses iTunes during calls.**
- To disable this, uncheck *Pause iTunes during calls* on the **General** tab of **Skype**'s preferences.
- **Plugging in or unplugging headphones when Background Music isn't running causes silence in the system audio.**
- Navigate to **System Preferences > Sound**. Click the **Output** tab and change your default output device to something other than the **Background Music** device. Alternatively, press **Option + Click** on the sound icon within the menu bar to select a different output device. This happens when macOS remembers that the **Background Music** device was your default audio device the last time you used (or didn't use) headphones.
- **Plugging in or unplugging headphones when Background Music isn't running causes silence in the system audio.**
- Navigate to **System Settings > Sound**. Click the **Output** tab and change your default output device to something other than the **Background Music** device. Alternatively, press **Option + Click** on the sound icon within the menu bar to select a different output device. This happens when macOS remembers that the **Background Music** device was your default audio device the last time you used (or didn't use) headphones.
- **[A Chrome bug](https://bugs.chromium.org/p/chromium/issues/detail?id=557620) stops Chrome from switching to the Background Music device after you open Background Music.**
- Chrome's audio will still play, but **Background Music** won't be aware of it.
@@ -220,7 +227,7 @@ Issues](https://github.com/kyleneideck/BackgroundMusic/issues).
## License
Copyright © 2016-2021 [Background Music contributors](https://github.com/kyleneideck/BackgroundMusic/graphs/contributors).
Copyright © 2016-2024 [Background Music contributors](https://github.com/kyleneideck/BackgroundMusic/graphs/contributors).
Licensed under [GPLv2](https://www.gnu.org/licenses/gpl-2.0.html), or any later version.
**Background Music** includes code from:
+2 -1
View File
@@ -17,7 +17,7 @@
// BGM_Types.h
// SharedSource
//
// Copyright © 2016, 2017, 2019 Kyle Neideck
// Copyright © 2016, 2017, 2019, 2024 Kyle Neideck
//
#ifndef SharedSource__BGM_Types
@@ -36,6 +36,7 @@
static const char* const kBGMProjectURL = "https://github.com/kyleneideck/BackgroundMusic";
static const char* const kBGMIssueTrackerURL = "https://github.com/kyleneideck/BackgroundMusic/issues";
static const char* const kBGMContributorsURL = "https://github.com/kyleneideck/BackgroundMusic/graphs/contributors";
#pragma mark IDs
+12 -2
View File
@@ -19,7 +19,7 @@
#
# build_and_install.sh
#
# Copyright © 2016-2022 Kyle Neideck
# Copyright © 2016-2022, 2024 Kyle Neideck
# Copyright © 2016 Nick Jacques
#
# Builds and installs BGMApp, BGMDriver and BGMXPCHelper. Requires xcodebuild and Xcode.
@@ -136,7 +136,7 @@ BUILD_FAILED_ERROR_MSG="A build command failed. Probably a compilation error."
BGMAPP_FAILED_TO_START_ERROR_MSG="Background Music (${APP_PATH}/${APP_DIR}) didn't seem to start \
up. It might just be taking a while.
If it didn't install correctly, you'll need to open the Sound control panel in System Preferences \
If it didn't install correctly, you'll need to open the Sound control panel in System Settings \
and change your output device at least once. Your sound probably won't work until you do. (Or you \
restart your computer.)
@@ -641,6 +641,16 @@ if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
SUDO="sudo"
ACTIONING="Installing"
DSTROOT_ARG="DSTROOT=/"
# Work around an Xcode (15.2) bug where xcodebuild incorrectly detects a dependency cycle if
# DSTROOT is set to /.
for v in /Volumes/*; do
if [[ "$(realpath "$v")" == "/" ]]; then
DSTROOT_ARG="DSTROOT=$v"
echo "Set DSTROOT_ARG to ${DSTROOT_ARG} to work around an Xcode bug." >> ${LOG_FILE}
break
fi
done
echo "DSTROOT_ARG: ${DSTROOT_ARG}." >> ${LOG_FILE}
elif [[ "${XCODEBUILD_ACTION}" == "archive" ]]; then
SUDO=""
ACTIONING="Building and archiving"
Executable → Regular
+9 -8
View File
@@ -19,7 +19,7 @@
#
# postinstall
#
# Copyright © 2017-2022 Kyle Neideck
# Copyright © 2017-2022, 2024 Kyle Neideck
#
# Make sure we use the built-in versions of programs, for consistency. Probably not necessary
@@ -53,13 +53,14 @@ bash "post_install.sh" "$xpc_helper_install_path" "BGMXPCHelper.xpc/Contents/Mac
# some of these commands don't work with older versions of launchctl, so I figure there's no
# harm in trying a bunch of different ways (which should all work).
(sudo launchctl kickstart -k system/com.apple.audio.coreaudiod &>/dev/null || \
launchctl kill SIGTERM system/com.apple.audio.coreaudiod &>/dev/null || \
launchctl kill TERM system/com.apple.audio.coreaudiod &>/dev/null || \
launchctl kill 15 system/com.apple.audio.coreaudiod &>/dev/null || \
launchctl kill -15 system/com.apple.audio.coreaudiod &>/dev/null || \
(launchctl unload "$coreaudiod_plist" &>/dev/null && \
launchctl load "$coreaudiod_plist" &>/dev/null) || \
killall coreaudiod &>/dev/null) && \
sudo launchctl kill SIGTERM system/com.apple.audio.coreaudiod &>/dev/null || \
sudo launchctl kill TERM system/com.apple.audio.coreaudiod &>/dev/null || \
sudo launchctl kill 15 system/com.apple.audio.coreaudiod &>/dev/null || \
sudo launchctl kill -15 system/com.apple.audio.coreaudiod &>/dev/null || \
sudo killall coreaudiod &>/dev/null || \
(sudo launchctl unload "$coreaudiod_plist" &>/dev/null && \
sudo launchctl load "$coreaudiod_plist" &>/dev/null)
) && \
sleep 2
# Wait until coreaudiod has restarted and BGMDevice is ready to use.
+1 -1
View File
@@ -63,7 +63,7 @@ if [ "$user_prompt" == "y" ] || [ "$user_prompt" == "Y" ]; then
# Invalidate sudo ticket
sudo -k
# Open System Preferences and go to Sound > Output.
# Open System Settings and go to Sound > Output.
osascript -e 'tell application id "com.apple.systempreferences"
activate
reveal anchor "output" of pane id "com.apple.preference.sound"