mirror of
https://github.com/kyleneideck/BackgroundMusic
synced 2024-11-22 20:23:04 +00:00
Add packaging script and (possibly) support for OS X 10.9.
This commit is contained in:
parent
8d1adf25bb
commit
5e4556b49d
17 changed files with 656 additions and 187 deletions
|
@ -62,6 +62,15 @@ script:
|
||||||
- if ls -la "/usr/local/libexec/BGMXPCHelper.xpc"; then false; fi
|
- if ls -la "/usr/local/libexec/BGMXPCHelper.xpc"; then false; fi
|
||||||
- if ls -la "/Library/Application Support/Background Music/BGMXPCHelper.xpc"; then false; fi
|
- if ls -la "/Library/Application Support/Background Music/BGMXPCHelper.xpc"; then false; fi
|
||||||
- if ls -la "/Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist"; then false; fi
|
- if ls -la "/Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist"; then false; fi
|
||||||
|
# Build the .pkg installer.
|
||||||
|
- ./package.sh
|
||||||
|
# Install the .pkg.
|
||||||
|
- sudo installer -pkg Background-Music-*/BackgroundMusic-*.pkg -target / -verbose -dumplog
|
||||||
|
# Check the BGM dirs and files were installed again.
|
||||||
|
- ls -la "/Applications/Background Music.app"
|
||||||
|
- ls -la "/Library/Audio/Plug-Ins/HAL/Background Music Device.driver"
|
||||||
|
- ls -la "/usr/local/libexec/BGMXPCHelper.xpc" || ls -la "/Library/Application Support/Background Music/BGMXPCHelper.xpc"
|
||||||
|
- ls -la "/Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist"
|
||||||
# Post on IRC when Travis builds finish.
|
# Post on IRC when Travis builds finish.
|
||||||
notifications:
|
notifications:
|
||||||
irc: "irc.freenode.org#backgroundmusic"
|
irc: "irc.freenode.org#backgroundmusic"
|
||||||
|
|
|
@ -36,6 +36,9 @@
|
||||||
1C4699471BD5C0E400F78043 /* BGMiTunes.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C4699461BD5C0E400F78043 /* BGMiTunes.m */; };
|
1C4699471BD5C0E400F78043 /* BGMiTunes.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C4699461BD5C0E400F78043 /* BGMiTunes.m */; };
|
||||||
1C46994E1BD7694C00F78043 /* BGMDeviceControlSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */; };
|
1C46994E1BD7694C00F78043 /* BGMDeviceControlSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */; };
|
||||||
1C50FF631EC9F4490031A6EA /* BGMAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CF5423A1EAAEE4300445AD8 /* BGMAudioDevice.cpp */; };
|
1C50FF631EC9F4490031A6EA /* BGMAudioDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CF5423A1EAAEE4300445AD8 /* BGMAudioDevice.cpp */; };
|
||||||
|
1C533C7A1EED28B700270802 /* uninstall.sh in Resources */ = {isa = PBXBuildFile; fileRef = 1C533C791EED28B700270802 /* uninstall.sh */; };
|
||||||
|
1C533C7B1EED2F6200270802 /* safe_install_dir.sh in Resources */ = {isa = PBXBuildFile; fileRef = 276972901CB16008007A2F7C /* safe_install_dir.sh */; };
|
||||||
|
1C533C7C1EED2F8A00270802 /* com.bearisdriving.BGM.XPCHelper.plist.template in Resources */ = {isa = PBXBuildFile; fileRef = 2769728D1CAFCEFD007A2F7C /* com.bearisdriving.BGM.XPCHelper.plist.template */; };
|
||||||
1CB8B33D1BBA75EF000E2DD1 /* BGMAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CB8B33C1BBA75EF000E2DD1 /* BGMAppDelegate.mm */; };
|
1CB8B33D1BBA75EF000E2DD1 /* BGMAppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CB8B33C1BBA75EF000E2DD1 /* BGMAppDelegate.mm */; };
|
||||||
1CB8B33F1BBA75EF000E2DD1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CB8B33E1BBA75EF000E2DD1 /* main.m */; };
|
1CB8B33F1BBA75EF000E2DD1 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1CB8B33E1BBA75EF000E2DD1 /* main.m */; };
|
||||||
1CC1DF811BE5068A00FB8FE4 /* CACFArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CC1DF7D1BE5068A00FB8FE4 /* CACFArray.cpp */; };
|
1CC1DF811BE5068A00FB8FE4 /* CACFArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1CC1DF7D1BE5068A00FB8FE4 /* CACFArray.cpp */; };
|
||||||
|
@ -127,8 +130,6 @@
|
||||||
2743CA221D86DE960089613B /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C1963021BCAC160008A4DF7 /* CoreAudio.framework */; };
|
2743CA221D86DE960089613B /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1C1963021BCAC160008A4DF7 /* CoreAudio.framework */; };
|
||||||
2743CA231D86DEA70089613B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD1FD2F1BDDEAF2004F7E1B /* AudioToolbox.framework */; };
|
2743CA231D86DEA70089613B /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1CD1FD2F1BDDEAF2004F7E1B /* AudioToolbox.framework */; };
|
||||||
274827951E11052500B31D8D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1CB8B3421BBA75EF000E2DD1 /* MainMenu.xib */; };
|
274827951E11052500B31D8D /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1CB8B3421BBA75EF000E2DD1 /* MainMenu.xib */; };
|
||||||
2769728F1CAFF22C007A2F7C /* com.bearisdriving.BGM.XPCHelper.plist.template in Resources */ = {isa = PBXBuildFile; fileRef = 2769728D1CAFCEFD007A2F7C /* com.bearisdriving.BGM.XPCHelper.plist.template */; };
|
|
||||||
276972921CB1603E007A2F7C /* safe_install_dir.sh in Resources */ = {isa = PBXBuildFile; fileRef = 276972901CB16008007A2F7C /* safe_install_dir.sh */; };
|
|
||||||
277170161CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 277170151CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m */; };
|
277170161CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 277170151CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m */; };
|
||||||
2795973B1C982E4E00A002FB /* BGMXPCListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2795973A1C982E4E00A002FB /* BGMXPCListener.mm */; };
|
2795973B1C982E4E00A002FB /* BGMXPCListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2795973A1C982E4E00A002FB /* BGMXPCListener.mm */; };
|
||||||
279F48771DD6D73A00768A85 /* BGMHermes.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F48761DD6D73900768A85 /* BGMHermes.m */; };
|
279F48771DD6D73A00768A85 /* BGMHermes.m in Sources */ = {isa = PBXBuildFile; fileRef = 279F48761DD6D73900768A85 /* BGMHermes.m */; };
|
||||||
|
@ -214,6 +215,7 @@
|
||||||
1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BGMDeviceControlSync.cpp; sourceTree = "<group>"; };
|
1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BGMDeviceControlSync.cpp; sourceTree = "<group>"; };
|
||||||
1C46994D1BD7694C00F78043 /* BGMDeviceControlSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMDeviceControlSync.h; sourceTree = "<group>"; };
|
1C46994D1BD7694C00F78043 /* BGMDeviceControlSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMDeviceControlSync.h; sourceTree = "<group>"; };
|
||||||
1C50FF641EC9F4500031A6EA /* libPublicUtility.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPublicUtility.a; path = "../../../Library/Developer/Xcode/DerivedData/BGM-cgeucfvbrkmtbnhewbqjwrqspirp/Build/Products/Debug/libPublicUtility.a"; sourceTree = "<group>"; };
|
1C50FF641EC9F4500031A6EA /* libPublicUtility.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libPublicUtility.a; path = "../../../Library/Developer/Xcode/DerivedData/BGM-cgeucfvbrkmtbnhewbqjwrqspirp/Build/Products/Debug/libPublicUtility.a"; sourceTree = "<group>"; };
|
||||||
|
1C533C791EED28B700270802 /* uninstall.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; name = uninstall.sh; path = ../../uninstall.sh; sourceTree = "<group>"; };
|
||||||
1C8034C21BDAFD5700668E00 /* CAPThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAPThread.cpp; path = PublicUtility/CAPThread.cpp; sourceTree = "<group>"; };
|
1C8034C21BDAFD5700668E00 /* CAPThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CAPThread.cpp; path = PublicUtility/CAPThread.cpp; sourceTree = "<group>"; };
|
||||||
1C8034C31BDAFD5700668E00 /* CAPThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CAPThread.h; path = PublicUtility/CAPThread.h; sourceTree = "<group>"; };
|
1C8034C31BDAFD5700668E00 /* CAPThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CAPThread.h; path = PublicUtility/CAPThread.h; sourceTree = "<group>"; };
|
||||||
1CB8B3361BBA75EF000E2DD1 /* Background Music.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Background Music.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
1CB8B3361BBA75EF000E2DD1 /* Background Music.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Background Music.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -518,6 +520,7 @@
|
||||||
1CED61681C3081C2002CAFCF /* LICENSE */,
|
1CED61681C3081C2002CAFCF /* LICENSE */,
|
||||||
1CC1DF951BE8607700FB8FE4 /* Images.xcassets */,
|
1CC1DF951BE8607700FB8FE4 /* Images.xcassets */,
|
||||||
1CB8B33A1BBA75EF000E2DD1 /* Info.plist */,
|
1CB8B33A1BBA75EF000E2DD1 /* Info.plist */,
|
||||||
|
1C533C791EED28B700270802 /* uninstall.sh */,
|
||||||
1CB8B33E1BBA75EF000E2DD1 /* main.m */,
|
1CB8B33E1BBA75EF000E2DD1 /* main.m */,
|
||||||
);
|
);
|
||||||
name = "Supporting Files";
|
name = "Supporting Files";
|
||||||
|
@ -795,6 +798,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
274827951E11052500B31D8D /* MainMenu.xib in Resources */,
|
274827951E11052500B31D8D /* MainMenu.xib in Resources */,
|
||||||
|
1C533C7A1EED28B700270802 /* uninstall.sh in Resources */,
|
||||||
1CED61691C3081C2002CAFCF /* LICENSE in Resources */,
|
1CED61691C3081C2002CAFCF /* LICENSE in Resources */,
|
||||||
1C2FC3041EB4D6E700A76592 /* BGMApp.sdef in Resources */,
|
1C2FC3041EB4D6E700A76592 /* BGMApp.sdef in Resources */,
|
||||||
1CC1DF961BE8607700FB8FE4 /* Images.xcassets in Resources */,
|
1CC1DF961BE8607700FB8FE4 /* Images.xcassets in Resources */,
|
||||||
|
@ -812,8 +816,8 @@
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
276972921CB1603E007A2F7C /* safe_install_dir.sh in Resources */,
|
1C533C7C1EED2F8A00270802 /* com.bearisdriving.BGM.XPCHelper.plist.template in Resources */,
|
||||||
2769728F1CAFF22C007A2F7C /* com.bearisdriving.BGM.XPCHelper.plist.template in Resources */,
|
1C533C7B1EED2F6200270802 /* safe_install_dir.sh in Resources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -1114,7 +1118,7 @@
|
||||||
GCC_WARN_UNUSED_LABEL = YES;
|
GCC_WARN_UNUSED_LABEL = YES;
|
||||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||||
|
@ -1210,7 +1214,7 @@
|
||||||
GCC_WARN_UNUSED_LABEL = YES;
|
GCC_WARN_UNUSED_LABEL = YES;
|
||||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||||
|
@ -1284,7 +1288,7 @@
|
||||||
GCC_WARN_UNUSED_LABEL = YES;
|
GCC_WARN_UNUSED_LABEL = YES;
|
||||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
|
|
|
@ -64,22 +64,58 @@ static float const kStatusBarIconPadding = 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
haveShownXPCHelperErrorMessage = NO;
|
haveShownXPCHelperErrorMessage = NO;
|
||||||
|
|
||||||
// Set up the status bar item
|
[self initStatusBarItem];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set up the status bar item. (The thing you click to show BGMApp's UI.)
|
||||||
|
- (void) initStatusBarItem {
|
||||||
statusBarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
statusBarItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSSquareStatusItemLength];
|
||||||
|
|
||||||
// Set the icon
|
// Set the icon
|
||||||
NSImage* icon = [NSImage imageNamed:@"FermataIcon"];
|
NSImage* icon = [NSImage imageNamed:@"FermataIcon"];
|
||||||
|
|
||||||
|
// NSStatusItem doesn't have the "button" property on OS X 10.9.
|
||||||
|
BOOL buttonAvailable = (floor(NSAppKitVersionNumber) >= NSAppKitVersionNumber10_10);
|
||||||
|
|
||||||
if (icon != nil) {
|
if (icon != nil) {
|
||||||
CGFloat lengthMinusPadding = [[statusBarItem button] frame].size.height * (1 - kStatusBarIconPadding);
|
NSRect statusBarItemFrame;
|
||||||
|
|
||||||
|
if (buttonAvailable) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
statusBarItemFrame = statusBarItem.button.frame;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
} else {
|
||||||
|
// OS X 10.9 fallback. I haven't tested this (or anything else on 10.9).
|
||||||
|
statusBarItemFrame = statusBarItem.view.frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat lengthMinusPadding = statusBarItemFrame.size.height * (1 - kStatusBarIconPadding);
|
||||||
[icon setSize:NSMakeSize(lengthMinusPadding, lengthMinusPadding)];
|
[icon setSize:NSMakeSize(lengthMinusPadding, lengthMinusPadding)];
|
||||||
|
|
||||||
// Make the icon a "template image" so it gets drawn colour-inverted when it's highlighted or the status
|
// Make the icon a "template image" so it gets drawn colour-inverted when it's highlighted or the status
|
||||||
// bar's in dark mode
|
// bar's in dark mode
|
||||||
[icon setTemplate:YES];
|
[icon setTemplate:YES];
|
||||||
statusBarItem.button.image = icon;
|
|
||||||
|
if (buttonAvailable) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
statusBarItem.button.image = icon;
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
} else {
|
||||||
|
statusBarItem.image = icon;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// If our icon is missing for some reason, fallback to a fermata character (1D110)
|
// If our icon is missing for some reason, fallback to a fermata character (1D110)
|
||||||
statusBarItem.button.title = @"𝄐";
|
if (buttonAvailable) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
statusBarItem.button.title = @"𝄐";
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
} else {
|
||||||
|
statusBarItem.title = @"𝄐";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the main menu
|
// Set the main menu
|
||||||
|
|
|
@ -124,9 +124,12 @@ static CGFloat const kAppVolumeViewInitialHeight = 20;
|
||||||
|
|
||||||
// NSMenuItem didn't implement NSAccessibility before OS X SDK 10.12.
|
// NSMenuItem didn't implement NSAccessibility before OS X SDK 10.12.
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 // MAC_OS_X_VERSION_10_12
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101200 // MAC_OS_X_VERSION_10_12
|
||||||
if ([self respondsToSelector:@selector(accessibilityTitle)]) {
|
if ([appVolItem respondsToSelector:@selector(setAccessibilityTitle:)]) {
|
||||||
// TODO: This doesn't show up in Accessibility Inspector for me. Not sure why.
|
// TODO: This doesn't show up in Accessibility Inspector for me. Not sure why.
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
appVolItem.accessibilityTitle = [NSString stringWithFormat:@"%@", [app localizedName]];
|
appVolItem.accessibilityTitle = [NSString stringWithFormat:@"%@", [app localizedName]];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -365,7 +368,12 @@ static CGFloat const kAppVolumeViewInitialHeight = 20;
|
||||||
// when they have non-default values.
|
// when they have non-default values.
|
||||||
[ctx showHideExtraControls:self];
|
[ctx showHideExtraControls:self];
|
||||||
|
|
||||||
self.accessibilityTitle = @"More options";
|
if ([self respondsToSelector:@selector(setAccessibilityTitle:)]) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
self.accessibilityTitle = @"More options";
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -391,7 +399,12 @@ static CGFloat const kAppVolumeViewInitialHeight = 20;
|
||||||
self.maxValue = kAppRelativeVolumeMaxRawValue;
|
self.maxValue = kAppRelativeVolumeMaxRawValue;
|
||||||
self.minValue = kAppRelativeVolumeMinRawValue;
|
self.minValue = kAppRelativeVolumeMinRawValue;
|
||||||
|
|
||||||
self.accessibilityTitle = [NSString stringWithFormat:@"Volume for %@", [app localizedName]];
|
if ([self respondsToSelector:@selector(setAccessibilityTitle:)]) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
self.accessibilityTitle = [NSString stringWithFormat:@"Volume for %@", [app localizedName]];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We have to handle snapping for volume sliders ourselves because adding a tick mark (snap point) in Interface Builder
|
// We have to handle snapping for volume sliders ourselves because adding a tick mark (snap point) in Interface Builder
|
||||||
|
@ -442,7 +455,12 @@ static CGFloat const kAppVolumeViewInitialHeight = 20;
|
||||||
self.minValue = kAppPanLeftRawValue;
|
self.minValue = kAppPanLeftRawValue;
|
||||||
self.maxValue = kAppPanRightRawValue;
|
self.maxValue = kAppPanRightRawValue;
|
||||||
|
|
||||||
self.accessibilityTitle = [NSString stringWithFormat:@"Pan for %@", [app localizedName]];
|
if ([self respondsToSelector:@selector(setAccessibilityTitle:)]) {
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
self.accessibilityTitle = [NSString stringWithFormat:@"Pan for %@", [app localizedName]];
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setPanPosition:(NSNumber *)panPosition {
|
- (void) setPanPosition:(NSNumber *)panPosition {
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
// BGMAutoPauseMusic.m
|
// BGMAutoPauseMusic.m
|
||||||
// BGMApp
|
// BGMApp
|
||||||
//
|
//
|
||||||
// Copyright © 2016 Kyle Neideck
|
// Copyright © 2016, 2017 Kyle Neideck
|
||||||
//
|
//
|
||||||
|
|
||||||
// Self Include
|
// Self Include
|
||||||
|
@ -84,7 +84,18 @@ static Float32 const kUnpauseDelayWeightingFactor = 0.25f;
|
||||||
enabled = NO;
|
enabled = NO;
|
||||||
wePaused = NO;
|
wePaused = NO;
|
||||||
|
|
||||||
dispatch_queue_attr_t attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
|
dispatch_queue_attr_t attr;
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
if (&dispatch_queue_attr_make_with_qos_class) {
|
||||||
|
attr = dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
|
||||||
|
} else {
|
||||||
|
// OS X 10.9 fallback
|
||||||
|
attr = DISPATCH_QUEUE_SERIAL;
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
listenerQueue = dispatch_queue_create("com.bearisdriving.BGM.AutoPauseMusic.Listener", attr);
|
listenerQueue = dispatch_queue_create("com.bearisdriving.BGM.AutoPauseMusic.Listener", attr);
|
||||||
pauseUnpauseMusicQueue = dispatch_queue_create("com.bearisdriving.BGM.AutoPauseMusic.PauseUnpauseMusic", attr);
|
pauseUnpauseMusicQueue = dispatch_queue_create("com.bearisdriving.BGM.AutoPauseMusic.PauseUnpauseMusic", attr);
|
||||||
|
|
||||||
|
|
|
@ -50,12 +50,25 @@ BGMDeviceControlsList::BGMDeviceControlsList(AudioObjectID inBGMDevice,
|
||||||
BGMAssert((mBGMDevice.GetObjectID() == mAudioSystem.GetAudioDeviceForUID(CFSTR(kBGMDeviceUID)) ||
|
BGMAssert((mBGMDevice.GetObjectID() == mAudioSystem.GetAudioDeviceForUID(CFSTR(kBGMDeviceUID)) ||
|
||||||
mBGMDevice.GetObjectID() == kAudioObjectUnknown),
|
mBGMDevice.GetObjectID() == kAudioObjectUnknown),
|
||||||
"BGMDeviceControlsList::BGMDeviceControlsList: Given device is not BGMDevice");
|
"BGMDeviceControlsList::BGMDeviceControlsList: Given device is not BGMDevice");
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
mCanToggleDeviceOnSystem = (&dispatch_block_wait &&
|
||||||
|
&dispatch_block_cancel &&
|
||||||
|
&dispatch_block_testcancel &&
|
||||||
|
&dispatch_queue_attr_make_with_qos_class);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
}
|
}
|
||||||
|
|
||||||
BGMDeviceControlsList::~BGMDeviceControlsList()
|
BGMDeviceControlsList::~BGMDeviceControlsList()
|
||||||
{
|
{
|
||||||
CAMutex::Locker locker(mMutex);
|
CAMutex::Locker locker(mMutex);
|
||||||
|
|
||||||
|
if(!mDeviceTogglingInitialised)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
BGMLogAndSwallowExceptions("BGMDeviceControlsList::~BGMDeviceControlsList", [&] {
|
BGMLogAndSwallowExceptions("BGMDeviceControlsList::~BGMDeviceControlsList", [&] {
|
||||||
mAudioSystem.RemovePropertyListenerBlock(CAPropertyAddress(kAudioHardwarePropertyDevices),
|
mAudioSystem.RemovePropertyListenerBlock(CAPropertyAddress(kAudioHardwarePropertyDevices),
|
||||||
mListenerQueue,
|
mListenerQueue,
|
||||||
|
@ -75,7 +88,10 @@ BGMDeviceControlsList::~BGMDeviceControlsList()
|
||||||
// Note that if mDisableNullDeviceBlock is currently running this will return after it
|
// Note that if mDisableNullDeviceBlock is currently running this will return after it
|
||||||
// finishes and if it's already run this will return immediately. So we don't have to
|
// finishes and if it's already run this will return immediately. So we don't have to
|
||||||
// worry about ending up waiting for mDisableNullDeviceBlock when it isn't queued.
|
// worry about ending up waiting for mDisableNullDeviceBlock when it isn't queued.
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
bool timedOut = dispatch_block_wait(disableNullDeviceBlock, kDisableNullDeviceTimeout);
|
bool timedOut = dispatch_block_wait(disableNullDeviceBlock, kDisableNullDeviceTimeout);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
if(timedOut)
|
if(timedOut)
|
||||||
{
|
{
|
||||||
|
@ -111,10 +127,9 @@ bool BGMDeviceControlsList::MatchControlsListOf(AudioObjectID inDeviceID)
|
||||||
{
|
{
|
||||||
CAMutex::Locker locker(mMutex);
|
CAMutex::Locker locker(mMutex);
|
||||||
|
|
||||||
LazyInit();
|
if(mBGMDevice.GetObjectID() != mAudioSystem.GetAudioDeviceForUID(CFSTR(kBGMDeviceUID)))
|
||||||
|
|
||||||
if(mBGMDevice == kAudioObjectUnknown)
|
|
||||||
{
|
{
|
||||||
|
LogWarning("BGMDeviceControlsList::MatchControlsListOf: BGMDevice ID not set");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,13 +243,13 @@ void BGMDeviceControlsList::PropagateControlListChange()
|
||||||
{
|
{
|
||||||
CAMutex::Locker locker(mMutex);
|
CAMutex::Locker locker(mMutex);
|
||||||
|
|
||||||
LazyInit();
|
if((mBGMDevice == kAudioObjectUnknown) || !mCanToggleDeviceOnSystem)
|
||||||
|
|
||||||
if(mBGMDevice == kAudioObjectUnknown)
|
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
InitDeviceToggling();
|
||||||
|
|
||||||
// Leave the default device alone if the user has changed it since launching BGMApp.
|
// Leave the default device alone if the user has changed it since launching BGMApp.
|
||||||
bool bgmDeviceIsDefault = true;
|
bool bgmDeviceIsDefault = true;
|
||||||
|
|
||||||
|
@ -267,17 +282,18 @@ void BGMDeviceControlsList::PropagateControlListChange()
|
||||||
|
|
||||||
#pragma mark Implementation
|
#pragma mark Implementation
|
||||||
|
|
||||||
void BGMDeviceControlsList::LazyInit()
|
void BGMDeviceControlsList::InitDeviceToggling()
|
||||||
{
|
{
|
||||||
CAMutex::Locker locker(mMutex);
|
CAMutex::Locker locker(mMutex);
|
||||||
|
|
||||||
if(mInitialised)
|
if(mDeviceTogglingInitialised || !mCanToggleDeviceOnSystem)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
BGMAssert(mBGMDevice.GetObjectID() == mAudioSystem.GetAudioDeviceForUID(CFSTR(kBGMDeviceUID)),
|
BGMAssert(mBGMDevice.GetObjectID() == mAudioSystem.GetAudioDeviceForUID(CFSTR(kBGMDeviceUID)),
|
||||||
"BGMDeviceControlsList::LazyInit: mBGMDevice device is not set to BGMDevice's ID");
|
"BGMDeviceControlsList::InitDeviceToggling: mBGMDevice device is not set to "
|
||||||
|
"BGMDevice's ID");
|
||||||
|
|
||||||
mDeviceToggleBlock = CreateDeviceToggleBlock();
|
mDeviceToggleBlock = CreateDeviceToggleBlock();
|
||||||
mDeviceToggleBackBlock = CreateDeviceToggleBackBlock();
|
mDeviceToggleBackBlock = CreateDeviceToggleBackBlock();
|
||||||
|
@ -285,8 +301,11 @@ void BGMDeviceControlsList::LazyInit()
|
||||||
|
|
||||||
// Register a listener to find out when the Null Device becomes available/unavailable. See
|
// Register a listener to find out when the Null Device becomes available/unavailable. See
|
||||||
// ToggleDefaultDevice.
|
// ToggleDefaultDevice.
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
dispatch_queue_attr_t attr =
|
dispatch_queue_attr_t attr =
|
||||||
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
|
dispatch_queue_attr_make_with_qos_class(DISPATCH_QUEUE_SERIAL, QOS_CLASS_DEFAULT, 0);
|
||||||
|
#pragma clang diagnostic pop
|
||||||
mListenerQueue = dispatch_queue_create("com.bearisdriving.BGM.BGMDeviceControlsList", attr);
|
mListenerQueue = dispatch_queue_create("com.bearisdriving.BGM.BGMDeviceControlsList", attr);
|
||||||
|
|
||||||
mListenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress* inAddresses) {
|
mListenerBlock = ^(UInt32 inNumberAddresses, const AudioObjectPropertyAddress* inAddresses) {
|
||||||
|
@ -302,35 +321,35 @@ void BGMDeviceControlsList::LazyInit()
|
||||||
switch(inAddresses[i].mSelector)
|
switch(inAddresses[i].mSelector)
|
||||||
{
|
{
|
||||||
case kAudioHardwarePropertyDevices:
|
case kAudioHardwarePropertyDevices:
|
||||||
{
|
{
|
||||||
CAMutex::Locker innerLocker(mMutex);
|
CAMutex::Locker innerLocker(mMutex);
|
||||||
|
|
||||||
DebugMsg("BGMDeviceControlsList::LazyInit: Got "
|
DebugMsg("BGMDeviceControlsList::InitDeviceToggling: Got "
|
||||||
"kAudioHardwarePropertyDevices");
|
"kAudioHardwarePropertyDevices");
|
||||||
|
|
||||||
// Cancel the previous block in case it hasn't run yet.
|
// Cancel the previous block in case it hasn't run yet.
|
||||||
DestroyBlock(mDeviceToggleBlock);
|
DestroyBlock(mDeviceToggleBlock);
|
||||||
|
|
||||||
mDeviceToggleBlock = CreateDeviceToggleBlock();
|
mDeviceToggleBlock = CreateDeviceToggleBlock();
|
||||||
|
|
||||||
// Changing the default device too quickly after enabling the Null Device
|
// Changing the default device too quickly after enabling the Null Device
|
||||||
// seems to cause problems with some programs. Not sure why.
|
// seems to cause problems with some programs. Not sure why.
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kToggleDeviceInitialDelay),
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kToggleDeviceInitialDelay),
|
||||||
dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0),
|
||||||
mDeviceToggleBlock);
|
mDeviceToggleBlock);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
BGMLogAndSwallowExceptions("BGMDeviceControlsList::LazyInit", [&] {
|
BGMLogAndSwallowExceptions("BGMDeviceControlsList::InitDeviceToggling", [&] {
|
||||||
mAudioSystem.AddPropertyListenerBlock(CAPropertyAddress(kAudioHardwarePropertyDevices),
|
mAudioSystem.AddPropertyListenerBlock(CAPropertyAddress(kAudioHardwarePropertyDevices),
|
||||||
mListenerQueue,
|
mListenerQueue,
|
||||||
mListenerBlock);
|
mListenerBlock);
|
||||||
});
|
});
|
||||||
|
|
||||||
mInitialised = true;
|
mDeviceTogglingInitialised = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BGMDeviceControlsList::ToggleDefaultDevice()
|
void BGMDeviceControlsList::ToggleDefaultDevice()
|
||||||
|
@ -386,6 +405,9 @@ void BGMDeviceControlsList::SetNullDeviceEnabled(bool inEnabled)
|
||||||
(inEnabled ? kCFBooleanTrue : kCFBooleanFalse));
|
(inEnabled ? kCFBooleanTrue : kCFBooleanFalse));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wpartial-availability"
|
||||||
|
|
||||||
dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBlock()
|
dispatch_block_t BGMDeviceControlsList::CreateDeviceToggleBlock()
|
||||||
{
|
{
|
||||||
return dispatch_block_create((dispatch_block_flags_t)0, ^{
|
return dispatch_block_create((dispatch_block_flags_t)0, ^{
|
||||||
|
@ -479,5 +501,7 @@ void BGMDeviceControlsList::DestroyBlock(dispatch_block_t __nullable & block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#pragma clang diagnostic pop /* -Wpartial-availability */
|
||||||
|
|
||||||
#pragma clang assume_nonnull end
|
#pragma clang assume_nonnull end
|
||||||
|
|
||||||
|
|
|
@ -88,8 +88,8 @@ public:
|
||||||
#pragma mark Implementation
|
#pragma mark Implementation
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/* This class is lazily initialised, mainly as a convenience for the unit tests. */
|
/*! Lazily initialises the fields used to toggle the default device. */
|
||||||
void LazyInit();
|
void InitDeviceToggling();
|
||||||
/*! Changes the OS X default audio device to the Null Device and then back to BGMDevice. */
|
/*! Changes the OS X default audio device to the Null Device and then back to BGMDevice. */
|
||||||
void ToggleDefaultDevice();
|
void ToggleDefaultDevice();
|
||||||
/*!
|
/*!
|
||||||
|
@ -109,7 +109,9 @@ private:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CAMutex mMutex { "Device Controls List" };
|
CAMutex mMutex { "Device Controls List" };
|
||||||
bool mInitialised = false;
|
bool mDeviceTogglingInitialised = false;
|
||||||
|
// OS X 10.9 doesn't have the functions we use for PropagateControlListChange.
|
||||||
|
bool mCanToggleDeviceOnSystem;
|
||||||
|
|
||||||
BGMAudioDevice mBGMDevice;
|
BGMAudioDevice mBGMDevice;
|
||||||
CAHALAudioSystemObject mAudioSystem; // Not guarded by the mutex.
|
CAHALAudioSystemObject mAudioSystem; // Not guarded by the mutex.
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
# post_install.sh
|
# post_install.sh
|
||||||
# BGMXPCHelper
|
# BGMXPCHelper
|
||||||
#
|
#
|
||||||
# Copyright © 2016 Kyle Neideck
|
# Copyright © 2016, 2017 Kyle Neideck
|
||||||
#
|
#
|
||||||
# Installs BGMXPCHelper's launchd plist file and "bootstraps" (registers/enables) it with launchd.
|
# Installs BGMXPCHelper's launchd plist file and "bootstraps" (registers/enables) it with launchd.
|
||||||
#
|
#
|
||||||
|
@ -28,30 +28,47 @@
|
||||||
# runs as the final build phase.
|
# runs as the final build phase.
|
||||||
#
|
#
|
||||||
|
|
||||||
# Check the environment variables we need from Xcode.
|
PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
|
||||||
if [[ -z ${EXECUTABLE_PATH} ]]; then
|
|
||||||
echo "Environment variable EXECUTABLE_PATH was not set." >&2
|
# Check we have the paths we need, either in environment variables from Xcode or from the args.
|
||||||
exit 1
|
if [[ -z $1 ]]; then
|
||||||
|
if [[ -z ${INSTALL_DIR} ]]; then
|
||||||
|
echo "Environment variable INSTALL_DIR was not set." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
INSTALL_DIR="$1"
|
||||||
fi
|
fi
|
||||||
if [[ -z ${INSTALL_DIR} ]]; then
|
|
||||||
echo "Environment variable INSTALL_DIR was not set." >&2
|
if [[ -z $2 ]]; then
|
||||||
exit 1
|
if [[ -z ${EXECUTABLE_PATH} ]]; then
|
||||||
|
echo "Environment variable EXECUTABLE_PATH was not set." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
EXECUTABLE_PATH="$2"
|
||||||
fi
|
fi
|
||||||
if [[ -z ${TARGET_BUILD_DIR} ]]; then
|
|
||||||
echo "Environment variable TARGET_BUILD_DIR was not set." >&2
|
if [[ -z $3 ]]; then
|
||||||
exit 1
|
if [[ -z ${TARGET_BUILD_DIR} ]]; then
|
||||||
fi
|
echo "Environment variable TARGET_BUILD_DIR was not set." >&2
|
||||||
if [[ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH} ]]; then
|
exit 1
|
||||||
echo "Environment variable UNLOCALIZED_RESOURCES_FOLDER_PATH was not set." >&2
|
fi
|
||||||
exit 1
|
|
||||||
|
if [[ -z ${UNLOCALIZED_RESOURCES_FOLDER_PATH} ]]; then
|
||||||
|
echo "Environment variable UNLOCALIZED_RESOURCES_FOLDER_PATH was not set." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
RESOURCES_PATH="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
||||||
|
else
|
||||||
|
RESOURCES_PATH="$3"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Safe mode.
|
# Safe mode.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
|
||||||
RESOURCES_PATH="${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}"
|
|
||||||
|
|
||||||
# Show a warning if INSTALL_DIR isn't set to a safe installation directory.
|
# Show a warning if INSTALL_DIR isn't set to a safe installation directory.
|
||||||
if [[ $(bash "${RESOURCES_PATH}/safe_install_dir.sh" "${INSTALL_DIR}") != 1 ]]; then
|
if [[ $(bash "${RESOURCES_PATH}/safe_install_dir.sh" "${INSTALL_DIR}") != 1 ]]; then
|
||||||
echo "$(tput setaf 11)WARNING$(tput sgr0): Installing to \"${INSTALL_DIR}\" may be" \
|
echo "$(tput setaf 11)WARNING$(tput sgr0): Installing to \"${INSTALL_DIR}\" may be" \
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
# safe_install_dir.sh
|
# safe_install_dir.sh
|
||||||
# BGMXPCHelper
|
# BGMXPCHelper
|
||||||
#
|
#
|
||||||
# Copyright © 2016 Kyle Neideck
|
# Copyright © 2016, 2017 Kyle Neideck
|
||||||
#
|
#
|
||||||
# Prints the path to a directory the BGMXPCHelper bundle can safely be installed to. Intended to be
|
# Prints the path to a directory the BGMXPCHelper bundle can safely be installed to. Intended to be
|
||||||
# used as the INSTALL_DIR environment variable for xcodebuild commands. For example,
|
# used as the INSTALL_DIR environment variable for xcodebuild commands. For example,
|
||||||
|
@ -56,6 +56,8 @@
|
||||||
# recommendation above, or "0" otherwise.
|
# recommendation above, or "0" otherwise.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
|
||||||
|
|
||||||
# Safe mode.
|
# Safe mode.
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
IFS=$'\n\t'
|
IFS=$'\n\t'
|
||||||
|
@ -96,13 +98,17 @@ check_dir() {
|
||||||
# Used when we can't find a suitable installation directory. Prints an error message and exits.
|
# Used when we can't find a suitable installation directory. Prints an error message and exits.
|
||||||
# (Reaching this point should be very uncommon.)
|
# (Reaching this point should be very uncommon.)
|
||||||
fail() {
|
fail() {
|
||||||
echo "$(tput setaf 11)WARNING$(tput sgr0): Installing BGMXPCHelper to its default location" \
|
if [[ $ALLOW_UNSAFE_FALLBACK -eq 1 ]]; then
|
||||||
"(${INSTALL_DIR} or, as a backup, ${BACKUP_INSTALL_DIR}) might not be secure on this" \
|
CONTINUE_ANYWAY="y"
|
||||||
"system. It's recommended that each directory from the installation directory up to the" \
|
else
|
||||||
"root directory should be owned by root and not writable by any other user. See" \
|
echo "$(tput setaf 11)WARNING$(tput sgr0): Installing BGMXPCHelper to its default" \
|
||||||
"safe_install_dir.sh for more details." >&2
|
"location (${INSTALL_DIR} or, as a backup, ${BACKUP_INSTALL_DIR}) might not be" \
|
||||||
|
"secure on this system. It's recommended that each directory from the installation" \
|
||||||
|
"directory up to the root directory should be owned by root and not writable by any" \
|
||||||
|
"other user. See safe_install_dir.sh for more details." >&2
|
||||||
|
|
||||||
read -e -p "Continue anyway? [y/N]" CONTINUE_ANYWAY
|
read -e -p "Continue anyway? [y/N]" CONTINUE_ANYWAY
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "${CONTINUE_ANYWAY}" == "y" ]] || [[ "${CONTINUE_ANYWAY}" == "Y" ]]; then
|
if [[ "${CONTINUE_ANYWAY}" == "y" ]] || [[ "${CONTINUE_ANYWAY}" == "Y" ]]; then
|
||||||
echo "${INSTALL_DIR}"
|
echo "${INSTALL_DIR}"
|
||||||
|
@ -114,16 +120,26 @@ fail() {
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# This script can be given a directory to check as an argument.
|
ALLOW_UNSAFE_FALLBACK=0
|
||||||
# (Uses "${1+x}" instead of "$1" because having our "safe mode" enabled makes the script fail if you
|
|
||||||
# reference an unset variable, even to check whether it's set or not.)
|
|
||||||
if [[ ! -z "${1+x}" ]]; then
|
|
||||||
# Check the given path exists and is a directory.
|
|
||||||
if [[ ! -d "$1" ]]; then echo "$1 is not a directory." >&2; exit 1; fi
|
|
||||||
|
|
||||||
check_dir "$1"
|
# This script can be given a directory to check as an argument, or the -y option, which tells this
|
||||||
echo ${DIR_IS_SAFE}
|
# script to print the default dir if neither of the dirs are safe. The pkg installer uses -y so it
|
||||||
exit 0
|
# can install anyway and show the user instructions to fix the permissions, rather than just
|
||||||
|
# failing.
|
||||||
|
#
|
||||||
|
# (This line uses "${1+x}" instead of "$1" because having our "safe mode" enabled makes the script
|
||||||
|
# fail if you reference an unset variable, even to check whether it's set or not.)
|
||||||
|
if [[ ! -z "${1+x}" ]]; then
|
||||||
|
if [[ "$1" == "-y" ]]; then
|
||||||
|
ALLOW_UNSAFE_FALLBACK=1
|
||||||
|
else
|
||||||
|
# Check the given path exists and is a directory.
|
||||||
|
if [[ ! -d "$1" ]]; then echo "$1 is not a directory." >&2; exit 1; fi
|
||||||
|
|
||||||
|
check_dir "$1"
|
||||||
|
echo ${DIR_IS_SAFE}
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# These are just for readability and to save keystrokes. If you change them, you'll have to change
|
# These are just for readability and to save keystrokes. If you change them, you'll have to change
|
||||||
|
@ -143,7 +159,7 @@ if [[ ! -e "${INSTALL_DIR}" ]]; then
|
||||||
sudo chmod go-w "${INSTALL_DIR}"
|
sudo chmod go-w "${INSTALL_DIR}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check the directory Xcode installed the build to.
|
# Check the directory the build was installed to.
|
||||||
check_dir "${INSTALL_DIR}"
|
check_dir "${INSTALL_DIR}"
|
||||||
|
|
||||||
if [[ ${DIR_IS_SAFE} -eq 1 ]]; then
|
if [[ ${DIR_IS_SAFE} -eq 1 ]]; then
|
||||||
|
|
|
@ -622,7 +622,7 @@
|
||||||
GCC_WARN_UNUSED_LABEL = YES;
|
GCC_WARN_UNUSED_LABEL = YES;
|
||||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||||
WARNING_CFLAGS = "-Wpartial-availability";
|
WARNING_CFLAGS = "-Wpartial-availability";
|
||||||
|
@ -684,7 +684,7 @@
|
||||||
GCC_WARN_UNUSED_LABEL = YES;
|
GCC_WARN_UNUSED_LABEL = YES;
|
||||||
GCC_WARN_UNUSED_PARAMETER = YES;
|
GCC_WARN_UNUSED_PARAMETER = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
||||||
RUN_CLANG_STATIC_ANALYZER = YES;
|
RUN_CLANG_STATIC_ANALYZER = YES;
|
||||||
WARNING_CFLAGS = "-Wpartial-availability";
|
WARNING_CFLAGS = "-Wpartial-availability";
|
||||||
};
|
};
|
||||||
|
@ -714,7 +714,6 @@
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
INFOPLIST_FILE = BGMDriver/Info.plist;
|
INFOPLIST_FILE = BGMDriver/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.Driver;
|
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.Driver;
|
||||||
|
@ -749,7 +748,6 @@
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
INFOPLIST_FILE = BGMDriver/Info.plist;
|
INFOPLIST_FILE = BGMDriver/Info.plist;
|
||||||
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
|
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Audio/Plug-Ins/HAL";
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.9;
|
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.Driver;
|
PRODUCT_BUNDLE_IDENTIFIER = com.bearisdriving.BGM.Driver;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
|
|
@ -2,6 +2,10 @@
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>AudioServerPlugIn_MachServices</key>
|
||||||
|
<array>
|
||||||
|
<string>com.bearisdriving.BGM.XPCHelper</string>
|
||||||
|
</array>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>en</string>
|
<string>en</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
|
@ -15,11 +19,11 @@
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>BNDL</string>
|
<string>BNDL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.0</string>
|
<string>0.0.1</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1</string>
|
<string>1.0.0</string>
|
||||||
<key>CFPlugInFactories</key>
|
<key>CFPlugInFactories</key>
|
||||||
<dict>
|
<dict>
|
||||||
<key>C957AD43-DACA-4A40-8850-3BA8CE28FAF9</key>
|
<key>C957AD43-DACA-4A40-8850-3BA8CE28FAF9</key>
|
||||||
|
@ -34,9 +38,5 @@
|
||||||
</dict>
|
</dict>
|
||||||
<key>NSPrincipalClass</key>
|
<key>NSPrincipalClass</key>
|
||||||
<string></string>
|
<string></string>
|
||||||
<key>AudioServerPlugIn_MachServices</key>
|
|
||||||
<array>
|
|
||||||
<string>com.bearisdriving.BGM.XPCHelper</string>
|
|
||||||
</array>
|
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
#
|
#
|
||||||
# build_and_install.sh
|
# build_and_install.sh
|
||||||
#
|
#
|
||||||
# Copyright © 2016 Kyle Neideck
|
# Copyright © 2016, 2017 Kyle Neideck
|
||||||
# Copyright © 2016 Nick Jacques
|
# Copyright © 2016 Nick Jacques
|
||||||
#
|
#
|
||||||
# Builds and installs BGMApp, BGMDriver and BGMXPCHelper. Requires xcodebuild and Xcode.
|
# Builds and installs BGMApp, BGMDriver and BGMXPCHelper. Requires xcodebuild and Xcode.
|
||||||
|
@ -99,6 +99,8 @@ disable_error_handling() {
|
||||||
CONFIGURATION=Release
|
CONFIGURATION=Release
|
||||||
#CONFIGURATION=Debug
|
#CONFIGURATION=Debug
|
||||||
|
|
||||||
|
XCODEBUILD_ACTION="install"
|
||||||
|
|
||||||
# The default is to clean before installing because we want the log file to have roughly the same
|
# The default is to clean before installing because we want the log file to have roughly the same
|
||||||
# information after every build.
|
# information after every build.
|
||||||
CLEAN=clean
|
CLEAN=clean
|
||||||
|
@ -154,6 +156,7 @@ usage() {
|
||||||
echo "Usage: $0 [options]" >&2
|
echo "Usage: $0 [options]" >&2
|
||||||
echo -e "\t-n Don't clean before building/installing." >&2
|
echo -e "\t-n Don't clean before building/installing." >&2
|
||||||
echo -e "\t-d Debug build. (Release is the default.)" >&2
|
echo -e "\t-d Debug build. (Release is the default.)" >&2
|
||||||
|
echo -e "\t-b Build only, don't install." >&2
|
||||||
echo -e "\t-w Ignore compiler warnings. (They're treated as errors by default.)" >&2
|
echo -e "\t-w Ignore compiler warnings. (They're treated as errors by default.)" >&2
|
||||||
echo -e "\t-x [options] Extra options to pass to xcodebuild." >&2
|
echo -e "\t-x [options] Extra options to pass to xcodebuild." >&2
|
||||||
echo -e "\t-c Continue on script errors. Might not be safe." >&2
|
echo -e "\t-c Continue on script errors. Might not be safe." >&2
|
||||||
|
@ -236,7 +239,7 @@ show_spinner() {
|
||||||
}
|
}
|
||||||
|
|
||||||
parse_options() {
|
parse_options() {
|
||||||
while getopts ":ndwx:ch" opt; do
|
while getopts ":ndbwx:ch" opt; do
|
||||||
case $opt in
|
case $opt in
|
||||||
n)
|
n)
|
||||||
CLEAN=""
|
CLEAN=""
|
||||||
|
@ -244,6 +247,13 @@ parse_options() {
|
||||||
d)
|
d)
|
||||||
CONFIGURATION="Debug"
|
CONFIGURATION="Debug"
|
||||||
;;
|
;;
|
||||||
|
b)
|
||||||
|
XCODEBUILD_ACTION="build"
|
||||||
|
# The dirs xcodebuild will build in.
|
||||||
|
APP_PATH="./BGMApp/build"
|
||||||
|
DRIVER_PATH="./BGMDriver/build"
|
||||||
|
XPC_HELPER_PATH="${APP_PATH}"
|
||||||
|
;;
|
||||||
w)
|
w)
|
||||||
# TODO: What if they also pass their own OTHER_CFLAGS with -x?
|
# TODO: What if they also pass their own OTHER_CFLAGS with -x?
|
||||||
XCODEBUILD_OPTIONS="${XCODEBUILD_OPTIONS} OTHER_CFLAGS=\"-Wno-error\""
|
XCODEBUILD_OPTIONS="${XCODEBUILD_OPTIONS} OTHER_CFLAGS=\"-Wno-error\""
|
||||||
|
@ -529,15 +539,20 @@ if [[ $(id -u) -eq 0 ]]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Print initial message.
|
# Print initial message.
|
||||||
echo "$(bold_face About to install Background Music). Please pause all audio, if you can."
|
if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
|
||||||
[[ "${CONFIGURATION}" == "Debug" ]] && echo "Debug build."
|
echo "$(bold_face About to install Background Music). Please pause all audio, if you can."
|
||||||
echo
|
[[ "${CONFIGURATION}" == "Debug" ]] && echo "Debug build."
|
||||||
echo "This script will install:"
|
echo
|
||||||
echo " - ${APP_PATH}/${APP_DIR}"
|
echo "This script will install:"
|
||||||
echo " - ${DRIVER_PATH}/${DRIVER_DIR}"
|
echo " - ${APP_PATH}/${APP_DIR}"
|
||||||
echo " - ${XPC_HELPER_PATH}/${XPC_HELPER_DIR}"
|
echo " - ${DRIVER_PATH}/${DRIVER_DIR}"
|
||||||
echo " - /Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist"
|
echo " - ${XPC_HELPER_PATH}/${XPC_HELPER_DIR}"
|
||||||
echo
|
echo " - /Library/LaunchDaemons/com.bearisdriving.BGM.XPCHelper.plist"
|
||||||
|
echo
|
||||||
|
elif [[ "${XCODEBUILD_ACTION}" == "build" ]]; then
|
||||||
|
echo "$(bold_face Building Background Music...)"
|
||||||
|
echo
|
||||||
|
fi
|
||||||
|
|
||||||
# Make sure Xcode and the command line tools are installed and recent enough.
|
# Make sure Xcode and the command line tools are installed and recent enough.
|
||||||
# This sets XCODE_VERSION to major.minor, e.g. 8.3, or -1 if Xcode isn't installed.
|
# This sets XCODE_VERSION to major.minor, e.g. 8.3, or -1 if Xcode isn't installed.
|
||||||
|
@ -545,11 +560,13 @@ XCODE_VERSION=$((${XCODEBUILD} -version 2>/dev/null || echo 'V -1') | head -n 1
|
||||||
check_xcode &
|
check_xcode &
|
||||||
CHECK_XCODE_TASK_PID=$!
|
CHECK_XCODE_TASK_PID=$!
|
||||||
|
|
||||||
read -p "Continue (y/N)? " CONTINUE_INSTALLATION
|
if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
|
||||||
|
read -p "Continue (y/N)? " CONTINUE_INSTALLATION
|
||||||
|
|
||||||
if [[ "${CONTINUE_INSTALLATION}" != "y" ]] && [[ "${CONTINUE_INSTALLATION}" != "Y" ]]; then
|
if [[ "${CONTINUE_INSTALLATION}" != "y" ]] && [[ "${CONTINUE_INSTALLATION}" != "Y" ]]; then
|
||||||
echo "Installation cancelled."
|
echo "Installation cancelled."
|
||||||
exit 0
|
exit 0
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If the check_xcode process has already finished, we can check the result early.
|
# If the check_xcode process has already finished, we can check the result early.
|
||||||
|
@ -563,14 +580,16 @@ if ! is_alive ${CHECK_XCODE_TASK_PID}; then
|
||||||
enable_error_handling
|
enable_error_handling
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Update the user's sudo timestamp. (Prompts the user for their password.)
|
if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
|
||||||
# Don't call sudo -v if this is a Travis CI build.
|
# Update the user's sudo timestamp. (Prompts the user for their password.)
|
||||||
if ([[ -z ${TRAVIS:-} ]] || [[ "${TRAVIS}" != true ]]) && ! sudo -v; then
|
# Don't call sudo -v if this is a Travis CI build.
|
||||||
echo "$(tput setaf 9)ERROR$(tput sgr0): This script must be run by a user with administrator" \
|
if ([[ -z ${TRAVIS:-} ]] || [[ "${TRAVIS}" != true ]]) && ! sudo -v; then
|
||||||
"(sudo) privileges." >&2
|
echo "$(tput setaf 9)ERROR$(tput sgr0): This script must be run by a user with" \
|
||||||
exit 1
|
"administrator (sudo) privileges." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo
|
||||||
fi
|
fi
|
||||||
echo
|
|
||||||
|
|
||||||
while [[ ${NEED_TO_HANDLE_CHECK_XCODE_RESULT} -ne 0 ]]; do
|
while [[ ${NEED_TO_HANDLE_CHECK_XCODE_RESULT} -ne 0 ]]; do
|
||||||
disable_error_handling
|
disable_error_handling
|
||||||
|
@ -585,119 +604,127 @@ log_debug_info $*
|
||||||
|
|
||||||
# BGMDriver
|
# BGMDriver
|
||||||
|
|
||||||
echo "[1/3] Installing the virtual audio device $(bold_face ${DRIVER_DIR}) to" \
|
if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
|
||||||
"$(bold_face ${DRIVER_PATH})." \
|
SUDO="sudo"
|
||||||
|
ACTIONING="Installing"
|
||||||
|
else
|
||||||
|
SUDO=""
|
||||||
|
ACTIONING="Building"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "[1/3] ${ACTIONING} the virtual audio device $(bold_face ${DRIVER_DIR}) to" \
|
||||||
|
"$(bold_face ${DRIVER_PATH})" \
|
||||||
| tee -a ${LOG_FILE}
|
| tee -a ${LOG_FILE}
|
||||||
|
|
||||||
# Disable the -e shell option and error trap for build commands so we can handle errors differently.
|
# Disable the -e shell option and error trap for build commands so we can handle errors differently.
|
||||||
(disable_error_handling
|
(disable_error_handling
|
||||||
# Build Apple's PublicUtility classes as a static library.
|
# Build Apple's PublicUtility classes as a static library.
|
||||||
sudo "${XCODEBUILD}" -project BGMDriver/BGMDriver.xcodeproj \
|
${SUDO} "${XCODEBUILD}" -project BGMDriver/BGMDriver.xcodeproj \
|
||||||
-target "PublicUtility" \
|
-target "PublicUtility" \
|
||||||
-configuration ${CONFIGURATION} \
|
-configuration ${CONFIGURATION} \
|
||||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||||
${XCODEBUILD_OPTIONS} \
|
${XCODEBUILD_OPTIONS} \
|
||||||
${CLEAN} build >> ${LOG_FILE} 2>&1) &
|
${CLEAN} build >> ${LOG_FILE} 2>&1) &
|
||||||
|
|
||||||
(disable_error_handling
|
(disable_error_handling
|
||||||
# Build and install BGMDriver
|
# Build and install BGMDriver
|
||||||
# TODO: Should these use -scheme instead?
|
# TODO: Should these use -scheme instead?
|
||||||
sudo "${XCODEBUILD}" -project BGMDriver/BGMDriver.xcodeproj \
|
${SUDO} "${XCODEBUILD}" -project BGMDriver/BGMDriver.xcodeproj \
|
||||||
-target "Background Music Device" \
|
-target "Background Music Device" \
|
||||||
-configuration ${CONFIGURATION} \
|
-configuration ${CONFIGURATION} \
|
||||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||||
DSTROOT="/" \
|
DSTROOT="/" \
|
||||||
${XCODEBUILD_OPTIONS} \
|
${XCODEBUILD_OPTIONS} \
|
||||||
${CLEAN} install >> ${LOG_FILE} 2>&1) &
|
${CLEAN} "${XCODEBUILD_ACTION}" >> ${LOG_FILE} 2>&1) &
|
||||||
|
|
||||||
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
||||||
|
|
||||||
# BGMXPCHelper
|
# BGMXPCHelper
|
||||||
|
|
||||||
echo "[2/3] Installing $(bold_face ${XPC_HELPER_DIR}) to $(bold_face ${XPC_HELPER_PATH})." \
|
echo "[2/3] ${ACTIONING} $(bold_face ${XPC_HELPER_DIR}) to $(bold_face ${XPC_HELPER_PATH})" \
|
||||||
| tee -a ${LOG_FILE}
|
| tee -a ${LOG_FILE}
|
||||||
|
|
||||||
(disable_error_handling
|
(disable_error_handling
|
||||||
sudo "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
${SUDO} "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
||||||
-target BGMXPCHelper \
|
-target BGMXPCHelper \
|
||||||
-configuration ${CONFIGURATION} \
|
-configuration ${CONFIGURATION} \
|
||||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||||
DSTROOT="/" \
|
DSTROOT="/" \
|
||||||
INSTALL_PATH="${XPC_HELPER_PATH}" \
|
INSTALL_PATH="${XPC_HELPER_PATH}" \
|
||||||
${XCODEBUILD_OPTIONS} \
|
${XCODEBUILD_OPTIONS} \
|
||||||
${CLEAN} install >> ${LOG_FILE} 2>&1) &
|
${CLEAN} "${XCODEBUILD_ACTION}" >> ${LOG_FILE} 2>&1) &
|
||||||
|
|
||||||
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
||||||
|
|
||||||
# BGMApp
|
# BGMApp
|
||||||
|
|
||||||
echo "[3/3] Installing $(bold_face ${APP_DIR}) to $(bold_face ${APP_PATH})." \
|
echo "[3/3] ${ACTIONING} $(bold_face ${APP_DIR}) to $(bold_face ${APP_PATH})" \
|
||||||
| tee -a ${LOG_FILE}
|
| tee -a ${LOG_FILE}
|
||||||
|
|
||||||
(disable_error_handling
|
(disable_error_handling
|
||||||
sudo "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
${SUDO} "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
||||||
-target "Background Music" \
|
-target "Background Music" \
|
||||||
-configuration ${CONFIGURATION} \
|
-configuration ${CONFIGURATION} \
|
||||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||||
DSTROOT="/" \
|
DSTROOT="/" \
|
||||||
${XCODEBUILD_OPTIONS} \
|
${XCODEBUILD_OPTIONS} \
|
||||||
${CLEAN} install >> ${LOG_FILE} 2>&1) &
|
${CLEAN} "${XCODEBUILD_ACTION}" >> ${LOG_FILE} 2>&1) &
|
||||||
|
|
||||||
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
show_spinner "${BUILD_FAILED_ERROR_MSG}"
|
||||||
|
|
||||||
# Fix Background Music.app owner/group.
|
if [[ "${XCODEBUILD_ACTION}" == "install" ]]; then
|
||||||
#
|
# Fix Background Music.app owner/group.
|
||||||
# We have to run xcodebuild as root to install BGMXPCHelper because it installs to directories
|
#
|
||||||
# owned by root. But that means the build directory gets created by root, and since BGMApp uses the
|
# We have to run xcodebuild as root to install BGMXPCHelper because it installs to directories
|
||||||
# same build directory we have to run xcodebuild as root to install BGMApp as well.
|
# owned by root. But that means the build directory gets created by root, and since BGMApp uses
|
||||||
#
|
# the same build directory we have to run xcodebuild as root to install BGMApp as well.
|
||||||
# TODO: Can't we just chown -R the build dir before we install BGMApp? Then we wouldn't have to
|
#
|
||||||
# install BGMApp as root. (But maybe still handle the unlikely case of APP_PATH not being
|
# TODO: Can't we just chown -R the build dir before we install BGMApp? Then we wouldn't have to
|
||||||
# user-writable.)
|
# install BGMApp as root. (But maybe still handle the unlikely case of APP_PATH not being
|
||||||
sudo chown -R "$(whoami):admin" "${APP_PATH}/${APP_DIR}"
|
# user-writable.)
|
||||||
|
sudo chown -R "$(whoami):admin" "${APP_PATH}/${APP_DIR}"
|
||||||
|
|
||||||
# Fix the build directories' owner/group. This is mainly so the whole source directory can be
|
# Fix the build directories' owner/group. This is mainly so the whole source directory can be
|
||||||
# deleted easily after installing.
|
# deleted easily after installing.
|
||||||
sudo chown -R "$(whoami):admin" "BGMApp/build" "BGMDriver/build"
|
sudo chown -R "$(whoami):admin" "BGMApp/build" "BGMDriver/build"
|
||||||
|
|
||||||
# Restart coreaudiod.
|
# Restart coreaudiod.
|
||||||
|
|
||||||
echo "Restarting coreaudiod to load the virtual audio device." \
|
echo "Restarting coreaudiod to load the virtual audio device." \
|
||||||
| tee -a ${LOG_FILE}
|
| tee -a ${LOG_FILE}
|
||||||
|
|
||||||
# The extra or-clauses are fallback versions of the command that restarts coreaudiod. Apparently
|
# The extra or-clauses are fallback versions of the command that restarts coreaudiod. Apparently
|
||||||
# some of these commands don't work with older versions of launchctl, so I figure there's no harm in
|
# some of these commands don't work with older versions of launchctl, so I figure there's no
|
||||||
# trying a bunch of different ways (which should all work).
|
# harm in trying a bunch of different ways (which should all work).
|
||||||
(sudo launchctl kill SIGTERM system/com.apple.audio.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 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 launchctl kill -15 system/com.apple.audio.coreaudiod &>/dev/null || \
|
sudo launchctl kill -15 system/com.apple.audio.coreaudiod &>/dev/null || \
|
||||||
(sudo launchctl unload "${COREAUDIOD_PLIST}" &>/dev/null && \
|
(sudo launchctl unload "${COREAUDIOD_PLIST}" &>/dev/null && \
|
||||||
sudo launchctl load "${COREAUDIOD_PLIST}" &>/dev/null) || \
|
sudo launchctl load "${COREAUDIOD_PLIST}" &>/dev/null) || \
|
||||||
sudo killall coreaudiod &>/dev/null) && \
|
sudo killall coreaudiod &>/dev/null) && \
|
||||||
sleep 5
|
sleep 5
|
||||||
|
|
||||||
# Invalidate sudo ticket
|
# Invalidate sudo ticket
|
||||||
sudo -k
|
sudo -k
|
||||||
|
|
||||||
# Open BGMApp.
|
# Open BGMApp. We have to change the default audio device after restarting coreaudiod and this
|
||||||
#
|
# is the easiest way.
|
||||||
# I'd rather not open BGMApp here, or at least ask first, but you have to change your default audio
|
echo "Launching Background Music."
|
||||||
# device after restarting coreaudiod and this is the easiest way.
|
|
||||||
echo "Launching Background Music."
|
|
||||||
|
|
||||||
ERROR_MSG="${BGMAPP_FAILED_TO_START_ERROR_MSG}"
|
ERROR_MSG="${BGMAPP_FAILED_TO_START_ERROR_MSG}"
|
||||||
open "${APP_PATH}/${APP_DIR}"
|
open "${APP_PATH}/${APP_DIR}"
|
||||||
|
|
||||||
# Ignore script errors from this point.
|
# Ignore script errors from this point.
|
||||||
disable_error_handling
|
disable_error_handling
|
||||||
|
|
||||||
# Wait up to 5 seconds for Background Music to start.
|
# Wait up to 5 seconds for Background Music to start.
|
||||||
(trap 'exit 1' TERM
|
(trap 'exit 1' TERM
|
||||||
while ! (ps -Ao ucomm= | grep 'Background Music' > /dev/null); do
|
while ! (ps -Ao ucomm= | grep 'Background Music' > /dev/null); do
|
||||||
sleep 1
|
sleep 1
|
||||||
done) &
|
done) &
|
||||||
show_spinner "${BGMAPP_FAILED_TO_START_ERROR_MSG}" 5
|
show_spinner "${BGMAPP_FAILED_TO_START_ERROR_MSG}" 5
|
||||||
|
fi
|
||||||
|
|
||||||
echo "Done."
|
echo "Done."
|
||||||
|
|
||||||
|
|
138
package.sh
Executable file
138
package.sh
Executable file
|
@ -0,0 +1,138 @@
|
||||||
|
#!/bin/bash
|
||||||
|
# vim: tw=100:
|
||||||
|
|
||||||
|
# This file is part of Background Music.
|
||||||
|
#
|
||||||
|
# Background Music is free software: you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 2 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Background Music is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# package.sh
|
||||||
|
#
|
||||||
|
# Copyright © 2017 Kyle Neideck
|
||||||
|
# Copyright © 2016, 2017 Takayama Fumihiko
|
||||||
|
#
|
||||||
|
# Build Background Music and package it into a .pkg file and a .zip of the debug symbols (dSYM).
|
||||||
|
#
|
||||||
|
# Based on https://github.com/tekezo/Karabiner-Elements/blob/master/make-package.sh
|
||||||
|
#
|
||||||
|
|
||||||
|
# TODO: Code signing. See `man pkgbuild`.
|
||||||
|
|
||||||
|
PATH="/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin"; export PATH
|
||||||
|
|
||||||
|
# Sets all dirs in $1 to 755 (rwxr-xr-x) and all files in $1 to 644 (rw-r--r--).
|
||||||
|
set_permissions() {
|
||||||
|
find "$1" -print0 | while read -d $'\0' filepath; do
|
||||||
|
filename="${filepath##*/}"
|
||||||
|
|
||||||
|
if [ -d "$filepath" ]; then
|
||||||
|
chmod -h 755 "$filepath"
|
||||||
|
else
|
||||||
|
chmod -h 644 "$filepath"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
# Build
|
||||||
|
bash build_and_install.sh -b
|
||||||
|
|
||||||
|
version="$(/usr/libexec/PlistBuddy \
|
||||||
|
-c "Print CFBundleShortVersionString" \
|
||||||
|
"BGMApp/build/Release/Background Music.app/Contents/Info.plist")"
|
||||||
|
|
||||||
|
out_dir="Background-Music-$version"
|
||||||
|
rm -rf "$out_dir"
|
||||||
|
mkdir "$out_dir"
|
||||||
|
|
||||||
|
# Separate the debug symbols and the .app
|
||||||
|
echo "Archiving debug symbols"
|
||||||
|
|
||||||
|
dsym_archive="$out_dir/Background Music.dSYM-$version.zip"
|
||||||
|
mv "BGMApp/build/Release/Background Music.app/Contents/MacOS/Background Music.dSYM" \
|
||||||
|
"Background Music.dSYM"
|
||||||
|
zip -r "$dsym_archive" "Background Music.dSYM"
|
||||||
|
rm -r "Background Music.dSYM"
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
echo "Copying Files"
|
||||||
|
|
||||||
|
rm -rf "pkgroot"
|
||||||
|
mkdir -p "pkgroot"
|
||||||
|
|
||||||
|
mkdir -p "pkgroot/Library/Audio/Plug-Ins/HAL"
|
||||||
|
cp -R "BGMDriver/build/Release/Background Music Device.driver" "pkgroot/Library/Audio/Plug-Ins/HAL/"
|
||||||
|
|
||||||
|
mkdir -p "pkgroot/Applications"
|
||||||
|
cp -R "BGMApp/build/Release/Background Music.app" "pkgroot/Applications"
|
||||||
|
|
||||||
|
scripts_dir="$(mktemp -d)"
|
||||||
|
cp "pkg/preinstall" "$scripts_dir"
|
||||||
|
cp "pkg/postinstall" "$scripts_dir"
|
||||||
|
cp "BGMApp/BGMXPCHelper/com.bearisdriving.BGM.XPCHelper.plist.template" "$scripts_dir"
|
||||||
|
cp "BGMApp/BGMXPCHelper/safe_install_dir.sh" "$scripts_dir"
|
||||||
|
cp "BGMApp/BGMXPCHelper/post_install.sh" "$scripts_dir"
|
||||||
|
cp -R "BGMApp/build/Release/BGMXPCHelper.xpc" "$scripts_dir"
|
||||||
|
|
||||||
|
set_permissions "pkgroot"
|
||||||
|
chmod 755 "pkgroot/Applications/Background Music.app/Contents/MacOS/Background Music"
|
||||||
|
chmod 755 "pkgroot/Library/Audio/Plug-Ins/HAL/Background Music Device.driver/Contents/MacOS/Background Music Device"
|
||||||
|
|
||||||
|
set_permissions "$scripts_dir"
|
||||||
|
chmod 755 "$scripts_dir/preinstall"
|
||||||
|
chmod 755 "$scripts_dir/postinstall"
|
||||||
|
chmod 755 "$scripts_dir/BGMXPCHelper.xpc/Contents/MacOS/BGMXPCHelper"
|
||||||
|
|
||||||
|
rm -rf "pkgres"
|
||||||
|
mkdir -p "pkgres"
|
||||||
|
cp "Images/FermataIcon.pdf" "pkgres"
|
||||||
|
|
||||||
|
sed "s/{{VERSION}}/$version/g" "pkg/Distribution.xml.template" > "pkg/Distribution.xml"
|
||||||
|
|
||||||
|
# --------------------------------------------------
|
||||||
|
|
||||||
|
pkg="$out_dir/BackgroundMusic-$version.pkg"
|
||||||
|
pkg_identifier="com.bearisdriving.BGM"
|
||||||
|
|
||||||
|
echo "Creating $pkg"
|
||||||
|
|
||||||
|
pkgbuild \
|
||||||
|
--root "pkgroot" \
|
||||||
|
--component-plist "pkg/pkgbuild.plist" \
|
||||||
|
--identifier "$pkg_identifier" \
|
||||||
|
--scripts "$scripts_dir" \
|
||||||
|
--version "$version" \
|
||||||
|
--install-location "/" \
|
||||||
|
"$out_dir/Installer.pkg"
|
||||||
|
|
||||||
|
productbuild \
|
||||||
|
--distribution "pkg/Distribution.xml" \
|
||||||
|
--resources "pkgres" \
|
||||||
|
--package-path "$out_dir" \
|
||||||
|
"$pkg"
|
||||||
|
|
||||||
|
rm -f "$out_dir/Installer.pkg"
|
||||||
|
rm -rf "pkgroot"
|
||||||
|
rm -rf "pkgres"
|
||||||
|
rm -f "pkg/Distribution.xml"
|
||||||
|
|
||||||
|
# Print checksums
|
||||||
|
echo "MD5 checksums:"
|
||||||
|
md5 {"$pkg","$dsym_archive"}
|
||||||
|
echo "SHA256 checksums:"
|
||||||
|
shasum -a 256 {"$pkg","$dsym_archive"}
|
||||||
|
|
||||||
|
|
45
pkg/Distribution.xml.template
Normal file
45
pkg/Distribution.xml.template
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||||
|
<installer-gui-script minSpecVersion="1">
|
||||||
|
<title>Background Music {{VERSION}}</title>
|
||||||
|
|
||||||
|
<volume-check>
|
||||||
|
<allowed-os-versions>
|
||||||
|
<!-- TODO: Get this from the Xcode project files instead of hardcoding it. -->
|
||||||
|
<os-version min="10.9" />
|
||||||
|
</allowed-os-versions>
|
||||||
|
</volume-check>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Do not specify <domains>.
|
||||||
|
Installer does not show "OS X version X.Y.Z or later is required" message when <domains> exists.
|
||||||
|
<domains enable_anywhere="false" enable_currentUserHome="false" enable_localSystem="true" />
|
||||||
|
-->
|
||||||
|
|
||||||
|
<pkg-ref id="com.bearisdriving.BGM"/>
|
||||||
|
|
||||||
|
<options customize="never" require-scripts="false" />
|
||||||
|
|
||||||
|
<choices-outline>
|
||||||
|
<line choice="default">
|
||||||
|
<line choice="com.bearisdriving.BGM" />
|
||||||
|
</line>
|
||||||
|
</choices-outline>
|
||||||
|
|
||||||
|
<choice id="default"/>
|
||||||
|
|
||||||
|
<choice id="com.bearisdriving.BGM" visible="false">
|
||||||
|
<pkg-ref id="com.bearisdriving.BGM" />
|
||||||
|
</choice>
|
||||||
|
|
||||||
|
<pkg-ref id="com.bearisdriving.BGM" version="{{VERSION}}">Installer.pkg</pkg-ref>
|
||||||
|
|
||||||
|
<pkg-ref id="com.bearisdriving.BGM">
|
||||||
|
<must-close>
|
||||||
|
<app id="com.bearisdriving.BGM.App" />
|
||||||
|
</must-close>
|
||||||
|
</pkg-ref>
|
||||||
|
|
||||||
|
<background file="FermataIcon.pdf" alignment="bottomleft" />
|
||||||
|
</installer-gui-script>
|
||||||
|
|
||||||
|
|
14
pkg/pkgbuild.plist
Normal file
14
pkg/pkgbuild.plist
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<array>
|
||||||
|
<dict>
|
||||||
|
<key>RootRelativeBundlePath</key> <string>Applications/Background Music.app</string>
|
||||||
|
<key>BundleHasStrictIdentifier</key> <false/>
|
||||||
|
<key>BundleIsRelocatable</key> <false/>
|
||||||
|
<key>BundleIsVersionChecked</key> <false/>
|
||||||
|
<key>BundleOverwriteAction</key> <string>upgrade</string>
|
||||||
|
</dict>
|
||||||
|
</array>
|
||||||
|
</plist>
|
||||||
|
|
55
pkg/postinstall
Executable file
55
pkg/postinstall
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# vim: tw=100:
|
||||||
|
|
||||||
|
# This file is part of Background Music.
|
||||||
|
#
|
||||||
|
# Background Music is free software: you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 2 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Background Music is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# preinstall
|
||||||
|
#
|
||||||
|
# Copyright © 2017 Kyle Neideck
|
||||||
|
#
|
||||||
|
|
||||||
|
PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
|
||||||
|
|
||||||
|
dest_volume="$3"
|
||||||
|
xpc_helper_path="$(bash safe_install_dir.sh -y)"
|
||||||
|
|
||||||
|
logger "Installing BGMXPCHelper to $xpc_helper_path"
|
||||||
|
cp -Rf "BGMXPCHelper.xpc" "$xpc_helper_path"
|
||||||
|
|
||||||
|
# TODO: Fail the install and show an error message if this fails.
|
||||||
|
bash "post_install.sh" "$xpc_helper_path" "BGMXPCHelper.xpc/Contents/MacOS/BGMXPCHelper" "."
|
||||||
|
|
||||||
|
# TODO: Verify the installed files, their permissions, the _BGMXPCHelper user/group, etc.
|
||||||
|
|
||||||
|
# The extra or-clauses are fallback versions of the command that restarts coreaudiod. Apparently
|
||||||
|
# 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).
|
||||||
|
(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) && \
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
open "${dest_volume}/Applications/Background Music.app"
|
||||||
|
|
||||||
|
# The installer plays a sound when it finishes, so give BGMApp a second to launch.
|
||||||
|
sleep 1
|
||||||
|
|
||||||
|
|
55
pkg/preinstall
Executable file
55
pkg/preinstall
Executable file
|
@ -0,0 +1,55 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# vim: tw=100:
|
||||||
|
|
||||||
|
# This file is part of Background Music.
|
||||||
|
#
|
||||||
|
# Background Music is free software: you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 2 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Background Music is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#
|
||||||
|
# preinstall
|
||||||
|
#
|
||||||
|
# Copyright © 2017 Kyle Neideck
|
||||||
|
#
|
||||||
|
|
||||||
|
PATH=/bin:/sbin:/usr/bin:/usr/sbin; export PATH
|
||||||
|
|
||||||
|
# Show a warning if we can't find a safe dir to install BGMXPCHelper in. Should be very unlikely.
|
||||||
|
xpc_helper_path="$(bash safe_install_dir.sh -y)"
|
||||||
|
|
||||||
|
if [ "$(bash safe_install_dir.sh "$xpc_helper_path")" != "1" ]; then
|
||||||
|
# TODO: This message could be more user friendly.
|
||||||
|
msg="We need to install a helper app called BGMXPCHelper to ${xpc_helper_path}, but it may not "
|
||||||
|
msg+="be secure to do so.\n\n"
|
||||||
|
msg+="${xpc_helper_path} and all of its parent directories should be owned by 'root', with the "
|
||||||
|
msg+="group 'wheel', and have permissions 755 (rwxr-xr-x).\n\n"
|
||||||
|
msg+="Background Music will still work if you decide to continue."
|
||||||
|
|
||||||
|
if ! osascript <<EOT
|
||||||
|
tell application id "com.apple.systemuiserver"
|
||||||
|
display alert "Warning" \
|
||||||
|
message "$msg" \
|
||||||
|
buttons {"Cancel", "Install Anyway"} \
|
||||||
|
default button "Cancel" \
|
||||||
|
cancel button "Cancel" \
|
||||||
|
as warning
|
||||||
|
end tell
|
||||||
|
EOT
|
||||||
|
then
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
exit 0
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue