├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── other.md
└── workflows
│ └── build-test-release.yml
├── .gitignore
├── BGM.xcworkspace
└── contents.xcworkspacedata
├── BGMApp
├── BGMApp.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── BGMXPCHelper.xcscheme
│ │ └── Background Music.xcscheme
├── BGMApp
│ ├── BGMApp-Debug.entitlements
│ ├── BGMApp.entitlements
│ ├── BGMAppDelegate.h
│ ├── BGMAppDelegate.mm
│ ├── BGMAppVolumes.h
│ ├── BGMAppVolumes.m
│ ├── BGMAppVolumesController.h
│ ├── BGMAppVolumesController.mm
│ ├── BGMAppWatcher.h
│ ├── BGMAppWatcher.m
│ ├── BGMAudioDevice.cpp
│ ├── BGMAudioDevice.h
│ ├── BGMAudioDeviceManager.h
│ ├── BGMAudioDeviceManager.mm
│ ├── BGMAutoPauseMenuItem.h
│ ├── BGMAutoPauseMenuItem.m
│ ├── BGMAutoPauseMusic.h
│ ├── BGMAutoPauseMusic.mm
│ ├── BGMBackgroundMusicDevice.cpp
│ ├── BGMBackgroundMusicDevice.h
│ ├── BGMDebugLoggingMenuItem.h
│ ├── BGMDebugLoggingMenuItem.m
│ ├── BGMDeviceControlSync.cpp
│ ├── BGMDeviceControlSync.h
│ ├── BGMDeviceControlsList.cpp
│ ├── BGMDeviceControlsList.h
│ ├── BGMOutputDeviceMenuSection.h
│ ├── BGMOutputDeviceMenuSection.mm
│ ├── BGMOutputVolumeMenuItem.h
│ ├── BGMOutputVolumeMenuItem.mm
│ ├── BGMPlayThrough.cpp
│ ├── BGMPlayThrough.h
│ ├── BGMPlayThroughRTLogger.cpp
│ ├── BGMPlayThroughRTLogger.h
│ ├── BGMPreferredOutputDevices.h
│ ├── BGMPreferredOutputDevices.mm
│ ├── BGMStatusBarItem.h
│ ├── BGMStatusBarItem.mm
│ ├── BGMSystemSoundsVolume.h
│ ├── BGMSystemSoundsVolume.mm
│ ├── BGMTermination.h
│ ├── BGMTermination.mm
│ ├── BGMUserDefaults.h
│ ├── BGMUserDefaults.m
│ ├── BGMVolumeChangeListener.cpp
│ ├── BGMVolumeChangeListener.h
│ ├── BGMXPCListener.h
│ ├── BGMXPCListener.mm
│ ├── Base.lproj
│ │ └── MainMenu.xib
│ ├── Images.xcassets
│ │ ├── AirPlayIcon.imageset
│ │ │ ├── AirPlay.pdf
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── appicon_1024.png
│ │ │ ├── appicon_128.png
│ │ │ ├── appicon_16.png
│ │ │ ├── appicon_256.png
│ │ │ ├── appicon_32.png
│ │ │ ├── appicon_512.png
│ │ │ └── appicon_64.png
│ │ ├── Contents.json
│ │ ├── FermataIcon.imageset
│ │ │ ├── Contents.json
│ │ │ └── FermataIcon.pdf
│ │ ├── Volume0.imageset
│ │ │ ├── Contents.json
│ │ │ └── Volume0.pdf
│ │ ├── Volume1.imageset
│ │ │ ├── Contents.json
│ │ │ └── Volume1.pdf
│ │ ├── Volume2.imageset
│ │ │ ├── Contents.json
│ │ │ └── Volume2.pdf
│ │ └── Volume3.imageset
│ │ │ ├── Contents.json
│ │ │ └── Volume3.pdf
│ ├── Info.plist
│ ├── LICENSE
│ ├── Music Players
│ │ ├── BGMDecibel.h
│ │ ├── BGMDecibel.m
│ │ ├── BGMGooglePlayMusicDesktopPlayer.h
│ │ ├── BGMGooglePlayMusicDesktopPlayer.m
│ │ ├── BGMGooglePlayMusicDesktopPlayerConnection.h
│ │ ├── BGMGooglePlayMusicDesktopPlayerConnection.m
│ │ ├── BGMHermes.h
│ │ ├── BGMHermes.m
│ │ ├── BGMMusic.h
│ │ ├── BGMMusic.m
│ │ ├── BGMMusicPlayer.h
│ │ ├── BGMMusicPlayer.m
│ │ ├── BGMMusicPlayers.h
│ │ ├── BGMMusicPlayers.mm
│ │ ├── BGMScriptingBridge.h
│ │ ├── BGMScriptingBridge.m
│ │ ├── BGMSpotify.h
│ │ ├── BGMSpotify.m
│ │ ├── BGMSwinsian.h
│ │ ├── BGMSwinsian.m
│ │ ├── BGMVLC.h
│ │ ├── BGMVLC.m
│ │ ├── BGMVOX.h
│ │ ├── BGMVOX.m
│ │ ├── BGMiTunes.h
│ │ ├── BGMiTunes.m
│ │ ├── Decibel.h
│ │ ├── GooglePlayMusicDesktopPlayer.js
│ │ ├── Hermes.h
│ │ ├── Music.h
│ │ ├── Spotify.h
│ │ ├── Swinsian.h
│ │ ├── VLC.h
│ │ ├── VOX.h
│ │ └── iTunes.h
│ ├── Preferences
│ │ ├── BGMAboutPanel.h
│ │ ├── BGMAboutPanel.m
│ │ ├── BGMAutoPauseMusicPrefs.h
│ │ ├── BGMAutoPauseMusicPrefs.mm
│ │ ├── BGMPreferencesMenu.h
│ │ └── BGMPreferencesMenu.mm
│ ├── Scripting
│ │ ├── BGMASApplication.h
│ │ ├── BGMASApplication.m
│ │ ├── BGMASOutputDevice.h
│ │ ├── BGMASOutputDevice.mm
│ │ ├── BGMApp.sdef
│ │ ├── BGMAppDelegate+AppleScript.h
│ │ └── BGMAppDelegate+AppleScript.mm
│ ├── SystemPreferences.h
│ ├── _uninstall-non-interactive.sh
│ └── main.m
├── BGMAppTests
│ ├── UITests
│ │ ├── BGMApp.h
│ │ ├── BGMAppUITests-Info.plist
│ │ ├── BGMAppUITests.mm
│ │ └── skip-ui-tests.py
│ └── UnitTests
│ │ ├── BGMAppUnitTests-Info.plist
│ │ ├── BGMMusicPlayersUnitTests.mm
│ │ ├── BGMPlayThroughRTLoggerTests.mm
│ │ ├── BGMPlayThroughTests.mm
│ │ └── Mocks
│ │ ├── MockAudioDevice.cpp
│ │ ├── MockAudioDevice.h
│ │ ├── MockAudioObject.cpp
│ │ ├── MockAudioObject.h
│ │ ├── MockAudioObjects.cpp
│ │ ├── MockAudioObjects.h
│ │ ├── Mock_CAHALAudioDevice.cpp
│ │ ├── Mock_CAHALAudioObject.cpp
│ │ └── Mock_CAHALAudioSystemObject.cpp
├── BGMThreadSafetyAnalysis.h
├── BGMXPCHelper
│ ├── BGMXPCHelperService.h
│ ├── BGMXPCHelperService.mm
│ ├── BGMXPCListenerDelegate.h
│ ├── BGMXPCListenerDelegate.m
│ ├── Info.plist
│ ├── com.bearisdriving.BGM.XPCHelper.plist.template
│ ├── main.m
│ ├── post_install.sh
│ └── safe_install_dir.sh
├── BGMXPCHelperTests
│ ├── BGMXPCHelperTests-Info.plist
│ └── BGMXPCHelperTests.m
├── OptimizationProfiles
│ └── BGMApp.profdata
└── PublicUtility
│ ├── BGMDebugLogging.c
│ ├── BGMDebugLogging.h
│ ├── CAAtomic.h
│ ├── CAAutoDisposer.h
│ ├── CABitOperations.h
│ ├── CACFArray.cpp
│ ├── CACFArray.h
│ ├── CACFDictionary.cpp
│ ├── CACFDictionary.h
│ ├── CACFNumber.cpp
│ ├── CACFNumber.h
│ ├── CACFString.cpp
│ ├── CACFString.h
│ ├── CADebugMacros.cpp
│ ├── CADebugMacros.h
│ ├── CADebugPrintf.cpp
│ ├── CADebugPrintf.h
│ ├── CADebugger.cpp
│ ├── CADebugger.h
│ ├── CAException.h
│ ├── CAHALAudioDevice.cpp
│ ├── CAHALAudioDevice.h
│ ├── CAHALAudioObject.cpp
│ ├── CAHALAudioObject.h
│ ├── CAHALAudioStream.cpp
│ ├── CAHALAudioStream.h
│ ├── CAHALAudioSystemObject.cpp
│ ├── CAHALAudioSystemObject.h
│ ├── CAHostTimeBase.cpp
│ ├── CAHostTimeBase.h
│ ├── CAMutex.cpp
│ ├── CAMutex.h
│ ├── CAPThread.cpp
│ ├── CAPThread.h
│ ├── CAPropertyAddress.h
│ ├── CARingBuffer.cpp
│ └── CARingBuffer.h
├── BGMDriver
├── BGMDriver.xcodeproj
│ ├── project.pbxproj
│ └── xcshareddata
│ │ └── xcschemes
│ │ ├── Background Music Device.xcscheme
│ │ └── PublicUtility.xcscheme
├── BGMDriver
│ ├── BGM_AbstractDevice.cpp
│ ├── BGM_AbstractDevice.h
│ ├── BGM_AudibleState.cpp
│ ├── BGM_AudibleState.h
│ ├── BGM_Control.cpp
│ ├── BGM_Control.h
│ ├── BGM_Device.cpp
│ ├── BGM_Device.h
│ ├── BGM_MuteControl.cpp
│ ├── BGM_MuteControl.h
│ ├── BGM_NullDevice.cpp
│ ├── BGM_NullDevice.h
│ ├── BGM_Object.cpp
│ ├── BGM_Object.h
│ ├── BGM_PlugIn.cpp
│ ├── BGM_PlugIn.h
│ ├── BGM_PlugInInterface.cpp
│ ├── BGM_Stream.cpp
│ ├── BGM_Stream.h
│ ├── BGM_TaskQueue.cpp
│ ├── BGM_TaskQueue.h
│ ├── BGM_VolumeControl.cpp
│ ├── BGM_VolumeControl.h
│ ├── BGM_WrappedAudioEngine.cpp
│ ├── BGM_WrappedAudioEngine.h
│ ├── BGM_XPCHelper.h
│ ├── BGM_XPCHelper.m
│ ├── DeviceClients
│ │ ├── BGM_Client.cpp
│ │ ├── BGM_Client.h
│ │ ├── BGM_ClientMap.cpp
│ │ ├── BGM_ClientMap.h
│ │ ├── BGM_ClientTasks.h
│ │ ├── BGM_Clients.cpp
│ │ └── BGM_Clients.h
│ ├── DeviceIcon.icns
│ ├── Info.plist
│ └── quick_install.sh
├── BGMDriverTests
│ ├── BGM_ClientMapTests.mm
│ ├── BGM_ClientsTests.mm
│ ├── BGM_DeviceTests.mm
│ └── Info.plist
└── PublicUtility
│ ├── CAAtomic.h
│ ├── CAAtomicStack.h
│ ├── CAAutoDisposer.h
│ ├── CABitOperations.h
│ ├── CACFArray.cpp
│ ├── CACFArray.h
│ ├── CACFDictionary.cpp
│ ├── CACFDictionary.h
│ ├── CACFNumber.cpp
│ ├── CACFNumber.h
│ ├── CACFString.cpp
│ ├── CACFString.h
│ ├── CADebugMacros.cpp
│ ├── CADebugMacros.h
│ ├── CADebugPrintf.cpp
│ ├── CADebugPrintf.h
│ ├── CADebugger.cpp
│ ├── CADebugger.h
│ ├── CADispatchQueue.cpp
│ ├── CADispatchQueue.h
│ ├── CAException.h
│ ├── CAHostTimeBase.cpp
│ ├── CAHostTimeBase.h
│ ├── CAMutex.cpp
│ ├── CAMutex.h
│ ├── CAPThread.cpp
│ ├── CAPThread.h
│ ├── CAPropertyAddress.h
│ ├── CARingBuffer.cpp
│ ├── CARingBuffer.h
│ ├── CAVolumeCurve.cpp
│ └── CAVolumeCurve.h
├── CONTRIBUTING.md
├── DEVELOPING.md
├── Images
├── FermataIcon.pdf
├── FermataIcon.tex
├── README
│ ├── FermataIcon.png
│ ├── Screenshot.png
│ └── pkg-icon.png
├── VolumeIcons.tex
├── generate_icon_pngs.sh
└── iconizer.sh
├── LICENSE
├── LICENSE-Apple-Sample-Code
├── MANUAL-INSTALL.md
├── MANUAL-UNINSTALL.md
├── README.md
├── SharedSource
├── BGMXPCProtocols.h
├── BGM_TestUtils.h
├── BGM_Types.h
├── BGM_Utils.cpp
├── BGM_Utils.h
└── Scripts
│ └── set-version.sh
├── TODO.md
├── build_and_install.sh
├── package.sh
├── pkg
├── Distribution.xml.template
├── ListInputDevices.swift
├── README.md
├── pkgbuild.plist
├── postinstall
└── preinstall
└── uninstall.sh
/.editorconfig:
--------------------------------------------------------------------------------
1 | # This file was added to get GitHub to display our source code correctly when
2 | # it has mixed tabs and spaces. (I didn't realise the sample code BGMDriver is
3 | # based on used tabs and it's too late to fix it now.)
4 | #
5 | # See http://editorconfig.org.
6 |
7 | # This is the top-most .editorconfig file.
8 | root = true
9 |
10 | # Set tabs to the width of 4 spaces in C, C++, Objective-C and Objective-C++
11 | # source files.
12 | [*.{h,c,cpp,m,mm}]
13 | tab_width = 4
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | ## Example bug report template
11 |
12 | > Don't worry if you have trouble getting some of this info. Just leave it out.
13 |
14 | **Description of the bug**
15 | > Please don't just say it's "not working".
16 |
17 | **Steps to reproduce**
18 | > Steps to reproduce the bug. This usually doesn't need to be super detailed.
19 | 1. Go to '...'
20 | 2. Click on '...'
21 | 3. See error message '...'
22 |
23 | **Versions**
24 | > Please complete the following information.
25 | - Background Music: [e.g. "0.4.3" or "0.4.0-SNAPSHOT-c0ab98b". `Preferences > About Background Music`]
26 | - macOS: [e.g. "11.3 Beta (20E5172i)" or "Big Sur". ` > About This Mac`]
27 |
28 | **Hardware**
29 | > Delete this part if you think it's probably not necessary.
30 | - Computer: [e.g. "MacBook Pro (13-inch, 2016, Four Thunderbolt 3 Ports)". ` > About This Mac`]
31 | - Audio Device: [e.g. "Built-in Output. Manufacturer: Apple Inc. Output Channels: 2 [...]". `System Information app > Hardware > Audio`]
32 |
33 | **Debug logs**
34 | > If you think the developers might not be able to reproduce the bug on their computers, e.g. because an important feature is completely broken and they would have noticed, it can help to include [debug logs](https://github.com/kyleneideck/BackgroundMusic/wiki/Getting-Debug-Logs). This takes a little effort, so feel free to leave it out at first.
35 |
36 | [Debug logs attached here](https://github.com/example/background-music-debug-logs.txt)
37 |
38 | **Other info**
39 | > Anything else you want to add?
40 |
41 | ---
42 |
43 | > Tips
44 | > (Delete this section before posting.)
45 | > - https://github.com/kyleneideck/BackgroundMusic#troubleshooting
46 | > - Try the latest SNAPSHOT version from https://github.com/kyleneideck/BackgroundMusic/releases (if it's newer than the latest non-SNAPSHOT release).
47 | > - If your bug is one of these common issues, consider leaving a comment or a +1 (👍) on an existing issue:
48 | > - Background Music currently only supports audio devices with two channels. Bluetooth devices often only have one.
49 | > - Volumes having no effect for certain apps: Microsoft Teams ([workaround](https://github.com/kyleneideck/BackgroundMusic/issues/268#issuecomment-604977210)), Zoom ([workaround](https://github.com/kyleneideck/BackgroundMusic/issues/396#issuecomment-741992157)), Discord ([workaround](https://github.com/kyleneideck/BackgroundMusic/issues/210#issuecomment-507048957), [see also](https://github.com/kyleneideck/BackgroundMusic/issues/267#issuecomment-617327850)), Chrome (sometimes)
50 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/other.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Other
3 | about: Feature request, question, support request or anything else
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | > There's no template for this issue type. I just wanted to make it clear that it's OK to submit other types of issues.
11 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | .*.swp
3 | /BGMDriver/BGMDriver/quick_install.conf
4 | /build_and_install.log
5 | .idea/
6 | tags
7 | cmake-build-debug/
8 | /Background-Music-*/
9 | BGM.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
10 | Images/*.aux
11 | Images/*.log
12 | /archives/
13 |
14 | # Everything below is from https://github.com/github/gitignore/blob/master/Objective-C.gitignore
15 |
16 | ## Build generated
17 | build/
18 | DerivedData
19 |
20 | ## Various settings
21 | *.pbxuser
22 | !default.pbxuser
23 | *.mode1v3
24 | !default.mode1v3
25 | *.mode2v3
26 | !default.mode2v3
27 | *.perspectivev3
28 | !default.perspectivev3
29 | xcuserdata
30 |
31 | ## Other
32 | *.xccheckout
33 | *.moved-aside
34 | *.xcuserstate
35 | *.xcscmblueprint
36 |
37 | ## Obj-C/Swift specific
38 | *.hmap
39 | *.ipa
40 |
--------------------------------------------------------------------------------
/BGM.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
12 |
13 |
15 |
16 |
18 |
19 |
21 |
22 |
24 |
25 |
27 |
28 |
30 |
31 |
33 |
34 |
36 |
37 |
39 |
40 |
42 |
43 |
45 |
46 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMApp-Debug.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.automation.apple-events
6 |
7 | com.apple.security.device.audio-input
8 |
9 |
12 | com.apple.security.cs.disable-library-validation
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMApp.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.automation.apple-events
6 |
7 | com.apple.security.device.audio-input
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAppDelegate.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAppDelegate.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2017, 2020 Kyle Neideck
21 | // Copyright © 2021 Marcus Wu
22 | //
23 | // Sets up and tears down the app.
24 | //
25 |
26 | // System Includes
27 | #import
28 |
29 | @class BGMAudioDeviceManager;
30 | @class BGMAppVolumesController;
31 |
32 | // Tags for UI elements in MainMenu.xib
33 | static NSInteger const kVolumesHeadingMenuItemTag = 3;
34 | static NSInteger const kSeparatorBelowVolumesMenuItemTag = 4;
35 |
36 | @interface BGMAppDelegate : NSObject
37 |
38 | @property (weak) IBOutlet NSMenu* bgmMenu;
39 |
40 | @property (weak) IBOutlet NSView* outputVolumeView;
41 | @property (weak) IBOutlet NSTextField* outputVolumeLabel;
42 | @property (weak) IBOutlet NSSlider* outputVolumeSlider;
43 |
44 | @property (weak) IBOutlet NSView* systemSoundsView;
45 | @property (weak) IBOutlet NSSlider* systemSoundsSlider;
46 |
47 | @property (weak) IBOutlet NSView* appVolumeView;
48 |
49 | @property (weak) IBOutlet NSPanel* aboutPanel;
50 | @property (unsafe_unretained) IBOutlet NSTextView* aboutPanelLicenseView;
51 |
52 | @property (weak) IBOutlet NSMenuItem* autoPauseMenuItemUnwrapped;
53 | @property (weak) IBOutlet NSMenuItem* debugLoggingMenuItemUnwrapped;
54 |
55 | @property (readonly) BGMAudioDeviceManager* audioDevices;
56 | @property BGMAppVolumesController* appVolumes;
57 |
58 | @end
59 |
60 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAppVolumes.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAppVolumes.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2017 Kyle Neideck
21 | // Copyright © 2021 Marcus Wu
22 | //
23 |
24 | // Local Includes
25 | #import "BGMAppVolumesController.h"
26 |
27 | // System Includes
28 | #import
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | @interface BGMAppVolumes : NSObject
34 |
35 | - (id) initWithController:(BGMAppVolumesController*)inController
36 | bgmMenu:(NSMenu*)inMenu
37 | appVolumeView:(NSView*)inView;
38 |
39 | // Pass -1 for initialVolume or kAppPanNoValue for initialPan to leave the volume/pan at its default level.
40 | - (void) insertMenuItemForApp:(NSRunningApplication*)app
41 | initialVolume:(int)volume
42 | initialPan:(int)pan;
43 |
44 | - (void) removeMenuItemForApp:(NSRunningApplication*)app;
45 |
46 | - (void) removeAllAppVolumeMenuItems;
47 |
48 | - (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication*)app;
49 | - (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app;
50 |
51 | @end
52 |
53 | // Protocol for the UI custom classes
54 |
55 | @protocol BGMAppVolumeMenuItemSubview
56 |
57 | - (void) setUpWithApp:(NSRunningApplication*)app
58 | context:(BGMAppVolumes*)ctx
59 | controller:(BGMAppVolumesController*)ctrl
60 | menuItem:(NSMenuItem*)item;
61 |
62 | @end
63 |
64 | // Custom classes for the UI elements in the app volume menu items
65 |
66 | @interface BGMAVM_AppIcon : NSImageView
67 | @end
68 |
69 | @interface BGMAVM_AppNameLabel : NSTextField
70 | @end
71 |
72 | @interface BGMAVM_ShowMoreControlsButton : NSButton
73 | @end
74 |
75 | @interface BGMAVM_VolumeSlider : NSSlider
76 |
77 | - (void) setRelativeVolume:(int)relativeVolume;
78 |
79 | @end
80 |
81 | @interface BGMAVM_PanSlider : NSSlider
82 |
83 | - (void) setPanPosition:(int)panPosition;
84 |
85 | @end
86 |
87 | #pragma clang assume_nonnull end
88 |
89 |
90 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAppVolumesController.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAppVolumesController.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | // Copyright © 2021 Marcus Wu
22 | //
23 |
24 | // Local Includes
25 | #import "BGMAudioDeviceManager.h"
26 |
27 | // System Includes
28 | #import
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | typedef struct BGMAppVolumeAndPan {
34 | int volume;
35 | int pan;
36 | } BGMAppVolumeAndPan;
37 |
38 | @interface BGMAppVolumesController : NSObject
39 |
40 | - (id) initWithMenu:(NSMenu*)menu
41 | appVolumeView:(NSView*)view
42 | audioDevices:(BGMAudioDeviceManager*)audioDevices;
43 |
44 | // See BGMBackgroundMusicDevice::SetAppVolume.
45 | - (void) setVolume:(SInt32)volume
46 | forAppWithProcessID:(pid_t)processID
47 | bundleID:(NSString* __nullable)bundleID;
48 |
49 | // See BGMBackgroundMusicDevice::SetPanVolume.
50 | - (void) setPanPosition:(SInt32)pan
51 | forAppWithProcessID:(pid_t)processID
52 | bundleID:(NSString* __nullable)bundleID;
53 |
54 | - (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication *)app;
55 | - (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app;
56 |
57 | @end
58 |
59 | #pragma clang assume_nonnull end
60 |
61 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAppWatcher.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAppWatcher.h
18 | // BGMApp
19 | //
20 | // Copyright © 2019 Kyle Neideck
21 | //
22 | // Calls callback functions when a given application is launched or terminated. Starts watching
23 | // after being initialised, stops after being destroyed.
24 | //
25 |
26 | // System Includes
27 | #import
28 |
29 |
30 | #pragma clang assume_nonnull begin
31 |
32 | @interface BGMAppWatcher : NSObject
33 |
34 | // appLaunched will be called when the application is launched and appTerminated will be called when
35 | // it's terminated. Background apps, status bar apps, etc. are ignored.
36 | - (instancetype) initWithBundleID:(NSString*)bundleID
37 | appLaunched:(void(^)(void))appLaunched
38 | appTerminated:(void(^)(void))appTerminated;
39 |
40 | // With this constructor, when an application is launched or terminated, isMatchingBundleID will be
41 | // called first to decide whether or not the callback should be called.
42 | - (instancetype) initWithAppLaunched:(void(^)(void))appLaunched
43 | appTerminated:(void(^)(void))appTerminated
44 | isMatchingBundleID:(BOOL(^)(NSString* appBundleID))isMatchingBundleID;
45 |
46 | @end
47 |
48 | #pragma clang assume_nonnull end
49 |
50 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAutoPauseMenuItem.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAutoPauseMenuItem.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #import "BGMAutoPauseMusic.h"
25 | #import "BGMMusicPlayers.h"
26 | #import "BGMUserDefaults.h"
27 |
28 | // System Includes
29 | #import
30 |
31 |
32 | #pragma clang assume_nonnull begin
33 |
34 | @interface BGMAutoPauseMenuItem : NSObject
35 |
36 | - (instancetype) initWithMenuItem:(NSMenuItem*)item
37 | autoPauseMusic:(BGMAutoPauseMusic*)autoPause
38 | musicPlayers:(BGMMusicPlayers*)players
39 | userDefaults:(BGMUserDefaults*)defaults;
40 |
41 | // Handle events passed along by the delegate (NSMenuDelegate) of the menu containing this menu item.
42 | - (void) parentMenuNeedsUpdate;
43 | - (void) parentMenuItemWillHighlight:(NSMenuItem* __nullable)item;
44 |
45 | @end
46 |
47 | #pragma clang assume_nonnull end
48 |
49 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMAutoPauseMusic.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAutoPauseMusic.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 | // When enabled, BGMAutoPauseMusic listens for notifications from BGMDevice to tell when music is playing and
23 | // pauses the music player if other audio starts.
24 | //
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMMusicPlayers.h"
29 |
30 | // System Includes
31 | #import
32 |
33 |
34 | #pragma clang assume_nonnull begin
35 |
36 | @interface BGMAutoPauseMusic : NSObject
37 |
38 | - (id) initWithAudioDevices:(BGMAudioDeviceManager*)inAudioDevices musicPlayers:(BGMMusicPlayers*)inMusicPlayers;
39 |
40 | - (void) enable;
41 | - (void) disable;
42 |
43 | @end
44 |
45 | #pragma clang assume_nonnull end
46 |
47 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMDebugLoggingMenuItem.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMDebugLoggingMenuItem.h
18 | // BGMApp
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 | // A menu item in the main menu that enables/disables debug logging. Only visible if you hold the
23 | // option down when you click the status bar icon to reveal the main menu.
24 | //
25 | // TODO: It would be better to have this menu item in the Preferences menu (maybe in an Advanced
26 | // section) and always visible, but first we'd need to add something that tells the user how
27 | // to view the log messages. Or better yet, something that automatically opens them.
28 | //
29 |
30 | // System Includes
31 | #import
32 |
33 |
34 | #pragma clang assume_nonnull begin
35 |
36 | @interface BGMDebugLoggingMenuItem : NSObject
37 |
38 | - (instancetype) initWithMenuItem:(NSMenuItem*)menuItem;
39 |
40 | // True if the main menu is showing hidden items/options because the user held the option key when
41 | // they clicked the icon. This class makes the debug logging menu item visible if this property has
42 | // been set true or if debug logging is enabled.
43 | @property (nonatomic) BOOL menuShowingExtraOptions;
44 |
45 | @end
46 |
47 | #pragma clang assume_nonnull end
48 |
49 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMDebugLoggingMenuItem.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMDebugLoggingMenuItem.m
18 | // BGMApp
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMDebugLoggingMenuItem.h"
25 |
26 | // PublicUtility Includes
27 | #import "BGMDebugLogging.h"
28 | #import "CADebugMacros.h"
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | @implementation BGMDebugLoggingMenuItem {
34 | NSMenuItem* _menuItem;
35 | BOOL _menuShowingExtraOptions;
36 | }
37 |
38 | - (instancetype) initWithMenuItem:(NSMenuItem*)menuItem {
39 | if ((self = [super init])) {
40 | _menuItem = menuItem;
41 | _menuItem.state =
42 | BGMDebugLoggingIsEnabled() ? NSControlStateValueOn : NSControlStateValueOff;
43 |
44 | [self setMenuShowingExtraOptions:NO];
45 |
46 | // Enable/disable debug logging when the menu item is clicked.
47 | menuItem.target = self;
48 | menuItem.action = @selector(toggleDebugLogging);
49 | }
50 |
51 | return self;
52 | }
53 |
54 | - (void) setMenuShowingExtraOptions:(BOOL)showingExtra {
55 | _menuShowingExtraOptions = showingExtra;
56 | _menuItem.hidden = !BGMDebugLoggingIsEnabled() && !showingExtra;
57 |
58 | DebugMsg("BGMDebugLoggingMenuItem::menuShowingExtraOptions: %s the menu item",
59 | _menuItem.hidden ? "Hiding" : "Showing");
60 | }
61 |
62 | - (void) toggleDebugLogging {
63 | BGMSetDebugLoggingEnabled(!BGMDebugLoggingIsEnabled());
64 | _menuItem.state = BGMDebugLoggingIsEnabled() ? NSControlStateValueOn : NSControlStateValueOff;
65 |
66 | DebugMsg("BGMDebugLoggingMenuItem::toggleDebugLogging: Debug logging %s",
67 | BGMDebugLoggingIsEnabled() ? "enabled" : "disabled");
68 | }
69 |
70 | @end
71 |
72 | #pragma clang assume_nonnull end
73 |
74 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMOutputDeviceMenuSection.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMOutputDeviceMenuSection.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2018 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #import "BGMAudioDeviceManager.h"
25 | #import "BGMPreferredOutputDevices.h"
26 |
27 | // System Includes
28 | #import
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | @interface BGMOutputDeviceMenuSection : NSObject
34 |
35 | - (instancetype) initWithBGMMenu:(NSMenu*)inBGMMenu
36 | audioDevices:(BGMAudioDeviceManager*)inAudioDevices
37 | preferredDevices:(BGMPreferredOutputDevices*)inPreferredDevices;
38 |
39 | // To be called when BGMApp has been set to use a different output device. For example, when a new
40 | // device is connected and BGMPreferredOutputDevices decides BGMApp should switch to it.
41 | - (void) outputDeviceDidChange;
42 |
43 | @end
44 |
45 | #pragma clang assume_nonnull end
46 |
47 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMOutputVolumeMenuItem.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMOutputVolumeMenuItem.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #import "BGMAudioDeviceManager.h"
25 |
26 | // System Includes
27 | #import
28 |
29 |
30 | #pragma clang assume_nonnull begin
31 |
32 | @interface BGMOutputVolumeMenuItem : NSMenuItem
33 |
34 | // A menu item with a slider for controlling the volume of the output device. Similar to the one in
35 | // macOS's Volume menu extra.
36 | //
37 | // view, slider and deviceLabel are the UI elements from MainMenu.xib.
38 | - (instancetype) initWithAudioDevices:(BGMAudioDeviceManager*)devices
39 | view:(NSView*)view
40 | slider:(NSSlider*)slider
41 | deviceLabel:(NSTextField*)label;
42 |
43 | - (void) outputDeviceDidChange;
44 |
45 | @end
46 |
47 | #pragma clang assume_nonnull end
48 |
49 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMPreferredOutputDevices.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMPreferredOutputDevices.h
18 | // BGMApp
19 | //
20 | // Copyright © 2018 Kyle Neideck
21 | //
22 | // Tries to change BGMApp's output device when the user plugs in or unplugs an audio device, in the
23 | // same way macOS would change its default device if Background Music wasn't running.
24 | //
25 | // For example, if you plug in some USB headphones, make them your default device and then unplug
26 | // them, macOS will change its default device to the previous default device. Then, if you plug
27 | // them back in, macOS will make them the default device again.
28 | //
29 | // This class isn't always able to figure out what macOS would do, in which case it leaves BGMApp's
30 | // output device as it is.
31 | //
32 |
33 | // Local Includes
34 | #import "BGMAudioDeviceManager.h"
35 | #import "BGMUserDefaults.h"
36 |
37 | // System Includes
38 | #import
39 | #import
40 |
41 |
42 | #pragma clang assume_nonnull begin
43 |
44 | @interface BGMPreferredOutputDevices : NSObject
45 |
46 | // Starts responding to device connections/disconnections immediately. Stops if/when the instance is
47 | // deallocated.
48 | - (instancetype) initWithDevices:(BGMAudioDeviceManager*)devices
49 | userDefaults:(BGMUserDefaults*)userDefaults;
50 |
51 | // Returns the most-preferred device that's currently connected. If no preferred devices are
52 | // connected, returns the current output device. If the current output device has been disconnected,
53 | // returns an arbitrary device.
54 | //
55 | // If none of the connected devices can be used as the output device, or if it can't find a device
56 | // to use because the HAL returned errors when queried, returns kAudioObjectUnknown.
57 | - (AudioObjectID) findPreferredDevice;
58 |
59 | - (void) userChangedOutputDeviceTo:(AudioObjectID)device;
60 |
61 | @end
62 |
63 | #pragma clang assume_nonnull end
64 |
65 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMStatusBarItem.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMStatusBarItem.h
18 | // BGMApp
19 | //
20 | // Copyright © 2019, 2020 Kyle Neideck
21 | //
22 | // The button in the system status bar (the bar with volume, battery, clock, etc.) to show the main
23 | // menu for the app. These are called "menu bar extras" in the Human Interface Guidelines.
24 | //
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMDebugLoggingMenuItem.h"
29 |
30 | // System Includes
31 | #import
32 |
33 | // Forward Declarations
34 | @class BGMUserDefaults;
35 |
36 |
37 | #pragma clang assume_nonnull begin
38 |
39 | typedef NS_ENUM(NSInteger, BGMStatusBarIcon) {
40 | BGMFermataStatusBarIcon = 0,
41 | BGMVolumeStatusBarIcon
42 | };
43 |
44 | static BGMStatusBarIcon const kBGMStatusBarIconMinValue = BGMFermataStatusBarIcon;
45 | static BGMStatusBarIcon const kBGMStatusBarIconMaxValue = BGMVolumeStatusBarIcon;
46 | static BGMStatusBarIcon const kBGMStatusBarIconDefaultValue = BGMFermataStatusBarIcon;
47 |
48 | @interface BGMStatusBarItem : NSObject
49 |
50 | - (instancetype) initWithMenu:(NSMenu*)bgmMenu
51 | audioDevices:(BGMAudioDeviceManager*)devices
52 | userDefaults:(BGMUserDefaults*)defaults;
53 |
54 | // Set this to BGMFermataStatusBarIcon to change the icon to the Background Music logo.
55 | //
56 | // Set this to BGMFermataStatusBarIcon to change the icon to a volume icon. This icon has the
57 | // advantage of indicating the volume level, but we can't make it the default because it looks the
58 | // same as the icon for the macOS volume status bar item.
59 | @property BGMStatusBarIcon icon;
60 |
61 | // If the user holds down the option key when they click the status bar icon, this menu item will be
62 | // shown in the main menu.
63 | - (void) setDebugLoggingMenuItem:(BGMDebugLoggingMenuItem*)menuItem;
64 |
65 | @end
66 |
67 | #pragma clang assume_nonnull end
68 |
69 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMSystemSoundsVolume.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMSystemSoundsVolume.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 | // The menu item with the volume slider that controls system-related sounds. The slider is used to
23 | // set the volume of the instance of BGMDevice that system sounds are played on, i.e. the audio
24 | // device returned by BGMBackgroundMusicDevice::GetUISoundsBGMDeviceInstance.
25 | //
26 | // System sounds are any sounds played using the audio device macOS is set to use as the device
27 | // "for system related sound from the alert sound to digital call progress". See
28 | // kAudioHardwarePropertyDefaultSystemOutputDevice in AudioHardware.h. They can be played by any
29 | // app, though most apps use systemsoundserverd to play their system sounds, which means BGMDriver
30 | // can't tell which app is actually playing the sounds.
31 | //
32 |
33 | // Local Includes
34 | #import "BGMAudioDevice.h"
35 |
36 | // System Includes
37 | #import
38 |
39 |
40 | #pragma clang assume_nonnull begin
41 |
42 | @interface BGMSystemSoundsVolume : NSObject
43 |
44 | // The volume level of uiSoundsDevice will be used to set the slider's initial position and will be
45 | // updated when the user moves the slider. view and slider are the UI elements from MainMenu.xib.
46 | - (instancetype) initWithUISoundsDevice:(BGMAudioDevice)uiSoundsDevice
47 | view:(NSView*)view
48 | slider:(NSSlider*)slider;
49 |
50 | // The menu item with the volume slider for system sounds.
51 | @property (readonly) NSMenuItem* menuItem;
52 |
53 | @end
54 |
55 | #pragma clang assume_nonnull end
56 |
57 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMSystemSoundsVolume.mm:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMSystemSoundsVolume.mm
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMSystemSoundsVolume.h"
25 |
26 | // Local Includes
27 | #import "BGM_Types.h"
28 | #import "BGM_Utils.h"
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | // TODO: It's a bit confusing that this slider's default position is all the way right, but the App
34 | // Volumes sliders default to 50%. After you move the slider there's no way to tell how to put
35 | // it back to its normal position.
36 |
37 | NSString* const kMenuItemToolTip =
38 | @"Alerts, notification sounds, etc. Usually short. Can be played by any app.";
39 |
40 | @implementation BGMSystemSoundsVolume {
41 | BGMAudioDevice uiSoundsDevice;
42 | NSSlider* volumeSlider;
43 | }
44 |
45 | - (instancetype) initWithUISoundsDevice:(BGMAudioDevice)inUISoundsDevice
46 | view:(NSView*)inView
47 | slider:(NSSlider*)inSlider {
48 | if ((self = [super init])) {
49 | uiSoundsDevice = inUISoundsDevice;
50 | volumeSlider = inSlider;
51 |
52 | _menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
53 | _menuItem.toolTip = kMenuItemToolTip;
54 |
55 | // Apply our custom view from MainMenu.xib. It's very similar to the one for app volumes.
56 | _menuItem.view = inView;
57 |
58 | try {
59 | volumeSlider.floatValue =
60 | uiSoundsDevice.GetVolumeControlScalarValue(kAudioObjectPropertyScopeOutput,
61 | kMasterChannel);
62 | } catch (const CAException& e) {
63 | BGMLogException(e);
64 | volumeSlider.floatValue = 1.0f; // Full volume
65 | }
66 |
67 | volumeSlider.target = self;
68 | volumeSlider.action = @selector(systemSoundsSliderChanged:);
69 | }
70 |
71 | return self;
72 | }
73 |
74 | - (void) systemSoundsSliderChanged:(id)sender {
75 | #pragma unused(sender)
76 |
77 | float sliderLevel = volumeSlider.floatValue;
78 |
79 | BGMAssert((sliderLevel >= 0.0f) && (sliderLevel <= 1.0f), "Invalid value from slider");
80 | DebugMsg("BGMSystemSoundsVolume::systemSoundsSliderChanged: UI sounds volume: %f", sliderLevel);
81 |
82 | BGMLogAndSwallowExceptions("BGMSystemSoundsVolume::systemSoundsSliderChanged", ([&] {
83 | uiSoundsDevice.SetVolumeControlScalarValue(kAudioObjectPropertyScopeOutput,
84 | kMasterChannel,
85 | sliderLevel);
86 | }));
87 | }
88 |
89 | @end
90 |
91 | #pragma clang assume_nonnull end
92 |
93 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMTermination.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMTermination.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 | // Cleans up if BGMApp crashes because of an uncaught C++ or Objective-C exception, or is sent
23 | // SIGINT/SIGTERM/SIGQUIT. Currently, it just changes the default output device from BGMDevice to
24 | // the real output device and records debug info for some types of crashes.
25 | //
26 | // BGMXPCHelper also changes the default device if BGMApp disconnects and leaves BGMDevice as the
27 | // default. This handles cases like segfaults where it wouldn't be safe to clean up from the
28 | // crashing process.
29 | //
30 |
31 | #ifndef BGMApp__BGMTermination
32 | #define BGMApp__BGMTermination
33 |
34 | // Local Includes
35 | #import "BGMAudioDeviceManager.h"
36 |
37 | // PublicUtility Includes
38 | #import "CAPThread.h"
39 |
40 | // STL Includes
41 | #import
42 |
43 |
44 | #pragma clang assume_nonnull begin
45 |
46 | class BGMTermination
47 | {
48 |
49 | public:
50 | /*!
51 | Starts a thread that will clean up before exiting if BGMApp receives SIGINT, SIGTERM or
52 | SIGQUIT. Sets a similar clean up function to run if BGMApp terminates due to an uncaught
53 | exception.
54 | */
55 | static void SetUpTerminationCleanUp(BGMAudioDeviceManager* inAudioDevices);
56 |
57 | /*! Some commented out ways to have BGMApp crash for testing. Does nothing if unmodified. */
58 | static void TestCrash() __attribute__((noinline));
59 |
60 | private:
61 | static void StartExitSignalsThread();
62 |
63 | static void CleanUpAudioDevices();
64 |
65 | /*! Adds some info about the uncaught exception that caused a crash to the crash report. */
66 | static void AddCurrentExceptionToCrashReport();
67 |
68 | /*! The entry point for sExitSignalsThread. */
69 | static void* __nullable ExitSignalsProc(void* __nullable ignored);
70 |
71 | /*! The thread that handles SIGQUIT, SIGTERM and SIGINT. Never destroyed. */
72 | static CAPThread* const sExitSignalsThread;
73 | static sigset_t sExitSignals;
74 |
75 | /*! The function that handles std::terminate by default. */
76 | static std::terminate_handler sOriginalTerminateHandler;
77 |
78 | /*! The audio device manager. (Must be static to be accessed in our std::terminate_handler.) */
79 | static BGMAudioDeviceManager* __nullable sAudioDevices;
80 |
81 | };
82 |
83 | #pragma clang assume_nonnull end
84 |
85 | #endif /* BGMApp__BGMTermination */
86 |
87 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMUserDefaults.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMUserDefaults.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2019 Kyle Neideck
21 | //
22 | // A simple wrapper around our use of NSUserDefaults. Used to store the preferences/state that only
23 | // apply to BGMApp. The others are stored by BGMDriver.
24 | //
25 | // Private data will be stored in the user's keychain instead of user defaults.
26 | //
27 |
28 | // Local Includes
29 | #import "BGMStatusBarItem.h"
30 |
31 | // System Includes
32 | #import
33 |
34 |
35 | #pragma clang assume_nonnull begin
36 |
37 | @interface BGMUserDefaults : NSObject
38 |
39 | // If inDefaults is nil, settings are not loaded from or saved to disk, which is useful for testing.
40 | - (instancetype) initWithDefaults:(NSUserDefaults* __nullable)inDefaults;
41 |
42 | // The musicPlayerID (see BGMMusicPlayer.h), as a string, of the music player selected by the user.
43 | // Must be either null or a string that can be parsed by NSUUID.
44 | @property NSString* __nullable selectedMusicPlayerID;
45 |
46 | @property BOOL autoPauseMusicEnabled;
47 |
48 | // The UIDs of the output devices most recently selected by the user. The most-recently selected
49 | // device is at index 0. See BGMPreferredOutputDevices.
50 | @property NSArray* preferredDeviceUIDs;
51 |
52 | // The (type of) icon to show in the button in the status bar. (The button the user clicks to open
53 | // BGMApp's main menu.)
54 | @property BGMStatusBarIcon statusBarIcon;
55 |
56 | // The auth code we're required to send when connecting to GPMDP. Stored in the keychain. Reading
57 | // this property is thread-safe, but writing it isn't.
58 | //
59 | // Returns nil if no code is found or if reading fails. If writing fails, an error is logged, but no
60 | // exception is thrown.
61 | @property NSString* __nullable googlePlayMusicDesktopPlayerPermanentAuthCode;
62 |
63 | @end
64 |
65 | #pragma clang assume_nonnull end
66 |
67 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMVolumeChangeListener.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMVolumeChangeListener.h
18 | // BGMApp
19 | //
20 | // Copyright © 2019 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #include "BGMBackgroundMusicDevice.h"
25 |
26 | // PublicUtility Includes
27 | #import "CAPropertyAddress.h"
28 |
29 | // STL Includes
30 | #include
31 |
32 | // System Includes
33 | #include
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | class BGMVolumeChangeListener
39 | {
40 |
41 | public:
42 | /*!
43 | * @param device Listens for notifications about this device.
44 | * @param handler The function to call when the device's volume (or mute) changes. Called on the
45 | * main queue.
46 | */
47 | BGMVolumeChangeListener(BGMAudioDevice device, std::function handler);
48 | virtual ~BGMVolumeChangeListener();
49 | BGMVolumeChangeListener(const BGMVolumeChangeListener&) = delete;
50 | BGMVolumeChangeListener& operator=(const BGMVolumeChangeListener&) = delete;
51 |
52 | private:
53 | AudioObjectPropertyListenerBlock mListenerBlock;
54 | BGMAudioDevice mDevice;
55 |
56 | };
57 |
58 | #pragma clang assume_nonnull end
59 |
60 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/BGMXPCListener.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMXPCListener.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 | // Connects to BGMXPCHelper via XPC. When BGMDriver wants BGMApp to do something it can call one of BGMHelper's
23 | // XPC methods, which passes the request along to this class.
24 | //
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMXPCProtocols.h"
29 |
30 | // System Includes
31 | #import
32 |
33 |
34 | #pragma clang assume_nonnull begin
35 |
36 | @interface BGMXPCListener : NSObject
37 |
38 | - (id) initWithAudioDevices:(BGMAudioDeviceManager*)devices helperConnectionErrorHandler:(void (^)(NSError* error))errorHandler;
39 |
40 | - (void) initHelperConnection;
41 |
42 | @end
43 |
44 | #pragma clang assume_nonnull end
45 |
46 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AirPlayIcon.imageset/AirPlay.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AirPlayIcon.imageset/AirPlay.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AirPlayIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "AirPlay.pdf",
6 | "scale" : "1x"
7 | },
8 | {
9 | "idiom" : "universal",
10 | "scale" : "2x"
11 | },
12 | {
13 | "idiom" : "universal",
14 | "scale" : "3x"
15 | }
16 | ],
17 | "info" : {
18 | "version" : 1,
19 | "author" : "xcode"
20 | }
21 | }
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "size" : "16x16",
5 | "idiom" : "mac",
6 | "filename" : "appicon_16.png",
7 | "scale" : "1x"
8 | },
9 | {
10 | "size" : "16x16",
11 | "idiom" : "mac",
12 | "filename" : "appicon_32.png",
13 | "scale" : "2x"
14 | },
15 | {
16 | "size" : "32x32",
17 | "idiom" : "mac",
18 | "filename" : "appicon_32.png",
19 | "scale" : "1x"
20 | },
21 | {
22 | "size" : "32x32",
23 | "idiom" : "mac",
24 | "filename" : "appicon_64.png",
25 | "scale" : "2x"
26 | },
27 | {
28 | "size" : "128x128",
29 | "idiom" : "mac",
30 | "filename" : "appicon_128.png",
31 | "scale" : "1x"
32 | },
33 | {
34 | "size" : "128x128",
35 | "idiom" : "mac",
36 | "filename" : "appicon_256.png",
37 | "scale" : "2x"
38 | },
39 | {
40 | "size" : "256x256",
41 | "idiom" : "mac",
42 | "filename" : "appicon_256.png",
43 | "scale" : "1x"
44 | },
45 | {
46 | "size" : "256x256",
47 | "idiom" : "mac",
48 | "filename" : "appicon_512.png",
49 | "scale" : "2x"
50 | },
51 | {
52 | "size" : "512x512",
53 | "idiom" : "mac",
54 | "filename" : "appicon_512.png",
55 | "scale" : "1x"
56 | },
57 | {
58 | "size" : "512x512",
59 | "idiom" : "mac",
60 | "filename" : "appicon_1024.png",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_1024.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_128.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_16.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_256.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_32.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_512.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/AppIcon.appiconset/appicon_64.png
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/FermataIcon.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "FermataIcon.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/FermataIcon.imageset/FermataIcon.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/FermataIcon.imageset/FermataIcon.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume0.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Volume0.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume0.imageset/Volume0.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/Volume0.imageset/Volume0.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume1.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Volume1.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume1.imageset/Volume1.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/Volume1.imageset/Volume1.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume2.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Volume2.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume2.imageset/Volume2.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/Volume2.imageset/Volume2.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume3.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "mac",
5 | "filename" : "Volume3.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Images.xcassets/Volume3.imageset/Volume3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/kyleneideck/BackgroundMusic/3d4e1bff10e18b43c83bfc81f4ed9cb056c16a70/BGMApp/BGMApp/Images.xcassets/Volume3.imageset/Volume3.pdf
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | AudioHardwarePowerHint
6 | None
7 | CFBundleDevelopmentRegion
8 | en
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 0.4.3
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 1.0.0
25 | LSApplicationCategoryType
26 | public.app-category.utilities
27 | LSMinimumSystemVersion
28 | $(MACOSX_DEPLOYMENT_TARGET)
29 | LSUIElement
30 |
31 | NSAppleEventsUsageDescription
32 | Background Music needs to control your music player app if you want it to automatically pause your music.
33 | NSAppleScriptEnabled
34 |
35 | NSHumanReadableCopyright
36 | Copyright © 2016-2024 Background Music contributors
37 | NSMainNibFile
38 | MainMenu
39 | NSMicrophoneUsageDescription
40 | The "Background Music" virtual audio device sends system audio to Background Music (the app) through a virtual input device.
41 | NSPrincipalClass
42 | NSApplication
43 | NSServices
44 |
45 |
46 |
47 | OSAScriptingDefinition
48 | BGMApp.sdef
49 |
53 | NSSupportsAutomaticGraphicsSwitching
54 |
55 |
56 |
57 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMDecibel.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMDecibel.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMDecibel : BGMMusicPlayerBase
28 |
29 | @end
30 |
31 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMDecibel.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMDecibel.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2018 Kyle Neideck
21 | // Copyright © 2016 Tanner Hoke
22 | //
23 |
24 | // Self Include
25 | #import "BGMDecibel.h"
26 |
27 | // Auto-generated Scripting Bridge header
28 | #import "Decibel.h"
29 |
30 | // Local Includes
31 | #import "BGMScriptingBridge.h"
32 |
33 | // PublicUtility Includes
34 | #import "CADebugMacros.h"
35 |
36 |
37 | #pragma clang assume_nonnull begin
38 |
39 | @implementation BGMDecibel {
40 | BGMScriptingBridge* scriptingBridge;
41 | }
42 |
43 | - (instancetype) init {
44 | if ((self = [super initWithMusicPlayerID:[BGMMusicPlayerBase makeID:@"A9790CD5-4886-47C7-9FFC-DD70743CF2BF"]
45 | name:@"Decibel"
46 | bundleID:@"org.sbooth.Decibel"])) {
47 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
48 | }
49 |
50 | return self;
51 | }
52 |
53 | - (DecibelApplication* __nullable) decibel {
54 | return (DecibelApplication* __nullable)scriptingBridge.application;
55 | }
56 |
57 | - (void) wasSelected {
58 | [super wasSelected];
59 | [scriptingBridge ensurePermission];
60 | }
61 |
62 | - (BOOL) isRunning {
63 | return self.decibel.running;
64 | }
65 |
66 | - (BOOL) isPlaying {
67 | return self.running && self.decibel.playing;
68 | }
69 |
70 | - (BOOL) isPaused {
71 | // We don't want to return true when Decibel is stopped, rather than paused. At least for me, Decibel
72 | // returns -1 for playbackTime and playbackPosition when it's neither playing nor paused.
73 | BOOL probablyNotStopped =
74 | self.decibel.playbackTime >= 0 || self.decibel.playbackPosition >= 0;
75 |
76 | return self.running && !self.decibel.playing && probablyNotStopped;
77 | }
78 |
79 | - (BOOL) pause {
80 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
81 | BOOL wasPlaying = self.playing;
82 |
83 | if (wasPlaying) {
84 | DebugMsg("BGMDecibel::pause: Pausing Decibel");
85 | [self.decibel pause];
86 | }
87 |
88 | return wasPlaying;
89 | }
90 |
91 | - (BOOL) unpause {
92 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event
93 | BOOL wasPaused = self.paused;
94 |
95 | if (wasPaused) {
96 | DebugMsg("BGMDecibel::unpause: Unpausing Decibel");
97 | [self.decibel play];
98 | }
99 |
100 | return wasPaused;
101 | }
102 |
103 | @end
104 |
105 | #pragma clang assume_nonnull end
106 |
107 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMGooglePlayMusicDesktopPlayer.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMGooglePlayMusicDesktopPlayer.h
18 | // BGMApp
19 | //
20 | // Copyright © 2019 Kyle Neideck
21 | //
22 | // We have a lot more code for GPMDP than most music players largely because GPMDP has a WebSockets
23 | // API and because the user has to enter a code from GPMDP to allow BGMApp to control it.
24 | // Currently, the other music players all have AppleScript APIs, so for them the OS asks the user
25 | // for permission on our behalf automatically and handles the whole process for us.
26 | //
27 | // This class implements the usual BGMMusicPlayer methods and handles the UI for authenticating
28 | // with GPMDP. BGMGooglePlayMusicDesktopPlayerConnection manages the connection to GPMDP and hides
29 | // the details of its API.
30 | //
31 |
32 | // Superclass/Protocol Import
33 | #import "BGMMusicPlayer.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | API_AVAILABLE(macos(10.10))
39 | @interface BGMGooglePlayMusicDesktopPlayer : BGMMusicPlayerBase
40 |
41 | + (NSArray>*) createInstancesWithDefaults:(BGMUserDefaults*)userDefaults;
42 |
43 | @end
44 |
45 | #pragma clang assume_nonnull end
46 |
47 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMGooglePlayMusicDesktopPlayerConnection.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMGooglePlayMusicDesktopPlayerConnection.h
18 | // BGMApp
19 | //
20 | // Copyright © 2019 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #import "BGMUserDefaults.h"
25 |
26 | // System Includes
27 | #import
28 | #import
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | API_AVAILABLE(macos(10.10))
34 | @interface BGMGooglePlayMusicDesktopPlayerConnection : NSObject
35 |
36 | // authRequiredHandler: A UI callback that asks the user for the auth code GPMDP will display.
37 | // Returns the auth code they entered, or nil.
38 | // connectionErrorHandler: A UI callback that shows a connection error message.
39 | // apiVersionMismatchHandler: A UI callback that shows a warning dialog explaining that GPMDP
40 | // reported an API version that we don't support yet.
41 | - (instancetype) initWithUserDefaults:(BGMUserDefaults*)defaults
42 | authRequiredHandler:(NSString* __nullable (^)(void))authHandler
43 | connectionErrorHandler:(void (^)(void))errorHandler
44 | apiVersionMismatchHandler:(void (^)(NSString* reportedAPIVersion))apiVersionHandler;
45 |
46 | // Returns before the connection has been fully established. The playing and paused properties will
47 | // remain false until the connection is complete, but playPause can be called at any time after
48 | // calling this method.
49 | //
50 | // If the connection fails, it will be retried after a one second delay, up to the number of times
51 | // given.
52 | - (void) connectWithRetries:(int)retries;
53 | - (void) disconnect;
54 |
55 | // Tell GPMDP to play if it's paused or pause if it's playing.
56 | - (void) playPause;
57 |
58 | @property (readonly) BOOL playing;
59 | @property (readonly) BOOL paused;
60 |
61 | @end
62 |
63 | #pragma clang assume_nonnull end
64 |
65 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMHermes.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMHermes.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMHermes : BGMMusicPlayerBase
28 |
29 | @end
30 |
31 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMHermes.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMHermes.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2018 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMHermes.h"
25 |
26 | // Auto-generated Scripting Bridge header
27 | #import "Hermes.h"
28 |
29 | // Local Includes
30 | #import "BGMScriptingBridge.h"
31 |
32 | // PublicUtility Includes
33 | #import "CADebugMacros.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | @implementation BGMHermes {
39 | BGMScriptingBridge* scriptingBridge;
40 | }
41 |
42 | - (instancetype) init {
43 | // If you're copying this class, replace the ID string with a new one generated by uuidgen. (Command line tool.)
44 | if ((self = [super initWithMusicPlayerID:[BGMMusicPlayerBase makeID:@"0CDC67B0-56D3-4D94-BC06-6E380D8F5E34"]
45 | name:@"Hermes"
46 | bundleID:@"com.alexcrichton.Hermes"])) {
47 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
48 | }
49 |
50 | return self;
51 | }
52 |
53 | - (HermesApplication* __nullable) hermes {
54 | return (HermesApplication* __nullable)scriptingBridge.application;
55 | }
56 |
57 | - (void) wasSelected {
58 | [super wasSelected];
59 | [scriptingBridge ensurePermission];
60 | }
61 |
62 | - (BOOL) isRunning {
63 | // Note that this will return NO if is self.hermes is nil (i.e. Hermes isn't running).
64 | return self.hermes.running;
65 | }
66 |
67 | // isPlaying and isPaused check self.running first just in case Hermes is closed but self.hermes hasn't become
68 | // nil yet. In that case, reading self.hermes.playerState could make Scripting Bridge open Hermes.
69 |
70 | - (BOOL) isPlaying {
71 | return self.running && (self.hermes.playbackState == HermesPlayerStatesPlaying);
72 | }
73 |
74 | - (BOOL) isPaused {
75 | return self.running && (self.hermes.playbackState == HermesPlayerStatesPaused);
76 | }
77 |
78 | - (BOOL) pause {
79 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
80 | BOOL wasPlaying = self.playing;
81 |
82 | if (wasPlaying) {
83 | DebugMsg("BGMHermes::pause: Pausing Hermes");
84 | [self.hermes pause];
85 | }
86 |
87 | return wasPlaying;
88 | }
89 |
90 | - (BOOL) unpause {
91 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event
92 | BOOL wasPaused = self.paused;
93 |
94 | if (wasPaused) {
95 | DebugMsg("BGMHermes::unpause: Unpausing Hermes");
96 | [self.hermes play];
97 | }
98 |
99 | return wasPaused;
100 | }
101 |
102 | @end
103 |
104 | #pragma clang assume_nonnull end
105 |
106 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMMusic.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMMusic.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2019 Kyle Neideck
21 | // Copyright © 2019 theLMGN
22 | //
23 |
24 | // Superclass/Protocol Import
25 | #import "BGMMusicPlayer.h"
26 |
27 |
28 | #pragma clang assume_nonnull begin
29 |
30 | @interface BGMMusic : BGMMusicPlayerBase
31 |
32 | @end
33 |
34 | #pragma clang assume_nonnull end
35 |
36 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMMusic.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMMusic.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2019 Kyle Neideck, theLMGN
21 | //
22 |
23 | // Self Include
24 | #import "BGMMusic.h"
25 |
26 | // Auto-generated Scripting Bridge header
27 | #import "Music.h"
28 |
29 | // Local Includes
30 | #import "BGMScriptingBridge.h"
31 |
32 | // PublicUtility Includes
33 | #import "CADebugMacros.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | @implementation BGMMusic {
39 | BGMScriptingBridge* scriptingBridge;
40 | }
41 |
42 | + (NSUUID*) sharedMusicPlayerID {
43 | NSUUID* __nullable musicPlayerID =
44 | [[NSUUID alloc] initWithUUIDString:@"829B8069-8BD2-481D-BD40-54AB8CDAE228"];
45 | NSAssert(musicPlayerID, @"BGMMusic::sharedMusicPlayerID: !musicPlayerID");
46 | return (NSUUID*)musicPlayerID;
47 | }
48 |
49 | - (instancetype) init {
50 | if ((self = [super initWithMusicPlayerID:[BGMMusic sharedMusicPlayerID]
51 | name:@"Music"
52 | bundleID:@"com.apple.Music"])) {
53 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
54 | }
55 |
56 | return self;
57 | }
58 |
59 | - (MusicApplication* __nullable) music {
60 | return (MusicApplication*)scriptingBridge.application;
61 | }
62 |
63 | - (void) wasSelected {
64 | [super wasSelected];
65 | [scriptingBridge ensurePermission];
66 | }
67 |
68 | - (BOOL) isRunning {
69 | return self.music.running;
70 | }
71 |
72 | // isPlaying and isPaused check self.running first just in case Music is closed but self.music
73 | // hasn't become nil yet. In that case, reading self.music.playerState could make Scripting Bridge
74 | // open Music.
75 |
76 | - (BOOL) isPlaying {
77 | return self.running && (self.music.playerState == MusicEPlSPlaying);
78 | }
79 |
80 | - (BOOL) isPaused {
81 | return self.running && (self.music.playerState == MusicEPlSPaused);
82 | }
83 |
84 | - (BOOL) pause {
85 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
86 | BOOL wasPlaying = self.playing;
87 |
88 | if (wasPlaying) {
89 | DebugMsg("BGMMusic::pause: Pausing Music");
90 | [self.music pause];
91 | }
92 |
93 | return wasPlaying;
94 | }
95 |
96 | - (BOOL) unpause {
97 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event
98 | BOOL wasPaused = self.paused;
99 |
100 | if (wasPaused) {
101 | DebugMsg("BGMMusic::unpause: Unpausing Music");
102 | [self.music playpause];
103 | }
104 |
105 | return wasPaused;
106 | }
107 |
108 | @end
109 |
110 | #pragma clang assume_nonnull end
111 |
112 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMMusicPlayers.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMMusicPlayers.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2019 Kyle Neideck
21 | //
22 | // Holds the music players (i.e. BGMMusicPlayer objects) available in BGMApp. Also keeps track of
23 | // which music player is currently selected by the user.
24 | //
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMMusicPlayer.h"
29 | #import "BGMUserDefaults.h"
30 |
31 | // System Includes
32 | #import
33 |
34 |
35 | #pragma clang assume_nonnull begin
36 |
37 | @interface BGMMusicPlayers : NSObject
38 |
39 | // Calls initWithAudioDevices:musicPlayers: with sensible defaults.
40 | - (instancetype) initWithAudioDevices:(BGMAudioDeviceManager*)devices
41 | userDefaults:(BGMUserDefaults*)defaults;
42 |
43 | // defaultMusicPlayerID is the musicPlayerID (see BGMMusicPlayer.h) of the music player that should be
44 | // selected by default.
45 | //
46 | // The createInstancesWithDefaults method of each class in musicPlayerClasses will be called and
47 | // the results will be stored in the musicPlayers property.
48 | - (instancetype) initWithAudioDevices:(BGMAudioDeviceManager*)devices
49 | defaultMusicPlayerID:(NSUUID*)defaultMusicPlayerID
50 | musicPlayerClasses:(NSArray>*)musicPlayerClasses
51 | userDefaults:(BGMUserDefaults*)defaults;
52 |
53 | @property (readonly) NSArray>* musicPlayers;
54 |
55 | // The music player currently selected in the preferences menu. BGMDevice is informed when this property
56 | // is changed.
57 | @property id selectedMusicPlayer;
58 |
59 | @end
60 |
61 | #pragma clang assume_nonnull end
62 |
63 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMScriptingBridge.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMScriptingBridge.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2018 Kyle Neideck
21 | //
22 | // A wrapper around Scripting Bridge's SBApplication that tries to avoid ever launching the application.
23 | //
24 | // We use Scripting Bridge to communicate with music player apps, which we never want to launch
25 | // ourselves. But creating an SBApplication for an app, or sending messages/events to an existing one,
26 | // can launch the app.
27 | //
28 | // As a workaround, this class has an SBApplication property, application (see below), which is nil
29 | // unless the music player app is running. That way messages sent while the app is closed are ignored.
30 | //
31 |
32 | // Local Includes
33 | #import "BGMMusicPlayer.h"
34 |
35 | // System Includes
36 | #import
37 | #import
38 |
39 |
40 | #pragma clang assume_nonnull begin
41 |
42 | @interface BGMScriptingBridge : NSObject
43 |
44 | // Only keeps a weak ref to musicPlayer.
45 | - (instancetype) initWithMusicPlayer:(id)musicPlayer;
46 |
47 | // If the music player application is running, this property is the Scripting Bridge object representing
48 | // it. If not, it's set to nil. Used to send Apple events to the music player app.
49 | @property (readonly) __kindof SBApplication* __nullable application;
50 |
51 | // macOS 10.14 requires the user's permission to send Apple Events. If the music player that owns
52 | // this object (i.e. the one passed to initWithMusicPlayer) is currently the selected music player
53 | // and the user hasn't already given us permission to send it Apple Events, this method asks the
54 | // user for permission.
55 | - (void) ensurePermission;
56 |
57 | // SBApplicationDelegate
58 |
59 | // On 10.11, SBApplicationDelegate.h declares eventDidFail with a non-null return type, but the docs
60 | // specifically say that returning nil is allowed.
61 | #pragma clang diagnostic push
62 | #pragma clang diagnostic ignored "-Wnullability"
63 | - (id __nullable) eventDidFail:(const AppleEvent*)event withError:(NSError*)error;
64 | #pragma clang diagnostic pop
65 |
66 | @end
67 |
68 | #pragma clang assume_nonnull end
69 |
70 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMSpotify.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMSpotify.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMSpotify : BGMMusicPlayerBase
28 |
29 | @end
30 |
31 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMSwinsian.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMSwinsian.h
18 | // BGMApp
19 | //
20 | // Copyright © 2018 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | #pragma clang assume_nonnull begin
28 |
29 | @interface BGMSwinsian : BGMMusicPlayerBase
30 |
31 | @end
32 |
33 | #pragma clang assume_nonnull end
34 |
35 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMSwinsian.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMSwinsian.m
18 | // BGMApp
19 | //
20 | // Copyright © 2018 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMSwinsian.h"
25 |
26 | // Auto-generated Scripting Bridge header
27 | #import "Swinsian.h"
28 |
29 | // Local Includes
30 | #import "BGMScriptingBridge.h"
31 |
32 | // PublicUtility Includes
33 | #import "CADebugMacros.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | @implementation BGMSwinsian {
39 | BGMScriptingBridge* scriptingBridge;
40 | }
41 |
42 | - (instancetype) init {
43 | // If you're copying this class, replace the ID string with a new one generated by uuidgen (the
44 | // command line tool).
45 | NSUUID* musicPlayerID = [BGMMusicPlayerBase makeID:@"B74D18F6-DFF7-4D88-B719-429CFF98CFFA"];
46 |
47 | if ((self = [super initWithMusicPlayerID:musicPlayerID
48 | name:@"Swinsian"
49 | bundleID:@"com.swinsian.Swinsian"])) {
50 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
51 | }
52 |
53 | return self;
54 | }
55 |
56 | - (SwinsianApplication* __nullable) swinsian {
57 | return (SwinsianApplication* __nullable)scriptingBridge.application;
58 | }
59 |
60 | - (void) wasSelected {
61 | [super wasSelected];
62 | [scriptingBridge ensurePermission];
63 | }
64 |
65 | - (BOOL) isRunning {
66 | // Note that this will return NO if is self.swinsian is nil (i.e. Swinsian isn't running).
67 | return self.swinsian.running;
68 | }
69 |
70 | // isPlaying and isPaused check self.running first just in case Swinsian is closed but self.swinsian
71 | // hasn't become nil yet. In that case, reading self.swinsian.playerState could make Scripting
72 | // Bridge open Swinsian.
73 |
74 | - (BOOL) isPlaying {
75 | return self.running && (self.swinsian.playerState == SwinsianPlayerStatePlaying);
76 | }
77 |
78 | - (BOOL) isPaused {
79 | return self.running && (self.swinsian.playerState == SwinsianPlayerStatePaused);
80 | }
81 |
82 | - (BOOL) pause {
83 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event.
84 | BOOL wasPlaying = self.playing;
85 |
86 | if (wasPlaying) {
87 | DebugMsg("BGMSwinsian::pause: Pausing Swinsian");
88 | [self.swinsian pause];
89 | }
90 |
91 | return wasPlaying;
92 | }
93 |
94 | - (BOOL) unpause {
95 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event.
96 | BOOL wasPaused = self.paused;
97 |
98 | if (wasPaused) {
99 | DebugMsg("BGMSwinsian::unpause: Unpausing Swinsian");
100 | [self.swinsian play];
101 | }
102 |
103 | return wasPaused;
104 | }
105 |
106 | @end
107 |
108 | #pragma clang assume_nonnull end
109 |
110 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMVLC.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMVLC.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMVLC : BGMMusicPlayerBase
28 |
29 | @end
30 |
31 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMVOX.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMVOX.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMVOX : BGMMusicPlayerBase
28 |
29 | @end
30 |
31 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMVOX.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMVOX.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2018 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMVOX.h"
25 |
26 | // Auto-generated Scripting Bridge header
27 | #import "VOX.h"
28 |
29 | // Local Includes
30 | #import "BGMScriptingBridge.h"
31 |
32 | // PublicUtility Includes
33 | #import "CADebugMacros.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | @implementation BGMVOX {
39 | BGMScriptingBridge* scriptingBridge;
40 | }
41 |
42 | - (instancetype) init {
43 | if ((self = [super initWithMusicPlayerID:[BGMMusicPlayerBase makeID:@"26498C5D-C18B-4689-8B41-9DA91A78FFAD"]
44 | name:@"VOX"
45 | bundleID:@"com.coppertino.Vox"])) {
46 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
47 | }
48 |
49 | return self;
50 | }
51 |
52 | - (VoxApplication* __nullable) vox {
53 | return (VoxApplication*)scriptingBridge.application;
54 | }
55 |
56 | - (void) wasSelected {
57 | [super wasSelected];
58 | [scriptingBridge ensurePermission];
59 | }
60 |
61 | - (BOOL) isRunning {
62 | return self.vox.running;
63 | }
64 |
65 | // isPlaying and isPaused check self.running first just in case VOX is closed but self.vox hasn't become
66 | // nil yet. In that case, reading self.vox.playerState could make Scripting Bridge open VOX.
67 | //
68 | // VOX's comment for its playerState property says "playing = 1, paused = 0".
69 |
70 | - (BOOL) isPlaying {
71 | return self.running && (self.vox.playerState == 1);
72 | }
73 |
74 | - (BOOL) isPaused {
75 | return self.running && (self.vox.playerState == 0);
76 | }
77 |
78 | - (BOOL) pause {
79 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
80 | BOOL wasPlaying = self.playing;
81 |
82 | if (wasPlaying) {
83 | DebugMsg("BGMVOX::pause: Pausing VOX");
84 | [self.vox pause];
85 | }
86 |
87 | return wasPlaying;
88 | }
89 |
90 | - (BOOL) unpause {
91 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event
92 | BOOL wasPaused = self.paused;
93 |
94 | if (wasPaused) {
95 | DebugMsg("BGMVOX::unpause: Unpausing VOX");
96 | [self.vox playpause];
97 | }
98 |
99 | return wasPaused;
100 | }
101 |
102 | @end
103 |
104 | #pragma clang assume_nonnull end
105 |
106 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMiTunes.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMiTunes.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Superclass/Protocol Import
24 | #import "BGMMusicPlayer.h"
25 |
26 |
27 | @interface BGMiTunes : BGMMusicPlayerBase
28 |
29 | // The music player ID (see BGMMusicPlayer.h) used by BGMiTunes instances. (Though BGMApp only ever creates one instance of
30 | // BGMiTunes, sharedMusicPlayerID is exposed so iTunes can be set as the default music player.)
31 | + (NSUUID*) sharedMusicPlayerID;
32 |
33 | @end
34 |
35 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/BGMiTunes.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMiTunes.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016-2018 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMiTunes.h"
25 |
26 | // Auto-generated Scripting Bridge header
27 | #import "iTunes.h"
28 |
29 | // Local Includes
30 | #import "BGMScriptingBridge.h"
31 |
32 | // PublicUtility Includes
33 | #import "CADebugMacros.h"
34 |
35 |
36 | #pragma clang assume_nonnull begin
37 |
38 | @implementation BGMiTunes {
39 | BGMScriptingBridge* scriptingBridge;
40 | }
41 |
42 | + (NSUUID*) sharedMusicPlayerID {
43 | NSUUID* __nullable musicPlayerID = [[NSUUID alloc] initWithUUIDString:@"7B62B5BF-CF90-4938-84E3-F16DEDC3F608"];
44 | NSAssert(musicPlayerID, @"BGMiTunes::sharedMusicPlayerID: !musicPlayerID");
45 | return (NSUUID*)musicPlayerID;
46 | }
47 |
48 | - (instancetype) init {
49 | if ((self = [super initWithMusicPlayerID:[BGMiTunes sharedMusicPlayerID]
50 | name:@"iTunes"
51 | bundleID:@"com.apple.iTunes"])) {
52 | scriptingBridge = [[BGMScriptingBridge alloc] initWithMusicPlayer:self];
53 | }
54 |
55 | return self;
56 | }
57 |
58 | - (iTunesApplication* __nullable) iTunes {
59 | return (iTunesApplication*)scriptingBridge.application;
60 | }
61 |
62 | - (void) wasSelected {
63 | [super wasSelected];
64 | [scriptingBridge ensurePermission];
65 | }
66 |
67 | - (BOOL) isRunning {
68 | return self.iTunes.running;
69 | }
70 |
71 | // isPlaying and isPaused check self.running first just in case iTunes is closed but self.iTunes hasn't become
72 | // nil yet. In that case, reading self.iTunes.playerState could make Scripting Bridge open iTunes.
73 |
74 | - (BOOL) isPlaying {
75 | return self.running && (self.iTunes.playerState == iTunesEPlSPlaying);
76 | }
77 |
78 | - (BOOL) isPaused {
79 | return self.running && (self.iTunes.playerState == iTunesEPlSPaused);
80 | }
81 |
82 | - (BOOL) pause {
83 | // isPlaying checks isRunning, so we don't need to check it here and waste an Apple event
84 | BOOL wasPlaying = self.playing;
85 |
86 | if (wasPlaying) {
87 | DebugMsg("BGMiTunes::pause: Pausing iTunes");
88 | [self.iTunes pause];
89 | }
90 |
91 | return wasPlaying;
92 | }
93 |
94 | - (BOOL) unpause {
95 | // isPaused checks isRunning, so we don't need to check it here and waste an Apple event
96 | BOOL wasPaused = self.paused;
97 |
98 | if (wasPaused) {
99 | DebugMsg("BGMiTunes::unpause: Unpausing iTunes");
100 | [self.iTunes playpause];
101 | }
102 |
103 | return wasPaused;
104 | }
105 |
106 | @end
107 |
108 | #pragma clang assume_nonnull end
109 |
110 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/Hermes.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Hermes.h
3 | *
4 | * Generated with
5 | * sdef /Applications/Hermes.app | sdp -fh --basename Hermes
6 | */
7 |
8 | #import
9 | #import
10 |
11 |
12 | @class HermesApplication, HermesSong, HermesStation;
13 |
14 | // Legal player states
15 | enum HermesPlayerStates {
16 | HermesPlayerStatesStopped = 'stop' /* Player is stopped */,
17 | HermesPlayerStatesPlaying = 'play' /* Player is playing */,
18 | HermesPlayerStatesPaused = 'paus' /* Player is paused */
19 | };
20 | typedef enum HermesPlayerStates HermesPlayerStates;
21 |
22 |
23 |
24 | /*
25 | * Hermes Suite
26 | */
27 |
28 | // The Pandora player.
29 | @interface HermesApplication : SBApplication
30 |
31 | - (SBElementArray *) stations;
32 |
33 | @property NSInteger playbackVolume; // The current playback volume (0–100).
34 | @property HermesPlayerStates playbackState; // The current playback state.
35 | @property (readonly) double playbackPosition; // The current song’s playback position, in seconds.
36 | @property (readonly) double currentSongDuration; // The duration (length) of the current song, in seconds.
37 | @property (copy) HermesStation *currentStation; // The currently selected Pandora station.
38 | @property (copy, readonly) HermesSong *currentSong; // The currently playing (or paused) Pandora song (WARNING: This is an invalid reference in current versions of Hermes; you must access the current song’s properties individually or as a group directly instead.)
39 |
40 | - (void) playpause; // Play the current song if it is paused; pause the current song if it is playing.
41 | - (void) pause; // Pause the currently playing song.
42 | - (void) play; // Resume playing the current song.
43 | - (void) nextSong; // Skip to the next song on the current station.
44 | - (void) thumbsUp; // Tell Pandora you like the current song.
45 | - (void) thumbsDown; // Tell Pandora you don’t like the current song.
46 | - (void) tiredOfSong; // Tell Pandora you’re tired of the current song.
47 | - (void) increaseVolume; // Increase the playback volume.
48 | - (void) decreaseVolume; // Decrease the playback volume.
49 | - (void) maximizeVolume; // Set the playback volume to its maximum level.
50 | - (void) mute; // Mutes playback, saving the current volume level.
51 | - (void) unmute; // Restores the volume to the level prior to muting.
52 |
53 | @end
54 |
55 | // A Pandora song (track).
56 | @interface HermesSong : SBObject
57 |
58 | @property (copy, readonly) NSString *title; // The song’s title.
59 | @property (copy, readonly) NSString *artist; // The song’s artist.
60 | @property (copy, readonly) NSString *album; // The song’s album.
61 | @property (copy, readonly) NSString *artworkURL; // An image URL for the album’s cover artwork.
62 | @property (readonly) NSInteger rating; // The song’s numeric rating.
63 | @property (copy, readonly) NSString *albumURL; // A Pandora URL for more information on the album.
64 | @property (copy, readonly) NSString *artistURL; // A Pandora URL for more information on the artist.
65 | @property (copy, readonly) NSString *trackURL; // A Pandora URL for more information on the track.
66 |
67 |
68 | @end
69 |
70 | // A Pandora station.
71 | @interface HermesStation : SBObject
72 |
73 | @property (copy, readonly) NSString *name; // The station’s name.
74 | @property (copy, readonly) NSString *stationID; // The station’s ID.
75 |
76 |
77 | @end
78 |
79 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/Spotify.h:
--------------------------------------------------------------------------------
1 | /*
2 | * Spotify.h
3 | *
4 | * Generated with
5 | * sdef /Applications/Spotify.app | sdp -fh --basename Spotify
6 | */
7 |
8 | #import
9 | #import
10 |
11 |
12 | @class SpotifyApplication, SpotifyTrack, SpotifyApplication;
13 |
14 | enum SpotifyEPlS {
15 | SpotifyEPlSStopped = 'kPSS',
16 | SpotifyEPlSPlaying = 'kPSP',
17 | SpotifyEPlSPaused = 'kPSp'
18 | };
19 | typedef enum SpotifyEPlS SpotifyEPlS;
20 |
21 |
22 |
23 | /*
24 | * Spotify Suite
25 | */
26 |
27 | // The Spotify application.
28 | @interface SpotifyApplication : SBApplication
29 |
30 | @property (copy, readonly) SpotifyTrack *currentTrack; // The current playing track.
31 | @property NSInteger soundVolume; // The sound output volume (0 = minimum, 100 = maximum)
32 | @property (readonly) SpotifyEPlS playerState; // Is Spotify stopped, paused, or playing?
33 | @property double playerPosition; // The player’s position within the currently playing track in seconds.
34 | @property (readonly) BOOL repeatingEnabled; // Is repeating enabled in the current playback context?
35 | @property BOOL repeating; // Is repeating on or off?
36 | @property (readonly) BOOL shufflingEnabled; // Is shuffling enabled in the current playback context?
37 | @property BOOL shuffling; // Is shuffling on or off?
38 |
39 | - (void) nextTrack; // Skip to the next track.
40 | - (void) previousTrack; // Skip to the previous track.
41 | - (void) playpause; // Toggle play/pause.
42 | - (void) pause; // Pause playback.
43 | - (void) play; // Resume playback.
44 | - (void) playTrack:(NSString *)x inContext:(NSString *)inContext; // Start playback of a track in the given context.
45 |
46 | @end
47 |
48 | // A Spotify track.
49 | @interface SpotifyTrack : SBObject
50 |
51 | @property (copy, readonly) NSString *artist; // The artist of the track.
52 | @property (copy, readonly) NSString *album; // The album of the track.
53 | @property (readonly) NSInteger discNumber; // The disc number of the track.
54 | @property (readonly) NSInteger duration; // The length of the track in seconds.
55 | @property (readonly) NSInteger playedCount; // The number of times this track has been played.
56 | @property (readonly) NSInteger trackNumber; // The index of the track in its album.
57 | @property (readonly) BOOL starred; // Is the track starred?
58 | @property (readonly) NSInteger popularity; // How popular is this track? 0-100
59 | - (NSString *) id; // The ID of the item.
60 | @property (copy, readonly) NSString *name; // The name of the track.
61 | @property (copy, readonly) NSImage *artwork; // The track's album cover.
62 | @property (copy, readonly) NSString *albumArtist; // That album artist of the track.
63 | @property (copy) NSString *spotifyUrl; // The URL of the track.
64 |
65 |
66 | @end
67 |
68 |
69 |
70 | /*
71 | * Standard Suite
72 | */
73 |
74 | // The application's top level scripting object.
75 | @interface SpotifyApplication (StandardSuite)
76 |
77 | @property (copy, readonly) NSString *name; // The name of the application.
78 | @property (readonly) BOOL frontmost; // Is this the frontmost (active) application?
79 | @property (copy, readonly) NSString *version; // The version of the application.
80 |
81 | @end
82 |
83 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Music Players/VOX.h:
--------------------------------------------------------------------------------
1 | /*
2 | * VOX.h
3 | *
4 | * Generated with
5 | * sdef /Applications/VOX.app | sdp -fh --basename VOX
6 | */
7 |
8 | #import
9 | #import
10 |
11 |
12 | @class VoxApplication, VoxApplication;
13 |
14 |
15 |
16 | /*
17 | * Standard Suite
18 | */
19 |
20 | // The application's top level scripting object.
21 | @interface VoxApplication : SBApplication
22 |
23 | @property (copy, readonly) NSString *name; // The name of the application.
24 | @property (readonly) BOOL frontmost; // Is this the frontmost (active) application?
25 | @property (copy, readonly) NSString *version; // The version of the application.
26 |
27 | - (void) quit; // Quit an application.
28 | - (void) pause; // Pause playback.
29 | - (void) play; // Begin playback.
30 | - (void) playpause; // Toggle playback between playing and paused.
31 | - (void) next; // Skip to the next track in the playlist.
32 | - (void) previous; // Skip to the previous track in the playlist.
33 | - (void) shuffle; // Shuffle the tracks in the playlist.
34 | - (void) playUrl:(NSString *)x; // Play specified URL.
35 | - (void) addUrl:(NSString *)x; // Add specified URL to playlist
36 | - (void) rewindForward; // Rewind current track forward.
37 | - (void) rewindForwardFast; // Rewind current track forward fast.
38 | - (void) rewindBackward; // Rewind current track backward.
39 | - (void) rewindBackwardFast; // Rewind current track backward fast.
40 | - (void) increasVolume; // Increase volume.
41 | - (void) decreaseVolume; // Decrease volume.
42 | - (void) showHidePlaylist; // Show/Hide playlist.
43 |
44 | @end
45 |
46 |
47 |
48 | /*
49 | * Vox Suite
50 | */
51 |
52 | // The application's top-level scripting object.
53 | @interface VoxApplication (VoxSuite)
54 |
55 | @property (copy, readonly) NSData *tiffArtworkData; // Current track artwork data in TIFF format.
56 | @property (copy, readonly) NSImage *artworkImage; // Current track artwork as an image.
57 | @property (readonly) NSInteger playerState; // Player state (playing = 1, paused = 0)
58 | @property (copy, readonly) NSString *track; // Current track title.
59 | @property (copy, readonly) NSString *trackUrl; // Current track URL.
60 | @property (copy, readonly) NSString *artist; // Current track artist.
61 | @property (copy, readonly) NSString *albumArtist; // Current track album artist.
62 | @property (copy, readonly) NSString *album; // Current track album.
63 | @property (copy, readonly) NSString *uniqueID; // Unique identifier for the current track.
64 | @property double currentTime; // The current playback position.
65 | @property (readonly) double totalTime; // The total time of the currently playing track.
66 | @property double playerVolume; // Player volume (0.0 to 1.0)
67 | @property NSInteger repeatState; // Player repeat state (none = 0, repeat one = 1, repeat all = 2)
68 |
69 | @end
70 |
71 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Preferences/BGMAboutPanel.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAboutPanel.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 | // This class manages the "About Background Music" window.
23 | //
24 |
25 | // System Includes
26 | #import
27 |
28 |
29 | NS_ASSUME_NONNULL_BEGIN
30 |
31 | @interface BGMAboutPanel : NSObject
32 |
33 | - (instancetype)initWithPanel:(NSPanel*)inAboutPanel licenseView:(NSTextView*)inLicenseView;
34 | - (void) show;
35 |
36 | @end
37 |
38 |
39 | @interface BGMLinkField : NSTextField
40 | @end
41 |
42 | NS_ASSUME_NONNULL_END
43 |
44 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Preferences/BGMAutoPauseMusicPrefs.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAutoPauseMusicPrefs.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // Local Includes
24 | #import "BGMAudioDeviceManager.h"
25 | #import "BGMMusicPlayers.h"
26 |
27 | // System Includes
28 | #import
29 |
30 |
31 | #pragma clang assume_nonnull begin
32 |
33 | @interface BGMAutoPauseMusicPrefs : NSObject
34 |
35 | - (id) initWithPreferencesMenu:(NSMenu*)inPrefsMenu
36 | audioDevices:(BGMAudioDeviceManager*)inAudioDevices
37 | musicPlayers:(BGMMusicPlayers*)inMusicPlayers;
38 |
39 | @end
40 |
41 | #pragma clang assume_nonnull end
42 |
43 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Preferences/BGMPreferencesMenu.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMPreferencesMenu.h
18 | // BGMApp
19 | //
20 | // Copyright © 2016, 2018, 2019 Kyle Neideck
21 | //
22 | // Handles the preferences menu UI. The user's preference changes are often passed directly to the driver rather
23 | // than to other BGMApp classes.
24 | //
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMMusicPlayers.h"
29 | #import "BGMStatusBarItem.h"
30 |
31 | // System Includes
32 | #import
33 |
34 |
35 | NS_ASSUME_NONNULL_BEGIN
36 |
37 | @interface BGMPreferencesMenu : NSObject
38 |
39 | - (id) initWithBGMMenu:(NSMenu*)inBGMMenu
40 | audioDevices:(BGMAudioDeviceManager*)inAudioDevices
41 | musicPlayers:(BGMMusicPlayers*)inMusicPlayers
42 | statusBarItem:(BGMStatusBarItem*)inStatusBarItem
43 | aboutPanel:(NSPanel*)inAboutPanel
44 | aboutPanelLicenseView:(NSTextView*)inAboutPanelLicenseView;
45 |
46 | @end
47 |
48 | NS_ASSUME_NONNULL_END
49 |
50 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Scripting/BGMASApplication.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMASApplication.h
18 | // BGMApp
19 | //
20 | // Copyright © 2021 Marcus Wu
21 | // Copyright © 2021 Kyle Neideck
22 | //
23 | // An AppleScript class for volume and pan settings for running applications.
24 | //
25 |
26 |
27 | // Local Includes
28 | #import "BGMAppVolumesController.h"
29 |
30 | // System Includes
31 | #import
32 | #import
33 |
34 |
35 | NS_ASSUME_NONNULL_BEGIN
36 |
37 | @interface BGMASApplication : NSObject
38 |
39 | - (instancetype) initWithApplication:(NSRunningApplication*)app
40 | volumeController:(BGMAppVolumesController*)volumeController
41 | parentSpecifier:(NSScriptObjectSpecifier* __nullable)parentSpecifier
42 | index:(int)i;
43 |
44 | @property (readonly) NSString* name;
45 | @property (readonly) NSString* bundleID;
46 | @property int volume;
47 | @property int pan;
48 | @end
49 |
50 | NS_ASSUME_NONNULL_END
51 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Scripting/BGMASApplication.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMASApplication.m
18 | // BGMApp
19 | //
20 | // Copyright © 2021 Marcus Wu
21 | // Copyright © 2021 Kyle Neideck
22 | //
23 |
24 | // Self Include
25 | #import "BGMASApplication.h"
26 |
27 | // Local Includes
28 | #import "BGM_Types.h"
29 |
30 | @implementation BGMASApplication {
31 | NSScriptObjectSpecifier* parentSpecifier;
32 | NSRunningApplication *application;
33 | BGMAppVolumesController* appVolumesController;
34 | int index;
35 | }
36 |
37 | - (instancetype) initWithApplication:(NSRunningApplication*)app
38 | volumeController:(BGMAppVolumesController*)volumeController
39 | parentSpecifier:(NSScriptObjectSpecifier* __nullable)parent
40 | index:(int)i {
41 | if ((self = [super init])) {
42 | parentSpecifier = parent;
43 | application = app;
44 | appVolumesController = volumeController;
45 | index = i;
46 | }
47 |
48 | return self;
49 | }
50 |
51 | - (NSString*) name {
52 | return [NSString stringWithFormat:@"%@", [application localizedName]];
53 | }
54 |
55 | - (NSString*) bundleID {
56 | return [NSString stringWithFormat:@"%@", [application bundleIdentifier]];
57 | }
58 |
59 | - (int) volume {
60 | return [appVolumesController getVolumeAndPanForApp:application].volume;
61 | }
62 |
63 | - (void) setVolume:(int)vol {
64 | BGMAppVolumeAndPan volume = {
65 | .volume = vol,
66 | .pan = kAppPanNoValue
67 | };
68 | [appVolumesController setVolumeAndPan:volume forApp:application];
69 | }
70 |
71 | - (int) pan {
72 | return [appVolumesController getVolumeAndPanForApp:application].pan;
73 | }
74 |
75 | - (void) setPan:(int)pan {
76 | BGMAppVolumeAndPan thePan = {
77 | .volume = -1,
78 | .pan = pan
79 | };
80 | [appVolumesController setVolumeAndPan:thePan forApp:application];
81 | }
82 |
83 | - (NSScriptObjectSpecifier* __nullable) objectSpecifier {
84 | NSScriptClassDescription* parentClassDescription = [parentSpecifier keyClassDescription];
85 | return [[NSNameSpecifier alloc] initWithContainerClassDescription:parentClassDescription
86 | containerSpecifier:parentSpecifier
87 | key:@"applications"
88 | name:self.name];
89 | }
90 |
91 | @end
92 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Scripting/BGMASOutputDevice.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMASOutputDevice.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 | // An AppleScript class for the output devices that can be selected in the preferences menu.
23 | //
24 |
25 | // Local Includes
26 | #import "BGMAudioDeviceManager.h"
27 |
28 | // System Includes
29 | #import
30 |
31 |
32 | #pragma clang assume_nonnull begin
33 |
34 | @interface BGMASOutputDevice : NSObject
35 |
36 | - (instancetype) initWithAudioObjectID:(AudioObjectID)objID
37 | audioDevices:(BGMAudioDeviceManager*)devices
38 | parentSpecifier:(NSScriptObjectSpecifier* __nullable)parentSpecifier;
39 |
40 | @property (readonly) NSString* name;
41 | @property BOOL selected; // is this the device to be used for audio output?
42 |
43 | @end
44 |
45 | #pragma clang assume_nonnull end
46 |
47 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Scripting/BGMASOutputDevice.mm:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMASOutputDevice.mm
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #import "BGMASOutputDevice.h"
25 |
26 | // Local Includes
27 | #import "BGMAudioDevice.h"
28 |
29 | // PublicUtility Includes
30 | #import "CADebugMacros.h"
31 |
32 |
33 | #pragma clang assume_nonnull begin
34 |
35 | @implementation BGMASOutputDevice {
36 | NSScriptObjectSpecifier* parentSpecifier;
37 | BGMAudioDevice device;
38 | BGMAudioDeviceManager* audioDevices;
39 | }
40 |
41 | - (instancetype) initWithAudioObjectID:(AudioObjectID)objID
42 | audioDevices:(BGMAudioDeviceManager*)devices
43 | parentSpecifier:(NSScriptObjectSpecifier* __nullable)parent {
44 | if ((self = [super init])) {
45 | parentSpecifier = parent;
46 | device = objID;
47 | audioDevices = devices;
48 | }
49 |
50 | return self;
51 | }
52 |
53 | - (NSString*) name {
54 | return (NSString*)CFBridgingRelease(device.CopyName());
55 | }
56 |
57 | - (BOOL) selected {
58 | return [audioDevices isOutputDevice:device];
59 | }
60 |
61 | - (void) setSelected:(BOOL)selected {
62 | if (selected && ![self selected]) {
63 | DebugMsg("BGMASOutputDevice::setSelected: A script is setting output device to %s",
64 | [[self name] UTF8String]);
65 |
66 | NSError* err = [audioDevices setOutputDeviceWithID:device revertOnFailure:YES];
67 | (void)err; // TODO: Return an error to the script somehow if this isn't nil. Also, should
68 | // we return an error if the script tries to set this property to false?
69 | }
70 | }
71 |
72 | - (NSScriptObjectSpecifier* __nullable) objectSpecifier {
73 | NSScriptClassDescription* parentClassDescription = [parentSpecifier keyClassDescription];
74 | return [[NSNameSpecifier alloc] initWithContainerClassDescription:parentClassDescription
75 | containerSpecifier:parentSpecifier
76 | key:@"output devices"
77 | name:self.name];
78 | }
79 |
80 | @end
81 |
82 | #pragma clang assume_nonnull end
83 |
84 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/Scripting/BGMAppDelegate+AppleScript.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // BGMAppDelegate+AppleScript.h
18 | // BGMApp
19 | //
20 | // Copyright © 2017 Kyle Neideck
21 | // Copyright © 2021 Marcus Wu
22 | //
23 |
24 | #import "BGMAppDelegate.h"
25 |
26 | // Local Includes
27 | #import "BGMAudioDeviceManager.h"
28 | #import "BGMAppVolumesController.h"
29 |
30 | // Local Includes
31 | #import "BGMASOutputDevice.h"
32 | #import "BGMASApplication.h"
33 |
34 | // System Includes
35 | #import
36 |
37 |
38 | #pragma clang assume_nonnull begin
39 |
40 | @interface BGMAppDelegate (AppleScript)
41 |
42 | - (BOOL) application:(NSApplication*)sender delegateHandlesKey:(NSString*)key;
43 |
44 | @property BGMASOutputDevice* selectedOutputDevice;
45 | @property (readonly) NSArray* outputDevices;
46 | @property double mainVolume;
47 | @property (readonly) NSArray* applications;
48 |
49 | @end
50 |
51 | #pragma clang assume_nonnull end
52 |
53 |
--------------------------------------------------------------------------------
/BGMApp/BGMApp/main.m:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // main.m
18 | // BGMApp
19 | //
20 | // Copyright © 2016 Kyle Neideck
21 | //
22 |
23 | // System Includes
24 | #import
25 |
26 |
27 | int main(int argc, const char * argv[]) {
28 | // Start BGMApp.
29 | return NSApplicationMain(argc, argv);
30 | }
31 |
32 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UITests/BGMApp.h:
--------------------------------------------------------------------------------
1 | /*
2 | * BGMApp.h
3 | *
4 | * Generated with
5 | * sdef "/Applications/Background Music.app" | sdp -fh --basename BGMApp
6 | */
7 |
8 | #import
9 | #import
10 |
11 |
12 | @class BGMAppOutputDevice, BGMAppApplication;
13 |
14 |
15 |
16 | /*
17 | * Background Music
18 | */
19 |
20 | // A hardware device that can play audio
21 | @interface BGMAppOutputDevice : SBObject
22 |
23 | @property (copy, readonly) NSString *name; // The name of the output device.
24 | @property BOOL selected; // Is this the device to be used for audio output?
25 |
26 | @end
27 |
28 | // The application program
29 | @interface BGMAppApplication : SBApplication
30 |
31 | - (SBElementArray *) outputDevices;
32 |
33 | @property (copy) BGMAppOutputDevice *selectedOutputDevice; // The device to be used for audio output
34 |
35 | @end
36 |
37 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UITests/BGMAppUITests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UITests/skip-ui-tests.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 |
3 | # This file is part of Background Music.
4 | #
5 | # Background Music is free software: you can redistribute it and/or
6 | # modify it under the terms of the GNU General Public License as
7 | # published by the Free Software Foundation, either version 2 of the
8 | # License, or (at your option) any later version.
9 | #
10 | # Background Music is distributed in the hope that it will be useful,
11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 | # GNU General Public License for more details.
14 | #
15 | # You should have received a copy of the GNU General Public License
16 | # along with Background Music. If not, see .
17 |
18 | #
19 | # skip-ui-tests.py
20 | # BGMAppUITests
21 | #
22 | # Copyright (c) 2017, 2024 Kyle Neideck
23 | #
24 | # Disables the UI tests. This is mainly useful on CI systems that don't support UI tests.
25 | #
26 |
27 | import xml.etree.ElementTree as ET
28 |
29 | SCHEME_FILE = "BGMApp/BGMApp.xcodeproj/xcshareddata/xcschemes/Background Music.xcscheme"
30 | UI_REF_XPATH = ".//BuildableReference[@BlueprintName='BGMAppUITests']/.."
31 |
32 | # Parse the Xcode scheme.
33 | tree = ET.parse(SCHEME_FILE)
34 |
35 | # Set the TestableReference for the UI tests to skipped.
36 | tree.getroot().findall(UI_REF_XPATH)[0].set("skipped", "YES")
37 |
38 | # Save the scheme.
39 | tree.write(SCHEME_FILE)
40 |
41 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/BGMAppUnitTests-Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleVersion
20 | 1
21 |
22 |
23 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/Mocks/MockAudioDevice.cpp:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // MockAudioDevice.cpp
18 | // BGMAppUnitTests
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #include "MockAudioDevice.h"
25 |
26 | // BGM Includes
27 | #include "BGM_Types.h"
28 |
29 | // STL Includes
30 | #include
31 |
32 |
33 | MockAudioDevice::MockAudioDevice(const std::string& inUID)
34 | :
35 | mUID(inUID),
36 | mNominalSampleRate(44100.0),
37 | mIOBufferSize(512),
38 | MockAudioObject(static_cast(std::hash{}(inUID)))
39 | {
40 | }
41 |
42 | CACFString MockAudioDevice::GetPlayerBundleID() const
43 | {
44 | if(mUID != kBGMDeviceUID)
45 | {
46 | throw "Only BGMDevice has kAudioDeviceCustomPropertyMusicPlayerBundleID";
47 | }
48 |
49 | return mPlayerBundleID;
50 | }
51 |
52 | void MockAudioDevice::SetPlayerBundleID(const CACFString& inPlayerBundleID)
53 | {
54 | if(mUID != kBGMDeviceUID)
55 | {
56 | throw "Only BGMDevice has kAudioDeviceCustomPropertyMusicPlayerBundleID";
57 | }
58 |
59 | mPlayerBundleID = inPlayerBundleID;
60 | }
61 |
62 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/Mocks/MockAudioDevice.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // MockAudioObject.h
18 | // BGMAppUnitTests
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | #ifndef BGMAppUnitTests__MockAudioDevice
24 | #define BGMAppUnitTests__MockAudioDevice
25 |
26 | // Superclass Includes
27 | #include "MockAudioObject.h"
28 |
29 | // STL Includes
30 | #include
31 |
32 |
33 | /*!
34 | * A mock audio device in our mock CoreAudio HAL. In the HAL's API class hierarchy, the base class
35 | * for audio devices, kAudioDeviceClassID, is the audio objects class, kAudioObjectClassID.
36 | *
37 | * The unit tests generally use instances of this class to verify the HAL is being queried correctly
38 | * and to control the responses that the code they're testing will receive from the mock HAL.
39 | */
40 | class MockAudioDevice
41 | :
42 | public MockAudioObject
43 | {
44 |
45 | public:
46 | MockAudioDevice(const std::string& inUID);
47 |
48 | /*!
49 | * @return This device's music player bundle ID property.
50 | * @throws If this device isn't a mock of BGMDevice.
51 | */
52 | CACFString GetPlayerBundleID() const;
53 | /*!
54 | * Set this device's music player bundle ID property.
55 | * @throws If this device isn't a mock of BGMDevice.
56 | */
57 | void SetPlayerBundleID(const CACFString& inPlayerBundleID);
58 |
59 | /*!
60 | * The device's UID. The UID is a persistent token used to identify a particular audio device
61 | * across boot sessions.
62 | */
63 | const std::string mUID;
64 | Float64 mNominalSampleRate;
65 | UInt32 mIOBufferSize;
66 |
67 | private:
68 | CACFString mPlayerBundleID { "" };
69 |
70 | };
71 |
72 | #endif /* BGMAppUnitTests__MockAudioDevice */
73 |
74 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/Mocks/MockAudioObject.cpp:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // MockAudioObject.cpp
18 | // BGMAppUnitTests
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | // Self Include
24 | #include "MockAudioObject.h"
25 |
26 |
27 | MockAudioObject::MockAudioObject(AudioObjectID inAudioObjectID)
28 | :
29 | mAudioObjectID(inAudioObjectID)
30 | {
31 | }
32 |
33 | AudioObjectID MockAudioObject::GetObjectID() const
34 | {
35 | return mAudioObjectID;
36 | }
37 |
38 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/Mocks/MockAudioObject.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // MockAudioObject.h
18 | // BGMAppUnitTests
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | #ifndef BGMAppUnitTests__MockAudioObject
24 | #define BGMAppUnitTests__MockAudioObject
25 |
26 | // PublicUtility Includes
27 | #include "CACFString.h"
28 |
29 | // STL Includes
30 | #include
31 |
32 | // System Includes
33 | #include
34 |
35 |
36 | /*!
37 | * The base class for mock audio objects in our mock CoreAudio HAL. Maps to kAudioObjectClassID
38 | * (AudioHardwareBase.h) in the HAL's API class hierarchy.
39 | */
40 | class MockAudioObject
41 | {
42 |
43 | public:
44 | MockAudioObject(AudioObjectID inAudioObjectID);
45 | virtual ~MockAudioObject() = default;
46 |
47 | AudioObjectID GetObjectID() const;
48 |
49 | /*!
50 | * The properties that callers have added listeners for (and haven't since removed). See
51 | * CAHALAudioObject::AddPropertyListener and CAHALAudioObject::RemovePropertyListener.
52 | */
53 | std::set mPropertiesWithListeners;
54 |
55 | private:
56 | AudioObjectID mAudioObjectID;
57 |
58 | };
59 |
60 | #endif /* BGMAppUnitTests__MockAudioObject */
61 |
62 |
--------------------------------------------------------------------------------
/BGMApp/BGMAppTests/UnitTests/Mocks/MockAudioObjects.h:
--------------------------------------------------------------------------------
1 | // This file is part of Background Music.
2 | //
3 | // Background Music is free software: you can redistribute it and/or
4 | // modify it under the terms of the GNU General Public License as
5 | // published by the Free Software Foundation, either version 2 of the
6 | // License, or (at your option) any later version.
7 | //
8 | // Background Music is distributed in the hope that it will be useful,
9 | // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | // GNU General Public License for more details.
12 | //
13 | // You should have received a copy of the GNU General Public License
14 | // along with Background Music. If not, see .
15 |
16 | //
17 | // MockAudioObjects.h
18 | // BGMAppUnitTests
19 | //
20 | // Copyright © 2020 Kyle Neideck
21 | //
22 |
23 | #ifndef BGMAppUnitTests__MockAudioObjects
24 | #define BGMAppUnitTests__MockAudioObjects
25 |
26 | // Local Includes
27 | #include "MockAudioObject.h"
28 | #include "MockAudioDevice.h"
29 |
30 | // STL Includes
31 | #include