IOAudioSelectorControl.cpp [plain text]
#include <IOKit/audio/IOAudioSelectorControl.h>
#include <IOKit/audio/IOAudioTypes.h>
#include <IOKit/audio/IOAudioDefines.h>
#include <libkern/c++/OSString.h>
#include <libkern/c++/OSArray.h>
#include <libkern/c++/OSDictionary.h>
#define super IOAudioControl
OSDefineMetaClassAndStructors(IOAudioSelectorControl, IOAudioControl)
OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 0);
OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 1);
OSMetaClassDefineReservedUsed(IOAudioSelectorControl, 2);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 3);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 4);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 5);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 6);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 7);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 8);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 9);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 10);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 11);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 12);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 13);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 14);
OSMetaClassDefineReservedUnused(IOAudioSelectorControl, 15);
IOAudioSelectorControl *IOAudioSelectorControl::createOutputClockSelector(SInt32 initialValue,
UInt32 channelID,
UInt32 clockSource,
const char *channelName,
UInt32 cntrlID)
{
IOAudioSelectorControl *clockControl;
if (clockControl = create (initialValue,
channelID,
channelName,
cntrlID,
kIOAudioSelectorControlSubTypeClockSource,
kIOAudioControlUsageOutput)) {
clockControl->setProperty(kIOAudioSelectorControlClockSourceKey, clockSource);
}
return clockControl;
}
IOAudioSelectorControl *IOAudioSelectorControl::createInputClockSelector(SInt32 initialValue,
UInt32 channelID,
UInt32 clockSource,
const char *channelName,
UInt32 cntrlID)
{
IOAudioSelectorControl *clockControl;
if (clockControl = create (initialValue,
channelID,
channelName,
cntrlID,
kIOAudioSelectorControlSubTypeClockSource,
kIOAudioControlUsageInput)) {
clockControl->setProperty(kIOAudioSelectorControlClockSourceKey, clockSource);
}
return clockControl;
}
IOAudioSelectorControl *IOAudioSelectorControl::createOutputSelector(SInt32 initialValue,
UInt32 channelID,
const char *channelName,
UInt32 cntrlID)
{
return create(initialValue,
channelID,
channelName,
cntrlID,
kIOAudioSelectorControlSubTypeOutput,
kIOAudioControlUsageOutput);
}
IOReturn IOAudioSelectorControl::removeAvailableSelection(SInt32 selectionValue)
{
OSCollectionIterator *iterator;
OSArray *newSelections;
OSArray *oldAvailableSelections;
IOReturn result = kIOReturnNotFound;
assert(availableSelections);
oldAvailableSelections = availableSelections;
newSelections = OSArray::withArray(availableSelections);
if (!newSelections)
return kIOReturnNoMemory;
iterator = OSCollectionIterator::withCollection(newSelections);
if (iterator) {
OSDictionary * selection;
UInt32 index;
index = 0;
while (selection = (OSDictionary *)iterator->getNextObject()) {
OSNumber * sValue;
sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey);
if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) {
newSelections->removeObject(index);
result = kIOReturnSuccess;
break;
}
index++;
}
availableSelections = newSelections;
setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
oldAvailableSelections->release();
iterator->release();
}
if (kIOReturnSuccess == result) {
sendChangeNotification(kIOAudioControlRangeChangeNotification);
}
return result;
}
IOReturn IOAudioSelectorControl::replaceAvailableSelection(SInt32 selectionValue, const char *selectionDescription)
{
IOReturn result = kIOReturnBadArgument;
if (selectionDescription != NULL) {
OSString *selDesc;
selDesc = OSString::withCString(selectionDescription);
if (selDesc) {
result = replaceAvailableSelection(selectionValue, selDesc);
} else {
result = kIOReturnNoMemory;
}
}
return result;
}
IOReturn IOAudioSelectorControl::replaceAvailableSelection(SInt32 selectionValue, OSString *selectionDescription)
{
OSCollectionIterator *iterator;
OSArray *newSelections;
OSArray *oldAvailableSelections;
IOReturn result = kIOReturnSuccess;
assert(availableSelections);
oldAvailableSelections = availableSelections;
newSelections = OSArray::withArray(availableSelections);
if (!newSelections)
return kIOReturnNoMemory;
iterator = OSCollectionIterator::withCollection(newSelections);
if (iterator) {
OSDictionary * selection;
UInt32 index;
index = 0;
while (selection = (OSDictionary *)iterator->getNextObject()) {
OSNumber * sValue;
sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey);
if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) {
newSelections->replaceObject(index, selectionDescription);
result = kIOReturnSuccess;
break;
}
index++;
}
availableSelections = newSelections;
setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
oldAvailableSelections->release();
iterator->release();
}
if (kIOReturnSuccess == result) {
sendChangeNotification(kIOAudioControlRangeChangeNotification);
}
return result;
}
IOAudioSelectorControl *IOAudioSelectorControl::create(SInt32 initialValue,
UInt32 channelID,
const char *channelName,
UInt32 cntrlID,
UInt32 subType,
UInt32 usage)
{
IOAudioSelectorControl *control;
control = new IOAudioSelectorControl;
if (control) {
if (!control->init(initialValue,
channelID,
channelName,
cntrlID,
subType,
usage)) {
control->release();
control = NULL;
}
}
return control;
}
IOAudioSelectorControl *IOAudioSelectorControl::createInputSelector(SInt32 initialValue,
UInt32 channelID,
const char *channelName,
UInt32 cntrlID)
{
return create(initialValue,
channelID,
channelName,
cntrlID,
kIOAudioSelectorControlSubTypeInput,
kIOAudioControlUsageInput);
}
bool IOAudioSelectorControl::init(SInt32 initialValue,
UInt32 channelID,
const char *channelName,
UInt32 cntrlID,
UInt32 subType,
UInt32 usage,
OSDictionary *properties)
{
bool result = false;
OSNumber *number;
number = OSNumber::withNumber(initialValue, sizeof(SInt32)*8);
if (number) {
result = super::init(kIOAudioControlTypeSelector,
number,
channelID,
channelName,
cntrlID,
subType,
usage,
properties);
number->release();
}
if (result) {
availableSelections = OSArray::withCapacity(2);
setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
}
return result;
}
void IOAudioSelectorControl::free()
{
if (availableSelections) {
availableSelections->release();
availableSelections = NULL;
}
super::free();
}
IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, const char *selectionDescription)
{
IOReturn result = kIOReturnBadArgument;
if (selectionDescription != NULL) {
OSString *selDesc;
selDesc = OSString::withCString(selectionDescription);
if (selDesc) {
result = addAvailableSelection(selectionValue, selDesc);
} else {
result = kIOReturnNoMemory;
}
}
return result;
}
IOReturn IOAudioSelectorControl::addAvailableSelection(SInt32 selectionValue, OSString *selectionDescription)
{
OSArray *newSelections;
OSArray *oldAvailableSelections;
IOReturn result = kIOReturnSuccess;
oldAvailableSelections = availableSelections;
newSelections = OSArray::withArray(availableSelections);
if (!newSelections)
return kIOReturnNoMemory;
if (selectionDescription == NULL) {
result = kIOReturnBadArgument;
} else {
if (valueExists(selectionValue)) {
result = kIOReturnError;
} else {
OSDictionary *newSelection;
newSelection = OSDictionary::withCapacity(2);
if (newSelection) {
OSNumber *number;
number = OSNumber::withNumber(selectionValue, sizeof(SInt32)*8);
if (number) {
newSelection->setObject(kIOAudioSelectorControlSelectionValueKey, number);
newSelection->setObject(kIOAudioSelectorControlSelectionDescriptionKey, selectionDescription);
newSelections->setObject(newSelection);
number->release();
} else {
result = kIOReturnError;
}
availableSelections = newSelections;
setProperty(kIOAudioSelectorControlAvailableSelectionsKey, availableSelections);
oldAvailableSelections->release();
newSelection->release();
} else {
result = kIOReturnError;
}
}
}
if (kIOReturnSuccess == result) {
sendChangeNotification(kIOAudioControlRangeChangeNotification);
}
return result;
}
bool IOAudioSelectorControl::valueExists(SInt32 selectionValue)
{
bool found = false;
OSCollectionIterator *iterator;
assert(availableSelections);
iterator = OSCollectionIterator::withCollection(availableSelections);
if (iterator) {
OSDictionary *selection;
while (selection = (OSDictionary *)iterator->getNextObject()) {
OSNumber *sValue;
sValue = (OSNumber *)selection->getObject(kIOAudioSelectorControlSelectionValueKey);
if (sValue && ((SInt32)sValue->unsigned32BitValue() == selectionValue)) {
found = true;
break;
}
}
iterator->release();
}
return found;
}
IOReturn IOAudioSelectorControl::validateValue(OSObject *newValue)
{
IOReturn result = kIOReturnBadArgument;
OSNumber *number;
number = OSDynamicCast(OSNumber, newValue);
if (number) {
result = super::validateValue(newValue);
if (result == kIOReturnSuccess) {
if (valueExists((SInt32)number->unsigned32BitValue())) {
result = kIOReturnSuccess;
} else {
result = kIOReturnNotFound;
}
}
}
return result;
}