2 * EchoGals/Echo24 BeOS Driver for Echo audio cards
4 * Copyright (c) 2003, Jerome Duval (jerome.duval@free.fr)
6 * Original code : BeOS Driver for Intel ICH AC'97 Link interface
7 * Copyright (c) 2002, Marcus Overhagen <marcus@overhagen.de>
10 * Redistribution and use in source and binary forms, with or without modification,
11 * are permitted provided that the following conditions are met:
13 * - Redistributions of source code must retain the above copyright notice,
14 * this list of conditions and the following disclaimer.
15 * - Redistributions in binary form must reproduce the above copyright notice,
16 * this list of conditions and the following disclaimer in the documentation
17 * and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
25 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
28 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include <driver_settings.h>
34 #include <MediaDefs.h>
36 #include "hmulti_audio.h"
47 B_MIX_NOMINAL
= 1 << 2
58 echo_settings current_settings
= {
60 16, // bits per sample
68 echo_channel_get_mix(void *card
, MIXER_AUDIO_CHANNEL channel
, int32 type
, float *values
) {
69 echo_dev
*dev
= (echo_dev
*) card
;
70 MIXER_MULTI_FUNCTION multi_function
[2];
71 PMIXER_FUNCTION function
= multi_function
[0].MixerFunction
;
72 INT32 size
= ComputeMixerMultiFunctionSize(2);
73 function
[0].Channel
= channel
;
74 function
[1].Channel
= channel
;
75 function
[1].Channel
.wChannel
++;
78 function
[0].iFunction
= function
[1].iFunction
= MXF_GET_LEVEL
;
81 function
[0].iFunction
= function
[1].iFunction
= MXF_GET_MUTE
;
84 function
[0].iFunction
= function
[1].iFunction
= MXF_GET_NOMINAL
;
88 multi_function
[0].iCount
= 2;
89 dev
->pEG
->ProcessMixerMultiFunction(multi_function
, size
);
91 if (function
[0].RtnStatus
== ECHOSTATUS_OK
) {
92 if (type
== B_MIX_GAIN
) {
93 values
[0] = (float)function
[0].Data
.iLevel
/ 256;
94 values
[1] = (float)function
[1].Data
.iLevel
/ 256;
95 } else if (type
== B_MIX_MUTE
) {
96 values
[0] = function
[0].Data
.bMuteOn
? 1.0 : 0.0;
98 values
[0] = function
[0].Data
.iNominal
== 4 ? 1.0 : 0.0;
100 PRINT(("echo_channel_get_mix iLevel: %" B_PRId32
", %d, %" B_PRIu32
101 "\n", function
[0].Data
.iLevel
, channel
.wChannel
, channel
.dwType
));
108 echo_channel_set_mix(void *card
, MIXER_AUDIO_CHANNEL channel
, int32 type
, float *values
) {
109 echo_dev
*dev
= (echo_dev
*) card
;
110 MIXER_MULTI_FUNCTION multi_function
[2];
111 PMIXER_FUNCTION function
= multi_function
[0].MixerFunction
;
112 INT32 size
= ComputeMixerMultiFunctionSize(2);
113 function
[0].Channel
= channel
;
114 function
[1].Channel
= channel
;
115 function
[1].Channel
.wChannel
++;
116 if (type
== B_MIX_GAIN
) {
117 function
[0].Data
.iLevel
= (int)(values
[0] * 256);
118 function
[0].iFunction
= MXF_SET_LEVEL
;
119 function
[1].Data
.iLevel
= (int)(values
[1] * 256);
120 function
[1].iFunction
= MXF_SET_LEVEL
;
121 } else if (type
== B_MIX_MUTE
) {
122 function
[0].Data
.bMuteOn
= values
[0] == 1.0;
123 function
[0].iFunction
= MXF_SET_MUTE
;
124 function
[1].Data
.bMuteOn
= values
[0] == 1.0;
125 function
[1].iFunction
= MXF_SET_MUTE
;
127 function
[0].Data
.iNominal
= values
[0] == 1.0 ? 4 : -10;
128 function
[0].iFunction
= MXF_SET_NOMINAL
;
129 function
[1].Data
.iNominal
= values
[0] == 1.0 ? 4 : -10;
130 function
[1].iFunction
= MXF_SET_NOMINAL
;
133 multi_function
[0].iCount
= 2;
134 dev
->pEG
->ProcessMixerMultiFunction(multi_function
, size
);
136 if (function
[0].RtnStatus
== ECHOSTATUS_OK
) {
137 PRINT(("echo_channel_set_mix OK: %" B_PRId32
", %d, %" B_PRIu32
"\n",
138 function
[0].Data
.iLevel
, channel
.wChannel
, channel
.dwType
));
145 echo_create_group_control(multi_dev
*multi
, uint32
*index
, int32 parent
,
146 enum strind_id string
, const char* name
) {
149 multi
->controls
[i
].mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
150 multi
->controls
[i
].mix_control
.parent
= parent
;
151 multi
->controls
[i
].mix_control
.flags
= B_MULTI_MIX_GROUP
;
152 multi
->controls
[i
].mix_control
.master
= MULTI_CONTROL_MASTERID
;
153 multi
->controls
[i
].mix_control
.string
= string
;
155 strcpy(multi
->controls
[i
].mix_control
.name
, name
);
157 return multi
->controls
[i
].mix_control
.id
;
161 echo_create_channel_control(multi_dev
*multi
, uint32
*index
, int32 parent
, int32 string
,
162 MIXER_AUDIO_CHANNEL channel
, bool nominal
) {
163 uint32 i
= *index
, id
;
164 multi_mixer_control control
;
166 control
.mix_control
.master
= MULTI_CONTROL_MASTERID
;
167 control
.mix_control
.parent
= parent
;
168 control
.channel
= channel
;
169 control
.get
= &echo_channel_get_mix
;
170 control
.set
= &echo_channel_set_mix
;
171 control
.mix_control
.gain
.min_gain
= -128;
172 control
.mix_control
.gain
.max_gain
= 6;
173 control
.mix_control
.gain
.granularity
= 0.5;
175 control
.mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
176 control
.mix_control
.flags
= B_MULTI_MIX_ENABLE
;
177 control
.mix_control
.string
= S_MUTE
;
178 control
.type
= B_MIX_MUTE
;
179 multi
->controls
[i
] = control
;
182 control
.mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
183 control
.mix_control
.flags
= B_MULTI_MIX_GAIN
;
184 control
.mix_control
.string
= S_null
;
185 control
.type
= B_MIX_GAIN
;
186 strcpy(control
.mix_control
.name
, "Gain");
187 multi
->controls
[i
] = control
;
188 id
= control
.mix_control
.id
;
192 control
.mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
193 control
.mix_control
.master
= id
;
194 multi
->controls
[i
] = control
;
197 // nominal level (+4/-10)
199 control
.mix_control
.id
= MULTI_CONTROL_FIRSTID
+ i
;
200 control
.mix_control
.master
= MULTI_CONTROL_MASTERID
;
201 control
.mix_control
.flags
= B_MULTI_MIX_ENABLE
;
202 control
.mix_control
.string
= S_null
;
203 control
.type
= B_MIX_NOMINAL
;
204 strcpy(control
.mix_control
.name
, "+4dB");
205 multi
->controls
[i
] = control
;
214 echo_create_controls_list(multi_dev
*multi
)
216 uint32 i
= 0, index
= 0, parent
, parent2
;
217 echo_dev
*card
= (echo_dev
*)multi
->card
;
219 parent
= echo_create_group_control(multi
, &index
, 0, S_OUTPUT
, NULL
);
221 MIXER_AUDIO_CHANNEL channel
;
223 channel
.dwType
= ECHO_BUS_OUT
;
224 for (i
= 0; i
< card
->caps
.wNumBussesOut
/ 2; i
++) {
225 channel
.wChannel
= i
* 2;
226 parent2
= echo_create_group_control(multi
, &index
, parent
, S_null
, "Output");
228 echo_create_channel_control(multi
, &index
, parent2
, 0, channel
,
229 card
->caps
.dwBusOutCaps
[i
* 2] & ECHOCAPS_NOMINAL_LEVEL
);
232 parent
= echo_create_group_control(multi
, &index
, 0, S_INPUT
, NULL
);
234 channel
.dwType
= ECHO_BUS_IN
;
235 for (i
= 0; i
< card
->caps
.wNumBussesIn
/ 2; i
++) {
236 channel
.wChannel
= i
* 2;
238 parent2
= echo_create_group_control(multi
, &index
, parent
, S_null
, "Input");
240 echo_create_channel_control(multi
, &index
, parent2
, 0, channel
,
241 card
->caps
.dwBusInCaps
[i
* 2] & ECHOCAPS_NOMINAL_LEVEL
);
244 multi
->control_count
= index
;
245 PRINT(("multi->control_count %" B_PRIu32
"\n", multi
->control_count
));
251 echo_get_mix(echo_dev
*card
, multi_mix_value_info
* mmvi
)
255 multi_mixer_control
*control
= NULL
;
256 for (i
= 0; i
< mmvi
->item_count
; i
++) {
257 id
= mmvi
->values
[i
].id
- MULTI_CONTROL_FIRSTID
;
258 if (id
< 0 || id
>= card
->multi
.control_count
) {
259 PRINT(("echo_get_mix : invalid control id requested : %" B_PRIu32
263 control
= &card
->multi
.controls
[id
];
265 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
268 control
->get(card
, control
->channel
, control
->type
, values
);
269 if (control
->mix_control
.master
== MULTI_CONTROL_MASTERID
)
270 mmvi
->values
[i
].gain
= values
[0];
272 mmvi
->values
[i
].gain
= values
[1];
276 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->get
) {
278 control
->get(card
, control
->channel
, control
->type
, values
);
279 mmvi
->values
[i
].enable
= (values
[0] == 1.0);
282 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->get
) {
284 control
->get(card
, control
->channel
, control
->type
, values
);
285 mmvi
->values
[i
].mux
= (int32
)values
[0];
293 echo_set_mix(echo_dev
*card
, multi_mix_value_info
* mmvi
)
297 multi_mixer_control
*control
= NULL
;
298 for (i
= 0; i
< mmvi
->item_count
; i
++) {
299 id
= mmvi
->values
[i
].id
- MULTI_CONTROL_FIRSTID
;
300 if (id
< 0 || id
>= card
->multi
.control_count
) {
301 PRINT(("echo_set_mix : invalid control id requested : %" B_PRIu32
305 control
= &card
->multi
.controls
[id
];
307 if (control
->mix_control
.flags
& B_MULTI_MIX_GAIN
) {
308 multi_mixer_control
*control2
= NULL
;
309 if (i
+ 1 < mmvi
->item_count
) {
310 id
= mmvi
->values
[i
+ 1].id
- MULTI_CONTROL_FIRSTID
;
311 if (id
< 0 || id
>= card
->multi
.control_count
) {
312 PRINT(("echo_set_mix : invalid control id requested : %"
315 control2
= &card
->multi
.controls
[id
];
316 if (control2
->mix_control
.master
!= control
->mix_control
.id
)
326 if (control
->mix_control
.master
== MULTI_CONTROL_MASTERID
)
327 values
[0] = mmvi
->values
[i
].gain
;
329 values
[1] = mmvi
->values
[i
].gain
;
331 if (control2
&& control2
->mix_control
.master
!= MULTI_CONTROL_MASTERID
)
332 values
[1] = mmvi
->values
[i
+ 1].gain
;
334 control
->set(card
, control
->channel
, control
->type
, values
);
341 if (control
->mix_control
.flags
& B_MULTI_MIX_ENABLE
&& control
->set
) {
344 values
[0] = mmvi
->values
[i
].enable
? 1.0 : 0.0;
345 control
->set(card
, control
->channel
, control
->type
, values
);
348 if (control
->mix_control
.flags
& B_MULTI_MIX_MUX
&& control
->set
) {
351 values
[0] = (float)mmvi
->values
[i
].mux
;
352 control
->set(card
, control
->channel
, control
->type
, values
);
360 echo_list_mix_controls(echo_dev
*card
, multi_mix_control_info
* mmci
)
362 multi_mix_control
*mmc
;
365 mmc
= mmci
->controls
;
366 if (mmci
->control_count
< 24)
369 if (echo_create_controls_list(&card
->multi
) < B_OK
)
371 for (i
= 0; i
< card
->multi
.control_count
; i
++) {
372 mmc
[i
] = card
->multi
.controls
[i
].mix_control
;
375 mmci
->control_count
= card
->multi
.control_count
;
381 echo_list_mix_connections(echo_dev
* card
, multi_mix_connection_info
* data
)
388 echo_list_mix_channels(echo_dev
*card
, multi_mix_channel_info
*data
)
393 /*multi_channel_info chans[] = {
394 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
395 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
396 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
397 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
398 { 4, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
399 { 5, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
400 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
401 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
402 { 8, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
403 { 9, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
404 { 10, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
405 { 11, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
408 /*multi_channel_info chans[] = {
409 { 0, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
410 { 1, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
411 { 2, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_SURROUND_BUS, 0 },
412 { 3, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_SURROUND_BUS, 0 },
413 { 4, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARLEFT | B_CHANNEL_SURROUND_BUS, 0 },
414 { 5, B_MULTI_OUTPUT_CHANNEL, B_CHANNEL_REARRIGHT | B_CHANNEL_SURROUND_BUS, 0 },
415 { 6, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
416 { 7, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
417 { 8, B_MULTI_INPUT_CHANNEL, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, 0 },
418 { 9, B_MULTI_INPUT_CHANNEL, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, 0 },
419 { 10, B_MULTI_OUTPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
420 { 11, B_MULTI_OUTPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
421 { 12, B_MULTI_INPUT_BUS, B_CHANNEL_LEFT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
422 { 13, B_MULTI_INPUT_BUS, B_CHANNEL_RIGHT | B_CHANNEL_STEREO_BUS, B_CHANNEL_MINI_JACK_STEREO },
427 echo_create_channels_list(multi_dev
*multi
)
431 uint32 index
, i
, designations
;
432 multi_channel_info
*chans
;
433 uint32 chan_designations
[] = {
442 chans
= multi
->chans
;
445 for (mode
=ECHO_USE_PLAY
; mode
!=-1;
446 mode
= (mode
== ECHO_USE_PLAY
) ? ECHO_USE_RECORD
: -1) {
447 LIST_FOREACH(stream
, &((echo_dev
*)multi
->card
)->streams
, next
) {
448 if ((stream
->use
& mode
) == 0)
451 if (stream
->channels
== 2)
452 designations
= B_CHANNEL_STEREO_BUS
;
454 designations
= B_CHANNEL_SURROUND_BUS
;
456 for (i
= 0; i
< stream
->channels
; i
++) {
457 chans
[index
].channel_id
= index
;
458 chans
[index
].kind
= (mode
== ECHO_USE_PLAY
) ? B_MULTI_OUTPUT_CHANNEL
: B_MULTI_INPUT_CHANNEL
;
459 chans
[index
].designations
= designations
| chan_designations
[i
];
460 chans
[index
].connectors
= 0;
465 if (mode
==ECHO_USE_PLAY
) {
466 multi
->output_channel_count
= index
;
468 multi
->input_channel_count
= index
- multi
->output_channel_count
;
472 chans
[index
].channel_id
= index
;
473 chans
[index
].kind
= B_MULTI_OUTPUT_BUS
;
474 chans
[index
].designations
= B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
;
475 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
478 chans
[index
].channel_id
= index
;
479 chans
[index
].kind
= B_MULTI_OUTPUT_BUS
;
480 chans
[index
].designations
= B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
;
481 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
484 multi
->output_bus_channel_count
= index
- multi
->output_channel_count
485 - multi
->input_channel_count
;
487 chans
[index
].channel_id
= index
;
488 chans
[index
].kind
= B_MULTI_INPUT_BUS
;
489 chans
[index
].designations
= B_CHANNEL_LEFT
| B_CHANNEL_STEREO_BUS
;
490 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
493 chans
[index
].channel_id
= index
;
494 chans
[index
].kind
= B_MULTI_INPUT_BUS
;
495 chans
[index
].designations
= B_CHANNEL_RIGHT
| B_CHANNEL_STEREO_BUS
;
496 chans
[index
].connectors
= B_CHANNEL_MINI_JACK_STEREO
;
499 multi
->input_bus_channel_count
= index
- multi
->output_channel_count
500 - multi
->input_channel_count
- multi
->output_bus_channel_count
;
502 multi
->aux_bus_channel_count
= 0;
507 echo_get_description(echo_dev
*card
, multi_description
*data
)
511 data
->interface_version
= B_CURRENT_INTERFACE_VERSION
;
512 data
->interface_minimum
= B_CURRENT_INTERFACE_VERSION
;
514 strlcpy(data
->friendly_name
, card
->caps
.szName
, sizeof(data
->friendly_name
));
515 strlcpy(data
->vendor_info
, AUTHOR
, sizeof(data
->vendor_info
));
517 data
->output_channel_count
= card
->multi
.output_channel_count
;
518 data
->input_channel_count
= card
->multi
.input_channel_count
;
519 data
->output_bus_channel_count
= card
->multi
.output_bus_channel_count
;
520 data
->input_bus_channel_count
= card
->multi
.input_bus_channel_count
;
521 data
->aux_bus_channel_count
= card
->multi
.aux_bus_channel_count
;
523 size
= card
->multi
.output_channel_count
+ card
->multi
.input_channel_count
524 + card
->multi
.output_bus_channel_count
+ card
->multi
.input_bus_channel_count
525 + card
->multi
.aux_bus_channel_count
;
527 // for each channel, starting with the first output channel,
528 // then the second, third..., followed by the first input
529 // channel, second, third, ..., followed by output bus
530 // channels and input bus channels and finally auxillary channels,
532 LOG(("request_channel_count = %d\n",data
->request_channel_count
));
533 if (data
->request_channel_count
>= size
) {
534 LOG(("copying data\n"));
535 memcpy(data
->channels
, card
->multi
.chans
, size
* sizeof(card
->multi
.chans
[0]));
538 switch (current_settings
.sample_rate
) {
539 case 192000: data
->output_rates
= data
->input_rates
= B_SR_192000
; break;
540 case 96000: data
->output_rates
= data
->input_rates
= B_SR_96000
; break;
541 case 48000: data
->output_rates
= data
->input_rates
= B_SR_48000
; break;
542 case 44100: data
->output_rates
= data
->input_rates
= B_SR_44100
; break;
544 data
->min_cvsr_rate
= 0;
545 data
->max_cvsr_rate
= 48000;
547 switch (current_settings
.bitsPerSample
) {
548 case 8: data
->output_formats
= data
->input_formats
= B_FMT_8BIT_U
; break;
549 case 16: data
->output_formats
= data
->input_formats
= B_FMT_16BIT
; break;
550 case 24: data
->output_formats
= data
->input_formats
= B_FMT_24BIT
; break;
551 case 32: data
->output_formats
= data
->input_formats
= B_FMT_32BIT
; break;
553 data
->lock_sources
= B_MULTI_LOCK_INTERNAL
;
554 data
->timecode_sources
= 0;
555 data
->interface_flags
= B_MULTI_INTERFACE_PLAYBACK
| B_MULTI_INTERFACE_RECORD
;
556 data
->start_latency
= 3000;
558 strcpy(data
->control_panel
, "");
565 echo_get_enabled_channels(echo_dev
*card
, multi_channel_enable
*data
)
567 B_SET_CHANNEL(data
->enable_bits
, 0, true);
568 B_SET_CHANNEL(data
->enable_bits
, 1, true);
569 B_SET_CHANNEL(data
->enable_bits
, 2, true);
570 B_SET_CHANNEL(data
->enable_bits
, 3, true);
571 data
->lock_source
= B_MULTI_LOCK_INTERNAL
;
575 uint32 timecode_source;
583 echo_set_enabled_channels(echo_dev
*card
, multi_channel_enable
*data
)
585 PRINT(("set_enabled_channels 0 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 0) ? "enabled": "disabled"));
586 PRINT(("set_enabled_channels 1 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 1) ? "enabled": "disabled"));
587 PRINT(("set_enabled_channels 2 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 2) ? "enabled": "disabled"));
588 PRINT(("set_enabled_channels 3 : %s\n", B_TEST_CHANNEL(data
->enable_bits
, 3) ? "enabled": "disabled"));
594 echo_get_global_format(echo_dev
*card
, multi_format_info
*data
)
596 data
->output_latency
= 0;
597 data
->input_latency
= 0;
598 data
->timecode_kind
= 0;
599 switch (current_settings
.sample_rate
) {
600 case 192000: data
->output
.rate
= data
->input
.rate
= B_SR_192000
; break;
601 case 96000: data
->output
.rate
= data
->input
.rate
= B_SR_96000
; break;
602 case 48000: data
->output
.rate
= data
->input
.rate
= B_SR_48000
; break;
603 case 44100: data
->output
.rate
= data
->input
.rate
= B_SR_44100
; break;
605 switch (current_settings
.bitsPerSample
) {
606 case 8: data
->input
.format
= data
->output
.format
= B_FMT_8BIT_U
; break;
607 case 16: data
->input
.format
= data
->output
.format
= B_FMT_16BIT
; break;
608 case 24: data
->input
.format
= data
->output
.format
= B_FMT_24BIT
; break;
609 case 32: data
->input
.format
= data
->output
.format
= B_FMT_32BIT
; break;
611 data
->input
.cvsr
= data
->output
.cvsr
= current_settings
.sample_rate
;
617 echo_get_buffers(echo_dev
*card
, multi_buffer_list
*data
)
619 int32 i
, j
, channels
;
622 LOG(("flags = %#x\n",data
->flags
));
623 LOG(("request_playback_buffers = %#x\n",data
->request_playback_buffers
));
624 LOG(("request_playback_channels = %#x\n",data
->request_playback_channels
));
625 LOG(("request_playback_buffer_size = %#x\n",data
->request_playback_buffer_size
));
626 LOG(("request_record_buffers = %#x\n",data
->request_record_buffers
));
627 LOG(("request_record_channels = %#x\n",data
->request_record_channels
));
628 LOG(("request_record_buffer_size = %#x\n",data
->request_record_buffer_size
));
630 if (data
->request_playback_buffers
< current_settings
.buffer_count
||
631 data
->request_record_buffers
< current_settings
.buffer_count
) {
632 LOG(("not enough channels/buffers\n"));
635 ASSERT(current_settings
.buffer_count
== 2);
637 data
->flags
= B_MULTI_BUFFER_PLAYBACK
| B_MULTI_BUFFER_RECORD
; // XXX ???
639 data
->return_playback_buffers
= current_settings
.buffer_count
; /* playback_buffers[b][] */
640 data
->return_playback_channels
= 0; /* playback_buffers[][c] */
641 data
->return_playback_buffer_size
= current_settings
.buffer_frames
; /* frames */
643 LIST_FOREACH(stream
, &card
->streams
, next
) {
644 if ((stream
->use
& ECHO_USE_PLAY
) == 0)
646 LOG(("get_buffers pipe %d\n", stream
->pipe
));
647 channels
= data
->return_playback_channels
;
648 data
->return_playback_channels
+= stream
->channels
;
649 if (data
->request_playback_channels
< data
->return_playback_channels
) {
650 LOG(("not enough channels\n"));
652 for (i
= 0; i
< current_settings
.buffer_count
; i
++)
653 for (j
=0; j
<stream
->channels
; j
++)
654 echo_stream_get_nth_buffer(stream
, j
, i
,
655 &data
->playback_buffers
[i
][channels
+j
].base
,
656 &data
->playback_buffers
[i
][channels
+j
].stride
);
659 data
->return_record_buffers
= current_settings
.buffer_count
;
660 data
->return_record_channels
= 0;
661 data
->return_record_buffer_size
= current_settings
.buffer_frames
; /* frames */
663 LIST_FOREACH(stream
, &card
->streams
, next
) {
664 if ((stream
->use
& ECHO_USE_PLAY
) != 0)
666 LOG(("get_buffers pipe %d\n", stream
->pipe
));
667 channels
= data
->return_record_channels
;
668 data
->return_record_channels
+= stream
->channels
;
669 if (data
->request_record_channels
< data
->return_record_channels
) {
670 LOG(("not enough channels\n"));
672 for (i
= 0; i
< current_settings
.buffer_count
; i
++)
673 for (j
= 0; j
< stream
->channels
; j
++)
674 echo_stream_get_nth_buffer(stream
, j
, i
,
675 &data
->record_buffers
[i
][channels
+ j
].base
,
676 &data
->record_buffers
[i
][channels
+ j
].stride
);
684 echo_play_inth(void* inthparams
)
686 echo_stream
*stream
= (echo_stream
*)inthparams
;
689 //TRACE(("echo_play_inth\n"));
691 acquire_spinlock(&slock
);
692 stream
->real_time
= system_time();
693 stream
->frames_count
+= current_settings
.buffer_frames
;
694 stream
->buffer_cycle
= (stream
->trigblk
695 + stream
->blkmod
) % stream
->blkmod
;
696 stream
->update_needed
= true;
697 release_spinlock(&slock
);
699 //get_sem_count(stream->card->buffer_ready_sem, &count);
701 release_sem_etc(stream
->card
->buffer_ready_sem
, 1, B_DO_NOT_RESCHEDULE
);
706 echo_record_inth(void* inthparams
)
708 echo_stream
*stream
= (echo_stream
*)inthparams
;
711 //TRACE(("echo_record_inth\n"));
713 acquire_spinlock(&slock
);
714 stream
->real_time
= system_time();
715 stream
->frames_count
+= current_settings
.buffer_frames
;
716 stream
->buffer_cycle
= (stream
->trigblk
717 + stream
->blkmod
- 1) % stream
->blkmod
;
718 stream
->update_needed
= true;
719 release_spinlock(&slock
);
721 //get_sem_count(stream->card->buffer_ready_sem, &count);
723 release_sem_etc(stream
->card
->buffer_ready_sem
, 1, B_DO_NOT_RESCHEDULE
);
728 echo_buffer_exchange(echo_dev
*card
, multi_buffer_info
*data
)
731 echo_stream
*pstream
, *rstream
, *stream
;
732 multi_buffer_info buffer_info
;
735 if (user_memcpy(&buffer_info
, data
, sizeof(buffer_info
)) < B_OK
)
736 return B_BAD_ADDRESS
;
738 memcpy(&buffer_info
, data
, sizeof(buffer_info
));
741 buffer_info
.flags
= B_MULTI_BUFFER_PLAYBACK
| B_MULTI_BUFFER_RECORD
;
743 LIST_FOREACH(stream
, &card
->streams
, next
) {
744 if ((stream
->state
& ECHO_STATE_STARTED
) != 0)
746 echo_stream_start(stream
,
747 ((stream
->use
& ECHO_USE_PLAY
) == 0) ? echo_record_inth
: echo_play_inth
, stream
);
750 if (acquire_sem_etc(card
->buffer_ready_sem
, 1, B_RELATIVE_TIMEOUT
| B_CAN_INTERRUPT
, 50000)
752 LOG(("buffer_exchange timeout ff\n"));
757 LIST_FOREACH(pstream
, &card
->streams
, next
) {
758 if ((pstream
->use
& ECHO_USE_PLAY
) == 0 ||
759 (pstream
->state
& ECHO_STATE_STARTED
) == 0)
761 if (pstream
->update_needed
)
765 LIST_FOREACH(rstream
, &card
->streams
, next
) {
766 if ((rstream
->use
& ECHO_USE_RECORD
) == 0 ||
767 (rstream
->state
& ECHO_STATE_STARTED
) == 0)
769 if (rstream
->update_needed
)
774 pstream
= card
->pstream
;
776 rstream
= card
->rstream
;
779 buffer_info
.playback_buffer_cycle
= pstream
->buffer_cycle
;
780 buffer_info
.played_real_time
= pstream
->real_time
;
781 buffer_info
.played_frames_count
= pstream
->frames_count
;
782 buffer_info
._reserved_0
= pstream
->first_channel
;
783 pstream
->update_needed
= false;
786 buffer_info
.record_buffer_cycle
= rstream
->buffer_cycle
;
787 buffer_info
.recorded_frames_count
= rstream
->frames_count
;
788 buffer_info
.recorded_real_time
= rstream
->real_time
;
789 buffer_info
._reserved_1
= rstream
->first_channel
;
790 rstream
->update_needed
= false;
794 if (user_memcpy(data
, &buffer_info
, sizeof(buffer_info
)) < B_OK
)
795 return B_BAD_ADDRESS
;
797 memcpy(data
, &buffer_info
, sizeof(buffer_info
));
800 //TRACE(("buffer_exchange ended\n"));
806 echo_buffer_force_stop(echo_dev
*card
)
808 //echo_voice_halt(card->pvoice);
814 echo_multi_control(void *cookie
, uint32 op
, void *data
, size_t length
)
816 echo_dev
*card
= (echo_dev
*)cookie
;
820 if (card
->plugged
== false) {
821 LOG(("device %s unplugged\n", card
->name
));
827 case B_MULTI_GET_DESCRIPTION
:
828 LOG(("B_MULTI_GET_DESCRIPTION\n"));
829 return echo_get_description(card
, (multi_description
*)data
);
830 case B_MULTI_GET_EVENT_INFO
:
831 LOG(("B_MULTI_GET_EVENT_INFO\n"));
833 case B_MULTI_SET_EVENT_INFO
:
834 LOG(("B_MULTI_SET_EVENT_INFO\n"));
836 case B_MULTI_GET_EVENT
:
837 LOG(("B_MULTI_GET_EVENT\n"));
839 case B_MULTI_GET_ENABLED_CHANNELS
:
840 LOG(("B_MULTI_GET_ENABLED_CHANNELS\n"));
841 return echo_get_enabled_channels(card
, (multi_channel_enable
*)data
);
842 case B_MULTI_SET_ENABLED_CHANNELS
:
843 LOG(("B_MULTI_SET_ENABLED_CHANNELS\n"));
844 return echo_set_enabled_channels(card
, (multi_channel_enable
*)data
);
845 case B_MULTI_GET_GLOBAL_FORMAT
:
846 LOG(("B_MULTI_GET_GLOBAL_FORMAT\n"));
847 return echo_get_global_format(card
, (multi_format_info
*)data
);
848 case B_MULTI_SET_GLOBAL_FORMAT
:
849 LOG(("B_MULTI_SET_GLOBAL_FORMAT\n"));
850 return B_OK
; /* XXX BUG! we *MUST* return B_OK, returning B_ERROR will prevent
851 * BeOS to accept the format returned in B_MULTI_GET_GLOBAL_FORMAT
853 case B_MULTI_GET_CHANNEL_FORMATS
:
854 LOG(("B_MULTI_GET_CHANNEL_FORMATS\n"));
856 case B_MULTI_SET_CHANNEL_FORMATS
: /* only implemented if possible */
857 LOG(("B_MULTI_SET_CHANNEL_FORMATS\n"));
859 case B_MULTI_GET_MIX
:
860 LOG(("B_MULTI_GET_MIX\n"));
861 return echo_get_mix(card
, (multi_mix_value_info
*)data
);
862 case B_MULTI_SET_MIX
:
863 LOG(("B_MULTI_SET_MIX\n"));
864 return echo_set_mix(card
, (multi_mix_value_info
*)data
);
865 case B_MULTI_LIST_MIX_CHANNELS
:
866 LOG(("B_MULTI_LIST_MIX_CHANNELS\n"));
867 return echo_list_mix_channels(card
, (multi_mix_channel_info
*)data
);
868 case B_MULTI_LIST_MIX_CONTROLS
:
869 LOG(("B_MULTI_LIST_MIX_CONTROLS\n"));
870 return echo_list_mix_controls(card
, (multi_mix_control_info
*)data
);
871 case B_MULTI_LIST_MIX_CONNECTIONS
:
872 LOG(("B_MULTI_LIST_MIX_CONNECTIONS\n"));
873 return echo_list_mix_connections(card
, (multi_mix_connection_info
*)data
);
874 case B_MULTI_GET_BUFFERS
: /* Fill out the struct for the first time; doesn't start anything. */
875 LOG(("B_MULTI_GET_BUFFERS\n"));
876 return echo_get_buffers(card
, (multi_buffer_list
*)data
);
877 case B_MULTI_SET_BUFFERS
: /* Set what buffers to use, if the driver supports soft buffers. */
878 LOG(("B_MULTI_SET_BUFFERS\n"));
879 return B_ERROR
; /* we do not support soft buffers */
880 case B_MULTI_SET_START_TIME
: /* When to actually start */
881 LOG(("B_MULTI_SET_START_TIME\n"));
883 case B_MULTI_BUFFER_EXCHANGE
: /* stop and go are derived from this being called */
884 //TRACE(("B_MULTI_BUFFER_EXCHANGE\n"));
885 return echo_buffer_exchange(card
, (multi_buffer_info
*)data
);
886 case B_MULTI_BUFFER_FORCE_STOP
: /* force stop of playback, nothing in data */
887 LOG(("B_MULTI_BUFFER_FORCE_STOP\n"));
888 return echo_buffer_force_stop(card
);
890 LOG(("ERROR: unknown multi_control %#x\n",op
));
895 static status_t
echo_open(const char *name
, uint32 flags
, void** cookie
);
896 static status_t
echo_close(void* cookie
);
897 static status_t
echo_free(void* cookie
);
898 static status_t
echo_control(void* cookie
, uint32 op
, void* arg
, size_t len
);
899 static status_t
echo_read(void* cookie
, off_t position
, void *buf
, size_t* num_bytes
);
900 static status_t
echo_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
);
903 device_hooks multi_hooks
= {
904 echo_open
, /* -> open entry point */
905 echo_close
, /* -> close entry point */
906 echo_free
, /* -> free cookie */
907 echo_control
, /* -> control entry point */
908 echo_read
, /* -> read entry point */
909 echo_write
, /* -> write entry point */
910 NULL
, /* start select */
911 NULL
, /* stop select */
912 NULL
, /* scatter-gather read from the device */
913 NULL
/* scatter-gather write to the device */
918 echo_open(const char *name
, uint32 flags
, void** cookie
)
920 echo_dev
*card
= NULL
;
921 int i
, first_record_channel
;
922 echo_stream
*stream
= NULL
;
924 LOG(("echo_open()\n"));
927 LIST_FOREACH(card
, &devices
, next
) {
928 if (!strcmp(card
->name
, name
)) {
933 for (i
= 0; i
< num_cards
; i
++) {
934 if (!strcmp(cards
[i
].name
, name
)) {
941 LOG(("open() card not found %s\n", name
));
943 LIST_FOREACH(card
, &devices
, next
) {
944 LOG(("open() card available %s\n", card
->name
));
947 for (int ix
=0; ix
<num_cards
; ix
++) {
948 LOG(("open() card available %s\n", cards
[ix
].name
));
955 if (card
->plugged
== false) {
956 LOG(("device %s unplugged\n", name
));
961 LOG(("open() got card\n"));
963 if (card
->pstream
!= NULL
)
965 if (card
->rstream
!= NULL
)
969 card
->multi
.card
= card
;
974 void *settings_handle
;
975 // get driver settings
976 settings_handle
= load_driver_settings ("echo.settings");
977 if (settings_handle
!= NULL
) {
982 item
= get_driver_parameter (settings_handle
, "channels", NULL
, NULL
);
984 value
= strtoul (item
, &end
, 0);
985 if (*end
== '\0') current_settings
.channels
= value
;
987 PRINT(("channels %u\n", current_settings
.channels
));
989 item
= get_driver_parameter (settings_handle
, "bitsPerSample", NULL
, NULL
);
991 value
= strtoul (item
, &end
, 0);
992 if (*end
== '\0') current_settings
.bitsPerSample
= value
;
994 PRINT(("bitsPerSample %u\n", current_settings
.bitsPerSample
));
996 item
= get_driver_parameter (settings_handle
, "sample_rate", NULL
, NULL
);
998 value
= strtoul (item
, &end
, 0);
999 if (*end
== '\0') current_settings
.sample_rate
= value
;
1001 PRINT(("sample_rate %" B_PRIu32
"\n", current_settings
.sample_rate
));
1003 item
= get_driver_parameter (settings_handle
, "buffer_frames", NULL
, NULL
);
1005 value
= strtoul (item
, &end
, 0);
1006 if (*end
== '\0') current_settings
.buffer_frames
= value
;
1008 PRINT(("buffer_frames %" B_PRIu32
"\n", current_settings
.buffer_frames
));
1010 item
= get_driver_parameter (settings_handle
, "buffer_count", NULL
, NULL
);
1012 value
= strtoul (item
, &end
, 0);
1013 if (*end
== '\0') current_settings
.buffer_count
= value
;
1015 PRINT(("buffer_count %" B_PRId32
"\n", current_settings
.buffer_count
));
1017 unload_driver_settings (settings_handle
);
1020 LOG(("creating play streams\n"));
1022 i
= card
->caps
.wNumPipesOut
- 2;
1023 first_record_channel
= card
->caps
.wNumPipesOut
;
1024 #ifdef ECHO3G_FAMILY
1025 if (current_settings
.sample_rate
> 50000) {
1026 i
= card
->caps
.wFirstDigitalBusOut
;
1027 first_record_channel
= card
->caps
.wFirstDigitalBusOut
+ 2;
1031 for (; i
>= 0 ; i
-= 2) {
1032 stream
= echo_stream_new(card
, ECHO_USE_PLAY
, current_settings
.buffer_frames
, current_settings
.buffer_count
);
1034 card
->pstream
= stream
;
1035 echo_stream_set_audioparms(stream
, current_settings
.channels
,
1036 current_settings
.bitsPerSample
, current_settings
.sample_rate
, i
);
1037 stream
->first_channel
= i
;
1040 LOG(("creating record streams\n"));
1041 i
= card
->caps
.wNumPipesIn
- 2;
1042 #ifdef ECHO3G_FAMILY
1043 if (current_settings
.sample_rate
> 50000) {
1044 i
= card
->caps
.wFirstDigitalBusIn
;
1048 for (; i
>= 0; i
-=2) {
1049 stream
= echo_stream_new(card
, ECHO_USE_RECORD
, current_settings
.buffer_frames
, current_settings
.buffer_count
);
1051 card
->rstream
= stream
;
1052 echo_stream_set_audioparms(stream
, current_settings
.channels
,
1053 current_settings
.bitsPerSample
, current_settings
.sample_rate
, i
);
1054 stream
->first_channel
= i
+ first_record_channel
;
1057 card
->buffer_ready_sem
= create_sem(0, "pbuffer ready");
1059 LOG(("creating channels list\n"));
1060 echo_create_channels_list(&card
->multi
);
1067 echo_close(void* cookie
)
1071 echo_dev
*card
= (echo_dev
*) cookie
;
1072 card
->opened
= false;
1080 echo_free(void* cookie
)
1082 echo_dev
*card
= (echo_dev
*) cookie
;
1083 echo_stream
*stream
;
1084 LOG(("echo_free()\n"));
1086 if (card
->buffer_ready_sem
> B_OK
)
1087 delete_sem(card
->buffer_ready_sem
);
1089 LIST_FOREACH(stream
, &card
->streams
, next
) {
1090 echo_stream_halt(stream
);
1093 while (!LIST_EMPTY(&card
->streams
)) {
1094 echo_stream_delete(LIST_FIRST(&card
->streams
));
1097 card
->pstream
= NULL
;
1098 card
->rstream
= NULL
;
1105 echo_control(void* cookie
, uint32 op
, void* arg
, size_t len
)
1107 return echo_multi_control(cookie
, op
, arg
, len
);
1112 echo_read(void* cookie
, off_t position
, void *buf
, size_t* num_bytes
)
1114 *num_bytes
= 0; /* tell caller nothing was read */
1120 echo_write(void* cookie
, off_t position
, const void* buffer
, size_t* num_bytes
)
1122 *num_bytes
= 0; /* tell caller nothing was written */