1 /* 2 * Copyright (c) 2002, 2007, 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 394 TRACE4(">PORT_GetControls(id=%p, portIndex=%d). controlIDs=%p, maxControlCount=%d\n", 395 id, portIndex, info->controlIDs, info->maxControlCount); 396 if ((portIndex >= 0) && (portIndex < portCount)) { 397 // if the memory isn't reserved for the control structures, allocate it 398 if (!info->controlIDs) { 399 int maxCount = 0; 400 TRACE0("getControl: allocate mem\n"); 401 // get a maximum number of controls: 402 // each port has a select, balance, and volume control. 403 maxCount = 3 * portCount; 404 // then there is monitorGain and outputMuted 405 maxCount += (2 * info->targetPortCount); 406 info->maxControlCount = maxCount; 407 info->controlIDs = (PortControlID*) malloc(sizeof(PortControlID) * maxCount); 408 } 409 if (!isSourcePort(info, portIndex)) { 410 type = PORT_CONTROL_TYPE_PLAY; 411 // add master mute control 412 createPortControl(info, creator, portIndex, 413 type | PORT_CONTROL_TYPE_OUTPUT_MUTED, 414 controls, &controlCount); 415 addAllControls(info, creator, controls, &controlCount); 416 #ifdef SOLARIS7_COMPATIBLE 417 selectable = info->audioInfo.play.avail_ports & targetPorts[info->ports[portIndex]]; 418 #else 419 selectable = info->audioInfo.play.mod_ports & targetPorts[info->ports[portIndex]]; 420 #endif 421 } else { 422 type = PORT_CONTROL_TYPE_RECORD; 423 #ifdef SOLARIS7_COMPATIBLE 424 selectable = info->audioInfo.record.avail_ports & sourcePorts[info->ports[portIndex]]; 425 #else 426 selectable = info->audioInfo.record.mod_ports & sourcePorts[info->ports[portIndex]]; 427 #endif 428 } 429 // add a mixer strip with volume, ... 430 createPortControl(info, creator, portIndex, 431 type | PORT_CONTROL_TYPE_GAIN, 432 controls, &controlCount); 433 // ... balance, ... 434 createPortControl(info, creator, portIndex, 435 type | PORT_CONTROL_TYPE_BALANCE, 436 controls, &controlCount); 437 // ... and select control (if not always on)... 438 if (selectable) { 439 createPortControl(info, creator, portIndex, 440 type | PORT_CONTROL_TYPE_SELECT_PORT, 441 controls, &controlCount); 442 } 443 // ... packaged in a compound control. 444 addCompoundControl(info, creator, getPortName(info, portIndex), controls, &controlCount); 445 446 if (type == PORT_CONTROL_TYPE_PLAY) { 447 // add a single strip for source ports with monitor gain 448 createPortControl(info, creator, portIndex, 449 type | PORT_CONTROL_TYPE_MONITOR_GAIN, 450 controls, &controlCount); 451 // also in a compound control 452 addCompoundControl(info, creator, MONITOR_GAIN_STRING, controls, &controlCount); 453 } 454 } 455 TRACE0("< PORT_getControls\n"); 456 } 457 458 INT32 PORT_GetIntValue(void* controlIDV) { 459 PortControlID* controlID = (PortControlID*) controlIDV; 460 audio_info_t audioInfo; 461 audio_prinfo_t* prinfo; 462 463 AUDIO_INITINFO(&audioInfo); 464 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 465 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 466 prinfo = &(audioInfo.play); 467 } else { 468 prinfo = &(audioInfo.record); 469 } 470 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 471 case PORT_CONTROL_TYPE_SELECT_PORT: 472 return (prinfo->port & controlID->port)?TRUE:FALSE; 473 case PORT_CONTROL_TYPE_OUTPUT_MUTED: 474 return (audioInfo.output_muted)?TRUE:FALSE; 475 default: 476 ERROR1("PORT_GetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 477 } 478 } 479 ERROR0("PORT_GetIntValue: Could not ioctl!\n"); 480 return 0; 481 } 482 483 void PORT_SetIntValue(void* controlIDV, INT32 value) { 484 PortControlID* controlID = (PortControlID*) controlIDV; 485 audio_info_t audioInfo; 486 audio_prinfo_t* prinfo; 487 int setPort; 488 489 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 490 prinfo = &(audioInfo.play); 491 } else { 492 prinfo = &(audioInfo.record); 493 } 494 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 495 case PORT_CONTROL_TYPE_SELECT_PORT: 496 // first try to just add this port. if that fails, set ONLY to this port. 497 AUDIO_INITINFO(&audioInfo); 498 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 499 if (value) { 500 setPort = (prinfo->port | controlID->port); 501 } else { 502 setPort = (prinfo->port - controlID->port); 503 } 504 AUDIO_INITINFO(&audioInfo); 505 prinfo->port = setPort; 506 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 507 // didn't work. Either this line doesn't support to select several 508 // ports at once (e.g. record), or a real error 509 if (value) { 510 // set to ONLY this port (and disable any other currently selected ports) 511 AUDIO_INITINFO(&audioInfo); 512 prinfo->port = controlID->port; 513 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 514 ERROR2("Error setting output select port %d to port %d!\n", controlID->port, controlID->port); 515 } 516 } else { 517 // assume it's an error 518 ERROR2("Error setting output select port %d to port %d!\n", controlID->port, setPort); 519 } 520 } 521 break; 522 case PORT_CONTROL_TYPE_OUTPUT_MUTED: 523 AUDIO_INITINFO(&audioInfo); 524 audioInfo.output_muted = (value?TRUE:FALSE); 525 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 526 ERROR2("Error setting output muted on port %d to %d!\n", controlID->port, value); 527 } 528 break; 529 default: 530 ERROR1("PORT_SetIntValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 531 } 532 } 533 } 534 535 float PORT_GetFloatValue(void* controlIDV) { 536 PortControlID* controlID = (PortControlID*) controlIDV; 537 audio_info_t audioInfo; 538 audio_prinfo_t* prinfo; 539 540 AUDIO_INITINFO(&audioInfo); 541 if (ioctl(controlID->portInfo->fd, AUDIO_GETINFO, &audioInfo) >= 0) { 542 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 543 prinfo = &(audioInfo.play); 544 } else { 545 prinfo = &(audioInfo.record); 546 } 547 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 548 case PORT_CONTROL_TYPE_GAIN: 549 return ((float) (prinfo->gain - AUDIO_MIN_GAIN)) 550 / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); 551 case PORT_CONTROL_TYPE_BALANCE: 552 return ((float) ((prinfo->balance - AUDIO_LEFT_BALANCE - AUDIO_MID_BALANCE) << 1)) 553 / ((float) (AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE)); 554 case PORT_CONTROL_TYPE_MONITOR_GAIN: 555 return ((float) (audioInfo.monitor_gain - AUDIO_MIN_GAIN)) 556 / ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN)); 557 default: 558 ERROR1("PORT_GetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 559 } 560 } 561 ERROR0("PORT_GetFloatValue: Could not ioctl!\n"); 562 return 0.0f; 563 } 564 565 void PORT_SetFloatValue(void* controlIDV, float value) { 566 PortControlID* controlID = (PortControlID*) controlIDV; 567 audio_info_t audioInfo; 568 audio_prinfo_t* prinfo; 569 570 AUDIO_INITINFO(&audioInfo); 571 572 if (controlID->controlType & PORT_CONTROL_TYPE_PLAY) { 573 prinfo = &(audioInfo.play); 574 } else { 575 prinfo = &(audioInfo.record); 576 } 577 switch (controlID->controlType & PORT_CONTROL_TYPE_MASK) { 578 case PORT_CONTROL_TYPE_GAIN: 579 prinfo->gain = AUDIO_MIN_GAIN 580 + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); 581 break; 582 case PORT_CONTROL_TYPE_BALANCE: 583 prinfo->balance = AUDIO_LEFT_BALANCE + AUDIO_MID_BALANCE 584 + ((int) (value * ((float) ((AUDIO_RIGHT_BALANCE - AUDIO_LEFT_BALANCE) >> 1))) + 0.5f); 585 break; 586 case PORT_CONTROL_TYPE_MONITOR_GAIN: 587 audioInfo.monitor_gain = AUDIO_MIN_GAIN 588 + (int) ((value * ((float) (AUDIO_MAX_GAIN - AUDIO_MIN_GAIN))) + 0.5f); 589 break; 590 default: 591 ERROR1("PORT_SetFloatValue: Wrong type %d !\n", controlID->controlType & PORT_CONTROL_TYPE_MASK); 592 return; 593 } 594 if (ioctl(controlID->portInfo->fd, AUDIO_SETINFO, &audioInfo) < 0) { 595 ERROR0("PORT_SetFloatValue: Could not ioctl!\n"); 596 } 597 } 598 599 #endif // USE_PORTS