| /* |
| * Copyright (c) 2002, 2007, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code 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 |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| #define USE_ERROR |
| //#define USE_TRACE |
| |
| #include "Ports.h" |
| #include "PLATFORM_API_SolarisOS_Utils.h" |
| |
| #if USE_PORTS == TRUE |
| |
| #define MONITOR_GAIN_STRING "Monitor Gain" |
| |
| #define ALL_TARGET_PORT_COUNT 6 |
| |
| // define the following to not use audio_prinfo_t.mod_ports |
| #define SOLARIS7_COMPATIBLE |
| |
| // Solaris audio defines |
| static int targetPorts[ALL_TARGET_PORT_COUNT] = { |
| AUDIO_SPEAKER, |
| AUDIO_HEADPHONE, |
| AUDIO_LINE_OUT, |
| AUDIO_AUX1_OUT, |
| AUDIO_AUX2_OUT, |
| AUDIO_SPDIF_OUT |
| }; |
| |
| static char* targetPortNames[ALL_TARGET_PORT_COUNT] = { |
| "Speaker", |
| "Headphone", |
| "Line Out", |
| "AUX1 Out", |
| "AUX2 Out", |
| "SPDIF Out" |
| }; |
| |
| // defined in Ports.h |
| static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = { |
| PORT_DST_SPEAKER, |
| PORT_DST_HEADPHONE, |
| PORT_DST_LINE_OUT, |
| PORT_DST_UNKNOWN, |
| PORT_DST_UNKNOWN, |
| PORT_DST_UNKNOWN, |
| }; |
| |
| #define ALL_SOURCE_PORT_COUNT 7 |
| |
| // Solaris audio defines |
| static int sourcePorts[ALL_SOURCE_PORT_COUNT] = { |
| AUDIO_MICROPHONE, |
| AUDIO_LINE_IN, |
| AUDIO_CD, |
| AUDIO_AUX1_IN, |
| AUDIO_AUX2_IN, |
| AUDIO_SPDIF_IN, |
| AUDIO_CODEC_LOOPB_IN |
| }; |
| |
| static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = { |
| "Microphone In", |
| "Line In", |
| "Compact Disc In", |
| "AUX1 In", |
| "AUX2 In", |
| "SPDIF In", |
| "Internal Loopback" |
| }; |
| |
| // Ports.h defines |
| static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = { |
| PORT_SRC_MICROPHONE, |
| PORT_SRC_LINE_IN, |
| PORT_SRC_COMPACT_DISC, |
| PORT_SRC_UNKNOWN, |
| PORT_SRC_UNKNOWN, |
| PORT_SRC_UNKNOWN, |
| PORT_SRC_UNKNOWN |
| }; |
| |
| struct tag_PortControlID; |
| |
| typedef struct tag_PortInfo { |
| int fd; // file descriptor of the pseudo device |
| audio_info_t audioInfo; |
| // ports |
| int targetPortCount; |
| int sourcePortCount; |
| // indexes to sourcePorts/targetPorts |
| // contains first target ports, then source ports |
| int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT]; |
| // controls |
| int maxControlCount; // upper bound of number of controls |
| int usedControlIDs; // number of items already filled in controlIDs |
| struct tag_PortControlID* controlIDs; // the control IDs themselves |
| } PortInfo; |
| |
| #define PORT_CONTROL_TYPE_PLAY 0x4000000 |
| #define PORT_CONTROL_TYPE_RECORD 0x8000000 |
| #define PORT_CONTROL_TYPE_SELECT_PORT 1 |
| #define PORT_CONTROL_TYPE_GAIN 2 |
| #define PORT_CONTROL_TYPE_BALANCE 3 |
| #define PORT_CONTROL_TYPE_MONITOR_GAIN 10 |
| #define PORT_CONTROL_TYPE_OUTPUT_MUTED 11 |
| #define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD |
| #define PORT_CONTROL_TYPE_MASK 0xFFFFFF |
| |
| |
| typedef struct tag_PortControlID { |
| PortInfo* portInfo; |
| INT32 controlType; // PORT_CONTROL_TYPE_XX |
| uint_t port; |
| } PortControlID; |
| |
| |
| ///// implemented functions of Ports.h |
| |
| INT32 PORT_GetPortMixerCount() { |
| return (INT32) getAudioDeviceCount(); |
| } |
| |
| |
| INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) { |
| AudioDeviceDescription desc; |
| |
| if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) { |
| strncpy(description->name, desc.name, PORT_STRING_LENGTH-1); |
| description->name[PORT_STRING_LENGTH-1] = 0; |
| strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1); |
| description->vendor[PORT_STRING_LENGTH-1] = 0; |
| strncpy(description->version, desc.version, PORT_STRING_LENGTH-1); |
| description->version[PORT_STRING_LENGTH-1] = 0; |
| /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/ |
| strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1); |
| description->description[PORT_STRING_LENGTH-1] = 0; |
| return TRUE; |
| } |
| return FALSE; |
| } |
| |
| |
| void* PORT_Open(INT32 mixerIndex) { |
| PortInfo* info = NULL; |
| int fd = -1; |
| AudioDeviceDescription desc; |
| int success = FALSE; |
| |
| TRACE0("PORT_Open\n"); |
| if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { |
| fd = open(desc.pathctl, O_RDWR); |
| } |
| if (fd < 0) { |
| ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex); |
| return NULL; |
| } |
| |
| info = (PortInfo*) malloc(sizeof(PortInfo)); |
| if (info != NULL) { |
| memset(info, 0, sizeof(PortInfo)); |
| info->fd = fd; |
| success = TRUE; |
| } |
| if (!success) { |
| if (fd >= 0) { |
| close(fd); |
| } |
| PORT_Close((void*) info); |
| info = NULL; |
| } |
| return info; |
| } |
| |
| void PORT_Close(void* id) { |
| TRACE0("PORT_Close\n"); |
| if (id != NULL) { |
| PortInfo* info = (PortInfo*) id; |
| if (info->fd >= 0) { |
| close(info->fd); |
| info->fd = -1; |
| } |
| if (info->controlIDs) { |
| free(info->controlIDs); |
| info->controlIDs = NULL; |
| } |
| free(info); |
| } |
| } |
| |
| |
| |
| INT32 PORT_GetPortCount(void* id) { |
| int ret = 0; |
| PortInfo* info = (PortInfo*) id; |
| if (info != NULL) { |
| if (!info->targetPortCount && !info->sourcePortCount) { |
| int i; |
| AUDIO_INITINFO(&info->audioInfo); |
| if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) { |
| for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) { |
| if (info->audioInfo.play.avail_ports & targetPorts[i]) { |
| info->ports[info->targetPortCount] = i; |
| info->targetPortCount++; |
| } |
| #ifdef SOLARIS7_COMPATIBLE |
| TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i], |
| info->audioInfo.play.avail_ports & targetPorts[i]); |
| #else |
| TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i], |
| info->audioInfo.play.avail_ports & targetPorts[i], |
| info->audioInfo.play.mod_ports & targetPorts[i]); |
| #endif |
| } |
| for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) { |
| if (info->audioInfo.record.avail_ports & sourcePorts[i]) { |
| info->ports[info->targetPortCount + info->sourcePortCount] = i; |
| info->sourcePortCount++; |
| } |
| #ifdef SOLARIS7_COMPATIBLE |
| TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i], |
| info->audioInfo.record.avail_ports & sourcePorts[i]); |
| #else |
| TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i], |
| info->audioInfo.record.avail_ports & sourcePorts[i], |
| info->audioInfo.record.mod_ports & sourcePorts[i]); |
| #endif |
| } |
| } |
| } |
| ret = info->targetPortCount + info->sourcePortCount; |
| } |
| return ret; |
| } |
| |
| int isSourcePort(PortInfo* info, INT32 portIndex) { |
| return (portIndex >= info->targetPortCount); |
| } |
| |
| INT32 PORT_GetPortType(void* id, INT32 portIndex) { |
| PortInfo* info = (PortInfo*) id; |
| if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) { |
| if (isSourcePort(info, portIndex)) { |
| return sourcePortJavaSoundMapping[info->ports[portIndex]]; |
| } else { |
| return targetPortJavaSoundMapping[info->ports[portIndex]]; |
| } |
| } |
| return 0; |
| } |
| |
| // pre-condition: portIndex must have been verified! |
| char* getPortName(PortInfo* info, INT32 portIndex) { |
| char* ret = NULL; |
| |
| if (isSourcePort(info, portIndex)) { |
| ret = sourcePortNames[info->ports[portIndex]]; |
| } else { |
| ret = targetPortNames[info->ports[portIndex]]; |
| } |
| return ret; |
| } |
| |
| INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) { |
| PortInfo* info = (PortInfo*) id; |
| char* n; |
| |
| if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) { |
| n = getPortName(info, portIndex); |
| if (n) { |
| strncpy(name, n, len-1); |
| name[len-1] = 0; |
| return TRUE; |
| } |
| } |
| return FALSE; |
| } |
| |
| void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex, |
| INT32 type, void** controlObjects, int* controlCount) { |
| PortControlID* controlID; |
| void* newControl = NULL; |
| int controlIndex; |
| char* jsType = NULL; |
| int isBoolean = FALSE; |
| |
| TRACE0(">createPortControl\n"); |
| |
| // fill the ControlID structure and add this control |
| if (info->usedControlIDs >= info->maxControlCount) { |
| ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount); |
| return; |
| } |
| controlID = &(info->controlIDs[info->usedControlIDs]); |
| controlID->portInfo = info; |
| controlID->controlType = type; |
| controlIndex = info->ports[portIndex]; |
| if (isSourcePort(info, portIndex)) { |
| controlID->port = sourcePorts[controlIndex]; |
| } else { |
| controlID->port = targetPorts[controlIndex]; |
| } |
| switch (type & PORT_CONTROL_TYPE_MASK) { |
| case PORT_CONTROL_TYPE_SELECT_PORT: |
| jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break; |
| case PORT_CONTROL_TYPE_GAIN: |
| jsType = CONTROL_TYPE_VOLUME; break; |
| case PORT_CONTROL_TYPE_BALANCE: |
| jsType = CONTROL_TYPE_BALANCE; break; |
| case PORT_CONTROL_TYPE_MONITOR_GAIN: |
| jsType = CONTROL_TYPE_VOLUME; break; |
| case PORT_CONTROL_TYPE_OUTPUT_MUTED: |
| jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break; |
| } |
| if (isBoolean) { |
| TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n"); |
| newControl = (creator->newBooleanControl)(creator, controlID, jsType); |
| } |
| else if (jsType == CONTROL_TYPE_BALANCE) { |
| TRACE0(" PORT_CONTROL_TYPE_BALANCE\n"); |
| newControl = (creator->newFloatControl)(creator, controlID, jsType, |
| -1.0f, 1.0f, 2.0f / 65.0f, ""); |
| } else { |
| TRACE0(" PORT_CONTROL_TYPE_FLOAT\n"); |
| newControl = (creator->newFloatControl)(creator, controlID, jsType, |
| 0.0f, 1.0f, 1.0f / 256.0f, ""); |
| } |
| if (newControl) { |
| controlObjects[*controlCount] = newControl; |
| (*controlCount)++; |
| info->usedControlIDs++; |
| } |
| TRACE0("<createPortControl\n"); |
| } |
| |
| |
| void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) { |
| void* compControl; |
| |
| TRACE1(">addCompoundControl %d controls\n", *controlCount); |
| if (*controlCount) { |
| // create compound control and add it to the vector |
| compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount); |
| if (compControl) { |
| TRACE1(" addCompoundControl: calling addControl %p\n", compControl); |
| (creator->addControl)(creator, compControl); |
| } |
| *controlCount = 0; |
| } |
| TRACE0("<addCompoundControl\n"); |
| } |
| |
| void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) { |
| int i = 0; |
| |
| TRACE0(">addAllControl\n"); |
| // go through all controls and add them to the vector |
| for (i = 0; i < *controlCount; i++) { |
| (creator->addControl)(creator, controlObjects[i]); |
| } |
| *controlCount = 0; |
| TRACE0("<addAllControl\n"); |
| } |
| |
| void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { |
| PortInfo* info = (PortInfo*) id; |
| int portCount = PORT_GetPortCount(id); |
| void* controls[4]; |
| int controlCount = 0; |
| INT32 type; |
| int selectable = 1; |
| |
| TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n", |
| id, portIndex, info->controlIDs, info->maxControlCount); |
| if ((portIndex >= 0) && (portIndex < portCount)) { |
| // if the memory isn't reserved for the control structures, allocate it |
| if (!info->controlIDs) { |
| int maxCount = 0; |
| TRACE0("getControl: allocate mem\n"); |
| // get a maximum number of controls: |
| // each port has a select, balance, and volume control. |
| maxCount = 3 * portCount; |
| // then there is monitorGain and outputMuted |
| maxCount += (2 * info->targetPortCount); |
| info->maxControlCount = maxCount; |
| info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount); |
| } |
| if (!isSourcePort(info, portIndex)) { |
| type = PORT_CONTROL_TYPE_PLAY; |
| // add master mute control |
| createPortControl(info, creator, portIndex, |
| type | PORT_CONTROL_TYPE_OUTPUT_MUTED, |
| controls, &controlCount); |
| addAllControls(info, creator, controls, &controlCount); |
| #ifdef SOLARIS7_COMPATIBLE |
| selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]]; |
| #else |
| selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]]; |
| #endif |
| } else { |
| type = PORT_CONTROL_TYPE_RECORD; |
| #ifdef SOLARIS7_COMPATIBLE |
| selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]]; |
| #else |
| selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]]; |
| #endif |
| } |
| // add a mixer strip with volume, ... |
| createPortControl(info, creator, portIndex, |
| type | PORT_CONTROL_TYPE_GAIN, |
| controls, &controlCount); |
| // ... balance, ... |
| createPortControl(info, creator, portIndex, |
| type | PORT_CONTROL_TYPE_BALANCE, |
| controls, &controlCount); |
| // ... and select control (if not always on)... |
| if (selectable) { |
| createPortControl(info, creator, portIndex, |
| type | PORT_CONTROL_TYPE_SELECT_PORT, |
| controls, &controlCount); |
| } |
| // ... packaged in a compound control. |
| addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount); |
| |
| if (type == PORT_CONTROL_TYPE_PLAY) { |
| // add a single strip for source ports with monitor gain |
| createPortControl(info, creator, portIndex, |
| type | PORT_CONTROL_TYPE_MONITOR_GAIN, |
| controls, &controlCount); |
| // also in a compound control |
| addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount); |
| } |
| } |
| TRACE0("< PORT_getControls\n"); |
| } |
| |
| INT32 PORT_GetIntValue(void* controlIDV) { |
| PortControlID* controlID = (PortControlID*) controlIDV; |
| audio_info_t audioInfo; |
| audio_prinfo_t* prinfo; |
| |
| AUDIO_INITINFO(&audioInfo); |
| if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { |
| if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { |
| prinfo = &(audioInfo.play); |
| } else { |
| prinfo = &(audioInfo.record); |
| } |
| switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { |
| case PORT_CONTROL_TYPE_SELECT_PORT: |
| return (prinfo->port & controlID->port)?TRUE:FALSE; |
| case PORT_CONTROL_TYPE_OUTPUT_MUTED: |
| return (audioInfo.output_muted)?TRUE:FALSE; |
| default: |
| ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); |
| } |
| } |
| ERROR0("PORT_GetIntValue: Could not ioctl!\n"); |
| return 0; |
| } |
| |
| void PORT_SetIntValue(void* controlIDV, INT32 value) { |
| PortControlID* controlID = (PortControlID*) controlIDV; |
| audio_info_t audioInfo; |
| audio_prinfo_t* prinfo; |
| int setPort; |
| |
| if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { |
| prinfo = &(audioInfo.play); |
| } else { |
| prinfo = &(audioInfo.record); |
| } |
| switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { |
| case PORT_CONTROL_TYPE_SELECT_PORT: |
| // first try to just add this port. if that fails, set ONLY to this port. |
| AUDIO_INITINFO(&audioInfo); |
| if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { |
| if (value) { |
| setPort = (prinfo->port | controlID->port); |
| } else { |
| setPort = (prinfo->port - controlID->port); |
| } |
| AUDIO_INITINFO(&audioInfo); |
| prinfo->port = setPort; |
| if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { |
| // didn't work. Either this line doesn't support to select several |
| // ports at once (e.g. record), or a real error |
| if (value) { |
| // set to ONLY this port (and disable any other currently selected ports) |
| AUDIO_INITINFO(&audioInfo); |
| prinfo->port = controlID->port; |
| if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { |
| ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port); |
| } |
| } else { |
| // assume it's an error |
| ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort); |
| } |
| } |
| break; |
| case PORT_CONTROL_TYPE_OUTPUT_MUTED: |
| AUDIO_INITINFO(&audioInfo); |
| audioInfo.output_muted = (value?TRUE:FALSE); |
| if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { |
| ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value); |
| } |
| break; |
| default: |
| ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); |
| } |
| } |
| } |
| |
| float PORT_GetFloatValue(void* controlIDV) { |
| PortControlID* controlID = (PortControlID*) controlIDV; |
| audio_info_t audioInfo; |
| audio_prinfo_t* prinfo; |
| |
| AUDIO_INITINFO(&audioInfo); |
| if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { |
| if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { |
| prinfo = &(audioInfo.play); |
| } else { |
| prinfo = &(audioInfo.record); |
| } |
| switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { |
| case PORT_CONTROL_TYPE_GAIN: |
| return ((float) (prinfo->gain - AUDIO_MIN_GAIN)) |
| / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); |
| case PORT_CONTROL_TYPE_BALANCE: |
| return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1)) |
| / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE)); |
| case PORT_CONTROL_TYPE_MONITOR_GAIN: |
| return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN)) |
| / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); |
| default: |
| ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); |
| } |
| } |
| ERROR0("PORT_GetFloatValue: Could not ioctl!\n"); |
| return 0.0f; |
| } |
| |
| void PORT_SetFloatValue(void* controlIDV, float value) { |
| PortControlID* controlID = (PortControlID*) controlIDV; |
| audio_info_t audioInfo; |
| audio_prinfo_t* prinfo; |
| |
| AUDIO_INITINFO(&audioInfo); |
| |
| if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { |
| prinfo = &(audioInfo.play); |
| } else { |
| prinfo = &(audioInfo.record); |
| } |
| switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { |
| case PORT_CONTROL_TYPE_GAIN: |
| prinfo->gain = AUDIO_MIN_GAIN |
| + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); |
| break; |
| case PORT_CONTROL_TYPE_BALANCE: |
| prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE |
| + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f); |
| break; |
| case PORT_CONTROL_TYPE_MONITOR_GAIN: |
| audioInfo.monitor_gain = AUDIO_MIN_GAIN |
| + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); |
| break; |
| default: |
| ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); |
| return; |
| } |
| if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { |
| ERROR0("PORT_SetFloatValue: Could not ioctl!\n"); |
| } |
| } |
| |
| #endif // USE_PORTS |