//This will create a Tab static int32 create_group_control(multi_mix_control **p_mmc, int32 index, int32 parent, enum strind_id string, const char* name) { multi_mix_control *mmc = *p_mmc; int32 group; TRACE_VV("Create ID create_group_control\n"); mmc->id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_SET_INDEX(index); mmc->parent = parent; mmc->flags = B_MULTI_MIX_GROUP; mmc->master = CONTROL_IS_MASTER; mmc->string = string; group = mmc->id; if (name != NULL) strcpy(mmc->name, name); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; (*p_mmc) = mmc; return group; }
static void set_volume_cb(ice1712 *card, multi_mix_value *mmv) { channel_volume *vol; uint32 chan = ICE1712_MULTI_GET_CHANNEL(mmv->id); TRACE_VV(" set_volume_cb\n"); if (chan < ICE1712_HARDWARE_VOLUME) { vol = card->settings.playback; } else { vol = card->settings.record; chan -= ICE1712_HARDWARE_VOLUME; } //chan is normaly <= ICE1712_HARDWARE_VOLUME switch (ICE1712_MULTI_GET_INDEX(mmv->id)) { case 0: //Mute vol[chan].mute = mmv->u.enable; vol[chan + 1].mute = mmv->u.enable; TRACE_VV("\tChange mute to %d for channel %d and %d\n", mmv->u.enable, (int)chan, (int)chan + 1); break; case 2: //Right channel chan++; //No break case 1: //Left channel vol[chan].volume = mmv->u.gain; TRACE_VV("\tChange Volume to %f for channel %d\n", mmv->u.gain, (int)chan); break; } }
status_t ice1712_set_mix(ice1712 *card, multi_mix_value_info *data) { int i; TRACE_VV(" Asking to set %ld control(s)\n", data->item_count); for (i = 0; i < data->item_count; i++) { multi_mix_value *mmv = &(data->values[i]); TRACE_VV(" Id %#x\n", (unsigned int)mmv->id); switch (mmv->id & ICE1712_MULTI_CONTROL_TYPE_MASK) { case ICE1712_MULTI_CONTROL_TYPE_COMBO: set_combo_cb(card, ICE1712_MULTI_GET_CHANNEL(mmv->id), mmv->u.mux); break; case ICE1712_MULTI_CONTROL_TYPE_VOLUME: set_volume_cb(card, mmv); break; case ICE1712_MULTI_CONTROL_TYPE_OUTPUT: set_output_cb(card, ICE1712_MULTI_GET_CHANNEL(mmv->id), mmv->u.mux); break; default: TRACE_VV(" default 0x%x\n", (unsigned int)mmv->id); break; } } return apply_settings(card); }
//This will create a Slider with a "Mute" CheckBox static void create_channel_control(multi_mix_control **p_mmc, int32 channel, int32 parent, const char* name) { int32 id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_TYPE_VOLUME + ICE1712_MULTI_SET_CHANNEL(channel); multi_mix_control *mmc = *p_mmc; multi_mix_control control; TRACE_VV("Create ID create_channel_control\n"); control.master = CONTROL_IS_MASTER; control.parent = parent; control.u.gain.max_gain = 0.0; control.u.gain.min_gain = -144.0; control.u.gain.granularity = 1.5; //The Mute Checkbox control.id = id++; control.flags = B_MULTI_MIX_ENABLE; control.string = S_MUTE; *mmc = control; mmc++; TRACE_VV("Create ID %#x\n", (unsigned int)control.id); //The Left Slider control.string = S_null; control.id = id++; control.flags = B_MULTI_MIX_GAIN; if (name != NULL) strcpy(control.name, name); *mmc = control; mmc++; TRACE_VV("Create ID %#x\n", (unsigned int)control.id); //The Right Slider control.master = control.id; //The Id of the Left Slider control.id = id++; *mmc = control; mmc++; TRACE_VV("Create ID %#x\n", (unsigned int)control.id); nb_control_created += 3; (*p_mmc) = mmc; }
static void set_combo_cb(ice1712 *card, uint32 index, uint32 value) { TRACE_VV(" set_combo_cb: %ld, %ld\n", index, value); switch (index) { case 0: if (value < 2) card->settings.clock = value; break; case 1: if (value < 2) card->settings.outFormat = value; break; case 2: if (value < 3) card->settings.emphasis = value; break; case 3: if (value < 3) card->settings.copyMode = value; break; } }
static uint32 get_combo_cb(ice1712 *card, uint32 index) { uint32 value = 0; TRACE_VV(" get_combo_cb: %ld, %ld\n", index, value); switch (index) { case 0: value = card->settings.clock; break; case 1: value = card->settings.outFormat; break; case 2: value = card->settings.emphasis; break; case 3: value = card->settings.copyMode; break; } return value; }
static void set_output_cb(ice1712 *card, uint32 index, uint32 value) { if (index < 5) card->settings.output[index] = value; TRACE_VV(" set_output_cb: %ld, %ld\n", index, value); }
static uint32 get_output_cb(ice1712 *card, uint32 index) { uint32 value = 0; if (index < 5) value = card->settings.output[index]; TRACE_VV(" get_output_cb: %ld, %ld\n", index, value); return value; }
static void create_combo_control(multi_mix_control **p_mmc, const char *values[], int32 parent, int32 nb_combo, const char *name) { int32 id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_TYPE_COMBO + ICE1712_MULTI_SET_CHANNEL(nb_combo); multi_mix_control *mmc = *p_mmc; int32 parentControl, i; TRACE_VV("Create ID create_combo_control\n"); //The label parentControl = mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX; mmc->parent = parent; strcpy(mmc->name, name); TRACE_VV("Create ID %#x\n", (unsigned int)parentControl); nb_control_created++; mmc++; //The values for (i = 0; values[i] != NULL; i++) { mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX_VALUE; mmc->parent = parentControl; strcpy(mmc->name, values[i]); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; } (*p_mmc) = mmc; }
status_t applySettings(ice1712 *card) { int i; uint16 val, mt30 = 0; uint32 mt34 = 0; for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) { //Select the channel write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i); if (card->settings.playback[i].mute == true) { val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8); } else { unsigned char volume = card->settings.playback[i].volume / -1.5; if (i & 1) {//a right channel val = ICE1712_MUTE_VALUE << 0; //Mute left volume val |= volume << 8; } else {//a left channel val = ICE1712_MUTE_VALUE << 8; //Mute right volume val |= volume << 0; } } write_mt_uint16(card, MT_LR_VOLUME_CONTROL, val); TRACE_VV("Apply Settings %d : 0x%x\n", i, val); } for (i = 0; i < ICE1712_HARDWARE_VOLUME; i++) { //Select the channel write_mt_uint8(card, MT_VOLUME_CONTROL_CHANNEL_INDEX, i + ICE1712_HARDWARE_VOLUME); if (card->settings.record[i].mute == true) { val = (ICE1712_MUTE_VALUE << 0) | (ICE1712_MUTE_VALUE << 8); } else { uint8 volume = card->settings.record[i].volume / -1.5; if (i & 1) {//a right channel val = ICE1712_MUTE_VALUE << 0; //Mute left volume val |= volume << 8; } else {//a left channel val = ICE1712_MUTE_VALUE << 8; //Mute right volume val |= volume << 0; } } write_mt_uint16(card, MT_LR_VOLUME_CONTROL, val); TRACE_VV("Apply Settings %d : 0x%x\n", i, val); } //Analog output selection for (i = 0; i < 4; i++) { uint8 out = card->settings.output[i]; if (out == 0) { TRACE_VV("Output %d is haiku output\n", i); //Nothing to do } else if (out <= (card->config.nb_ADC / 2)) { uint8 mt34_c; out--; TRACE_VV("Output %d is input %d\n", i, out); mt34_c = (out * 2); mt34_c |= (out * 2 + 1) << 4; mt30 |= 0x0202 << (2*i); mt30 |= mt34_c << (8*i); } else if (out == ((card->config.nb_ADC / 2) + 1) && (card->config.spdif & SPDIF_IN_PRESENT) != 0) { TRACE_VV("Output %d is digital input\n", i); mt30 |= 0x0303 << (2*i); mt34 |= 0x80 << (8*i); } else { TRACE_VV("Output %d is digital Mixer\n", i); mt30 |= 0x0101; } } write_mt_uint16(card, MT_ROUTING_CONTROL_PSDOUT, mt30); write_mt_uint32(card, MT_CAPTURED_DATA, mt34); //Digital output if ((card->config.spdif & SPDIF_OUT_PRESENT) != 0) { uint16 mt32 = 0; uint8 out = card->settings.output[4]; if (out == 0) { TRACE_VV("Digital output is haiku output\n"); //Nothing to do } else if (out <= (card->config.nb_ADC / 2)) { out--; TRACE_VV("Digital output is input %d\n", out); mt32 |= 0x0202; mt32 |= (out * 2) << 8; mt32 |= (out * 2 + 1) << 12; } else if (out == ((card->config.nb_ADC / 2) + 1) && (card->config.spdif & SPDIF_IN_PRESENT) != 0) { TRACE_VV("Digital output is digital input\n"); mt32 |= 0x800F; } else { TRACE_VV("Digital output is digital Mixer\n"); mt32 |= 0x0005; } write_mt_uint16(card, MT_ROUTING_CONTROL_SPDOUT, mt32); } return B_OK; }
status_t ice1712_get_buffers(ice1712 *card, multi_buffer_list *data) { int buff, chan_i = 0, chan_o = 0; TRACE_VV("flags = %#lx\n", data->flags); TRACE_VV("request_playback_buffers = %ld\n", data->request_playback_buffers); TRACE_VV("request_playback_channels = %ld\n", data->request_playback_channels); TRACE_VV("request_playback_buffer_size = %lx\n", data->request_playback_buffer_size); TRACE_VV("request_record_buffers = %ld\n", data->request_record_buffers); TRACE_VV("request_record_channels = %ld\n", data->request_record_channels); TRACE_VV("request_record_buffer_size = %lx\n", data->request_record_buffer_size); for (buff = 0; buff < SWAPPING_BUFFERS; buff++) { uint32 stride_o = MAX_DAC * SAMPLE_SIZE; uint32 stride_i = MAX_ADC * SAMPLE_SIZE; uint32 buf_o = stride_o * card->buffer_size; uint32 buf_i = stride_i * card->buffer_size; if (data->request_playback_channels == card->total_output_channels) { for (chan_o = 0; chan_o < card->config.nb_DAC; chan_o++) { //Analog STEREO output data->playback_buffers[buff][chan_o].base = card->log_addr_pb + buf_o * buff + SAMPLE_SIZE * chan_o; data->playback_buffers[buff][chan_o].stride = stride_o; TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o, data->playback_buffers[buff][chan_o].base); } if (card->config.spdif & SPDIF_OUT_PRESENT) { //SPDIF STEREO output data->playback_buffers[buff][chan_o].base = card->log_addr_pb + buf_o * buff + SAMPLE_SIZE * SPDIF_LEFT; data->playback_buffers[buff][chan_o].stride = stride_o; TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o, data->playback_buffers[buff][chan_o].base); chan_o++; data->playback_buffers[buff][chan_o].base = card->log_addr_pb + buf_o * buff + SAMPLE_SIZE * SPDIF_RIGHT; data->playback_buffers[buff][chan_o].stride = stride_o; TRACE_VV("pb_buffer[%ld][%ld] = %p\n", buff, chan_o, data->playback_buffers[buff][chan_o].base); chan_o++; } } if (data->request_record_channels == card->total_input_channels) { for (chan_i = 0; chan_i < card->config.nb_ADC; chan_i++) { //Analog STEREO input data->record_buffers[buff][chan_i].base = card->log_addr_rec + buf_i * buff + SAMPLE_SIZE * chan_i; data->record_buffers[buff][chan_i].stride = stride_i; TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i, data->record_buffers[buff][chan_i].base); } if (card->config.spdif & SPDIF_IN_PRESENT) { //SPDIF STEREO input data->record_buffers[buff][chan_i].base = card->log_addr_rec + buf_i * buff + SAMPLE_SIZE * SPDIF_LEFT; data->record_buffers[buff][chan_i].stride = stride_i; TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i, data->record_buffers[buff][chan_i].base); chan_i++; data->record_buffers[buff][chan_i].base = card->log_addr_rec + buf_i * buff + SAMPLE_SIZE * SPDIF_RIGHT; data->record_buffers[buff][chan_i].stride = stride_i; TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i, data->record_buffers[buff][chan_i].base); chan_i++; } //The digital mixer output data->record_buffers[buff][chan_i].base = card->log_addr_rec + buf_i * buff + SAMPLE_SIZE * MIXER_OUT_LEFT; data->record_buffers[buff][chan_i].stride = stride_i; TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i, data->record_buffers[buff][chan_i].base); chan_i++; data->record_buffers[buff][chan_i].base = card->log_addr_rec + buf_i * buff + SAMPLE_SIZE * MIXER_OUT_RIGHT; data->record_buffers[buff][chan_i].stride = stride_i; TRACE_VV("rec_buffer[%ld][%ld] = %p\n", buff, chan_i, data->record_buffers[buff][chan_i].base); chan_i++; } } data->return_playback_buffers = SWAPPING_BUFFERS; data->return_playback_channels = card->total_output_channels; data->return_playback_buffer_size = card->buffer_size; TRACE("return_playback_buffers = %ld\n", data->return_playback_buffers); TRACE("return_playback_channels = %ld\n", data->return_playback_channels); TRACE("return_playback_buffer_size = %ld\n", data->return_playback_buffer_size); data->return_record_buffers = SWAPPING_BUFFERS; data->return_record_channels = card->total_input_channels; data->return_record_channels = chan_i; data->return_record_buffer_size = card->buffer_size; TRACE("return_record_buffers = %ld\n", data->return_record_buffers); TRACE("return_record_channels = %ld\n", data->return_record_channels); TRACE("return_record_buffer_size = %ld\n", data->return_record_buffer_size); start_DMA(card); return B_OK; }
status_t ice1712_list_mix_controls(ice1712 *card, multi_mix_control_info *mmci) { uint32 i, parentTab, parentTabColumn; multi_mix_control *mmc = mmci->controls; uint32 group = 0, combo = 0, channel = 0; nb_control_created = 0; TRACE_VV("count = %ld\n", mmci->control_count); //Cleaning memset(mmc, 0, mmci->control_count * sizeof(multi_mix_control)); //Setup tab parentTab = create_group_control(&mmc, group++, CONTROL_IS_MASTER, S_SETUP, NULL); //General Settings parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[1]); for (i = 0; SettingsGeneral[i] != NULL; i++) { create_combo_control(&mmc, SettingsGeneral[i], parentTabColumn, combo++, string_list[5 + i]); } //Digital Settings parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[2]); for (i = 0; SettingsDigital[i] != NULL; i++) { create_combo_control(&mmc, SettingsDigital[i], parentTabColumn, combo++, string_list[8 + i]); } //Output Selection Settings parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[3]); for (i = 0; i < card->config.nb_DAC; i += 2) { create_output_choice(card, &mmc, i / 2, parentTabColumn); } if (card->config.spdif & SPDIF_OUT_PRESENT) { create_output_choice(card, &mmc, 4, parentTabColumn); } //Internal Mixer Tab //Output parentTab = create_group_control(&mmc, group++, CONTROL_IS_MASTER, S_null, string_list[4]); for (i = 0; i < card->config.nb_DAC; i += 2) { parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[(i / 2) + 11]); create_channel_control(&mmc, channel++, parentTabColumn, NULL); } if (card->config.spdif & SPDIF_OUT_PRESENT) { parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[15]); create_channel_control(&mmc, ICE1712_HARDWARE_VOLUME - 2, parentTabColumn, NULL); } //Input channel = ICE1712_HARDWARE_VOLUME; for (i = 0; i < card->config.nb_ADC; i += 2) { parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[(i / 2) + 17]); create_channel_control(&mmc, channel++, parentTabColumn, NULL); } if (card->config.spdif & SPDIF_IN_PRESENT) { parentTabColumn = create_group_control(&mmc, group++, parentTab, S_null, string_list[21]); create_channel_control(&mmc, 2 * ICE1712_HARDWARE_VOLUME - 2, parentTabColumn, NULL); } TRACE_VV("Return %ld control(s)\n", nb_control_created); mmci->control_count = nb_control_created; return B_OK; }
//This will create all possible value for the output //output 0 -> 3 (physical stereo output) 4 is the Digital static void create_output_choice(ice1712 *card, multi_mix_control **p_mmc, int32 output, int32 parent) { int32 id = ICE1712_MULTI_CONTROL_FIRSTID + ICE1712_MULTI_CONTROL_TYPE_OUTPUT + ICE1712_MULTI_SET_CHANNEL(output); multi_mix_control *mmc = *p_mmc; int32 parentControl, i; TRACE_VV("Create ID create_output_choice\n"); //The label parentControl = mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX; mmc->parent = parent; strcpy(mmc->name, string_list[11 + output]); nb_control_created++; mmc++; TRACE_VV("Create ID %#x\n", (unsigned int)parentControl); //Haiku output mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX_VALUE; mmc->parent = parentControl; strcpy(mmc->name, string_list[16]); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; //Physical Input for (i = 0; i < card->config.nb_DAC; i += 2) { mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX_VALUE; mmc->parent = parentControl; strcpy(mmc->name, string_list[17 + (i / 2)]); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; } //Physical Digital Input if (card->config.spdif & SPDIF_IN_PRESENT) { mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX_VALUE; mmc->parent = parentControl; strcpy(mmc->name, string_list[21]); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; } //Internal mixer only for Output 1 and Digital Output if ((output == 0) || (output == 4)) { mmc->id = id++; mmc->flags = B_MULTI_MIX_MUX_VALUE; mmc->parent = parentControl; strcpy(mmc->name, string_list[22]); TRACE_VV("Create ID %#x\n", (unsigned int)mmc->id); nb_control_created++; mmc++; } (*p_mmc) = mmc; }
status_t ice1712_get_description(ice1712 *card, multi_description *data) { int chan = 0, i, size; data->interface_version = B_CURRENT_INTERFACE_VERSION; data->interface_minimum = B_CURRENT_INTERFACE_VERSION; switch (card->product) { case ICE1712_SUBDEVICE_DELTA1010: strncpy(data->friendly_name, "Delta 1010", 32); break; case ICE1712_SUBDEVICE_DELTADIO2496: strncpy(data->friendly_name, "Delta DIO 2496", 32); break; case ICE1712_SUBDEVICE_DELTA66: strncpy(data->friendly_name, "Delta 66", 32); break; case ICE1712_SUBDEVICE_DELTA44: strncpy(data->friendly_name, "Delta 44", 32); break; case ICE1712_SUBDEVICE_AUDIOPHILE_2496: strncpy(data->friendly_name, "Audiophile 2496", 32); break; case ICE1712_SUBDEVICE_DELTA410: strncpy(data->friendly_name, "Delta 410", 32); break; case ICE1712_SUBDEVICE_DELTA1010LT: strncpy(data->friendly_name, "Delta 1010 LT", 32); break; case ICE1712_SUBDEVICE_VX442: strncpy(data->friendly_name, "VX 442", 32); break; default: strncpy(data->friendly_name, "Unknow device", 32); break; } strncpy(data->vendor_info, "Haiku OS", 32); data->output_channel_count = card->total_output_channels; data->input_channel_count = card->total_input_channels; data->output_bus_channel_count = 0; data->input_bus_channel_count = 0; data->aux_bus_channel_count = 0; size = data->output_channel_count + data->input_channel_count + data->output_bus_channel_count + data->input_bus_channel_count + data->aux_bus_channel_count; TRACE_VV("request_channel_count = %ld\n", data->request_channel_count); if (size <= data->request_channel_count) { for (i = 0; i < card->config.nb_DAC; i++) { //Analog STEREO output data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | (((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT); data->channels[chan].connectors = 0; chan++; } if (card->config.spdif & SPDIF_OUT_PRESENT) { //SPDIF STEREO output data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT; data->channels[chan].connectors = 0; chan++; data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_OUTPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT; data->channels[chan].connectors = 0; chan++; } for (i = 0; i < card->config.nb_ADC; i++) { //Analog STEREO input data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | (((i & 1) == 0) ? B_CHANNEL_LEFT : B_CHANNEL_RIGHT); data->channels[chan].connectors = 0; chan++; } if (card->config.spdif & SPDIF_IN_PRESENT) { //SPDIF STEREO input data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT; data->channels[chan].connectors = 0; chan++; data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT; data->channels[chan].connectors = 0; chan++; } //The digital mixer output (it's an Input for Haiku) data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_LEFT; data->channels[chan].connectors = 0; chan++; data->channels[chan].channel_id = chan; data->channels[chan].kind = B_MULTI_INPUT_CHANNEL; data->channels[chan].designations = B_CHANNEL_STEREO_BUS | B_CHANNEL_RIGHT; data->channels[chan].connectors = 0; chan++; } TRACE("output_channel_count = %ld\n", data->output_channel_count); TRACE("input_channel_count = %ld\n", data->input_channel_count); TRACE("output_bus_channel_count = %ld\n", data->output_bus_channel_count); TRACE("input_bus_channel_count = %ld\n", data->input_bus_channel_count); data->output_rates = data->input_rates = AUTHORIZED_RATE; data->min_cvsr_rate = 44100; data->max_cvsr_rate = 96000; data->output_formats = data->input_formats = AUTHORIZED_SAMPLE_SIZE; data->lock_sources = B_MULTI_LOCK_INTERNAL | B_MULTI_LOCK_SPDIF; data->timecode_sources = 0; data->interface_flags = B_MULTI_INTERFACE_PLAYBACK | B_MULTI_INTERFACE_RECORD; data->start_latency = 0; strcpy(data->control_panel,""); return B_OK; }