2 * Copyright 2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
6 * Jérôme Duval (korli@users.berlios.de)
10 #include "hmulti_audio.h"
18 #define TRACE_MULTI_AUDIO
19 #ifdef TRACE_MULTI_AUDIO
20 # define TRACE(a...) dprintf("\33[34mgeode:\33[0m " a)
22 # define TRACE(a...) ;
26 static multi_channel_info sChannels
[] = {
27 { 0, B_MULTI_OUTPUT_CHANNEL
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, 0 },
28 { 1, B_MULTI_OUTPUT_CHANNEL
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, 0 },
29 { 2, B_MULTI_INPUT_CHANNEL
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
, 0 },
30 { 3, B_MULTI_INPUT_CHANNEL
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
, 0 },
31 { 4, B_MULTI_OUTPUT_BUS
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
,
32 B_CHANNEL_MINI_JACK_STEREO
},
33 { 5, B_MULTI_OUTPUT_BUS
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
,
34 B_CHANNEL_MINI_JACK_STEREO
},
35 { 6, B_MULTI_INPUT_BUS
, B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
,
36 B_CHANNEL_MINI_JACK_STEREO
},
37 { 7, B_MULTI_INPUT_BUS
, B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
,
38 B_CHANNEL_MINI_JACK_STEREO
},
43 format2size(uint32 format
)
64 get_description(geode_controller
* controller
, multi_description
* data
)
66 data
->interface_version
= B_CURRENT_INTERFACE_VERSION
;
67 data
->interface_minimum
= B_CURRENT_INTERFACE_VERSION
;
69 strcpy(data
->friendly_name
, "Geode");
70 strcpy(data
->vendor_info
, "Haiku");
73 if (controller
->record_stream
!= NULL
)
76 int32 outChannels
= 0;
77 if (controller
->playback_stream
!= NULL
)
80 data
->output_channel_count
= outChannels
;
81 data
->output_bus_channel_count
= outChannels
;
82 data
->input_channel_count
= inChannels
;
83 data
->input_bus_channel_count
= inChannels
;
84 data
->aux_bus_channel_count
= 0;
86 dprintf("%s: request_channel_count: %ld\n", __func__
,
87 data
->request_channel_count
);
89 if (data
->request_channel_count
>= (int)(sizeof(sChannels
)
90 / sizeof(sChannels
[0]))) {
91 memcpy(data
->channels
, &sChannels
, sizeof(sChannels
));
94 /* determine output/input rates */
95 data
->output_rates
= B_SR_48000
;
96 data
->input_rates
= B_SR_48000
;
98 /* force existance of 48kHz if variable rates are not supported */
99 if (data
->output_rates
== 0)
100 data
->output_rates
= B_SR_48000
;
101 if (data
->input_rates
== 0)
102 data
->input_rates
= B_SR_48000
;
104 data
->max_cvsr_rate
= 0;
105 data
->min_cvsr_rate
= 0;
107 data
->output_formats
= B_FMT_16BIT
;
108 data
->input_formats
= B_FMT_16BIT
;
109 data
->lock_sources
= B_MULTI_LOCK_INTERNAL
;
110 data
->timecode_sources
= 0;
111 data
->interface_flags
= B_MULTI_INTERFACE_PLAYBACK
| B_MULTI_INTERFACE_RECORD
;
112 data
->start_latency
= 30000;
114 strcpy(data
->control_panel
, "");
121 get_enabled_channels(geode_controller
* controller
, multi_channel_enable
* data
)
123 B_SET_CHANNEL(data
->enable_bits
, 0, true);
124 B_SET_CHANNEL(data
->enable_bits
, 1, true);
125 B_SET_CHANNEL(data
->enable_bits
, 2, true);
126 B_SET_CHANNEL(data
->enable_bits
, 3, true);
127 data
->lock_source
= B_MULTI_LOCK_INTERNAL
;
134 get_global_format(geode_controller
* controller
, multi_format_info
* data
)
136 data
->output_latency
= 0;
137 data
->input_latency
= 0;
138 data
->timecode_kind
= 0;
140 if (controller
->playback_stream
!= NULL
) {
141 data
->output
.format
= controller
->playback_stream
->sample_format
;
142 data
->output
.rate
= controller
->playback_stream
->sample_rate
;
144 data
->output
.format
= 0;
145 data
->output
.rate
= 0;
148 if (controller
->record_stream
!= NULL
) {
149 data
->input
.format
= controller
->record_stream
->sample_format
;
150 data
->input
.rate
= controller
->record_stream
->sample_format
;
152 data
->input
.format
= 0;
153 data
->input
.rate
= 0;
161 set_global_format(geode_controller
* controller
, multi_format_info
* data
)
163 // TODO: it looks like we're not supposed to fail; fix this!
165 if ((data
->output
.format
& audioGroup
->supported_formats
) == 0)
166 || (data
->output
.rate
& audioGroup
->supported_rates
) == 0)
170 if (controller
->playback_stream
!= NULL
) {
171 controller
->playback_stream
->sample_format
= data
->output
.format
;
172 controller
->playback_stream
->sample_rate
= data
->output
.rate
;
173 controller
->playback_stream
->sample_size
= format2size(
174 controller
->playback_stream
->sample_format
);
177 if (controller
->record_stream
!= NULL
) {
178 controller
->record_stream
->sample_rate
= data
->input
.rate
;
179 controller
->record_stream
->sample_format
= data
->input
.format
;
180 controller
->record_stream
->sample_size
= format2size(
181 controller
->record_stream
->sample_format
);
189 geode_ac97_get_mix(geode_controller
*controller
, const void *cookie
, int32 type
, float *values
) {
190 ac97_source_info
*info
= (ac97_source_info
*)cookie
;
196 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
197 //TRACE("B_MIX_GAIN value : %u\n", value);
198 if (info
->type
& B_MIX_STEREO
) {
199 mask
= ((1 << (info
->bits
+ 1)) - 1) << 8;
200 gain
= ((value
& mask
) >> 8) * info
->granularity
;
201 if (info
->polarity
== 1)
202 values
[0] = info
->max_gain
- gain
;
204 values
[0] = gain
- info
->min_gain
;
206 mask
= ((1 << (info
->bits
+ 1)) - 1);
207 gain
= (value
& mask
) * info
->granularity
;
208 if (info
->polarity
== 1)
209 values
[1] = info
->max_gain
- gain
;
211 values
[1] = gain
- info
->min_gain
;
213 mask
= ((1 << (info
->bits
+ 1)) - 1);
214 gain
= (value
& mask
) * info
->granularity
;
215 if (info
->polarity
== 1)
216 values
[0] = info
->max_gain
- gain
;
218 values
[0] = gain
- info
->min_gain
;
222 mask
= ((1 << 1) - 1) << 15;
223 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
224 //TRACE("B_MIX_MUTE value : %u\n", value);
226 values
[0] = ((value
>> 15) == 1) ? 1.0 : 0.0;
229 mask
= ((1 << 1) - 1) << 6;
230 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
231 //TRACE("B_MIX_MICBOOST value : %u\n", value);
233 values
[0] = ((value
>> 6) == 1) ? 1.0 : 0.0;
236 mask
= ((1 << 3) - 1);
237 value
= ac97_reg_cached_read(controller
->ac97
, AC97_RECORD_SELECT
);
239 //TRACE("B_MIX_MUX value : %u\n", value);
240 values
[0] = (float)value
;
247 geode_ac97_set_mix(geode_controller
*controller
, const void *cookie
, int32 type
, float *values
) {
248 ac97_source_info
*info
= (ac97_source_info
*)cookie
;
254 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
255 if (info
->type
& B_MIX_STEREO
) {
256 mask
= ((1 << (info
->bits
+ 1)) - 1) << 8;
259 if (info
->polarity
== 1)
260 gain
= info
->max_gain
- values
[0];
262 gain
= values
[0] - info
->min_gain
;
263 value
|= ((uint16
)(gain
/ info
->granularity
) << 8) & mask
;
265 mask
= ((1 << (info
->bits
+ 1)) - 1);
267 if (info
->polarity
== 1)
268 gain
= info
->max_gain
- values
[1];
270 gain
= values
[1] - info
->min_gain
;
271 value
|= ((uint16
)(gain
/ info
->granularity
)) & mask
;
273 mask
= ((1 << (info
->bits
+ 1)) - 1);
275 if (info
->polarity
== 1)
276 gain
= info
->max_gain
- values
[0];
278 gain
= values
[0] - info
->min_gain
;
279 value
|= ((uint16
)(gain
/ info
->granularity
)) & mask
;
281 //TRACE("B_MIX_GAIN value : %u\n", value);
282 ac97_reg_cached_write(controller
->ac97
, info
->reg
, value
);
285 mask
= ((1 << 1) - 1) << 15;
286 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
288 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 15 & mask
);
289 if (info
->reg
== AC97_SURR_VOLUME
) {
290 // there is a independent mute for each channel
291 mask
= ((1 << 1) - 1) << 7;
293 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 7 & mask
);
295 //TRACE("B_MIX_MUTE value : %u\n", value);
296 ac97_reg_cached_write(controller
->ac97
, info
->reg
, value
);
299 mask
= ((1 << 1) - 1) << 6;
300 value
= ac97_reg_cached_read(controller
->ac97
, info
->reg
);
302 value
|= ((values
[0] == 1.0 ? 1 : 0 ) << 6 & mask
);
303 //TRACE("B_MIX_MICBOOST value : %u\n", value);
304 ac97_reg_cached_write(controller
->ac97
, info
->reg
, value
);
307 mask
= ((1 << 3) - 1);
308 value
= ((int32
)values
[0]) & mask
;
309 value
= value
| (value
<< 8);
310 //TRACE("B_MIX_MUX value : %u\n", value);
311 ac97_reg_cached_write(controller
->ac97
, AC97_RECORD_SELECT
, value
);
319 create_group_control(geode_multi
*multi
, uint32
*index
, uint32 parent
,
320 strind_id string
, const char* name
) {
323 multi
->controls
[i
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
324 multi
->controls
[i
].mix_control
.parent
= parent
;
325 multi
->controls
[i
].mix_control
.flags
= B_MULTI_MIX_GROUP
;
326 multi
->controls
[i
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
327 multi
->controls
[i
].mix_control
.string
= string
;
329 strcpy(multi
->controls
[i
].mix_control
.name
, name
);
331 return multi
->controls
[i
].mix_control
.id
;
336 create_controls_list(geode_multi
*multi
)
338 uint32 i
= 0, index
= 0, count
, id
, parent
, parent2
, parent3
;
339 const ac97_source_info
*info
;
342 parent
= create_group_control(multi
, &index
, 0, S_null
, "AC97 mixer");
344 count
= source_info_size
;
345 //Note that we ignore first item in source_info
346 //It's for recording, but do match this with ac97.c's source_info
347 for (i
= 1; i
< count
; i
++) {
348 info
= &source_info
[i
];
349 TRACE("name : %s\n", info
->name
);
351 parent2
= create_group_control(multi
, &index
, parent
, S_null
, info
->name
);
353 if (info
->type
& B_MIX_GAIN
) {
354 if (info
->type
& B_MIX_MUTE
) {
355 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
356 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
357 multi
->controls
[index
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
358 multi
->controls
[index
].mix_control
.parent
= parent2
;
359 multi
->controls
[index
].mix_control
.string
= S_MUTE
;
360 multi
->controls
[index
].cookie
= info
;
361 multi
->controls
[index
].type
= B_MIX_MUTE
;
362 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
363 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
367 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
368 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
369 multi
->controls
[index
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
370 multi
->controls
[index
].mix_control
.parent
= parent2
;
371 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
372 multi
->controls
[index
].mix_control
.gain
.min_gain
= info
->min_gain
;
373 multi
->controls
[index
].mix_control
.gain
.max_gain
= info
->max_gain
;
374 multi
->controls
[index
].mix_control
.gain
.granularity
= info
->granularity
;
375 multi
->controls
[index
].cookie
= info
;
376 multi
->controls
[index
].type
= B_MIX_GAIN
;
377 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
378 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
379 id
= multi
->controls
[index
].mix_control
.id
;
382 if (info
->type
& B_MIX_STEREO
) {
383 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
384 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
385 multi
->controls
[index
].mix_control
.master
= id
;
386 multi
->controls
[index
].mix_control
.parent
= parent2
;
387 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
388 multi
->controls
[index
].mix_control
.gain
.min_gain
= info
->min_gain
;
389 multi
->controls
[index
].mix_control
.gain
.max_gain
= info
->max_gain
;
390 multi
->controls
[index
].mix_control
.gain
.granularity
= info
->granularity
;
391 multi
->controls
[index
].cookie
= info
;
392 multi
->controls
[index
].type
= B_MIX_GAIN
;
393 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
394 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
398 if (info
->type
& B_MIX_MICBOOST
) {
399 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
400 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
401 multi
->controls
[index
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
402 multi
->controls
[index
].mix_control
.parent
= parent2
;
403 strcpy(multi
->controls
[index
].mix_control
.name
, "+20 dB");
404 multi
->controls
[index
].cookie
= info
;
405 multi
->controls
[index
].type
= B_MIX_MICBOOST
;
406 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
407 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
414 parent
= create_group_control(multi
, &index
, 0, S_null
, "Recording");
416 info
= &source_info
[0];
417 TRACE("name : %s\n", info
->name
);
419 parent2
= create_group_control(multi
, &index
, parent
, S_null
, info
->name
);
421 if (info
->type
& B_MIX_GAIN
) {
422 if (info
->type
& B_MIX_MUTE
) {
423 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
424 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_ENABLE
;
425 multi
->controls
[index
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
426 multi
->controls
[index
].mix_control
.parent
= parent2
;
427 multi
->controls
[index
].mix_control
.string
= S_MUTE
;
428 multi
->controls
[index
].cookie
= info
;
429 multi
->controls
[index
].type
= B_MIX_MUTE
;
430 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
431 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
435 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
436 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
437 multi
->controls
[index
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
438 multi
->controls
[index
].mix_control
.parent
= parent2
;
439 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
440 multi
->controls
[index
].mix_control
.gain
.min_gain
= info
->min_gain
;
441 multi
->controls
[index
].mix_control
.gain
.max_gain
= info
->max_gain
;
442 multi
->controls
[index
].mix_control
.gain
.granularity
= info
->granularity
;
443 multi
->controls
[index
].cookie
= info
;
444 multi
->controls
[index
].type
= B_MIX_GAIN
;
445 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
446 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
447 id
= multi
->controls
[index
].mix_control
.id
;
450 if (info
->type
& B_MIX_STEREO
) {
451 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
452 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_GAIN
;
453 multi
->controls
[index
].mix_control
.master
= id
;
454 multi
->controls
[index
].mix_control
.parent
= parent2
;
455 strcpy(multi
->controls
[index
].mix_control
.name
, info
->name
);
456 multi
->controls
[index
].mix_control
.gain
.min_gain
= info
->min_gain
;
457 multi
->controls
[index
].mix_control
.gain
.max_gain
= info
->max_gain
;
458 multi
->controls
[index
].mix_control
.gain
.granularity
= info
->granularity
;
459 multi
->controls
[index
].cookie
= info
;
460 multi
->controls
[index
].type
= B_MIX_GAIN
;
461 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
462 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
466 if (info
->type
& B_MIX_RECORDMUX
) {
467 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
468 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX
;
469 multi
->controls
[index
].mix_control
.parent
= parent2
;
470 strcpy(multi
->controls
[index
].mix_control
.name
, "Record mux");
471 multi
->controls
[index
].cookie
= info
;
472 multi
->controls
[index
].type
= B_MIX_MUX
;
473 multi
->controls
[index
].get
= &geode_ac97_get_mix
;
474 multi
->controls
[index
].set
= &geode_ac97_set_mix
;
475 parent3
= multi
->controls
[index
].mix_control
.id
;
478 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
479 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
480 multi
->controls
[index
].mix_control
.parent
= parent3
;
481 multi
->controls
[index
].mix_control
.string
= S_MIC
;
483 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
484 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
485 multi
->controls
[index
].mix_control
.parent
= parent3
;
486 strcpy(multi
->controls
[index
].mix_control
.name
, "CD in");
488 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
489 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
490 multi
->controls
[index
].mix_control
.parent
= parent3
;
491 strcpy(multi
->controls
[index
].mix_control
.name
, "Video in");
493 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
494 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
495 multi
->controls
[index
].mix_control
.parent
= parent3
;
496 strcpy(multi
->controls
[index
].mix_control
.name
, "Aux in");
498 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
499 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
500 multi
->controls
[index
].mix_control
.parent
= parent3
;
501 strcpy(multi
->controls
[index
].mix_control
.name
, "Line in");
503 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
504 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
505 multi
->controls
[index
].mix_control
.parent
= parent3
;
506 multi
->controls
[index
].mix_control
.string
= S_STEREO_MIX
;
508 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
509 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
510 multi
->controls
[index
].mix_control
.parent
= parent3
;
511 multi
->controls
[index
].mix_control
.string
= S_MONO_MIX
;
513 multi
->controls
[index
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ index
;
514 multi
->controls
[index
].mix_control
.flags
= B_MULTI_MIX_MUX_VALUE
;
515 multi
->controls
[index
].mix_control
.parent
= parent3
;
516 strcpy(multi
->controls
[index
].mix_control
.name
, "TAD");
521 multi
->control_count
= index
;
522 TRACE("multi->control_count %lu\n", multi
->control_count
);
528 list_mix_controls(geode_controller
* controller
, multi_mix_control_info
* mmci
)
530 multi_mix_control
* mmc
= mmci
->controls
;
531 if (mmci
->control_count
< 24)
534 if (create_controls_list(controller
->multi
) < B_OK
)
536 for (uint32 i
= 0; i
< controller
->multi
->control_count
; i
++) {
537 mmc
[i
] = controller
->multi
->controls
[i
].mix_control
;
540 mmci
->control_count
= controller
->multi
->control_count
;
546 list_mix_connections(geode_controller
* controller
,
547 multi_mix_connection_info
* data
)
549 data
->actual_count
= 0;
555 list_mix_channels(geode_controller
* controller
, multi_mix_channel_info
*data
)
562 get_mix(geode_controller
*controller
, multi_mix_value_info
* mmvi
)
564 for (int32 i
= 0; i
< mmvi
->item_count
; i
++) {
565 uint32 id
= mmvi
->values
[i
].id
- MULTI_CONTROL_FIRSTID
;
566 if (id
< 0 || id
>= controller
->multi
->control_count
) {
567 dprintf("geode_get_mix : invalid control id requested : %li\n", id
);
570 multi_mixer_control
*control
= &controller
->multi
->controls
[id
];
572 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
575 control
->get(controller
, control
->cookie
, control
->type
, values
);
576 if (control
->mix_control
.master
== MULTI_CONTROL_MASTERID
)
577 mmvi
->values
[i
].gain
= values
[0];
579 mmvi
->values
[i
].gain
= values
[1];
583 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->get
) {
585 control
->get(controller
, control
->cookie
, control
->type
, values
);
586 mmvi
->values
[i
].enable
= (values
[0] == 1.0);
589 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->get
) {
591 control
->get(controller
, control
->cookie
, control
->type
, values
);
592 mmvi
->values
[i
].mux
= (int32
)values
[0];
600 set_mix(geode_controller
*controller
, multi_mix_value_info
* mmvi
)
602 geode_multi
*multi
= controller
->multi
;
603 for (int32 i
= 0; i
< mmvi
->item_count
; i
++) {
604 uint32 id
= mmvi
->values
[i
].id
- MULTI_CONTROL_FIRSTID
;
605 if (id
< 0 || id
>= multi
->control_count
) {
606 dprintf("geode_set_mix : invalid control id requested : %li\n", id
);
609 multi_mixer_control
*control
= &multi
->controls
[id
];
611 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
612 multi_mixer_control
*control2
= NULL
;
613 if (i
+1<mmvi
->item_count
) {
614 id
= mmvi
->values
[i
+ 1].id
- MULTI_CONTROL_FIRSTID
;
615 if (id
< 0 || id
>= multi
->control_count
) {
616 dprintf("geode_set_mix : invalid control id requested : %li\n", id
);
618 control2
= &multi
->controls
[id
];
619 if (control2
->mix_control
.master
!= control
->mix_control
.id
)
629 if (control
->mix_control
.master
== MULTI_CONTROL_MASTERID
)
630 values
[0] = mmvi
->values
[i
].gain
;
632 values
[1] = mmvi
->values
[i
].gain
;
634 if (control2
&& control2
->mix_control
.master
!= MULTI_CONTROL_MASTERID
)
635 values
[1] = mmvi
->values
[i
+1].gain
;
637 control
->set(controller
, control
->cookie
, control
->type
, values
);
644 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->set
) {
647 values
[0] = mmvi
->values
[i
].enable
? 1.0 : 0.0;
648 control
->set(controller
, control
->cookie
, control
->type
, values
);
651 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->set
) {
654 values
[0] = (float)mmvi
->values
[i
].mux
;
655 control
->set(controller
, control
->cookie
, control
->type
, values
);
663 get_buffers(geode_controller
* controller
, multi_buffer_list
* data
)
665 TRACE("playback: %ld buffers, %ld channels, %ld samples\n",
666 data
->request_playback_buffers
, data
->request_playback_channels
,
667 data
->request_playback_buffer_size
);
668 TRACE("record: %ld buffers, %ld channels, %ld samples\n",
669 data
->request_record_buffers
, data
->request_record_channels
,
670 data
->request_record_buffer_size
);
672 /* Determine what buffers we return given the request */
674 data
->return_playback_buffers
= data
->request_playback_buffers
;
675 data
->return_playback_channels
= data
->request_playback_channels
;
676 data
->return_playback_buffer_size
= data
->request_playback_buffer_size
;
677 data
->return_record_buffers
= data
->request_record_buffers
;
678 data
->return_record_channels
= data
->request_record_channels
;
679 data
->return_record_buffer_size
= data
->request_record_buffer_size
;
681 /* Workaround for Haiku multi_audio API, since it prefers to let the
682 driver pick values, while the BeOS multi_audio actually gives the
684 if (data
->return_playback_buffers
> STREAM_MAX_BUFFERS
685 || data
->return_playback_buffers
< STREAM_MIN_BUFFERS
)
686 data
->return_playback_buffers
= STREAM_MIN_BUFFERS
;
688 if (data
->return_record_buffers
> STREAM_MAX_BUFFERS
689 || data
->return_record_buffers
< STREAM_MIN_BUFFERS
)
690 data
->return_record_buffers
= STREAM_MIN_BUFFERS
;
692 if (data
->return_playback_buffer_size
== 0)
693 data
->return_playback_buffer_size
= DEFAULT_FRAMES_PER_BUFFER
;
695 if (data
->return_record_buffer_size
== 0)
696 data
->return_record_buffer_size
= DEFAULT_FRAMES_PER_BUFFER
;
698 /* ... from here on, we can assume again that a reasonable request is
701 data
->flags
= B_MULTI_BUFFER_PLAYBACK
| B_MULTI_BUFFER_RECORD
;
703 /* Copy the settings into the streams */
705 if (controller
->playback_stream
!= NULL
) {
706 controller
->playback_stream
->num_buffers
= data
->return_playback_buffers
;
707 controller
->playback_stream
->num_channels
= data
->return_playback_channels
;
708 controller
->playback_stream
->buffer_length
709 = data
->return_playback_buffer_size
;
711 status_t status
= geode_stream_setup_buffers(
712 controller
->playback_stream
, "Playback");
713 if (status
!= B_OK
) {
714 dprintf("geode: Error setting up playback buffers: %s\n",
720 if (controller
->record_stream
!= NULL
) {
721 controller
->record_stream
->num_buffers
= data
->return_record_buffers
;
722 controller
->record_stream
->num_channels
= data
->return_record_channels
;
723 controller
->record_stream
->buffer_length
724 = data
->return_record_buffer_size
;
726 status_t status
= geode_stream_setup_buffers(
727 controller
->record_stream
, "Recording");
728 if (status
!= B_OK
) {
729 dprintf("geode: Error setting up recording buffers: %s\n",
735 /* Setup data structure for multi_audio API... */
737 if (controller
->playback_stream
!= NULL
) {
738 uint32 playbackSampleSize
= controller
->playback_stream
->sample_size
;
740 for (int32 i
= 0; i
< data
->return_playback_buffers
; i
++) {
741 for (int32 channelIndex
= 0;
742 channelIndex
< data
->return_playback_channels
; channelIndex
++) {
743 data
->playback_buffers
[i
][channelIndex
].base
744 = (char*)controller
->playback_stream
->buffers
[i
]
745 + playbackSampleSize
* channelIndex
;
746 data
->playback_buffers
[i
][channelIndex
].stride
747 = playbackSampleSize
* data
->return_playback_channels
;
752 if (controller
->record_stream
!= NULL
) {
753 uint32 recordSampleSize
= controller
->record_stream
->sample_size
;
755 for (int32 i
= 0; i
< data
->return_record_buffers
; i
++) {
756 for (int32 channelIndex
= 0;
757 channelIndex
< data
->return_record_channels
; channelIndex
++) {
758 data
->record_buffers
[i
][channelIndex
].base
759 = (char*)controller
->record_stream
->buffers
[i
]
760 + recordSampleSize
* channelIndex
;
761 data
->record_buffers
[i
][channelIndex
].stride
762 = recordSampleSize
* data
->return_record_channels
;
771 /*! playback_buffer_cycle is the buffer we want to have played */
773 buffer_exchange(geode_controller
* controller
, multi_buffer_info
* data
)
775 static int debug_buffers_exchanged
= 0;
778 multi_buffer_info buffer_info
;
780 if (controller
->playback_stream
== NULL
)
783 if (!controller
->playback_stream
->running
) {
784 geode_stream_start(controller
->playback_stream
);
786 if (controller
->record_stream
&& !controller
->record_stream
->running
) {
787 geode_stream_start(controller
->record_stream
);
791 if (user_memcpy(&buffer_info
, data
, sizeof(buffer_info
)) < B_OK
)
792 return B_BAD_ADDRESS
;
794 memcpy(&buffer_info
, data
, sizeof(buffer_info
));
798 err
= acquire_sem_etc(controller
->playback_stream
->buffer_ready_sem
,
799 1, B_CAN_INTERRUPT
, 0);
801 dprintf("%s: Error waiting for playback buffer to finish (%s)!\n", __func__
,
806 status
= disable_interrupts();
807 acquire_spinlock(&controller
->playback_stream
->lock
);
809 buffer_info
.playback_buffer_cycle
= controller
->playback_stream
->buffer_cycle
;
810 buffer_info
.played_real_time
= controller
->playback_stream
->real_time
;
811 buffer_info
.played_frames_count
= controller
->playback_stream
->frames_count
;
813 release_spinlock(&controller
->playback_stream
->lock
);
815 if (controller
->record_stream
) {
816 acquire_spinlock(&controller
->record_stream
->lock
);
817 buffer_info
.record_buffer_cycle
= controller
->record_stream
->buffer_cycle
;
818 buffer_info
.recorded_real_time
= controller
->record_stream
->real_time
;
819 buffer_info
.recorded_frames_count
= controller
->record_stream
->frames_count
;
820 release_spinlock(&controller
->record_stream
->lock
);
823 restore_interrupts(status
);
826 if (user_memcpy(data
, &buffer_info
, sizeof(buffer_info
)) < B_OK
)
827 return B_BAD_ADDRESS
;
829 memcpy(data
, &buffer_info
, sizeof(buffer_info
));
832 debug_buffers_exchanged
++;
833 if (((debug_buffers_exchanged
% 100) == 1) && (debug_buffers_exchanged
< 1111)) {
834 dprintf("%s: %d buffers processed\n", __func__
, debug_buffers_exchanged
);
842 buffer_force_stop(geode_controller
* controller
)
844 if (controller
->playback_stream
!= NULL
) {
845 geode_stream_stop(controller
->playback_stream
);
847 if (controller
->record_stream
!= NULL
) {
848 geode_stream_stop(controller
->record_stream
);
856 multi_audio_control(geode_controller
* controller
, uint32 op
, void* arg
, size_t len
)
858 // TODO: make userland-safe when built for Haiku!
861 case B_MULTI_GET_DESCRIPTION
:
864 multi_description description
;
865 multi_channel_info channels
[16];
866 multi_channel_info
* originalChannels
;
868 if (user_memcpy(&description
, arg
, sizeof(multi_description
))
870 return B_BAD_ADDRESS
;
872 originalChannels
= description
.channels
;
873 description
.channels
= channels
;
874 if (description
.request_channel_count
> 16)
875 description
.request_channel_count
= 16;
877 status_t status
= get_description(controller
, &description
);
881 description
.channels
= originalChannels
;
882 if (user_memcpy(arg
, &description
, sizeof(multi_description
))
884 return B_BAD_ADDRESS
;
885 return user_memcpy(originalChannels
, channels
, sizeof(multi_channel_info
)
886 * description
.request_channel_count
);
888 return get_description(controller
, (multi_description
*)arg
);
892 case B_MULTI_GET_ENABLED_CHANNELS
:
893 return get_enabled_channels(controller
, (multi_channel_enable
*)arg
);
894 case B_MULTI_SET_ENABLED_CHANNELS
:
897 case B_MULTI_GET_GLOBAL_FORMAT
:
898 return get_global_format(controller
, (multi_format_info
*)arg
);
899 case B_MULTI_SET_GLOBAL_FORMAT
:
900 return set_global_format(controller
, (multi_format_info
*)arg
);
902 case B_MULTI_LIST_MIX_CHANNELS
:
903 return list_mix_channels(controller
, (multi_mix_channel_info
*)arg
);
904 case B_MULTI_LIST_MIX_CONTROLS
:
905 return list_mix_controls(controller
, (multi_mix_control_info
*)arg
);
906 case B_MULTI_LIST_MIX_CONNECTIONS
:
907 return list_mix_connections(controller
,
908 (multi_mix_connection_info
*)arg
);
909 case B_MULTI_GET_MIX
:
910 return get_mix(controller
, (multi_mix_value_info
*)arg
);
911 case B_MULTI_SET_MIX
:
912 return set_mix(controller
, (multi_mix_value_info
*)arg
);
914 case B_MULTI_GET_BUFFERS
:
915 return get_buffers(controller
, (multi_buffer_list
*)arg
);
917 case B_MULTI_BUFFER_EXCHANGE
:
918 return buffer_exchange(controller
, (multi_buffer_info
*)arg
);
919 case B_MULTI_BUFFER_FORCE_STOP
:
920 return buffer_force_stop(controller
);
922 case B_MULTI_GET_EVENT_INFO
:
923 case B_MULTI_SET_EVENT_INFO
:
924 case B_MULTI_GET_EVENT
:
925 case B_MULTI_GET_CHANNEL_FORMATS
:
926 case B_MULTI_SET_CHANNEL_FORMATS
:
927 case B_MULTI_SET_BUFFERS
:
928 case B_MULTI_SET_START_TIME
: