Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3e528c7de0 | |||
| 03135dbc6e |
@@ -25,7 +25,6 @@
|
||||
1C1963091BCAF677008A4DF7 /* CAHostTimeBase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C1963071BCAF677008A4DF7 /* CAHostTimeBase.cpp */; };
|
||||
1C2336DA1BEAB6E7004C1C4E /* BGMMusicPlayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C2336D91BEAB6E7004C1C4E /* BGMMusicPlayer.m */; };
|
||||
1C2336DF1BEAE10C004C1C4E /* BGMSpotify.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C2336DE1BEAE10C004C1C4E /* BGMSpotify.m */; };
|
||||
1C3DB4891BE0885A00EC8160 /* BGMAppVolumes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1C3DB4881BE0885A00EC8160 /* BGMAppVolumes.mm */; };
|
||||
1C4699471BD5C0E400F78043 /* BGMiTunes.m in Sources */ = {isa = PBXBuildFile; fileRef = 1C4699461BD5C0E400F78043 /* BGMiTunes.m */; };
|
||||
1C46994E1BD7694C00F78043 /* BGMDeviceControlSync.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */; };
|
||||
1CB8B33D1BBA75EF000E2DD1 /* AppDelegate.mm in Sources */ = {isa = PBXBuildFile; fileRef = 1CB8B33C1BBA75EF000E2DD1 /* AppDelegate.mm */; };
|
||||
@@ -48,12 +47,15 @@
|
||||
276972911CB16008007A2F7C /* safe_install_dir.sh in Resources */ = {isa = PBXBuildFile; fileRef = 276972901CB16008007A2F7C /* safe_install_dir.sh */; };
|
||||
276972921CB1603E007A2F7C /* safe_install_dir.sh in Resources */ = {isa = PBXBuildFile; fileRef = 276972901CB16008007A2F7C /* safe_install_dir.sh */; };
|
||||
277170161CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 277170151CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m */; };
|
||||
2783ABB71CE36CDB00F11FD4 /* BGMApps.m in Sources */ = {isa = PBXBuildFile; fileRef = 2783ABB61CE36CDB00F11FD4 /* BGMApps.m */; };
|
||||
2783ABB81CE36CDB00F11FD4 /* BGMApps.m in Sources */ = {isa = PBXBuildFile; fileRef = 2783ABB61CE36CDB00F11FD4 /* BGMApps.m */; };
|
||||
278D71E91CABB6FF00899CF9 /* BGMXPCHelperTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 279597401C996E2000A002FB /* BGMXPCHelperTests.m */; };
|
||||
278D71F61CABBC3B00899CF9 /* BGMXPCHelperTests-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 278D71F51CABBC3B00899CF9 /* BGMXPCHelperTests-Info.plist */; };
|
||||
2795973B1C982E4E00A002FB /* BGMXPCListener.mm in Sources */ = {isa = PBXBuildFile; fileRef = 2795973A1C982E4E00A002FB /* BGMXPCListener.mm */; };
|
||||
27D643BE1C9FB84C00737F6E /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 27D643BB1C9FB84C00737F6E /* Info.plist */; };
|
||||
27D643C01C9FB99200737F6E /* BGMXPCHelperService.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D643BA1C9FB84C00737F6E /* BGMXPCHelperService.m */; };
|
||||
27D643C11C9FB99200737F6E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 27D643BC1C9FB84C00737F6E /* main.m */; };
|
||||
27DEE37C1D4F8DA300DBFDF1 /* BGMAppVolumes.mm in Sources */ = {isa = PBXBuildFile; fileRef = 27DEE37A1D4F8DA300DBFDF1 /* BGMAppVolumes.mm */; };
|
||||
27F7D4901D2483B100821C4B /* BGMDecibel.m in Sources */ = {isa = PBXBuildFile; fileRef = 27F7D48F1D2483B100821C4B /* BGMDecibel.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
@@ -114,8 +116,6 @@
|
||||
1C2336DC1BEAB73F004C1C4E /* BGMMusicPlayer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = BGMMusicPlayer.h; path = "Music Players/BGMMusicPlayer.h"; sourceTree = "<group>"; };
|
||||
1C2336DD1BEAE10C004C1C4E /* BGMSpotify.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMSpotify.h; path = "Music Players/BGMSpotify.h"; sourceTree = "<group>"; };
|
||||
1C2336DE1BEAE10C004C1C4E /* BGMSpotify.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMSpotify.m; path = "Music Players/BGMSpotify.m"; sourceTree = "<group>"; };
|
||||
1C3DB4881BE0885A00EC8160 /* BGMAppVolumes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BGMAppVolumes.mm; sourceTree = "<group>"; };
|
||||
1C3DB48A1BE0888500EC8160 /* BGMAppVolumes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMAppVolumes.h; sourceTree = "<group>"; };
|
||||
1C4699461BD5C0E400F78043 /* BGMiTunes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMiTunes.m; path = "Music Players/BGMiTunes.m"; sourceTree = "<group>"; };
|
||||
1C46994C1BD7694C00F78043 /* BGMDeviceControlSync.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BGMDeviceControlSync.cpp; sourceTree = "<group>"; };
|
||||
1C46994D1BD7694C00F78043 /* BGMDeviceControlSync.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BGMDeviceControlSync.h; sourceTree = "<group>"; };
|
||||
@@ -161,6 +161,8 @@
|
||||
2771700F1CA0C83B00AB34B4 /* BGM_Utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGM_Utils.h; path = ../SharedSource/BGM_Utils.h; sourceTree = "<group>"; };
|
||||
277170141CA24D7C00AB34B4 /* BGMXPCListenerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMXPCListenerDelegate.h; path = BGMXPCHelper/BGMXPCListenerDelegate.h; sourceTree = SOURCE_ROOT; };
|
||||
277170151CA24D7C00AB34B4 /* BGMXPCListenerDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMXPCListenerDelegate.m; path = BGMXPCHelper/BGMXPCListenerDelegate.m; sourceTree = SOURCE_ROOT; };
|
||||
2783ABB51CE36CDB00F11FD4 /* BGMApps.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMApps.h; path = "App Volumes/BGMApps.h"; sourceTree = "<group>"; };
|
||||
2783ABB61CE36CDB00F11FD4 /* BGMApps.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BGMApps.m; path = "App Volumes/BGMApps.m"; sourceTree = "<group>"; };
|
||||
278D71F11CABB6FF00899CF9 /* BGMXPCHelperTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BGMXPCHelperTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
278D71F51CABBC3B00899CF9 /* BGMXPCHelperTests-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "BGMXPCHelperTests-Info.plist"; sourceTree = "<group>"; };
|
||||
2795970D1C91589B00A002FB /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||
@@ -174,6 +176,8 @@
|
||||
27D643BB1C9FB84C00737F6E /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = BGMXPCHelper/Info.plist; sourceTree = SOURCE_ROOT; };
|
||||
27D643BC1C9FB84C00737F6E /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = BGMXPCHelper/main.m; sourceTree = SOURCE_ROOT; };
|
||||
27D643C41C9FBE5600737F6E /* BGM_TestUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGM_TestUtils.h; path = ../SharedSource/BGM_TestUtils.h; sourceTree = "<group>"; };
|
||||
27DEE37A1D4F8DA300DBFDF1 /* BGMAppVolumes.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; name = BGMAppVolumes.mm; path = "App Volumes/BGMAppVolumes.mm"; sourceTree = "<group>"; };
|
||||
27DEE37B1D4F8DA300DBFDF1 /* BGMAppVolumes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMAppVolumes.h; path = "App Volumes/BGMAppVolumes.h"; sourceTree = "<group>"; };
|
||||
27F7D48E1D2483B100821C4B /* BGMDecibel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BGMDecibel.h; path = "Music Players/BGMDecibel.h"; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@@ -331,8 +335,7 @@
|
||||
children = (
|
||||
1CB8B33B1BBA75EF000E2DD1 /* AppDelegate.h */,
|
||||
1CB8B33C1BBA75EF000E2DD1 /* AppDelegate.mm */,
|
||||
1C3DB48A1BE0888500EC8160 /* BGMAppVolumes.h */,
|
||||
1C3DB4881BE0885A00EC8160 /* BGMAppVolumes.mm */,
|
||||
2783ABB01CE35C1D00F11FD4 /* App Volumes */,
|
||||
1CED616A1C316E1A002CAFCF /* BGMAudioDeviceManager.h */,
|
||||
1CED616B1C316E1A002CAFCF /* BGMAudioDeviceManager.mm */,
|
||||
1C1465B91BCC49D1003AEFE6 /* BGMAutoPauseMusic.h */,
|
||||
@@ -427,6 +430,17 @@
|
||||
name = "Supporting Files";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2783ABB01CE35C1D00F11FD4 /* App Volumes */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
27DEE37B1D4F8DA300DBFDF1 /* BGMAppVolumes.h */,
|
||||
27DEE37A1D4F8DA300DBFDF1 /* BGMAppVolumes.mm */,
|
||||
2783ABB51CE36CDB00F11FD4 /* BGMApps.h */,
|
||||
2783ABB61CE36CDB00F11FD4 /* BGMApps.m */,
|
||||
);
|
||||
name = "App Volumes";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
@@ -610,14 +624,15 @@
|
||||
1C4699471BD5C0E400F78043 /* BGMiTunes.m in Sources */,
|
||||
1C1962E41BC94E15008A4DF7 /* CARingBuffer.cpp in Sources */,
|
||||
273F10DF1CC3D0B900C1C6DA /* BGMVox.m in Sources */,
|
||||
27DEE37C1D4F8DA300DBFDF1 /* BGMAppVolumes.mm in Sources */,
|
||||
1CC1DF811BE5068A00FB8FE4 /* CACFArray.cpp in Sources */,
|
||||
2783ABB71CE36CDB00F11FD4 /* BGMApps.m in Sources */,
|
||||
1C0BD0A81BF1B029004F4CF5 /* BGMPreferencesMenu.mm in Sources */,
|
||||
1C1962F41BCABFC5008A4DF7 /* CAHALAudioObject.cpp in Sources */,
|
||||
27F7D4901D2483B100821C4B /* BGMDecibel.m in Sources */,
|
||||
1C2336DA1BEAB6E7004C1C4E /* BGMMusicPlayer.m in Sources */,
|
||||
1C1962F61BCABFC5008A4DF7 /* CAHALAudioSystemObject.cpp in Sources */,
|
||||
1CC1DF821BE5068A00FB8FE4 /* CACFDictionary.cpp in Sources */,
|
||||
1C3DB4891BE0885A00EC8160 /* BGMAppVolumes.mm in Sources */,
|
||||
1C0BD0A51BF1A8E6004F4CF5 /* BGMAutoPauseMusicPrefs.mm in Sources */,
|
||||
1C1963061BCAF468008A4DF7 /* CAMutex.cpp in Sources */,
|
||||
1CE7064C1BF1EC0600BFC06D /* BGMOutputDevicePrefs.mm in Sources */,
|
||||
@@ -646,6 +661,7 @@
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
1CB8B3501BBA75F0000E2DD1 /* BGMAppTests.m in Sources */,
|
||||
2783ABB81CE36CDB00F11FD4 /* BGMApps.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
|
||||
@interface BGMAppVolumes : NSObject
|
||||
@interface BGMAppVolumes : NSObject // todo: rename to BGMAppVolumesMenu
|
||||
|
||||
- (id) initWithMenu:(NSMenu*)menu appVolumeView:(NSView*)view audioDevices:(BGMAudioDeviceManager*)audioDevices;
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
// along with Background Music. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//
|
||||
// BGMAppVolumes.m
|
||||
// BGMAppVolumes.mm
|
||||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016 Kyle Neideck
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
// BGM Includes
|
||||
#include "BGM_Types.h"
|
||||
#import "BGMApps.h"
|
||||
|
||||
// PublicUtility Includes
|
||||
#include "CACFDictionary.h"
|
||||
@@ -57,6 +58,10 @@ static float const kSlidersSnapWithin = 5;
|
||||
forKeyPath:@"runningApplications"
|
||||
options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
|
||||
context:nil];
|
||||
|
||||
// todo: delete this
|
||||
NSArray* clients = (__bridge NSArray*)[audioDevices bgmDevice].GetPropertyData_CFType(kBGMClientsAddress);
|
||||
BGMApps* __unused apps = [[BGMApps alloc] initWithClients:clients];
|
||||
}
|
||||
|
||||
return self;
|
||||
@@ -90,9 +95,6 @@ static float const kSlidersSnapWithin = 5;
|
||||
// TODO: Would it be better to only show apps that are registered as HAL clients?
|
||||
if ([app activationPolicy] != NSApplicationActivationPolicyRegular) continue;
|
||||
|
||||
// Don't show Finder
|
||||
if ([[app bundleIdentifier] isEqualTo:@"com.apple.finder"]) continue;
|
||||
|
||||
#ifndef NS_BLOCK_ASSERTIONS // If assertions are enabled
|
||||
// Count how many apps we should add menu items for so we can check it at the end of the method
|
||||
numApps++;
|
||||
@@ -103,7 +105,7 @@ static float const kSlidersSnapWithin = 5;
|
||||
// Look through the menu item's subviews for the ones we want to set up
|
||||
for (NSView* subview in [[appVolItem view] subviews]) {
|
||||
if ([subview conformsToProtocol:@protocol(BGMAppVolumeSubview)]) {
|
||||
[subview performSelector:@selector(setUpWithApp:context:) withObject:app withObject:self];
|
||||
[(NSView<BGMAppVolumeSubview>*)subview setUpWithApp:app context:self];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,6 +152,7 @@ static float const kSlidersSnapWithin = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: split this method up so it can have a cleaner (less coupled) signature?
|
||||
- (void) setVolumeOfMenuItem:(NSMenuItem*)menuItem fromAppVolumes:(CACFArray&)appVolumes {
|
||||
// Set menuItem's volume slider to the volume of the app in appVolumes that menuItem represents
|
||||
// Leaves menuItem unchanged if it doesn't match any of the apps in appVolumes
|
||||
@@ -214,6 +217,7 @@ static float const kSlidersSnapWithin = 5;
|
||||
}
|
||||
}
|
||||
|
||||
// todo: move this into BGMApps. (it's not ui code.) should be able to remove the audioDevices instance var from this class then
|
||||
- (void) sendVolumeChangeToBGMDevice:(SInt32)newVolume appProcessID:(pid_t)appProcessID appBundleID:(NSString*)appBundleID {
|
||||
CACFDictionary appVolumeChange(true);
|
||||
appVolumeChange.AddSInt32(CFSTR(kBGMAppVolumesKey_ProcessID), appProcessID);
|
||||
@@ -0,0 +1,51 @@
|
||||
// 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/>.
|
||||
|
||||
//
|
||||
// BGMApps.h
|
||||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016 Kyle Neideck
|
||||
//
|
||||
|
||||
// System Includes
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
@interface BGMApp : NSObject
|
||||
|
||||
- (id) initWithName:(NSString*)name;
|
||||
|
||||
@property NSString* name;
|
||||
@property NSImage* icon;
|
||||
@property Float32 volume;
|
||||
//@property ? clients;
|
||||
@property pid_t PID;
|
||||
@property NSString* bundleID;
|
||||
@property NSArray<BGMApp*>* children;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface BGMApps : NSObject
|
||||
|
||||
// todo: comment (takes the data from kAudioDeviceCustomPropertyClients)
|
||||
// todo: seems like this type could be stricter/better
|
||||
- (id) initWithClients:(NSArray<NSDictionary*>*)clients;
|
||||
|
||||
@property (readonly) NSArray<BGMApp*>* apps;
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// 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/>.
|
||||
|
||||
//
|
||||
// BGMApps.m
|
||||
// BGMApp
|
||||
//
|
||||
// Copyright © 2016 Kyle Neideck
|
||||
// todo: need to move any copyright notices around?
|
||||
//
|
||||
|
||||
// Self Include
|
||||
#import "BGMApps.h"
|
||||
|
||||
|
||||
@implementation BGMApps
|
||||
|
||||
- (id) initWithClients:(NSArray<NSDictionary*>*)clients {
|
||||
if ((self = [super init])) {
|
||||
NSLog(@"%@", clients);
|
||||
// todo
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -107,7 +107,7 @@ static BGMMusicPlayer* sSelectedMusicPlayer;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) eventDidFail:(const AppleEvent*)event withError:(NSError*)error {
|
||||
- (id __nullable) eventDidFail:(const AppleEvent*)event withError:(NSError*)error {
|
||||
// SBApplicationDelegate method. So far, this just logs the error.
|
||||
|
||||
#if DEBUG
|
||||
|
||||
@@ -290,6 +290,7 @@ bool BGM_Device::Device_HasProperty(AudioObjectID inObjectID, pid_t inClientPID,
|
||||
case kAudioDeviceCustomPropertyMusicPlayerBundleID:
|
||||
case kAudioDeviceCustomPropertyDeviceIsRunningSomewhereOtherThanBGMApp:
|
||||
case kAudioDeviceCustomPropertyAppVolumes:
|
||||
case kAudioDeviceCustomPropertyClients:
|
||||
theAnswer = true;
|
||||
break;
|
||||
|
||||
@@ -342,6 +343,7 @@ bool BGM_Device::Device_IsPropertySettable(AudioObjectID inObjectID, pid_t inCli
|
||||
case kAudioObjectPropertyCustomPropertyInfoList:
|
||||
case kAudioDeviceCustomPropertyDeviceAudibleState:
|
||||
case kAudioDeviceCustomPropertyDeviceIsRunningSomewhereOtherThanBGMApp:
|
||||
case kAudioDeviceCustomPropertyClients:
|
||||
theAnswer = false;
|
||||
break;
|
||||
|
||||
@@ -487,7 +489,7 @@ UInt32 BGM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
|
||||
break;
|
||||
|
||||
case kAudioObjectPropertyCustomPropertyInfoList:
|
||||
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 5;
|
||||
theAnswer = sizeof(AudioServerPlugInCustomPropertyInfo) * 6;
|
||||
break;
|
||||
|
||||
case kAudioDeviceCustomPropertyDeviceAudibleState:
|
||||
@@ -507,7 +509,11 @@ UInt32 BGM_Device::Device_GetPropertyDataSize(AudioObjectID inObjectID, pid_t in
|
||||
break;
|
||||
|
||||
case kAudioDeviceCustomPropertyAppVolumes:
|
||||
theAnswer = sizeof(CFPropertyListRef);
|
||||
theAnswer = sizeof(CFArrayRef);
|
||||
break;
|
||||
|
||||
case kAudioDeviceCustomPropertyClients:
|
||||
theAnswer = sizeof(CFArrayRef);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -902,7 +908,7 @@ void BGM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
|
||||
break;
|
||||
|
||||
case kAudioDevicePropertyPreferredChannelsForStereo:
|
||||
// This property returns which two channesl to use as left/right for stereo
|
||||
// This property returns which two channels to use as left/right for stereo
|
||||
// data by default. Note that the channel numbers are 1-based.
|
||||
ThrowIf(inDataSize < (2 * sizeof(UInt32)), CAException(kAudioHardwareBadPropertySizeError), "BGM_Device::Device_GetPropertyData: not enough space for the return value of kAudioDevicePropertyPreferredChannelsForStereo for the device");
|
||||
((UInt32*)outData)[0] = 1;
|
||||
@@ -959,9 +965,9 @@ void BGM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
|
||||
theNumberItemsToFetch = inDataSize / sizeof(AudioServerPlugInCustomPropertyInfo);
|
||||
|
||||
// clamp it to the number of items we have
|
||||
if(theNumberItemsToFetch > 5)
|
||||
if(theNumberItemsToFetch > 6)
|
||||
{
|
||||
theNumberItemsToFetch = 5;
|
||||
theNumberItemsToFetch = 6;
|
||||
}
|
||||
|
||||
if(theNumberItemsToFetch > 0)
|
||||
@@ -994,6 +1000,12 @@ void BGM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
|
||||
((AudioServerPlugInCustomPropertyInfo*)outData)[4].mPropertyDataType = kAudioServerPlugInCustomPropertyDataTypeCFPropertyList;
|
||||
((AudioServerPlugInCustomPropertyInfo*)outData)[4].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
|
||||
}
|
||||
if(theNumberItemsToFetch > 5)
|
||||
{
|
||||
((AudioServerPlugInCustomPropertyInfo*)outData)[5].mSelector = kAudioDeviceCustomPropertyClients;
|
||||
((AudioServerPlugInCustomPropertyInfo*)outData)[5].mPropertyDataType = kAudioServerPlugInCustomPropertyDataTypeCFPropertyList;
|
||||
((AudioServerPlugInCustomPropertyInfo*)outData)[5].mQualifierDataType = kAudioServerPlugInCustomPropertyDataTypeNone;
|
||||
}
|
||||
outDataSize = theNumberItemsToFetch * sizeof(AudioServerPlugInCustomPropertyInfo);
|
||||
break;
|
||||
|
||||
@@ -1042,6 +1054,15 @@ void BGM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
|
||||
outDataSize = sizeof(CFArrayRef);
|
||||
}
|
||||
break;
|
||||
|
||||
case kAudioDeviceCustomPropertyClients:
|
||||
{
|
||||
ThrowIf(inDataSize < sizeof(CFArrayRef), CAException(kAudioHardwareBadPropertySizeError), "BGM_Device::Device_GetPropertyData: not enough space for the return value of kAudioDeviceCustomPropertyClients for the device");
|
||||
CAMutex::Locker theStateLocker(mStateMutex);
|
||||
*reinterpret_cast<CFArrayRef*>(outData) = mClients.CopyClientPIDsAndBundleIDs().GetCFArray();
|
||||
outDataSize = sizeof(CFArrayRef);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
BGM_Object::GetPropertyData(inObjectID, inClientPID, inAddress, inQualifierDataSize, inQualifierData, inDataSize, outDataSize, outData);
|
||||
|
||||
@@ -172,6 +172,29 @@ std::vector<BGM_Client> BGM_ClientMap::GetClientsByPID(pid_t inPID) const
|
||||
return theClients;
|
||||
}
|
||||
|
||||
CACFArray BGM_ClientMap::CopyClientPIDsAndBundleIDs() const
|
||||
{
|
||||
// Since this is a read-only, non-real-time operation we can read from the shadow maps to avoid
|
||||
// locking the main maps.
|
||||
CAMutex::Locker theShadowMapsLocker(mShadowMapsMutex);
|
||||
|
||||
CACFArray theClientPIDsAndBundleIDs(false);
|
||||
|
||||
for(auto& theClientEntry : mClientMapShadow)
|
||||
{
|
||||
CACFDictionary theClientDict(false);
|
||||
|
||||
theClientDict.AddSInt32(CFSTR(kBGMClientsKey_ProcessID), theClientEntry.second.mProcessID);
|
||||
// todo: is this a memory leak? (over retaining mBundleID, cause adding it to the dict also retains it) check for the same bug
|
||||
// in CopyClientIntoAppVolumesArray if so.
|
||||
theClientDict.AddString(CFSTR(kBGMClientsKey_BundleID), theClientEntry.second.mBundleID.CopyCFString());
|
||||
|
||||
theClientPIDsAndBundleIDs.AppendDictionary(theClientDict.GetDict());
|
||||
}
|
||||
|
||||
return theClientPIDsAndBundleIDs;
|
||||
}
|
||||
|
||||
#pragma mark Music Player
|
||||
|
||||
void BGM_ClientMap::UpdateMusicPlayerFlags(pid_t inMusicPlayerPID)
|
||||
@@ -213,7 +236,7 @@ void BGM_ClientMap::UpdateMusicPlayerFlagsInShadowMaps(std::function<bool(BGM
|
||||
|
||||
CACFArray BGM_ClientMap::CopyClientRelativeVolumesAsAppVolumes(CAVolumeCurve inVolumeCurve) const
|
||||
{
|
||||
// Since this is a read-only, non-real-time operation, we can read from the shadow maps to avoid
|
||||
// Since this is a read-only, non-real-time operation we can read from the shadow maps to avoid
|
||||
// locking the main maps.
|
||||
CAMutex::Locker theShadowMapsLocker(mShadowMapsMutex);
|
||||
|
||||
|
||||
@@ -101,6 +101,10 @@ private:
|
||||
public:
|
||||
std::vector<BGM_Client> GetClientsByPID(pid_t inPID) const;
|
||||
|
||||
// todo: comment
|
||||
// todo: would it be useful at all to have a similar property that returns past clients instead? probably not...
|
||||
CACFArray CopyClientPIDsAndBundleIDs() const;
|
||||
|
||||
// Set the isMusicPlayer flag for each client. (True if the client has the given bundle ID/PID, false otherwise.)
|
||||
void UpdateMusicPlayerFlags(pid_t inMusicPlayerPID);
|
||||
void UpdateMusicPlayerFlags(CACFString inMusicPlayerBundleID);
|
||||
|
||||
@@ -108,6 +108,8 @@ public:
|
||||
// Returns true if any clients' relative volumes were changed.
|
||||
bool SetClientsRelativeVolumes(const CACFArray inAppVolumes);
|
||||
|
||||
CACFArray CopyClientPIDsAndBundleIDs() const { return mClientMap.CopyClientPIDsAndBundleIDs(); }
|
||||
|
||||
private:
|
||||
BGM_ClientMap mClientMap;
|
||||
|
||||
|
||||
@@ -56,6 +56,9 @@ enum
|
||||
{
|
||||
// TODO: Combine the two music player properties
|
||||
|
||||
// Remember to update the values BGM_Device returns for kAudioObjectPropertyCustomPropertyInfoList if you
|
||||
// modify this enum.
|
||||
|
||||
// The process ID of the music player as a CFNumber. Setting this property will also clear the value of
|
||||
// kAudioDeviceCustomPropertyMusicPlayerBundleID. We use 0 to mean unset.
|
||||
//
|
||||
@@ -74,13 +77,17 @@ enum
|
||||
// A CFBoolean similar to kAudioDevicePropertyDeviceIsRunning except it ignores whether IO is running for
|
||||
// BGMApp. This is so BGMApp knows when it can stop doing IO to save CPU.
|
||||
kAudioDeviceCustomPropertyDeviceIsRunningSomewhereOtherThanBGMApp = 'runo',
|
||||
// A CFArray of CFDictionaries that each contain an app's pid, bundle ID and volume relative to other
|
||||
// A CFArray of CFDictionaries that each contain an app's PID, bundle ID and volume relative to other
|
||||
// running apps. See the dictionary keys below for more info.
|
||||
//
|
||||
// Getting this property will only return apps with volumes other than the default. Setting this property
|
||||
// will add new app volumes or replace existing ones, but there's currently no way to delete an app from
|
||||
// the internal collection.
|
||||
kAudioDeviceCustomPropertyAppVolumes = 'apvs'
|
||||
kAudioDeviceCustomPropertyAppVolumes = 'apvs',
|
||||
// todo: send the client ids as well. maybe combine with kAudioDeviceCustomPropertyAppVolumes
|
||||
// A CFArray with one entry for each client of BGMDevice. Each entry is a CFDictionary that contains the
|
||||
// client's PID and, if it has one, the client's bundle ID. See the dictionary keys below for more info.
|
||||
kAudioDeviceCustomPropertyClients = 'clts'
|
||||
};
|
||||
|
||||
// The number of silent/audible frames before BGMDriver will change kAudioDeviceCustomPropertyDeviceAudibleState
|
||||
@@ -104,11 +111,18 @@ enum
|
||||
// the midpoint increases the client's volume and a value less than the midpoint decreases it. A volume curve is
|
||||
// applied to kBGMAppVolumesKey_RelativeVolume when it's first set and then each of the app's samples are multiplied
|
||||
// by it.
|
||||
#define kBGMAppVolumesKey_RelativeVolume "rvol"
|
||||
// The app's pid as a CFNumber. May be omitted if kBGMAppVolumesKey_BundleID is present.
|
||||
#define kBGMAppVolumesKey_ProcessID "pid"
|
||||
#define kBGMAppVolumesKey_RelativeVolume "av_rvol"
|
||||
// The app's process ID as a CFNumber (which wraps a pid_t). May be omitted if kBGMAppVolumesKey_BundleID is present.
|
||||
#define kBGMAppVolumesKey_ProcessID "av_pid"
|
||||
// The app's bundle ID as a CFString. May be omitted if kBGMAppVolumesKey_ProcessID is present.
|
||||
#define kBGMAppVolumesKey_BundleID "bid"
|
||||
#define kBGMAppVolumesKey_BundleID "av_bid"
|
||||
|
||||
// kAudioDeviceCustomPropertyClients keys
|
||||
//
|
||||
// The client's process ID as a CFNumber<pid_t>.
|
||||
#define kBGMClientsKey_ProcessID "c_pid"
|
||||
// The client's bundle ID as a CFString. Omitted if the client doesn't have a bundle ID.
|
||||
#define kBGMClientsKey_BundleID "c_bid"
|
||||
|
||||
// Volume curve range for app volumes
|
||||
#define kAppRelativeVolumeMaxRawValue 100
|
||||
@@ -150,6 +164,12 @@ static const AudioObjectPropertyAddress kBGMAppVolumesAddress = {
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
static const AudioObjectPropertyAddress kBGMClientsAddress = {
|
||||
kAudioDeviceCustomPropertyClients,
|
||||
kAudioObjectPropertyScopeGlobal,
|
||||
kAudioObjectPropertyElementMaster
|
||||
};
|
||||
|
||||
#pragma mark XPC Return Codes
|
||||
|
||||
enum {
|
||||
|
||||
@@ -445,6 +445,7 @@ echo "[2/3] Installing $(bold_face ${XPC_HELPER_DIR}) to $(bold_face ${XPC_HELPE
|
||||
sudo "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
||||
-target BGMXPCHelper \
|
||||
-configuration ${CONFIGURATION} \
|
||||
OTHER_CFLAGS="-Wno-everything" \
|
||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||
DSTROOT="/" \
|
||||
INSTALL_PATH="${XPC_HELPER_PATH}" \
|
||||
@@ -461,6 +462,7 @@ echo "[3/3] Installing $(bold_face ${APP_DIR}) to $(bold_face ${APP_PATH})." \
|
||||
sudo "${XCODEBUILD}" -project BGMApp/BGMApp.xcodeproj \
|
||||
-target "Background Music" \
|
||||
-configuration ${CONFIGURATION} \
|
||||
OTHER_CFLAGS="-Wno-everything" \
|
||||
RUN_CLANG_STATIC_ANALYZER=0 \
|
||||
DSTROOT="/" \
|
||||
${CLEAN} install >> ${LOG_FILE} 2>&1) &
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
// TODO: Delete this before merging WIP-MultiprocessAppVols into master.
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <libproc.h>
|
||||
#include <errno.h>
|
||||
|
||||
extern int responsibility_get_responsible_for_pid(pid_t, int32_t*, uint64_t*, size_t*, char*);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc < 2) {
|
||||
printf("Usage: %s <pid>\n", argv[0]);
|
||||
return -1;
|
||||
}
|
||||
pid_t pid = (pid_t)atoi(argv[1]);
|
||||
|
||||
{
|
||||
char path_buf[PROC_PIDPATHINFO_MAXSIZE] = "";
|
||||
size_t path_len = sizeof(path_buf);
|
||||
if (proc_pidpath(pid, path_buf, path_len) <= 0) {
|
||||
printf("Couldn't get pid path for pid %d\n", pid);
|
||||
printf("Error %d: %s\n", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
path_buf[path_len - 1] = '\0';
|
||||
printf("Path for process: %s\n", path_buf);
|
||||
}
|
||||
|
||||
{
|
||||
int32_t rpid;
|
||||
uint64_t urpid;
|
||||
char responsible_path_buf[PROC_PIDPATHINFO_MAXSIZE] = "";
|
||||
size_t responsible_path_len = sizeof(responsible_path_buf);
|
||||
if (responsibility_get_responsible_for_pid(pid, &rpid, &urpid, &responsible_path_len, responsible_path_buf) != 0) {
|
||||
printf("Couldn't get responsibility pid for pid %d\n", pid);
|
||||
printf("Error %d: %s\n", errno, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
responsible_path_buf[responsible_path_len - 1] = '\0';
|
||||
printf("Path for responsible process: %s\n", responsible_path_buf);
|
||||
printf("Responsible PID: %d\n", rpid);
|
||||
printf("Responsible unique PID: %llu\n", urpid);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user