This is mostly so BGMApp won't leave BGMDevice as the default if BGMApp
crashes, which would stop audio from playing until the user changed the
default device themselves. Also handles SIGINT, SIGTERM and SIGQUIT.
For crashes where the BGMApp process may be in an unknown state, e.g.
segfaults, BGMXPCHelper handles changing the default device.
Should fix the Travis Xcode 9 build, which is currently failing because
the AppleScript we use to quit BGMApp in .travis.yml gets "user
cancelled" for some reason.
Also makes some minor improvements to the reports generated by
CrashReporter. The way CrashReporter works with Background Music should
otherwise be unchanged.
Specifically, apps with NSApplicationActivationPolicyAccessory. That
includes status bar apps like Background Music, but also includes some
that aren't intended to be shown to users as applications like
SystemUIServer.
I'm not sure how much we can do about that. It would probably help if we
hid apps that BGMDriver isn't able to match to a CoreAudio client.
Resolves#122.
If the bundle ID passed to the function (a CACFString) was wrapping a
null CFStringRef, one of the comparison operator functions of CACFString
would pass null to CFStringCompare.
Similar to the one in macOS's Volume menu extra.
I'm mainly adding it so we can increase the output volume when the user
sets an app volume above 50%. Currently, setting an app volume above 50%
(the default) risks clipping, so it doesn't make sense to do so unless
your main output volume is at its max.
The volume slider added in this commit will make it clear to the user
that their main output volume is also increasing.
The other app volumes won't change, so in the ideal case the user
wouldn't need to be aware that their output device's volume is being
changed. But they might play audio to the device directly and would
expect it to play at the same volume as before they changed the app
volume.
Fix the workaround for apps whose bundle IDs don't match their CoreAudio
clients. BGMBackgroundMusicDevice::ResponsibleBundleIDsOf was always
returning an empty list.
Also fix over-releasing the app's bundle ID CFString in
BGMAVM_VolumeSlider::appVolumeChanged and
BGMAVM_PanSlider::appPanPositionChanged.
Both bugs were introduced two commits ago in
e05acde351.
There's still some code left that should be moved into the new class,
BGMBackgroundMusicDevice, but I think this is most of it.
This also helps reduce/contain the code that has to be aware of the
second instance of BGMDevice, which handles UI-related audio.
On macOS, apps are supposed to play UI-related sounds using the "system
default" device. This commit creates a new instance of BGM_Driver, which
BGMApp sets as the system default device. BGMApp ignores audio played to
that device when deciding whether to pause/unpause the user's music
player.
Since UI sounds are short, this helps avoid pausing the music player and
unpausing it shortly after.
Some apps have different bundle IDs to their CoreAudio clients, so
the bundle ID BGMApp sends with the app's volume doesn't match any
client in BGMDriver.
This change hardcodes the bundle IDs used by some popular apps and the
bundle IDs their clients use. We should be able to fix this for all
(almost all?) apps at some point.
It turns out that the HAL will sometimes call BGM_Driver::StartIO before
sending kAudioDevicePropertyDeviceIsRunning to BGMPlayThrough. In that
case, BGMApp would start playthrough and tell BGMDriver to return from
StartIO immediately, which meant we would drop the initial frames while
the output device started up.
So now BGMApp waits for the output device in that case as well.
Fixes#7.
The non-interactive version can be called by a Homebrew Cask formula.
Also, change some AppleScript to reference applications by their IDs
rather than their names, which should make them slightly more robust.
Also,
- add Background Music Device.driver to the array of bundles in
pkgbuild.plist, and
- don't warn about the permissions of the install dir for BGMXPCHelper
in build_and_install.sh if it's only building.
BGM_Device::Device_SetPropertyData was releasing the CFArray it gets
from the host (i.e. coreaudiod) when BGMApp sets
kAudioDeviceCustomPropertyEnabledOutputControls, which would deallocate
it, but coreaudiod also releases that CFArray.
Found with AddressSanitizer.
As a safety check, uninstall.sh refuses to delete a file if it's over a
certain size. With debug symbols, Background Music.app was just over the
previous 5MB limit.
BGMApp now disables BGMDevice's volume and/or mute controls if the
output device selected in BGMApp doesn't have matching controls. This
prevents the controls from being presented to the user when they don't
do anything.
In BGMPlayThrough, wait much longer for our IOProcs to stop themselves
before assuming something's gone wrong. In testing, rapidly changing
between output devices with and without controls while playing audio
would occasionally cause one of the IOProcs to take too long to stop
itself.
Also adds some basic scriptability, mainly so UI tests can use
AppleScript to check BGMApp's state that would be complicated to check
otherwise. (In this case, to check which output device is selected.)
Fixes#101.
If the Xcode command line tools were set to use a "command line tools
instance", which can be installed without having Xcode installed,
build_and_install.sh would fail. It prints an error message with a
command that can fix it if you do have Xcode installed, but the message
was kind of confusing and the command would fail if you didn't run it as
root.
build_and_install.sh now offers to run the command for you and then
continues the installation. I've also tried to make the message a bit
clearer and cleaned up some of the code.
Also fixes another bug that occurred with this configuration problem,
where the error from xcodebuild would be printed at an unintended (and
confusing) point in the script.
Fixes#108.