// 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 .
//
// VC_MuteControl.cpp
// VCDriver
//
// Copyright © 2016, 2017 Kyle Neideck
//
// Self Include
#include "VC_MuteControl.h"
// Local Includes
#include "VC_PlugIn.h"
// PublicUtility Includes
#include "CADebugMacros.h"
#include "CAException.h"
#include "CADispatchQueue.h"
#pragma clang assume_nonnull begin
#pragma mark Construction/Destruction
VC_MuteControl::VC_MuteControl(AudioObjectID inObjectID,
AudioObjectID inOwnerObjectID,
AudioObjectPropertyScope inScope,
AudioObjectPropertyElement inElement)
:
VC_Control(inObjectID,
kAudioMuteControlClassID,
kAudioBooleanControlClassID,
inOwnerObjectID,
inScope,
inElement),
mMutex("Mute Control"),
mMuted(false)
{
}
#pragma mark Property Operations
bool VC_MuteControl::HasProperty(AudioObjectID inObjectID,
pid_t inClientPID,
const AudioObjectPropertyAddress& inAddress) const
{
CheckObjectID(inObjectID);
bool theAnswer = false;
switch(inAddress.mSelector)
{
case kAudioBooleanControlPropertyValue:
theAnswer = true;
break;
default:
theAnswer = VC_Control::HasProperty(inObjectID, inClientPID, inAddress);
break;
};
return theAnswer;
}
bool VC_MuteControl::IsPropertySettable(AudioObjectID inObjectID,
pid_t inClientPID,
const AudioObjectPropertyAddress& inAddress) const
{
CheckObjectID(inObjectID);
bool theAnswer = false;
switch(inAddress.mSelector)
{
case kAudioBooleanControlPropertyValue:
theAnswer = true;
break;
default:
theAnswer = VC_Control::IsPropertySettable(inObjectID, inClientPID, inAddress);
break;
};
return theAnswer;
}
UInt32 VC_MuteControl::GetPropertyDataSize(AudioObjectID inObjectID,
pid_t inClientPID,
const AudioObjectPropertyAddress& inAddress,
UInt32 inQualifierDataSize,
const void* inQualifierData) const
{
CheckObjectID(inObjectID);
UInt32 theAnswer = 0;
switch(inAddress.mSelector)
{
case kAudioBooleanControlPropertyValue:
theAnswer = sizeof(UInt32);
break;
default:
theAnswer = VC_Control::GetPropertyDataSize(inObjectID,
inClientPID,
inAddress,
inQualifierDataSize,
inQualifierData);
break;
};
return theAnswer;
}
void VC_MuteControl::GetPropertyData(AudioObjectID inObjectID,
pid_t inClientPID,
const AudioObjectPropertyAddress& inAddress,
UInt32 inQualifierDataSize,
const void* inQualifierData,
UInt32 inDataSize,
UInt32& outDataSize,
void* outData) const
{
CheckObjectID(inObjectID);
switch(inAddress.mSelector)
{
case kAudioBooleanControlPropertyValue:
// This returns the mute value of the control.
{
ThrowIf(inDataSize < sizeof(UInt32),
CAException(kAudioHardwareBadPropertySizeError),
"VC_MuteControl::GetPropertyData: not enough space for the return value "
"of kAudioBooleanControlPropertyValue for the mute control");
CAMutex::Locker theLocker(mMutex);
// Non-zero for true, which means audio is being muted.
*reinterpret_cast(outData) = mMuted ? 1 : 0;
outDataSize = sizeof(UInt32);
}
break;
default:
VC_Control::GetPropertyData(inObjectID,
inClientPID,
inAddress,
inQualifierDataSize,
inQualifierData,
inDataSize,
outDataSize,
outData);
break;
};
}
void VC_MuteControl::SetPropertyData(AudioObjectID inObjectID,
pid_t inClientPID,
const AudioObjectPropertyAddress& inAddress,
UInt32 inQualifierDataSize,
const void* inQualifierData,
UInt32 inDataSize,
const void* inData)
{
CheckObjectID(inObjectID);
switch(inAddress.mSelector)
{
case kAudioBooleanControlPropertyValue:
{
ThrowIf(inDataSize < sizeof(UInt32),
CAException(kAudioHardwareBadPropertySizeError),
"VC_MuteControl::SetPropertyData: wrong size for the data for "
"kAudioBooleanControlPropertyValue");
CAMutex::Locker theLocker(mMutex);
// Non-zero for true, meaning audio will be muted.
bool theNewMuted = (*reinterpret_cast(inData) != 0);
if(mMuted != theNewMuted)
{
mMuted = theNewMuted;
// Send notifications.
CADispatchQueue::GetGlobalSerialQueue().Dispatch(false, ^{
AudioObjectPropertyAddress theChangedProperty[1];
theChangedProperty[0] = {
kAudioBooleanControlPropertyValue, mScope, mElement
};
VC_PlugIn::Host_PropertiesChanged(inObjectID, 1, theChangedProperty);
});
}
}
break;
default:
VC_Control::SetPropertyData(inObjectID,
inClientPID,
inAddress,
inQualifierDataSize,
inQualifierData,
inDataSize,
inData);
break;
};
}
#pragma clang assume_nonnull end