1 /* 2 * Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 #define USE_ERROR 27 //#define USE_TRACE 28 29 #include "Ports.h" 30 #include "PLATFORM_API_SolarisOS_Utils.h" 31 32 #if USE_PORTS == TRUE 33 34 #define MONITOR_GAIN_STRING "Monitor Gain" 35 36 #define ALL_TARGET_PORT_COUNT 6 37 38 // define the following to not use audio_prinfo_t.mod_ports 39 #define SOLARIS7_COMPATIBLE 40 41 // Solaris audio defines 42 static int targetPorts[ALL_TARGET_PORT_COUNT] = { 43 AUDIO_SPEAKER, 44 AUDIO_HEADPHONE, 45 AUDIO_LINE_OUT, 46 AUDIO_AUX1_OUT, 47 AUDIO_AUX2_OUT, 48 AUDIO_SPDIF_OUT 49 }; 50 51 static char* targetPortNames[ALL_TARGET_PORT_COUNT] = { 52 "Speaker", 53 "Headphone", 54 "Line Out", 55 "AUX1 Out", 56 "AUX2 Out", 57 "SPDIF Out" 58 }; 59 60 // defined in Ports.h 61 static int targetPortJavaSoundMapping[ALL_TARGET_PORT_COUNT] = { 62 PORT_DST_SPEAKER, 63 PORT_DST_HEADPHONE, 64 PORT_DST_LINE_OUT, 65 PORT_DST_UNKNOWN, 66 PORT_DST_UNKNOWN, 67 PORT_DST_UNKNOWN, 68 }; 69 70 #define ALL_SOURCE_PORT_COUNT 7 71 72 // Solaris audio defines 73 static int sourcePorts[ALL_SOURCE_PORT_COUNT] = { 74 AUDIO_MICROPHONE, 75 AUDIO_LINE_IN, 76 AUDIO_CD, 77 AUDIO_AUX1_IN, 78 AUDIO_AUX2_IN, 79 AUDIO_SPDIF_IN, 80 AUDIO_CODEC_LOOPB_IN 81 }; 82 83 static char* sourcePortNames[ALL_SOURCE_PORT_COUNT] = { 84 "Microphone In", 85 "Line In", 86 "Compact Disc In", 87 "AUX1 In", 88 "AUX2 In", 89 "SPDIF In", 90 "Internal Loopback" 91 }; 92 93 // Ports.h defines 94 static int sourcePortJavaSoundMapping[ALL_SOURCE_PORT_COUNT] = { 95 PORT_SRC_MICROPHONE, 96 PORT_SRC_LINE_IN, 97 PORT_SRC_COMPACT_DISC, 98 PORT_SRC_UNKNOWN, 99 PORT_SRC_UNKNOWN, 100 PORT_SRC_UNKNOWN, 101 PORT_SRC_UNKNOWN 102 }; 103 104 struct tag_PortControlID; 105 106 typedef struct tag_PortInfo { 107 int fd; // file descriptor of the pseudo device 108 audio_info_t audioInfo; 109 // ports 110 int targetPortCount; 111 int sourcePortCount; 112 // indexes to sourcePorts/targetPorts 113 // contains first target ports, then source ports 114 int ports[ALL_TARGET_PORT_COUNT + ALL_SOURCE_PORT_COUNT]; 115 // controls 116 int maxControlCount; // upper bound of number of controls 117 int usedControlIDs; // number of items already filled in controlIDs 118 struct tag_PortControlID* controlIDs; // the control IDs themselves 119 } PortInfo; 120 121 #define PORT_CONTROL_TYPE_PLAY 0x4000000 122 #define PORT_CONTROL_TYPE_RECORD 0x8000000 123 #define PORT_CONTROL_TYPE_SELECT_PORT 1 124 #define PORT_CONTROL_TYPE_GAIN 2 125 #define PORT_CONTROL_TYPE_BALANCE 3 126 #define PORT_CONTROL_TYPE_MONITOR_GAIN 10 127 #define PORT_CONTROL_TYPE_OUTPUT_MUTED 11 128 #define PORT_CONTROL_TYPE_PLAYRECORD_MASK PORT_CONTROL_TYPE_PLAY | PORT_CONTROL_TYPE_RECORD 129 #define PORT_CONTROL_TYPE_MASK 0xFFFFFF 130 131 132 typedef struct tag_PortControlID { 133 PortInfo* portInfo; 134 INT32 controlType; // PORT_CONTROL_TYPE_XX 135 uint_t port; 136 } PortControlID; 137 138 139 ///// implemented functions of Ports.h 140 141 INT32 PORT_GetPortMixerCount() { 142 return (INT32) getAudioDeviceCount(); 143 } 144 145 146 INT32 PORT_GetPortMixerDescription(INT32 mixerIndex, PortMixerDescription* description) { 147 AudioDeviceDescription desc; 148 149 if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, TRUE)) { 150 strncpy(description->name, desc.name, PORT_STRING_LENGTH-1); 151 description->name[PORT_STRING_LENGTH-1] = 0; 152 strncpy(description->vendor, desc.vendor, PORT_STRING_LENGTH-1); 153 description->vendor[PORT_STRING_LENGTH-1] = 0; 154 strncpy(description->version, desc.version, PORT_STRING_LENGTH-1); 155 description->version[PORT_STRING_LENGTH-1] = 0; 156 /*strncpy(description->description, desc.description, PORT_STRING_LENGTH-1);*/ 157 strncpy(description->description, "Solaris Ports", PORT_STRING_LENGTH-1); 158 description->description[PORT_STRING_LENGTH-1] = 0; 159 return TRUE; 160 } 161 return FALSE; 162 } 163 164 165 void* PORT_Open(INT32 mixerIndex) { 166 PortInfo* info = NULL; 167 int fd = -1; 168 AudioDeviceDescription desc; 169 int success = FALSE; 170 171 TRACE0("PORT_Open\n"); 172 if (getAudioDeviceDescriptionByIndex(mixerIndex, &desc, FALSE)) { 173 fd = open(desc.pathctl, O_RDWR); 174 } 175 if (fd < 0) { 176 ERROR1("Couldn't open audio device ctl for device %d!\n", mixerIndex); 177 return NULL; 178 } 179 180 info = (PortInfo*) malloc(sizeof(PortInfo)); 181 if (info != NULL) { 182 memset(info, 0, sizeof(PortInfo)); 183 info->fd = fd; 184 success = TRUE; 185 } 186 if (!success) { 187 if (fd >= 0) { 188 close(fd); 189 } 190 PORT_Close((void*) info); 191 info = NULL; 192 } 193 return info; 194 } 195 196 void PORT_Close(void* id) { 197 TRACE0("PORT_Close\n"); 198 if (id != NULL) { 199 PortInfo* info = (PortInfo*) id; 200 if (info->fd >= 0) { 201 close(info->fd); 202 info->fd = -1; 203 } 204 if (info->controlIDs) { 205 free(info->controlIDs); 206 info->controlIDs = NULL; 207 } 208 free(info); 209 } 210 } 211 212 213 214 INT32 PORT_GetPortCount(void* id) { 215 int ret = 0; 216 PortInfo* info = (PortInfo*) id; 217 if (info != NULL) { 218 if (!info->targetPortCount && !info->sourcePortCount) { 219 int i; 220 AUDIO_INITINFO(&info->audioInfo); 221 if (ioctl(info->fd, AUDIO_GETINFO, &info->audioInfo) >= 0) { 222 for (i = 0; i < ALL_TARGET_PORT_COUNT; i++) { 223 if (info->audioInfo.play.avail_ports & targetPorts[i]) { 224 info->ports[info->targetPortCount] = i; 225 info->targetPortCount++; 226 } 227 #ifdef SOLARIS7_COMPATIBLE 228 TRACE3("Target %d %s: avail=%d\n", i, targetPortNames[i], 229 info->audioInfo.play.avail_ports & targetPorts[i]); 230 #else 231 TRACE4("Target %d %s: avail=%d mod=%d\n", i, targetPortNames[i], 232 info->audioInfo.play.avail_ports & targetPorts[i], 233 info->audioInfo.play.mod_ports & targetPorts[i]); 234 #endif 235 } 236 for (i = 0; i < ALL_SOURCE_PORT_COUNT; i++) { 237 if (info->audioInfo.record.avail_ports & sourcePorts[i]) { 238 info->ports[info->targetPortCount + info->sourcePortCount] = i; 239 info->sourcePortCount++; 240 } 241 #ifdef SOLARIS7_COMPATIBLE 242 TRACE3("Source %d %s: avail=%d\n", i, sourcePortNames[i], 243 info->audioInfo.record.avail_ports & sourcePorts[i]); 244 #else 245 TRACE4("Source %d %s: avail=%d mod=%d\n", i, sourcePortNames[i], 246 info->audioInfo.record.avail_ports & sourcePorts[i], 247 info->audioInfo.record.mod_ports & sourcePorts[i]); 248 #endif 249 } 250 } 251 } 252 ret = info->targetPortCount + info->sourcePortCount; 253 } 254 return ret; 255 } 256 257 int isSourcePort(PortInfo* info, INT32 portIndex) { 258 return (portIndex >= info->targetPortCount); 259 } 260 261 INT32 PORT_GetPortType(void* id, INT32 portIndex) { 262 PortInfo* info = (PortInfo*) id; 263 if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) { 264 if (isSourcePort(info, portIndex)) { 265 return sourcePortJavaSoundMapping[info->ports[portIndex]]; 266 } else { 267 return targetPortJavaSoundMapping[info->ports[portIndex]]; 268 } 269 } 270 return 0; 271 } 272 273 // pre-condition: portIndex must have been verified! 274 char* getPortName(PortInfo* info, INT32 portIndex) { 275 char* ret = NULL; 276 277 if (isSourcePort(info, portIndex)) { 278 ret = sourcePortNames[info->ports[portIndex]]; 279 } else { 280 ret = targetPortNames[info->ports[portIndex]]; 281 } 282 return ret; 283 } 284 285 INT32 PORT_GetPortName(void* id, INT32 portIndex, char* name, INT32 len) { 286 PortInfo* info = (PortInfo*) id; 287 char* n; 288 289 if ((portIndex >= 0) && (portIndex < PORT_GetPortCount(id))) { 290 n = getPortName(info, portIndex); 291 if (n) { 292 strncpy(name, n, len-1); 293 name[len-1] = 0; 294 return TRUE; 295 } 296 } 297 return FALSE; 298 } 299 300 void createPortControl(PortInfo* info, PortControlCreator* creator, INT32 portIndex, 301 INT32 type, void** controlObjects, int* controlCount) { 302 PortControlID* controlID; 303 void* newControl = NULL; 304 int controlIndex; 305 char* jsType = NULL; 306 int isBoolean = FALSE; 307 308 TRACE0(">createPortControl\n"); 309 310 // fill the ControlID structure and add this control 311 if (info->usedControlIDs >= info->maxControlCount) { 312 ERROR1("not enough free controlIDs !! maxControlIDs = %d\n", info->maxControlCount); 313 return; 314 } 315 controlID = &(info->controlIDs[info->usedControlIDs]); 316 controlID->portInfo = info; 317 controlID->controlType = type; 318 controlIndex = info->ports[portIndex]; 319 if (isSourcePort(info, portIndex)) { 320 controlID->port = sourcePorts[controlIndex]; 321 } else { 322 controlID->port = targetPorts[controlIndex]; 323 } 324 switch (type & PORT_CONTROL_TYPE_MASK) { 325 case PORT_CONTROL_TYPE_SELECT_PORT: 326 jsType = CONTROL_TYPE_SELECT; isBoolean = TRUE; break; 327 case PORT_CONTROL_TYPE_GAIN: 328 jsType = CONTROL_TYPE_VOLUME; break; 329 case PORT_CONTROL_TYPE_BALANCE: 330 jsType = CONTROL_TYPE_BALANCE; break; 331 case PORT_CONTROL_TYPE_MONITOR_GAIN: 332 jsType = CONTROL_TYPE_VOLUME; break; 333 case PORT_CONTROL_TYPE_OUTPUT_MUTED: 334 jsType = CONTROL_TYPE_MUTE; isBoolean = TRUE; break; 335 } 336 if (isBoolean) { 337 TRACE0(" PORT_CONTROL_TYPE_BOOLEAN\n"); 338 newControl = (creator->newBooleanControl)(creator, controlID, jsType); 339 } 340 else if (jsType == CONTROL_TYPE_BALANCE) { 341 TRACE0(" PORT_CONTROL_TYPE_BALANCE\n"); 342 newControl = (creator->newFloatControl)(creator, controlID, jsType, 343 -1.0f, 1.0f, 2.0f / 65.0f, ""); 344 } else { 345 TRACE0(" PORT_CONTROL_TYPE_FLOAT\n"); 346 newControl = (creator->newFloatControl)(creator, controlID, jsType, 347 0.0f, 1.0f, 1.0f / 256.0f, ""); 348 } 349 if (newControl) { 350 controlObjects[*controlCount] = newControl; 351 (*controlCount)++; 352 info->usedControlIDs++; 353 } 354 TRACE0("<createPortControl\n"); 355 } 356 357 358 void addCompoundControl(PortInfo* info, PortControlCreator* creator, char* name, void** controlObjects, int* controlCount) { 359 void* compControl; 360 361 TRACE1(">addCompoundControl %d controls\n", *controlCount); 362 if (*controlCount) { 363 // create compound control and add it to the vector 364 compControl = (creator->newCompoundControl)(creator, name, controlObjects, *controlCount); 365 if (compControl) { 366 TRACE1(" addCompoundControl: calling addControl %p\n", compControl); 367 (creator->addControl)(creator, compControl); 368 } 369 *controlCount = 0; 370 } 371 TRACE0("<addCompoundControl\n"); 372 } 373 374 void addAllControls(PortInfo* info, PortControlCreator* creator, void** controlObjects, int* controlCount) { 375 int i = 0; 376 377 TRACE0(">addAllControl\n"); 378 // go through all controls and add them to the vector 379 for (i = 0; i < *controlCount; i++) { 380 (creator->addControl)(creator, controlObjects[i]); 381 } 382 *controlCount = 0; 383 TRACE0("<addAllControl\n"); 384 } 385 386 void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { 387 PortInfo* info = (PortInfo*) id; 388 int portCount = PORT_GetPortCount(id); 389 void* controls[4]; 390 int controlCount = 0; 391 INT32 type; 392 int selectable = 1; 393 memset(controls, 0, sizeof(controls)); 394 395 TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n", 396 id, portIndex, info->controlIDs, info->maxControlCount); 397 if ((portIndex >= 0) && (portIndex < portCount)) { 398 // if the memory isn't reserved for the control structures, allocate it 399 if (!info->controlIDs) { 400 int maxCount = 0; 401 TRACE0("getControl: allocate mem\n"); 402 // get a maximum number of controls: 403 // each port has a select, balance, and volume control. 404 maxCount = 3 * portCount; 405 // then there is monitorGain and outputMuted 406 maxCount += (2 * info->targetPortCount); 407 info->maxControlCount = maxCount; 408 info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount); 409 } 410 if (!isSourcePort(info, portIndex)) { 411 type = PORT_CONTROL_TYPE_PLAY; 412 // add master mute control 413 createPortControl(info, creator, portIndex, 414 type | PORT_CONTROL_TYPE_OUTPUT_MUTED, 415 controls, &controlCount); 416 addAllControls(info, creator, controls, &controlCount); 417 #ifdef SOLARIS7_COMPATIBLE 418 selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]]; 419 #else 420 selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]]; 421 #endif 422 } else { 423 type = PORT_CONTROL_TYPE_RECORD; 424 #ifdef SOLARIS7_COMPATIBLE 425 selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]]; 426 #else 427 selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]]; 428 #endif 429 } 430 // add a mixer strip with volume, ... 431 createPortControl(info, creator, portIndex, 432 type | PORT_CONTROL_TYPE_GAIN, 433 controls, &controlCount); 434 // ... balance, ... 435 createPortControl(info, creator, portIndex, 436 type | PORT_CONTROL_TYPE_BALANCE, 437 controls, &controlCount); 438 // ... and select control (if not always on)... 439 if (selectable) { 440 createPortControl(info, creator, portIndex, 441 type | PORT_CONTROL_TYPE_SELECT_PORT, 442 controls, &controlCount); 443 } 444 // ... packaged in a compound control. 445 addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount); 446 447 if (type == PORT_CONTROL_TYPE_PLAY) { 448 // add a single strip for source ports with monitor gain 449 createPortControl(info, creator, portIndex, 450 type | PORT_CONTROL_TYPE_MONITOR_GAIN, 451 controls, &controlCount); 452 // also in a compound control 453 addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount); 454 } 455 } 456 TRACE0("< PORT_getControls\n"); 457 } 458 459 INT32 PORT_GetIntValue(void* controlIDV) { 460 PortControlID* controlID = (PortControlID*) controlIDV; 461 audio_info_t audioInfo; 462 audio_prinfo_t* prinfo; 463 464 AUDIO_INITINFO(&audioInfo); 465 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 466 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 467 prinfo = &(audioInfo.play); 468 } else { 469 prinfo = &(audioInfo.record); 470 } 471 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 472 case PORT_CONTROL_TYPE_SELECT_PORT: 473 return (prinfo->port & controlID->port)?TRUE:FALSE; 474 case PORT_CONTROL_TYPE_OUTPUT_MUTED: 475 return (audioInfo.output_muted)?TRUE:FALSE; 476 default: 477 ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 478 } 479 } 480 ERROR0("PORT_GetIntValue: Could not ioctl!\n"); 481 return 0; 482 } 483 484 void PORT_SetIntValue(void* controlIDV, INT32 value) { 485 PortControlID* controlID = (PortControlID*) controlIDV; 486 audio_info_t audioInfo; 487 audio_prinfo_t* prinfo; 488 int setPort; 489 490 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 491 prinfo = &(audioInfo.play); 492 } else { 493 prinfo = &(audioInfo.record); 494 } 495 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 496 case PORT_CONTROL_TYPE_SELECT_PORT: 497 // first try to just add this port. if that fails, set ONLY to this port. 498 AUDIO_INITINFO(&audioInfo); 499 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 500 if (value) { 501 setPort = (prinfo->port | controlID->port); 502 } else { 503 setPort = (prinfo->port - controlID->port); 504 } 505 AUDIO_INITINFO(&audioInfo); 506 prinfo->port = setPort; 507 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 508 // didn't work. Either this line doesn't support to select several 509 // ports at once (e.g. record), or a real error 510 if (value) { 511 // set to ONLY this port (and disable any other currently selected ports) 512 AUDIO_INITINFO(&audioInfo); 513 prinfo->port = controlID->port; 514 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 515 ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port); 516 } 517 } else { 518 // assume it's an error 519 ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort); 520 } 521 } 522 break; 523 case PORT_CONTROL_TYPE_OUTPUT_MUTED: 524 AUDIO_INITINFO(&audioInfo); 525 audioInfo.output_muted = (value?TRUE:FALSE); 526 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 527 ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value); 528 } 529 break; 530 default: 531 ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 532 } 533 } 534 } 535 536 float PORT_GetFloatValue(void* controlIDV) { 537 PortControlID* controlID = (PortControlID*) controlIDV; 538 audio_info_t audioInfo; 539 audio_prinfo_t* prinfo; 540 541 AUDIO_INITINFO(&audioInfo); 542 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 543 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 544 prinfo = &(audioInfo.play); 545 } else { 546 prinfo = &(audioInfo.record); 547 } 548 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 549 case PORT_CONTROL_TYPE_GAIN: 550 return ((float) (prinfo->gain - AUDIO_MIN_GAIN)) 551 / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); 552 case PORT_CONTROL_TYPE_BALANCE: 553 return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1)) 554 / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE)); 555 case PORT_CONTROL_TYPE_MONITOR_GAIN: 556 return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN)) 557 / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); 558 default: 559 ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 560 } 561 } 562 ERROR0("PORT_GetFloatValue: Could not ioctl!\n"); 563 return 0.0f; 564 } 565 566 void PORT_SetFloatValue(void* controlIDV, float value) { 567 PortControlID* controlID = (PortControlID*) controlIDV; 568 audio_info_t audioInfo; 569 audio_prinfo_t* prinfo; 570 571 AUDIO_INITINFO(&audioInfo); 572 573 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 574 prinfo = &(audioInfo.play); 575 } else { 576 prinfo = &(audioInfo.record); 577 } 578 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 579 case PORT_CONTROL_TYPE_GAIN: 580 prinfo->gain = AUDIO_MIN_GAIN 581 + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); 582 break; 583 case PORT_CONTROL_TYPE_BALANCE: 584 prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE 585 + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f); 586 break; 587 case PORT_CONTROL_TYPE_MONITOR_GAIN: 588 audioInfo.monitor_gain = AUDIO_MIN_GAIN 589 + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); 590 break; 591 default: 592 ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 593 return; 594 } 595 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 596 ERROR0("PORT_SetFloatValue: Could not ioctl!\n"); 597 } 598 } 599 600 #endif // USE_PORTS