mirror of
https://github.com/kyleneideck/BackgroundMusic
synced 2024-11-22 12:13:03 +00:00
commit
c7df7506bc
19 changed files with 398 additions and 46 deletions
|
@ -2,7 +2,7 @@ language: objective-c
|
|||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode12
|
||||
osx_image: xcode12.2
|
||||
sudo: required
|
||||
env: DEPLOY=true
|
||||
- os: osx
|
||||
|
@ -85,9 +85,9 @@ script:
|
|||
# TODO: Debug packages are failing to install on Travis, but I can't reproduce the problem locally,
|
||||
# so temporarily allow debug builds to pass even if the install fails.
|
||||
- sudo installer -pkg Background-Music-*/BackgroundMusic-*.pkg -target / -verbose -dumplog || [[ "$TRAVIS_TAG" =~ .*DEBUG.* ]]
|
||||
# Print the installer logs. This only prints the current day's logs.
|
||||
# Print the installer logs. This trims the start of the log to save space.
|
||||
- echo -en '/var/log/install.log\ntravis_fold:start:install.log\\r'
|
||||
- grep -A 9999 $(date +%Y-%m-%d) /var/log/install.log
|
||||
- grep -E -A 9999 -B 20 'Background.?Music' /var/log/install.log
|
||||
- echo -en 'travis_fold:end:install.log\\r'
|
||||
# Check the BGM dirs and files were installed again.
|
||||
- ls -la "/Applications/Background Music.app"
|
||||
|
|
|
@ -225,6 +225,8 @@
|
|||
27FB8C2F1DE468320084DB9D /* BGM_Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27FB8C2E1DE468320084DB9D /* BGM_Utils.cpp */; settings = {COMPILER_FLAGS = "-frandom-seed=BGMApp-BGM_Utils.cpp"; }; };
|
||||
27FB8C301DE4758A0084DB9D /* BGMPlayThrough.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C1962E51BC94E91008A4DF7 /* BGMPlayThrough.cpp */; };
|
||||
27FB8C311DE4758A0084DB9D /* BGM_Utils.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 27FB8C2E1DE468320084DB9D /* BGM_Utils.cpp */; };
|
||||
9E129A412602AE620005851B /* BGMASApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E129A402602AE620005851B /* BGMASApplication.m */; };
|
||||
9E542C7026057FBA0016C0B5 /* BGMASApplication.m in Sources */ = {isa = PBXBuildFile; fileRef = 9E129A402602AE620005851B /* BGMASApplication.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
|
@ -433,6 +435,8 @@
|
|||
27F7D48F1D2483B100821C4B /* BGMDecibel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMDecibel.m; path = "Music Players/BGMDecibel.m"; sourceTree = "<group>"; };
|
||||
27F7D4911D2484A300821C4B /* Decibel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Decibel.h; path = "Music Players/Decibel.h"; sourceTree = "<group>"; };
|
||||
27FB8C2E1DE468320084DB9D /* BGM_Utils.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = BGM_Utils.cpp; path = ../SharedSource/BGM_Utils.cpp; sourceTree = "<group>"; };
|
||||
9E129A3F2602AE620005851B /* BGMASApplication.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BGMASApplication.h; path = Scripting/BGMASApplication.h; sourceTree = "<group>"; };
|
||||
9E129A402602AE620005851B /* BGMASApplication.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = BGMASApplication.m; path = Scripting/BGMASApplication.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -562,6 +566,8 @@
|
|||
1C2FC31D1EC723A100A76592 /* BGMASOutputDevice.h */,
|
||||
1C2FC31A1EC7238A00A76592 /* BGMASOutputDevice.mm */,
|
||||
1C2FC2FF1EB4D6E700A76592 /* BGMApp.sdef */,
|
||||
9E129A3F2602AE620005851B /* BGMASApplication.h */,
|
||||
9E129A402602AE620005851B /* BGMASApplication.m */,
|
||||
);
|
||||
name = Scripting;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1152,6 +1158,7 @@
|
|||
1C837DD81F6AA1F2004B1E60 /* BGMOutputVolumeMenuItem.mm in Sources */,
|
||||
1C9258472090287F00B8D3A6 /* BGMGooglePlayMusicDesktopPlayerConnection.m in Sources */,
|
||||
1C1963011BCAC0F6008A4DF7 /* CACFString.cpp in Sources */,
|
||||
9E129A412602AE620005851B /* BGMASApplication.m in Sources */,
|
||||
1C1962E71BC94E91008A4DF7 /* BGMPlayThrough.cpp in Sources */,
|
||||
1C8D8304204238DB00A838F2 /* BGMSwinsian.m in Sources */,
|
||||
1C1962FA1BCAC061008A4DF7 /* CADebugMacros.cpp in Sources */,
|
||||
|
@ -1218,6 +1225,7 @@
|
|||
1CD989361ECFFC9E0014BBBF /* CACFDictionary.cpp in Sources */,
|
||||
1CD989371ECFFC9E0014BBBF /* CACFNumber.cpp in Sources */,
|
||||
1CD989381ECFFC9E0014BBBF /* CACFString.cpp in Sources */,
|
||||
9E542C7026057FBA0016C0B5 /* BGMASApplication.m in Sources */,
|
||||
1CD989391ECFFC9E0014BBBF /* CADebugger.cpp in Sources */,
|
||||
1CD9893A1ECFFC9E0014BBBF /* CADebugMacros.cpp in Sources */,
|
||||
1CD9893B1ECFFC9E0014BBBF /* CADebugPrintf.cpp in Sources */,
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016, 2017, 2020 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
// Sets up and tears down the app.
|
||||
//
|
||||
|
||||
// Local Includes
|
||||
#import "BGMAudioDeviceManager.h"
|
||||
#import "BGMAppVolumesController.h"
|
||||
|
||||
// System Includes
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
@ -53,6 +55,7 @@ static NSInteger const kSeparatorBelowVolumesMenuItemTag = 4;
|
|||
@property (weak) IBOutlet NSMenuItem* debugLoggingMenuItemUnwrapped;
|
||||
|
||||
@property (readonly) BGMAudioDeviceManager* audioDevices;
|
||||
@property BGMAppVolumesController* appVolumes;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016-2020 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Self Include
|
||||
|
@ -64,7 +65,6 @@ static NSString* const kOptShowDockIcon = @"--show-dock-icon";
|
|||
BGMAutoPauseMenuItem* autoPauseMenuItem;
|
||||
BGMMusicPlayers* musicPlayers;
|
||||
BGMSystemSoundsVolume* systemSoundsVolume;
|
||||
BGMAppVolumesController* appVolumes;
|
||||
BGMOutputDeviceMenuSection* outputDeviceMenuSection;
|
||||
BGMPreferencesMenu* prefsMenu;
|
||||
BGMDebugLoggingMenuItem* debugLoggingMenuItem;
|
||||
|
@ -73,6 +73,7 @@ static NSString* const kOptShowDockIcon = @"--show-dock-icon";
|
|||
}
|
||||
|
||||
@synthesize audioDevices = audioDevices;
|
||||
@synthesize appVolumes = appVolumes;
|
||||
|
||||
- (void) awakeFromNib {
|
||||
[super awakeFromNib];
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016, 2017 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Local Includes
|
||||
|
@ -44,6 +45,9 @@
|
|||
|
||||
- (void) removeAllAppVolumeMenuItems;
|
||||
|
||||
- (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication*)app;
|
||||
- (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app;
|
||||
|
||||
@end
|
||||
|
||||
// Protocol for the UI custom classes
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
//
|
||||
// Copyright © 2016-2020 Kyle Neideck
|
||||
// Copyright © 2017 Andrew Tonner
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Self Include
|
||||
|
@ -124,6 +125,79 @@ static NSString* const kMoreAppsMenuTitle = @"More Apps";
|
|||
}
|
||||
}
|
||||
|
||||
- (NSMenuItem*) getMenuItemForApp:(NSRunningApplication*)app {
|
||||
NSInteger lastAppVolumeMenuItemIndex = [self lastMenuItemIndex] - 2;
|
||||
|
||||
for (NSInteger i = [self firstMenuItemIndex]; i <= lastAppVolumeMenuItemIndex; i++) {
|
||||
NSMenuItem* item = [bgmMenu itemAtIndex:i];
|
||||
NSRunningApplication* itemApp = item.representedObject;
|
||||
BGMAssert(itemApp, "!itemApp for %s", item.title.UTF8String);
|
||||
|
||||
if ([itemApp isEqual:app]) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
for (NSInteger i = 0; i < [moreAppsMenu numberOfItems]; i++) {
|
||||
NSMenuItem* item = [moreAppsMenu itemAtIndex:i];
|
||||
NSRunningApplication* itemApp = item.representedObject;
|
||||
BGMAssert(itemApp, "!itemApp for %s", item.title.UTF8String);
|
||||
|
||||
if ([itemApp isEqual:app]) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication*)app {
|
||||
BGMAppVolumeAndPan result = {
|
||||
.volume = -1,
|
||||
.pan = -1
|
||||
};
|
||||
|
||||
NSMenuItem *item = [self getMenuItemForApp:app];
|
||||
|
||||
if (item == nil) {
|
||||
return result;
|
||||
}
|
||||
|
||||
for (NSView* subview in item.view.subviews) {
|
||||
// Get the volume.
|
||||
if ([subview isKindOfClass:[BGMAVM_VolumeSlider class]]) {
|
||||
result.volume = [(BGMAVM_VolumeSlider*)subview intValue];
|
||||
}
|
||||
|
||||
// Get the pan position.
|
||||
if ([subview isKindOfClass:[BGMAVM_PanSlider class]]) {
|
||||
result.pan = [(BGMAVM_PanSlider*)subview intValue];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
- (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app {
|
||||
NSMenuItem *item = [self getMenuItemForApp:app];
|
||||
|
||||
if (item == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (NSView* subview in item.view.subviews) {
|
||||
// Set the volume.
|
||||
if (volumeAndPan.volume != -1 && [subview isKindOfClass:[BGMAVM_VolumeSlider class]]) {
|
||||
[(BGMAVM_VolumeSlider*)subview setRelativeVolume:volumeAndPan.volume];
|
||||
}
|
||||
|
||||
// Set the pan position.
|
||||
if (volumeAndPan.pan != -1 && [subview isKindOfClass:[BGMAVM_PanSlider class]]) {
|
||||
[(BGMAVM_PanSlider*)subview setPanPosition:volumeAndPan.pan];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Create a blank menu item to copy as a template.
|
||||
- (NSMenuItem*) createBlankAppVolumeMenuItem {
|
||||
NSMenuItem* menuItem = [[NSMenuItem alloc] initWithTitle:@"" action:nil keyEquivalent:@""];
|
||||
|
@ -447,4 +521,3 @@ static NSString* const kMoreAppsMenuTitle = @"More Apps";
|
|||
}
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2017 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Local Includes
|
||||
|
@ -29,6 +30,11 @@
|
|||
|
||||
#pragma clang assume_nonnull begin
|
||||
|
||||
typedef struct BGMAppVolumeAndPan {
|
||||
int volume;
|
||||
int pan;
|
||||
} BGMAppVolumeAndPan;
|
||||
|
||||
@interface BGMAppVolumesController : NSObject
|
||||
|
||||
- (id) initWithMenu:(NSMenu*)menu
|
||||
|
@ -45,6 +51,9 @@ forAppWithProcessID:(pid_t)processID
|
|||
forAppWithProcessID:(pid_t)processID
|
||||
bundleID:(NSString* __nullable)bundleID;
|
||||
|
||||
- (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication *)app;
|
||||
- (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app;
|
||||
|
||||
@end
|
||||
|
||||
#pragma clang assume_nonnull end
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
//
|
||||
// Copyright © 2017, 2018 Kyle Neideck
|
||||
// Copyright © 2017 Andrew Tonner
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Self Include
|
||||
|
@ -40,11 +41,6 @@
|
|||
|
||||
#pragma clang assume_nonnull begin
|
||||
|
||||
typedef struct BGMAppVolumeAndPan {
|
||||
int volume;
|
||||
int pan;
|
||||
} BGMAppVolumeAndPan;
|
||||
|
||||
@implementation BGMAppVolumesController {
|
||||
// The App Volumes UI.
|
||||
BGMAppVolumes* appVolumes;
|
||||
|
@ -104,6 +100,20 @@ typedef struct BGMAppVolumeAndPan {
|
|||
}
|
||||
}
|
||||
|
||||
- (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication *)app {
|
||||
return [appVolumes getVolumeAndPanForApp:app];
|
||||
}
|
||||
|
||||
- (void) setVolumeAndPan:(BGMAppVolumeAndPan)volumeAndPan forApp:(NSRunningApplication*)app {
|
||||
[appVolumes setVolumeAndPan:volumeAndPan forApp:app];
|
||||
if (volumeAndPan.volume != -1) {
|
||||
[self setVolume:volumeAndPan.volume forAppWithProcessID:app.processIdentifier bundleID:app.bundleIdentifier];
|
||||
}
|
||||
if (volumeAndPan.pan != -1) {
|
||||
[self setPanPosition:volumeAndPan.pan forAppWithProcessID:app.processIdentifier bundleID:app.bundleIdentifier];
|
||||
}
|
||||
}
|
||||
|
||||
- (BGMAppVolumeAndPan) getVolumeAndPanForApp:(NSRunningApplication*)app
|
||||
fromVolumes:(const CACFArray&)volumes {
|
||||
BGMAppVolumeAndPan volumeAndPan = {
|
||||
|
|
|
@ -92,7 +92,11 @@
|
|||
|
||||
+ (NSArray<id<BGMMusicPlayer>>*) createInstancesWithDefaults:(BGMUserDefaults*)userDefaults {
|
||||
#pragma unused (userDefaults)
|
||||
// TODO: Fix this warning properly.
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wobjc-literal-conversion"
|
||||
return @[ [self new] ];
|
||||
#pragma clang diagnostic pop
|
||||
}
|
||||
|
||||
- (NSImage* __nullable) icon {
|
||||
|
|
50
BGMApp/BGMApp/Scripting/BGMASApplication.h
Normal file
50
BGMApp/BGMApp/Scripting/BGMASApplication.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
// This file is part of Background Music.
|
||||
//
|
||||
// Background Music is free software: you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation, either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// Background Music is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
// BGMASApplication.h
|
||||
// BGMApp
|
||||
//
|
||||
// Copyright © 2021 Marcus Wu
|
||||
// Copyright © 2021 Kyle Neideck
|
||||
//
|
||||
// An AppleScript class for volume and pan settings for running applications.
|
||||
//
|
||||
|
||||
|
||||
// Local Includes
|
||||
#import "BGMAppVolumesController.h"
|
||||
|
||||
// System Includes
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface BGMASApplication : NSObject
|
||||
|
||||
- (instancetype) initWithApplication:(NSRunningApplication*)app
|
||||
volumeController:(BGMAppVolumesController*)volumeController
|
||||
parentSpecifier:(NSScriptObjectSpecifier* __nullable)parentSpecifier
|
||||
index:(int)i;
|
||||
|
||||
@property (readonly) NSString* name;
|
||||
@property (readonly) NSString* bundleID;
|
||||
@property int volume;
|
||||
@property int pan;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
88
BGMApp/BGMApp/Scripting/BGMASApplication.m
Normal file
88
BGMApp/BGMApp/Scripting/BGMASApplication.m
Normal file
|
@ -0,0 +1,88 @@
|
|||
// This file is part of Background Music.
|
||||
//
|
||||
// Background Music is free software: you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation, either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// Background Music is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
// BGMASApplication.m
|
||||
// BGMApp
|
||||
//
|
||||
// Copyright © 2021 Marcus Wu
|
||||
// Copyright © 2021 Kyle Neideck
|
||||
//
|
||||
|
||||
// Self Include
|
||||
#import "BGMASApplication.h"
|
||||
|
||||
@implementation BGMASApplication {
|
||||
NSScriptObjectSpecifier* parentSpecifier;
|
||||
NSRunningApplication *application;
|
||||
BGMAppVolumesController* appVolumesController;
|
||||
int index;
|
||||
}
|
||||
|
||||
- (instancetype) initWithApplication:(NSRunningApplication*)app
|
||||
volumeController:(BGMAppVolumesController*)volumeController
|
||||
parentSpecifier:(NSScriptObjectSpecifier* __nullable)parent
|
||||
index:(int)i {
|
||||
if ((self = [super init])) {
|
||||
parentSpecifier = parent;
|
||||
application = app;
|
||||
appVolumesController = volumeController;
|
||||
index = i;
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString*) name {
|
||||
return [NSString stringWithFormat:@"%@", [application localizedName]];
|
||||
}
|
||||
|
||||
- (NSString*) bundleID {
|
||||
return [NSString stringWithFormat:@"%@", [application bundleIdentifier]];
|
||||
}
|
||||
|
||||
- (int) volume {
|
||||
return [appVolumesController getVolumeAndPanForApp:application].volume;
|
||||
}
|
||||
|
||||
- (void) setVolume:(int)vol {
|
||||
BGMAppVolumeAndPan volume = {
|
||||
.volume = vol,
|
||||
.pan = -1
|
||||
};
|
||||
[appVolumesController setVolumeAndPan:volume forApp:application];
|
||||
}
|
||||
|
||||
- (int) pan {
|
||||
return [appVolumesController getVolumeAndPanForApp:application].pan;
|
||||
}
|
||||
|
||||
- (void) setPan:(int)pan {
|
||||
BGMAppVolumeAndPan thePan = {
|
||||
.volume = -1,
|
||||
.pan = pan
|
||||
};
|
||||
[appVolumesController setVolumeAndPan:thePan forApp:application];
|
||||
}
|
||||
|
||||
- (NSScriptObjectSpecifier* __nullable) objectSpecifier {
|
||||
NSScriptClassDescription* parentClassDescription = [parentSpecifier keyClassDescription];
|
||||
return [[NSNameSpecifier alloc] initWithContainerClassDescription:parentClassDescription
|
||||
containerSpecifier:parentSpecifier
|
||||
key:@"applications"
|
||||
name:self.name];
|
||||
}
|
||||
|
||||
@end
|
|
@ -9,8 +9,7 @@
|
|||
<class name="output device"
|
||||
code="aDev"
|
||||
description="A hardware device that can play audio"
|
||||
plural="output devices"
|
||||
inherits="item">
|
||||
plural="output devices">
|
||||
<synonym name="audio device"/>
|
||||
|
||||
<cocoa class="BGMASOutputDevice"/>
|
||||
|
@ -19,14 +18,58 @@
|
|||
code="pnam"
|
||||
description="The name of the output device."
|
||||
type="text"
|
||||
access="r"/>
|
||||
access="r">
|
||||
<cocoa key="name"/>
|
||||
</property>
|
||||
|
||||
<property name="selected"
|
||||
code="Slcd"
|
||||
type="boolean"
|
||||
access="rw"
|
||||
description="Is this the device to be used for audio output?">
|
||||
<synonym name="default"/>
|
||||
<synonym name="default"/>
|
||||
<cocoa key="selected"/>
|
||||
</property>
|
||||
</class>
|
||||
|
||||
<class name="audio application"
|
||||
code="aApp"
|
||||
description="An application that can play audio"
|
||||
plural="audio applications">
|
||||
<synonym name="audio app"/>
|
||||
|
||||
<cocoa class="BGMASApplication"/>
|
||||
|
||||
<property name="name"
|
||||
code="pnam"
|
||||
description="The name of the application."
|
||||
type="text"
|
||||
access="r">
|
||||
<cocoa key="name"/>
|
||||
</property>
|
||||
|
||||
<property name="bundleID"
|
||||
code="bdid"
|
||||
description="The bundle ID of the application, e.g. 'com.somecompany.coolapp'."
|
||||
type="text"
|
||||
access="r">
|
||||
<cocoa key="bundleID"/>
|
||||
</property>
|
||||
|
||||
<property name="vol"
|
||||
code="pVol"
|
||||
type="integer"
|
||||
access="rw"
|
||||
description="The volume setting of the application">
|
||||
<cocoa key="volume"/>
|
||||
</property>
|
||||
|
||||
<property name="pan"
|
||||
code="pPan"
|
||||
type="integer"
|
||||
access="rw"
|
||||
description="The pan setting of the application">
|
||||
<cocoa key="pan"/>
|
||||
</property>
|
||||
</class>
|
||||
|
||||
|
@ -48,11 +91,23 @@
|
|||
|
||||
<cocoa key="selectedOutputDevice"/>
|
||||
</property>
|
||||
<property name="output volume"
|
||||
type="real"
|
||||
code="oVol"
|
||||
access="rw"
|
||||
description="The main output volume">
|
||||
<synonym name="main volume"/>
|
||||
|
||||
<cocoa key="mainVolume"/>
|
||||
</property>
|
||||
|
||||
<!-- Unintuitively, this is for the array of output devices. -->
|
||||
<element type="output device" access="r">
|
||||
<cocoa key="outputDevices"/>
|
||||
</element>
|
||||
<element type="audio application" access="r">
|
||||
<cocoa key="applications"/>
|
||||
</element>
|
||||
</class>
|
||||
</suite>
|
||||
</dictionary>
|
||||
|
|
|
@ -18,12 +18,14 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2017 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
#import "BGMAppDelegate.h"
|
||||
|
||||
// Local Includes
|
||||
#import "BGMASOutputDevice.h"
|
||||
#import "BGMASApplication.h"
|
||||
|
||||
// System Includes
|
||||
#import <Foundation/Foundation.h>
|
||||
|
@ -37,6 +39,8 @@
|
|||
|
||||
@property BGMASOutputDevice* selectedOutputDevice;
|
||||
@property (readonly) NSArray<BGMASOutputDevice*>* outputDevices;
|
||||
@property double mainVolume;
|
||||
@property (readonly) NSArray<BGMASApplication*>* applications;
|
||||
|
||||
@end
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
// BGMApp
|
||||
//
|
||||
// Copyright © 2017 Kyle Neideck
|
||||
// Copyright © 2021 Marcus Wu
|
||||
//
|
||||
|
||||
// Self Include
|
||||
|
@ -30,6 +31,7 @@
|
|||
#import "CAHALAudioSystemObject.h"
|
||||
#import "CAAutoDisposer.h"
|
||||
|
||||
const AudioObjectPropertyScope kScope = kAudioDevicePropertyScopeOutput;
|
||||
|
||||
#pragma clang assume_nonnull begin
|
||||
|
||||
|
@ -43,7 +45,7 @@
|
|||
[key UTF8String]);
|
||||
}
|
||||
|
||||
return [@[@"selectedOutputDevice", @"outputDevices"] containsObject:key];
|
||||
return [@[@"selectedOutputDevice", @"outputDevices", @"mainVolume", @"applications"] containsObject:key];
|
||||
}
|
||||
|
||||
- (BGMASOutputDevice*) selectedOutputDevice {
|
||||
|
@ -83,6 +85,30 @@
|
|||
return outputDevices;
|
||||
}
|
||||
|
||||
- (double) mainVolume {
|
||||
BGMAudioDevice bgmDevice = [self.audioDevices bgmDevice];
|
||||
return bgmDevice.GetVolumeControlScalarValue(kScope, kMasterChannel);
|
||||
}
|
||||
|
||||
- (void) setMainVolume:(double)mainVolume {
|
||||
BGMAudioDevice bgmDevice = [self.audioDevices bgmDevice];
|
||||
bgmDevice.SetMasterVolumeScalar(kScope, (Float32)mainVolume);
|
||||
[self.outputVolumeSlider setFloatValue:(float)mainVolume];
|
||||
}
|
||||
|
||||
- (NSArray<BGMASApplication*>*) applications {
|
||||
NSArray<NSRunningApplication*>* apps = [[NSWorkspace sharedWorkspace] runningApplications];
|
||||
NSMutableArray<BGMASApplication*>* applications = [NSMutableArray arrayWithCapacity:[apps count]];
|
||||
|
||||
for (UInt32 i = 0; i < [apps count]; i++) {
|
||||
BGMASApplication *app = [[BGMASApplication alloc] initWithApplication:apps[i] volumeController:self.appVolumes parentSpecifier:[self objectSpecifier] index:i];
|
||||
|
||||
[applications addObject:app];
|
||||
}
|
||||
|
||||
return applications;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma clang assume_nonnull end
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
# _uninstall-non-interactive.sh
|
||||
#
|
||||
# Copyright © 2016 Nick Jacques
|
||||
# Copyright © 2016, 2017 Kyle Neideck
|
||||
# Copyright © 2016, 2017, 2021 Kyle Neideck
|
||||
#
|
||||
# Removes BGMApp, BGMDriver and BGMXPCHelper from the system immediately. Run by uninstall.sh and the Homebrew formula.
|
||||
#
|
||||
|
@ -43,8 +43,9 @@ driver_path="/Library/Audio/Plug-Ins/HAL/Background Music Device.driver"
|
|||
xpc_path1="/usr/local/libexec/BGMXPCHelper.xpc"
|
||||
xpc_path2="/Library/Application Support/Background Music/BGMXPCHelper.xpc"
|
||||
|
||||
# Check that files/directories are at most this big before we delete them, just to be safe.
|
||||
max_size_mb_for_rm=15
|
||||
# Check that files/directories are at most this big before we delete them, just to be safe. Note that the bundles can
|
||||
# include debug symbols, e.g. if you use build_and_install.sh, which makes them a lot bigger.
|
||||
max_size_mb_for_rm=30
|
||||
|
||||
file_paths=("${app_path}" "${driver_path}" "${xpc_path1}" "${xpc_path2}")
|
||||
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 192 KiB After Width: | Height: | Size: 157 KiB |
|
@ -5,7 +5,7 @@
|
|||
# Background Music
|
||||
##### macOS audio utility
|
||||
|
||||
<img src="Images/README/Screenshot.png" width="340" height="342" />
|
||||
<img src="Images/README/Screenshot.png" width="340" height="443" />
|
||||
|
||||
[Overview](#overview)<br/>
|
||||
[Auto-pause music](#auto-pause-music)<br/>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
// BGM_TestUtils.h
|
||||
// SharedSource
|
||||
//
|
||||
// Copyright © 2016 Kyle Neideck
|
||||
// Copyright © 2016, 2021 Kyle Neideck
|
||||
//
|
||||
|
||||
#ifndef __SharedSource__BGM_TestUtils__
|
||||
|
@ -37,6 +37,7 @@
|
|||
template<typename ExpectedException>
|
||||
void BGMShouldThrow(XCTestCase* self, const std::function<void()>& f)
|
||||
{
|
||||
#pragma unused (self)
|
||||
try
|
||||
{
|
||||
f();
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#
|
||||
# postinstall
|
||||
#
|
||||
# Copyright © 2017-2020 Kyle Neideck
|
||||
# Copyright © 2017-2021 Kyle Neideck
|
||||
#
|
||||
|
||||
# Make sure we use the built-in versions of programs, for consistency. Probably not necessary
|
||||
|
@ -83,43 +83,57 @@ while [[ $retries -gt 0 ]]; do
|
|||
fi
|
||||
done
|
||||
|
||||
# Try opening BGMApp using its bundle ID first so the installer can declare it as "relocatable".
|
||||
# That way, if the user moves BGMApp and then installs a newer version of Background Music, the
|
||||
# installer will try to find the old version of BGMApp and put the new one in the same place.
|
||||
# Launch BGMApp.
|
||||
#
|
||||
# Use launchctl to make sure we don't run BGMApp as the installer user.
|
||||
#
|
||||
# If we can't open BGMApp, it's very likely it didn't install properly, so we fail the install.
|
||||
# Allow a few retries because it seems to sometimes fail intermittently in CI builds. For example,
|
||||
# <https://travis-ci.org/github/kyleneideck/BackgroundMusic/jobs/764126689>. From the error
|
||||
# messages, it looks like BGMApp isn't always registered with Launch Services by this point.
|
||||
logged_in_user_id="$(id -u "${USER}")"
|
||||
did_open_bgmapp=false
|
||||
retries=5
|
||||
|
||||
# TODO: If they have multiple copies of BGMApp, this might open one of the old ones.
|
||||
log "Opening Background Music.app by bundle ID"
|
||||
if launchctl asuser "${logged_in_user_id}" \
|
||||
open -b com.bearisdriving.BGM.App; then
|
||||
did_open_bgmapp=true
|
||||
fi
|
||||
while [[ $did_open_bgmapp != "true" ]] && [[ $retries -gt 0 ]]; do
|
||||
retries=$((retries - 1))
|
||||
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
dest_volume_no_trailing_slash="${dest_volume/%\//}"
|
||||
log "Opening ${dest_volume_no_trailing_slash}/Applications/Background Music.app"
|
||||
# Try opening BGMApp using its bundle ID first so the installer can declare it as "relocatable".
|
||||
# That way, if the user moves BGMApp and then installs a newer version of Background Music, the
|
||||
# installer will try to find the old version of BGMApp and put the new one in the same place.
|
||||
#
|
||||
# Use launchctl to make sure we don't run BGMApp as the installer user.
|
||||
#
|
||||
# TODO: If they have multiple copies of BGMApp, this might open one of the old ones.
|
||||
log "Opening Background Music.app by bundle ID"
|
||||
if launchctl asuser "${logged_in_user_id}" \
|
||||
open "${dest_volume_no_trailing_slash}/Applications/Background Music.app"; then
|
||||
open -b com.bearisdriving.BGM.App; then
|
||||
did_open_bgmapp=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
log "Opening Background Music.app using AppleScript"
|
||||
if osascript -e 'tell application "Background Music" to activate'; then
|
||||
did_open_bgmapp=true
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
dest_volume_no_trailing_slash="${dest_volume/%\//}"
|
||||
log "Opening ${dest_volume_no_trailing_slash}/Applications/Background Music.app"
|
||||
if launchctl asuser "${logged_in_user_id}" \
|
||||
open "${dest_volume_no_trailing_slash}/Applications/Background Music.app"; then
|
||||
did_open_bgmapp=true
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
log "Opening Background Music.app using AppleScript"
|
||||
if osascript -e 'tell application "Background Music" to activate'; then
|
||||
did_open_bgmapp=true
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
log "Failed to open Background Music.app. Will retry shortly."
|
||||
sleep 1
|
||||
fi
|
||||
done
|
||||
|
||||
# If we couldn't open BGMApp, it probably didn't install properly, but it's not certain, so don't
|
||||
# fail the install.
|
||||
if [[ $did_open_bgmapp != "true" ]]; then
|
||||
log "Failed to open Background Music.app"
|
||||
# Fail the install.
|
||||
exit 1
|
||||
log "Failed to open Background Music.app. Giving up."
|
||||
fi
|
||||
|
||||
# The installer plays a sound when it finishes, so give BGMApp a second to launch.
|
||||
|
@ -128,3 +142,4 @@ sleep 1
|
|||
exit 0
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue