BGMApp: Move some more code into BGMBackgroundMusicDevice.

Mostly code for getting and setting BGMDevice's custom properties. Also
adds some stricter checking for property data received from BGMDevice.
This commit is contained in:
Kyle Neideck 2017-08-06 22:16:17 +10:00
parent e05acde351
commit 02558cd275
No known key found for this signature in database
GPG key ID: CAA8D9B8E39EC18C
8 changed files with 153 additions and 23 deletions

View file

@ -98,7 +98,7 @@ static CGFloat const kAppVolumeViewInitialHeight = 20;
#endif
// Get the app volumes currently set on the device
CACFArray appVolumesOnDevice((CFArrayRef)[audioDevices bgmDevice].GetPropertyData_CFType(kBGMAppVolumesAddress), false);
CACFArray appVolumesOnDevice((CFArrayRef)[audioDevices bgmDevice].GetAppVolumes(), false);
NSInteger index = [bgmMenu indexOfItemWithTag:kAppVolumesHeadingMenuItemTag] + 1;

View file

@ -145,14 +145,7 @@ static Float32 const kUnpauseDelayWeightingFactor = 0.1f;
}
- (BGMDeviceAudibleState) deviceAudibleState {
BGMDeviceAudibleState audibleState;
CFNumberRef audibleStateRef =
static_cast<CFNumberRef>([audioDevices bgmDevice].GetPropertyData_CFType(kBGMAudibleStateAddress));
CFNumberGetValue(audibleStateRef, kCFNumberSInt32Type, &audibleState);
CFRelease(audibleStateRef);
return audibleState;
return [audioDevices bgmDevice].GetAudibleState();
}
- (void) queuePauseBlock {

View file

@ -115,6 +115,20 @@ void BGMBackgroundMusicDevice::UnsetAsOSDefault(AudioDeviceID inOutputDeviceID)
#pragma mark App Volumes
CFArrayRef BGMBackgroundMusicDevice::GetAppVolumes() const
{
CFTypeRef appVolumes = GetPropertyData_CFType(kBGMAppVolumesAddress);
ThrowIfNULL(appVolumes,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetAppVolumes: !appVolumes");
ThrowIf(CFGetTypeID(appVolumes) != CFArrayGetTypeID(),
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetAppVolumes: Expected CFArray value");
return static_cast<CFArrayRef>(appVolumes);
}
void BGMBackgroundMusicDevice::SetAppVolume(SInt32 inVolume,
pid_t inAppProcessID,
CFStringRef inAppBundleID)
@ -226,5 +240,70 @@ BGMBackgroundMusicDevice::ResponsibleBundleIDsOf(CFStringRef inParentBundleID)
return bundleIDMap[inParentBundleID];
}
#pragma mark Audible State
BGMDeviceAudibleState BGMBackgroundMusicDevice::GetAudibleState() const
{
CFTypeRef propertyDataRef = GetPropertyData_CFType(kBGMAudibleStateAddress);
ThrowIfNULL(propertyDataRef,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetAudibleState: !propertyDataRef");
ThrowIf(CFGetTypeID(propertyDataRef) != CFNumberGetTypeID(),
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetAudibleState: Property was not a CFNumber");
CFNumberRef audibleStateRef = static_cast<CFNumberRef>(propertyDataRef);
BGMDeviceAudibleState audibleState;
Boolean success = CFNumberGetValue(audibleStateRef, kCFNumberSInt32Type, &audibleState);
CFRelease(audibleStateRef);
ThrowIf(!success,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetMusicPlayerProcessID: CFNumberGetValue failed");
return audibleState;
}
#pragma mark Music Player
pid_t BGMBackgroundMusicDevice::GetMusicPlayerProcessID() const
{
CFTypeRef propertyDataRef = GetPropertyData_CFType(kBGMMusicPlayerProcessIDAddress);
ThrowIfNULL(propertyDataRef,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetMusicPlayerProcessID: !propertyDataRef");
ThrowIf(CFGetTypeID(propertyDataRef) != CFNumberGetTypeID(),
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetMusicPlayerProcessID: Property was not a CFNumber");
CFNumberRef pidRef = static_cast<CFNumberRef>(propertyDataRef);
pid_t pid;
Boolean success = CFNumberGetValue(pidRef, kCFNumberIntType, &pid);
CFRelease(pidRef);
ThrowIf(!success,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetMusicPlayerProcessID: CFNumberGetValue failed");
return pid;
}
CFStringRef BGMBackgroundMusicDevice::GetMusicPlayerBundleID() const
{
CFStringRef bundleID = GetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress);
ThrowIfNULL(bundleID,
CAException(kAudioHardwareIllegalOperationError),
"BGMBackgroundMusicDevice::GetMusicPlayerBundleID: !bundleID");
return bundleID;
}
#pragma clang assume_nonnull end

View file

@ -37,6 +37,9 @@
// Superclass Includes
#include "BGMAudioDevice.h"
// Local Includes
#include "BGM_Types.h"
// STL Includes
#include <vector>
@ -60,6 +63,7 @@ public:
#pragma mark Systemwide Default Device
public:
/*!
Set BGMDevice as the default audio device for all processes.
@ -75,6 +79,14 @@ public:
#pragma mark App Volumes
public:
/*!
@return The current value of BGMDevice's kAudioDeviceCustomPropertyAppVolumes property. See
BGM_Types.h.
@throws CAException If the HAL returns an error or a non-array type. Callers are responsible
for validating and type-checking the values contained in the array.
*/
CFArrayRef GetAppVolumes() const;
/*!
@param inVolume A value between kAppRelativeVolumeMinRawValue and kAppRelativeVolumeMaxRawValue
from BGM_Types.h. See kBGMAppVolumesKey_RelativeVolume in BGM_Types.h.
@ -114,11 +126,60 @@ private:
static std::vector<CFStringRef>
ResponsibleBundleIDsOf(CFStringRef inParentBundleID);
#pragma mark Audible State
public:
/*!
@return BGMDevice's current "audible state", which can be either silent, silent except for the
user's music player or audible, meaning a program other than the music player is
playing audio.
@throws CAException If the HAL returns an error or invalid data when queried.
@see kAudioDeviceCustomPropertyDeviceAudibleState in BGM_Types.h.
*/
BGMDeviceAudibleState GetAudibleState() const;
#pragma mark Music Player
public:
/*!
@return The value of BGMDevice's property for the selected music player's process ID. Zero if
the property is unset. (We assume kernel_task will never be the user's music player.)
@throws CAException If the HAL returns an error or an invalid PID when queried.
@see kAudioDeviceCustomPropertyMusicPlayerProcessID in BGM_Types.h.
*/
pid_t GetMusicPlayerProcessID() const;
/*!
Set the value of BGMDevice's property for the selected music player's process ID. Pass zero to
unset the property. Setting this property will unset the bundle ID version of the property.
@throws CAException If the HAL returns an error.
@see kAudioDeviceCustomPropertyMusicPlayerProcessID in BGM_Types.h.
*/
void SetMusicPlayerProcessID(CFNumberRef inProcessID) {
SetPropertyData_CFType(kBGMMusicPlayerProcessIDAddress, inProcessID); }
/*!
@return The value of BGMDevice's property for the selected music player's bundle ID. The empty
string if the property is unset.
@throws CAException If the HAL returns an error or an invalid bundle ID when queried.
@see kAudioDeviceCustomPropertyMusicPlayerBundleID in BGM_Types.h.
*/
CFStringRef GetMusicPlayerBundleID() const;
/*!
Set the value of BGMDevice's property for the selected music player's bundle ID. Pass the empty
string to unset the property. Setting this property will unset the process ID version of the
property.
@throws CAException If the HAL returns an error.
@see kAudioDeviceCustomPropertyMusicPlayerBundleID in BGM_Types.h.
*/
void SetMusicPlayerBundleID(CFStringRef inBundleID) {
SetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress, inBundleID); }
#pragma mark UI Sounds Instance
public:
/*! @return The instance of BGMDevice that handles UI sounds. */
BGMAudioDevice GetUISoundsBGMDeviceInstance() const { return mUISoundsBGMDevice; }
BGMAudioDevice GetUISoundsBGMDeviceInstance() { return mUISoundsBGMDevice; }
private:
/*! The instance of BGMDevice that handles UI sounds. */

View file

@ -133,8 +133,8 @@
// backwards compatability.
NSString* __nullable bundleID =
(__bridge_transfer NSString* __nullable)[audioDevices bgmDevice].GetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress);
(__bridge_transfer NSString* __nullable)[audioDevices bgmDevice].GetMusicPlayerBundleID();
DebugMsg("BGMMusicPlayers::initSelectedMusicPlayerFromBGMDevice: "
"Trying to set selected music player by bundle ID (from BGMDriver). bundleID=%s",
(bundleID ? bundleID.UTF8String : "(null)"));
@ -224,13 +224,11 @@
@"BGMMusicPlayers::updateBGMDeviceMusicPlayerProperties: Music player has neither bundle ID nor PID");
if (self.selectedMusicPlayer.pid) {
[audioDevices bgmDevice].SetPropertyData_CFType(kBGMMusicPlayerProcessIDAddress,
(__bridge CFNumberRef)self.selectedMusicPlayer.pid);
[audioDevices bgmDevice].SetMusicPlayerProcessID((__bridge CFNumberRef)self.selectedMusicPlayer.pid);
}
if (self.selectedMusicPlayer.bundleID) {
[audioDevices bgmDevice].SetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress,
(__bridge CFStringRef)self.selectedMusicPlayer.bundleID);
[audioDevices bgmDevice].SetMusicPlayerBundleID((__bridge CFStringRef)self.selectedMusicPlayer.bundleID);
}
}

View file

@ -174,8 +174,7 @@
// When it doesn't find a selected music player in user defaults, it should check BGMDevice's music
// player properties.
[devices bgmDevice].SetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress,
CFSTR("org.videolan.vlc"));
[devices bgmDevice].SetMusicPlayerBundleID(CFSTR("org.videolan.vlc"));
BGMMusicPlayers* players = [[BGMMusicPlayers alloc] initWithAudioDevices:devices
userDefaults:defaults];
@ -190,7 +189,7 @@
- (void) resetDevice {
// Reset the mock BGMDevice.
[devices bgmDevice].SetPropertyData_CFString(kBGMMusicPlayerBundleIDAddress, NULL);
[devices bgmDevice].SetMusicPlayerBundleID(CFSTR(""));
}
@end

View file

@ -32,9 +32,9 @@
#pragma clang diagnostic ignored "-Wunused-parameter"
// The value of the music player bundle ID property. Tests should set this back to NULL when they finish. (Has
// The value of the music player bundle ID property. Tests should set this back to "" when they finish. (Has
// to be static because we can't add to the real class's interface.)
static CFStringRef __nullable playerBundleID = NULL;
static CFStringRef playerBundleID = CFSTR("");
CAHALAudioObject::CAHALAudioObject(AudioObjectID inObjectID)
:

View file

@ -946,7 +946,7 @@ void BGM_Device::Device_GetPropertyData(AudioObjectID inObjectID, pid_t inClient
ThrowIf(inDataSize < sizeof(CFNumberRef), CAException(kAudioHardwareBadPropertySizeError), "BGM_Device::Device_GetPropertyData: not enough space for the return value of kAudioDeviceCustomPropertyMusicPlayerProcessID for the device");
CAMutex::Locker theStateLocker(mStateMutex);
pid_t pid = mClients.GetMusicPlayerProcessIDProperty();
*reinterpret_cast<CFNumberRef*>(outData) = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pid);
*reinterpret_cast<CFNumberRef*>(outData) = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &pid);
outDataSize = sizeof(CFNumberRef);
}
break;
@ -1022,7 +1022,7 @@ void BGM_Device::Device_SetPropertyData(AudioObjectID inObjectID, pid_t inClient
// pid variable, and we want that to be an error.)
pid_t pid = INT_MIN;
// CFNumberGetValue docs: "If the conversion is lossy, or the value is out of range, false is returned."
Boolean success = CFNumberGetValue(pidRef, kCFNumberSInt32Type, &pid);
Boolean success = CFNumberGetValue(pidRef, kCFNumberIntType, &pid);
ThrowIf(!success, CAException(kAudioHardwareIllegalOperationError), "BGM_Device::Device_SetPropertyData: probable error from CFNumberGetValue when reading pid for kAudioDeviceCustomPropertyMusicPlayerProcessID");