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
PORT_GetPortMixerCount()141 INT32 PORT_GetPortMixerCount() {
142 return (INT32) getAudioDeviceCount();
143 }
144
145
PORT_GetPortMixerDescription(INT32 mixerIndex,PortMixerDescription * description)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
PORT_Open(INT32 mixerIndex)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
PORT_Close(void * id)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
PORT_GetPortCount(void * id)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
isSourcePort(PortInfo * info,INT32 portIndex)257 int isSourcePort(PortInfo* info, INT32 portIndex) {
258 return (portIndex >= info->targetPortCount);
259 }
260
PORT_GetPortType(void * id,INT32 portIndex)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!
getPortName(PortInfo * info,INT32 portIndex)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
PORT_GetPortName(void * id,INT32 portIndex,char * name,INT32 len)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
createPortControl(PortInfo * info,PortControlCreator * creator,INT32 portIndex,INT32 type,void ** controlObjects,int * controlCount)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
addCompoundControl(PortInfo * info,PortControlCreator * creator,char * name,void ** controlObjects,int * controlCount)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
addAllControls(PortInfo * info,PortControlCreator * creator,void ** controlObjects,int * controlCount)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
PORT_GetControls(void * id,INT32 portIndex,PortControlCreator * creator)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
PORT_GetIntValue(void * controlIDV)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
PORT_SetIntValue(void * controlIDV,INT32 value)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
PORT_GetFloatValue(void * controlIDV)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
PORT_SetFloatValue(void * controlIDV,float value)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
601