4639N/A * or visit www.oracle.com if you need additional information or have any
4639N/A#include "PLATFORM_API_MacOSX_Utils.h"
4688N/A * If the device has several (more than 1) AudioStreams, there are 2 ways to represent Ports:
4688N/A * AudioHardware.h claims that AudioStream objects share AudioControl objects with their owning AudioDevice.
4688N/A * In practice 10.7 OSX drivers (built-in devices, USB audio) implement AudioControl only for AudioDevice.
4688N/A * For now 1st way is implemented (2nd way can be better if AudioStreams provide AudioControls).
4688N/A#define FourCC2Str(n) ((char[5]){(char)(n >> 24), (char)(n >> 16), (char)(n >> 8), (char)(n), 0})
4688N/A// used for PORT_GetPortCount/PORT_GetPortType/PORT_GetPortName functions
4688N/A {kAudioHardwarePropertyDevices, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster},
4688N/A {kAudioObjectPropertyOwnedObjects, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster},
4688N/A {kAudioDevicePropertyDeviceHasChanged, kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster}
4688N/A for (size_t i=0; i<sizeof(changeListenersAddresses)/sizeof(changeListenersAddresses[0]); i++) {
4688N/A AudioObjectAddPropertyListener(mixer->deviceID, &changeListenersAddresses[i], ChangeListenerProc, mixer);
4688N/A for (size_t i=0; i<sizeof(changeListenersAddresses)/sizeof(changeListenersAddresses[0]); i++) {
4688N/A AudioObjectRemovePropertyListener(mixer->deviceID, &changeListenersAddresses[i], ChangeListenerProc, mixer);
4639N/AINT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* mixerDescription) {
4639N/A mixerDescription->name, mixerDescription->vendor, mixerDescription->description, mixerDescription->version);
4688N/A err = GetAudioObjectPropertySize(mixer->deviceID, scope, kAudioDevicePropertyStreams, &size);
4688N/A OS_ERROR1(err, "PORT_GetPortType(kAudioStreamPropertyTerminalType), portIndex=%d", portIndex);
4688N/A // IOAudioTypes.h, not the defined kAudioStreamTerminalType*.
4639N/A switch (terminalType) {
4639N/A case INPUT_MICROPHONE:
4639N/A case OUTPUT_SPEAKER:
4639N/A case OUTPUT_HEADPHONES:
4688N/Astatic void* CreatePortControl(PortMixer *mixer, PortControlCreator *creator, PortControl::ControlType type,
4688N/A jControl = creator->newFloatControl(creator, control, CONTROL_TYPE_VOLUME, 0, 1, precision, "");
4688N/A jControl = creator->newFloatControl(creator, control, CONTROL_TYPE_BALANCE, -1, 1, precision, "");
4688N/A mixer->deviceControls = (AudioControl *)calloc(mixer->deviceControlCount, sizeof(AudioControl));
4688N/A control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel);
4688N/A int totalChannels = GetChannelCount(mixer->deviceID, port->scope == kAudioDevicePropertyScopeOutput ? 1 : 0);
4688N/A if (control->classID == 0 || control->scope != port->scope || control->channel > (unsigned)totalChannels) {
4688N/A control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel);
4688N/A control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel);
4688N/A control->controlID, FourCC2Str(control->classID), FourCC2Str(control->scope), control->channel);
4688N/A // volumeControls[n] and muteControls[n] (n=1..totalChannels) - corresponding channel controls
4688N/A masterVolume = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, 0, 1);
4688N/A masterVolume = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, 1, totalChannels);
4688N/A TRACE2(" PORT_GetControls (master volume): totalChannels = %d, valid volume controls = %d\n",
4688N/A masterMute = CreatePortControl(mixer, creator, PortControl::Mute, muteControls, 1, totalChannels);
4688N/A masterBalance = CreatePortControl(mixer, creator, PortControl::Balance, volumeControls, 1, totalChannels);
4688N/A TRACE2(" PORT_GetControls (naster balance): totalChannels = %d, valid volume controls = %d\n",
4688N/A if (ValidControlCount(volumeControls, 1, totalChannels) > 0 || ValidControlCount(muteControls, 1, totalChannels) > 0) {
4688N/A const AudioObjectPropertyAddress address = {kAudioObjectPropertyElementName, port->scope, ch};
4688N/A OSStatus err = AudioObjectGetPropertyData(mixer->deviceID, &address, 0, NULL, &size, &cfname);
4688N/A jControls[controlCount++] = CreatePortControl(mixer, creator, PortControl::Volume, volumeControls, ch, 1);
4688N/A jControls[controlCount++] = CreatePortControl(mixer, creator, PortControl::Mute, muteControls, ch, 1);
4688N/A void *compoundControl = creator->newCompoundControl(creator, channelName, jControls, controlCount);
4688N/A return DEFAULT_MUTE_VALUE;
4688N/A result = 1; // default is "muted", if some channel in unmuted, then "virtual mute" is also unmuted
4688N/A kAudioObjectPropertyScopeGlobal, kAudioBooleanControlPropertyValue, sizeof(value), &value, 1);
4688N/A return DEFAULT_MUTE_VALUE;
4688N/A ERROR1("PORT_GetIntValue requested for non-Int control (control-type == %d)\n", control->type);
4688N/A ERROR1("PORT_SetIntValue requested for non-Int control (control-type == %d)\n", control->type);
4688N/Astatic bool GetPortControlVolumes(PortControl *control, Float32 *volumes, Float32 *maxVolume) {
4688N/A return DEFAULT_VOLUME_VALUE;
4688N/A return DEFAULT_VOLUME_VALUE;
4688N/A return DEFAULT_BALANCE_VALUE;
4688N/A return DEFAULT_VOLUME_VALUE;
4688N/A ERROR1("GetFloatValue requested for non-Float control (control-type == %d)\n", control->type);