Add script that builds and installs BGMApp, BGMDriver and BGMXPCHelper

This commit is contained in:
Kyle Neideck 2016-04-05 16:56:38 +10:00
parent 1672bb8ed0
commit 690d6221d7
5 changed files with 230 additions and 23 deletions

1
.gitignore vendored
View file

@ -1,6 +1,7 @@
.DS_Store
.*.swp
/BGMDriver/BGMDriver/quick_install.conf
/build_and_install.log
# Everything below is from https://github.com/github/gitignore/blob/master/Objective-C.gitignore

View file

@ -59,6 +59,10 @@
- (void) initHelperConnection {
// Note that this is called when the helper connection's interruption handler is retrying the connection after a timeout.
[self initHelperConnectionWithErrorHandler:^(NSError* error) {
#if !DEBUG
#pragma unused (error)
#endif
DebugMsg("BGMXPCListener::initHelperConnection: Connection error: %s", [[error description] UTF8String]);
}];
}

View file

@ -87,6 +87,9 @@ UInt64 WaitForBGMAppToStartOutputDevice()
// This remote call to BGMXPCHelper will send a reply when the output device is ready to receive IO. Note that we shouldn't trust
// the reply string.
[[theConnection remoteObjectProxyWithErrorHandler:^(NSError* error) {
#if !DEBUG
#pragma unused (error)
#endif
DebugMsg("BGM_XPCHelper::WaitForBGMAppToStartOutputDevice: Remote call error: %s",
[[error debugDescription] UTF8String]);

View file

@ -46,30 +46,12 @@ Background Music Device. You can create the aggregate device using the Audio MID
## Install
No binaries yet, but building only takes a few seconds (as long as you already have Xcode installed).
No binaries yet, but building should take less than a minute. To build and install everything, clone/download the
project and run the `build_and_install.sh` script. Unfortunately, **it won't build if you don't have Xcode installed**
because xcodebuild doesn't work on its own anymore.
- Install the virtual audio device `Background Music Device.driver` to `/Library/Audio/Plug-Ins/HAL`.
```shell
sudo xcodebuild -project BGMDriver/BGMDriver.xcodeproj -target "Background Music Device" RUN_CLANG_STATIC_ANALYZER=0 DSTROOT="/" install
```
- Install the XPC helper.
```shell
sudo xcodebuild -project BGMApp/BGMApp.xcodeproj -target BGMXPCHelper RUN_CLANG_STATIC_ANALYZER=0 DSTROOT="/" INSTALL_PATH="$(BGMApp/BGMXPCHelper/safe_install_dir.sh)" install
```
- Install `Background Music.app` to `/Applications` (or wherever).
```shell
xcodebuild -project BGMApp/BGMApp.xcodeproj -target "Background Music" RUN_CLANG_STATIC_ANALYZER=0 DSTROOT="/" install
```
- Restart `coreaudiod`: <br>
(Audio will stop working until the next step, so you might want to pause any running audio apps.)
```shell
sudo launchctl kill SIGTERM system/com.apple.audio.coreaudiod
```
- Run `Background Music.app`.
The script restarts the system audio process (coreaudiod) at the end of the installation, so you might want to pause any
apps playing audio.
## Uninstall

217
build_and_install.sh Executable file
View file

@ -0,0 +1,217 @@
#!/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/>.
#
# build_and_install.sh
#
# Copyright © 2016 Kyle Neideck
#
# Builds and installs BGMApp, BGMDriver and BGMXPCHelper. Requires xcodebuild.
#
# Safe mode
set -euo pipefail
IFS=$'\n\t'
# General error message
set -o errtrace
general_error() {
echo "$(tput setaf 1)ERROR$(tput sgr0): Install script failed at line $1. This is probably a" \
"bug in the script. Feel free to report it." >&2
}
trap 'general_error ${LINENO}' ERR
# Build for release by default.
# TODO: Add an option to use the debug configuration?
CONFIGURATION=Release
#CONFIGURATION=Debug
# Update .gitignore if you change this.
LOG_FILE=build_and_install.log
bold_face() {
echo $(tput bold)$*$(tput sgr0)
}
# Takes a PID and returns 0 if the process is running.
is_alive() {
kill -0 $1 > /dev/null 2>&1 && return 0 || return 1
}
# Shows a "..." animation until the previous command finishes. Shows an error message and exits the
# script if the command fails.
#
# Takes an optional timeout in seconds. The return value will be the exit status of the command.
show_spinner() {
local PREV_COMMAND_PID=$!
# Get the previous command as a string, with variables resolved. Assumes that if the command has
# a child process we just want the text of the child process's command. (And that it only has
# one child.)
local CHILD_PID=$(pgrep -P ${PREV_COMMAND_PID} | head -n1 || echo ${PREV_COMMAND_PID})
local PREV_COMMAND_STRING=$(ps -o command= ${CHILD_PID})
local TIMEOUT=${1:-0}
(I=1;
while (is_alive ${PREV_COMMAND_PID}) && ([[ ${TIMEOUT} -lt 1 ]] || [[ $I -lt ${TIMEOUT} ]]); do
printf '.';
sleep 1;
# Erase after we've printed three dots. (\b is backspace.)
[[ $(($I % 3)) -eq 0 ]] && printf '\b\b\b \b\b\b';
I=$(($I + 1));
done) &
set +e
wait ${PREV_COMMAND_PID}
local EXIT_STATUS=$?
set -e
# Clean up the dots.
printf '\b\b\b'
# Print an error message if the command fails.
# (wait returns 127 if the process has already exited.)
if [[ ${EXIT_STATUS} -ne 0 ]] && [[ ${EXIT_STATUS} -ne 127 ]]; then
echo "$(tput setaf 1)ERROR$(tput sgr0): Build step failed. See ${LOG_FILE} for details." >&2
echo "Failed command:" >&2
echo " ${PREV_COMMAND_STRING}" >&2
exit ${EXIT_STATUS}
fi
return ${EXIT_STATUS}
}
# Check for xcodebuild.
if [[ "$(which xcodebuild)" == "" ]]; then
echo "$(tput setaf 1)ERROR$(tput sgr0): Can't find xcodebuild in your \$PATH." >&2
echo >&2
echo "If you have Xcode installed, you should be able to install the command line developer" \
"tools, including xcodebuild, with" >&2
echo " xcode-select --install" >&2
echo "If not, you'll need to install Xcode (~9GB), because xcodebuild no longer works without" \
"it." >&2
# Disable error handlers.
trap - ERR
set +e
# Check for Xcode.
XCODE_PATH=$(which xcode-select > /dev/null && xcode-select --print-path)
XCODE_PATH=${XCODE_PATH%/Contents/Developer}
if [[ "${XCODE_PATH}" == "" ]] && [[ -d /Applications/Xcode.app ]]; then
XCODE_PATH="/Applications/Xcode.app"
fi
if [[ "${XCODE_PATH}" == "" ]] && [[ -d ~/Applications/Xcode.app ]]; then
XCODE_PATH="~/Applications/Xcode.app"
fi
if [[ "${XCODE_PATH}" != "" ]]; then
echo >&2
echo "It looks like you have Xcode installed to ${XCODE_PATH}" >&2
fi
exit 1
fi
# Go to the project directory.
cd "$( dirname "${BASH_SOURCE[0]}" )"
# BGMDriver
echo "Installing the virtual audio device $(bold_face Background Music Device.driver) to" \
"$(bold_face /Library/Audio/Plug-Ins/HAL)." \
| tee ${LOG_FILE}
sudo -v
# Disable the -e shell option here so we can handle the error differently.
(set +e;
sudo xcodebuild -project BGMDriver/BGMDriver.xcodeproj \
-target "Background Music Device" \
-configuration ${CONFIGURATION} \
RUN_CLANG_STATIC_ANALYZER=0 \
DSTROOT="/" \
install >> ${LOG_FILE} 2>&1) &
show_spinner
# BGMXPCHelper
INSTALL_DIR=$(BGMApp/BGMXPCHelper/safe_install_dir.sh)
echo "Installing $(bold_face BGMXPCHelper.xpc) to $(bold_face ${INSTALL_DIR})." \
| tee -a ${LOG_FILE}
(set +e;
sudo xcodebuild -project BGMApp/BGMApp.xcodeproj \
-target BGMXPCHelper \
-configuration ${CONFIGURATION} \
RUN_CLANG_STATIC_ANALYZER=0 \
DSTROOT="/" \
INSTALL_PATH="${INSTALL_DIR}" \
install >> ${LOG_FILE} 2>&1) &
show_spinner
# BGMApp
echo "Installing $(bold_face Background Music.app) to $(bold_face /Applications)." \
| tee -a ${LOG_FILE}
(set +e;
sudo xcodebuild -project BGMApp/BGMApp.xcodeproj \
-target "Background Music" \
-configuration ${CONFIGURATION} \
RUN_CLANG_STATIC_ANALYZER=0 \
DSTROOT="/" \
install >> ${LOG_FILE} 2>&1) &
show_spinner
# 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
# same build directory we have to run xcodebuild as root to install BGMApp as well.)
sudo chown -R $(whoami):admin "/Applications/Background Music.app"
# Restart coreaudiod.
echo "Restarting coreaudiod to load BGMDriver." \
| tee -a ${LOG_FILE}
sudo launchctl kill SIGTERM system/com.apple.audio.coreaudiod
# Open BGMApp.
# I'd rather not open BGMApp here, or at least ask first, but you have to change your default audio
# device after restarting coreaudiod and this is the easiest way.
echo "Launching Background Music."
open "/Applications/Background Music.app"
# Wait up to 5 seconds for Background Music to start.
(while [[ "$(ps -u $(whoami) -o ucomm= | grep 'Background Music')" == "" ]]; do
sleep 1;
done) &
show_spinner 5
echo "Done."