Skip to content

Commit

Permalink
Add optional debug logging in release builds.
Browse files Browse the repository at this point in the history
Clicking the status bar icon with the option key held now reveals a
setting that enables debug logging in BGMApp. It's enabled by default in
debug builds.

It doesn't enable debug logging in BGMDriver or BGMXPCHelper yet.

This will hopefully make it easier for people to include logs when they
report bugs that don't occur with most hardware or are otherwise hard to
reproduce.

Enabling debug logging should be unlikely to cause audio glitches, but I
haven't tried to make it completely safe.

Also,
 - add some basic unit tests for BGMPlayThrough and expand the mocks for
   the CoreAudio HAL API,
 - fix the UI tests so you can run them without code signing them, and
 - update copyright years.
  • Loading branch information
kyleneideck committed Jan 23, 2020
1 parent 8ca17bb commit 2c16773
Show file tree
Hide file tree
Showing 56 changed files with 3,182 additions and 439 deletions.
175 changes: 155 additions & 20 deletions BGMApp/BGMApp.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,42 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
enableAddressSanitizer = "YES"
language = ""
shouldUseLaunchSchemeArgsEnv = "YES">
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "27379B8E1C7F57DA0084A24C"
BuildableName = "BGMXPCHelper.xpc"
BlueprintName = "BGMXPCHelper"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "27379B8E1C7F57DA0084A24C"
BuildableName = "BGMXPCHelper.xpc"
BlueprintName = "BGMXPCHelper"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
<Testables>
<TestableReference
skipped = "NO">
Expand All @@ -41,24 +74,14 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "27379B8E1C7F57DA0084A24C"
BuildableName = "BGMXPCHelper.xpc"
BlueprintName = "BGMXPCHelper"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
language = ""
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand All @@ -82,6 +105,16 @@
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,47 @@
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES"
enableAddressSanitizer = "YES"
shouldUseLaunchSchemeArgsEnv = "YES">
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
codeCoverageEnabled = "YES"
onlyGenerateCoverageForSpecifiedTargets = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1CB8B3351BBA75EF000E2DD1"
BuildableName = "Background Music.app"
BlueprintName = "Background Music"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
<CodeCoverageTargets>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1CB8B3351BBA75EF000E2DD1"
BuildableName = "Background Music.app"
BlueprintName = "Background Music"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</CodeCoverageTargets>
<Testables>
<TestableReference
skipped = "NO">
skipped = "NO"
parallelizable = "YES"
testExecutionOrdering = "random">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "2743C9F51D86CFF90089613B"
Expand All @@ -50,23 +86,14 @@
</BuildableReference>
</TestableReference>
</Testables>
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "1CB8B3351BBA75EF000E2DD1"
BuildableName = "Background Music.app"
BlueprintName = "Background Music"
ReferencedContainer = "container:BGMApp.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
enableAddressSanitizer = "YES"
enableASanStackUseAfterReturn = "YES"
enableUBSanitizer = "YES"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
Expand Down Expand Up @@ -101,6 +128,16 @@
</EnvironmentVariable>
</EnvironmentVariables>
<AdditionalOptions>
<AdditionalOption
key = "NSZombieEnabled"
value = "YES"
isEnabled = "YES">
</AdditionalOption>
<AdditionalOption
key = "MallocScribble"
value = ""
isEnabled = "YES">
</AdditionalOption>
</AdditionalOptions>
</LaunchAction>
<ProfileAction
Expand Down
15 changes: 15 additions & 0 deletions BGMApp/BGMApp/BGMApp-Debug.entitlements
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?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">
<dict>
<key>com.apple.security.automation.apple-events</key>
<true/>
<key>com.apple.security.device.audio-input</key>
<true/>
<!--
Without this key, AddressSanitizer and the UI tests would only work when BGMApp is code signed.
-->
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>
File renamed without changes.
3 changes: 2 additions & 1 deletion BGMApp/BGMApp/BGMAppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// BGMAppDelegate.h
// BGMApp
//
// Copyright © 2016, 2017 Kyle Neideck
// Copyright © 2016, 2017, 2020 Kyle Neideck
//
// Sets up and tears down the app.
//
Expand Down Expand Up @@ -50,6 +50,7 @@ static NSInteger const kSeparatorBelowVolumesMenuItemTag = 4;
@property (unsafe_unretained) IBOutlet NSTextView* aboutPanelLicenseView;

@property (weak) IBOutlet NSMenuItem* autoPauseMenuItemUnwrapped;
@property (weak) IBOutlet NSMenuItem* debugLoggingMenuItemUnwrapped;

@property (readonly) BGMAudioDeviceManager* audioDevices;

Expand Down
9 changes: 8 additions & 1 deletion BGMApp/BGMApp/BGMAppDelegate.mm
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// BGMAppDelegate.mm
// BGMApp
//
// Copyright © 2016-2019 Kyle Neideck
// Copyright © 2016-2020 Kyle Neideck
//

// Self Include
Expand All @@ -28,6 +28,7 @@
#import "BGMAppVolumesController.h"
#import "BGMAutoPauseMusic.h"
#import "BGMAutoPauseMenuItem.h"
#import "BGMDebugLoggingMenuItem.h"
#import "BGMMusicPlayers.h"
#import "BGMOutputDeviceMenuSection.h"
#import "BGMOutputVolumeMenuItem.h"
Expand Down Expand Up @@ -66,6 +67,7 @@ @implementation BGMAppDelegate {
BGMAppVolumesController* appVolumes;
BGMOutputDeviceMenuSection* outputDeviceMenuSection;
BGMPreferencesMenu* prefsMenu;
BGMDebugLoggingMenuItem* debugLoggingMenuItem;
BGMXPCListener* xpcListener;
BGMPreferredOutputDevices* preferredOutputDevices;
}
Expand Down Expand Up @@ -251,6 +253,11 @@ - (void) setUpMainMenu {
aboutPanel:self.aboutPanel
aboutPanelLicenseView:self.aboutPanelLicenseView];

// Enable/disable debug logging. Hidden unless you option-click the status bar icon.
debugLoggingMenuItem =
[[BGMDebugLoggingMenuItem alloc] initWithMenuItem:self.debugLoggingMenuItemUnwrapped];
[statusBarItem setDebugLoggingMenuItem:debugLoggingMenuItem];

// Handle events about the main menu. (See the NSMenuDelegate methods below.)
self.bgmMenu.delegate = self;
}
Expand Down
11 changes: 6 additions & 5 deletions BGMApp/BGMApp/BGMAppVolumes.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
// BGMAppVolumes.m
// BGMApp
//
// Copyright © 2016-2018 Kyle Neideck
// Copyright © 2016-2020 Kyle Neideck
// Copyright © 2017 Andrew Tonner
//

Expand Down Expand Up @@ -196,14 +196,15 @@ - (void) showHideExtraControls:(BGMAVM_ShowMoreControlsButton*)button {

BGMAssert(button, "!button");
BGMAssert(menuItem, "!menuItem");

CGFloat width = menuItem.view.frame.size.width;
CGFloat height = menuItem.view.frame.size.height;

#if DEBUG
const char* appName = [((NSRunningApplication*)menuItem.representedObject).localizedName UTF8String];
CGFloat height = menuItem.view.frame.size.height;
#endif

const char* appName =
[((NSRunningApplication*)menuItem.representedObject).localizedName UTF8String];

// Using this function (instead of just ==) shouldn't be necessary, but just in case.
BOOL(^nearEnough)(CGFloat x, CGFloat y) = ^BOOL(CGFloat x, CGFloat y) {
return fabs(x - y) < 0.01; // We don't need much precision.
Expand Down
2 changes: 1 addition & 1 deletion BGMApp/BGMApp/BGMAudioDevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ BGMAudioDevice::BGMAudioDevice(const CAHALAudioDevice& inDevice)
:
BGMAudioDevice(inDevice.GetObjectID())
{
};
}

BGMAudioDevice::~BGMAudioDevice()
{
Expand Down
5 changes: 3 additions & 2 deletions BGMApp/BGMApp/BGMAudioDevice.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
// BGMAudioDevice.h
// BGMApp
//
// Copyright © 2017 Kyle Neideck
// Copyright © 2017, 2020 Kyle Neideck
//
// A HAL audio device. Note that this class's only state is the AudioObjectID of the device.
//
Expand Down Expand Up @@ -59,7 +59,8 @@ class BGMAudioDevice
operator AudioObjectID() const { return GetObjectID(); }

/*!
@return True if this device is BGMDevice. (Specifically, the main instance of BGMDevice.)
@return True if this device is BGMDevice. (Specifically, the main instance of BGMDevice, not
the instance used for UI sounds.)
@throws CAException If the HAL returns an error when queried.
*/
bool IsBGMDevice() const { return IsBGMDevice(false); };
Expand Down
48 changes: 48 additions & 0 deletions BGMApp/BGMApp/BGMDebugLoggingMenuItem.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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/>.

//
// BGMDebugLoggingMenuItem.h
// BGMApp
//
// Copyright © 2020 Kyle Neideck
//
// A menu item in the main menu that enables/disables debug logging. Only visible if you hold the
// option down when you click the status bar icon to reveal the main menu.
//
// TODO: It would be better to have this menu item in the Preferences menu (maybe in an Advanced
// section) and always visible, but first we'd need to add something that tells the user how
// to view the log messages. Or better yet, something that automatically opens them.
//

// System Includes
#import <Cocoa/Cocoa.h>


#pragma clang assume_nonnull begin

@interface BGMDebugLoggingMenuItem : NSObject

- (instancetype) initWithMenuItem:(NSMenuItem*)menuItem;

// True if the main menu is showing hidden items/options because the user held the option key when
// they clicked the icon. This class makes the debug logging menu item visible if this property has
// been set true or if debug logging is enabled.
@property (nonatomic) BOOL menuShowingExtraOptions;

@end

#pragma clang assume_nonnull end

Loading

0 comments on commit 2c16773

Please sign in to comment.