📄 vx_mixer.c
字号:
static int vx_audio_src_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); down(&chip->mixer_mutex); if (chip->audio_source_target != ucontrol->value.enumerated.item[0]) { chip->audio_source_target = ucontrol->value.enumerated.item[0]; vx_sync_audio_source(chip); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static snd_kcontrol_new_t vx_control_audio_src = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", .info = vx_audio_src_info, .get = vx_audio_src_get, .put = vx_audio_src_put,};/* * clock mode selection */static int vx_clock_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ static char *texts[3] = { "Auto", "Internal", "External" }; uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 1; uinfo->value.enumerated.items = 3; if (uinfo->value.enumerated.item > 2) uinfo->value.enumerated.item = 2; strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); return 0;}static int vx_clock_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); ucontrol->value.enumerated.item[0] = chip->clock_mode; return 0;}static int vx_clock_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); down(&chip->mixer_mutex); if (chip->clock_mode != ucontrol->value.enumerated.item[0]) { chip->clock_mode = ucontrol->value.enumerated.item[0]; vx_set_clock(chip, chip->freq); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static snd_kcontrol_new_t vx_control_clock_mode = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Clock Mode", .info = vx_clock_mode_info, .get = vx_clock_mode_get, .put = vx_clock_mode_put,};/* * Audio Gain */static int vx_audio_gain_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = CVAL_MAX; return 0;}static int vx_audio_gain_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; down(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_gain[capture][audio]; ucontrol->value.integer.value[1] = chip->audio_gain[capture][audio+1]; up(&chip->mixer_mutex); return 0;}static int vx_audio_gain_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; down(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_gain[capture][audio] || ucontrol->value.integer.value[1] != chip->audio_gain[capture][audio+1]) { vx_set_audio_gain(chip, audio, capture, ucontrol->value.integer.value[0]); vx_set_audio_gain(chip, audio+1, capture, ucontrol->value.integer.value[1]); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static int vx_audio_monitor_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor[audio+1]; up(&chip->mixer_mutex); return 0;}static int vx_audio_monitor_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_monitor[audio] || ucontrol->value.integer.value[1] != chip->audio_monitor[audio+1]) { vx_set_monitor_level(chip, audio, ucontrol->value.integer.value[0], chip->audio_monitor_active[audio]); vx_set_monitor_level(chip, audio+1, ucontrol->value.integer.value[1], chip->audio_monitor_active[audio+1]); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static int vx_audio_sw_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int vx_audio_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_active[audio]; ucontrol->value.integer.value[1] = chip->audio_active[audio+1]; up(&chip->mixer_mutex); return 0;}static int vx_audio_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_active[audio] || ucontrol->value.integer.value[1] != chip->audio_active[audio+1]) { vx_set_audio_switch(chip, audio, ucontrol->value.integer.value[0]); vx_set_audio_switch(chip, audio+1, ucontrol->value.integer.value[1]); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static int vx_monitor_sw_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); ucontrol->value.integer.value[0] = chip->audio_monitor_active[audio]; ucontrol->value.integer.value[1] = chip->audio_monitor_active[audio+1]; up(&chip->mixer_mutex); return 0;}static int vx_monitor_sw_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); int audio = kcontrol->private_value & 0xff; down(&chip->mixer_mutex); if (ucontrol->value.integer.value[0] != chip->audio_monitor_active[audio] || ucontrol->value.integer.value[1] != chip->audio_monitor_active[audio+1]) { vx_set_monitor_level(chip, audio, chip->audio_monitor[audio], ucontrol->value.integer.value[0]); vx_set_monitor_level(chip, audio+1, chip->audio_monitor[audio+1], ucontrol->value.integer.value[1]); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static snd_kcontrol_new_t vx_control_audio_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, /* name will be filled later */ .info = vx_audio_gain_info, .get = vx_audio_gain_get, .put = vx_audio_gain_put};static snd_kcontrol_new_t vx_control_output_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "PCM Playback Switch", .info = vx_audio_sw_info, .get = vx_audio_sw_get, .put = vx_audio_sw_put};static snd_kcontrol_new_t vx_control_monitor_gain = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Volume", .info = vx_audio_gain_info, /* shared */ .get = vx_audio_monitor_get, .put = vx_audio_monitor_put};static snd_kcontrol_new_t vx_control_monitor_switch = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Monitoring Switch", .info = vx_audio_sw_info, /* shared */ .get = vx_monitor_sw_get, .put = vx_monitor_sw_put};/* * IEC958 status bits */static int vx_iec958_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; uinfo->count = 1; return 0;}static int vx_iec958_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); down(&chip->mixer_mutex); ucontrol->value.iec958.status[0] = (chip->uer_bits >> 0) & 0xff; ucontrol->value.iec958.status[1] = (chip->uer_bits >> 8) & 0xff; ucontrol->value.iec958.status[2] = (chip->uer_bits >> 16) & 0xff; ucontrol->value.iec958.status[3] = (chip->uer_bits >> 24) & 0xff; up(&chip->mixer_mutex); return 0;}static int vx_iec958_mask_get(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t *ucontrol){ ucontrol->value.iec958.status[0] = 0xff; ucontrol->value.iec958.status[1] = 0xff; ucontrol->value.iec958.status[2] = 0xff; ucontrol->value.iec958.status[3] = 0xff; return 0;}static int vx_iec958_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); unsigned int val; val = (ucontrol->value.iec958.status[0] << 0) | (ucontrol->value.iec958.status[1] << 8) | (ucontrol->value.iec958.status[2] << 16) | (ucontrol->value.iec958.status[3] << 24); down(&chip->mixer_mutex); if (chip->uer_bits != val) { chip->uer_bits = val; vx_set_iec958_status(chip, val); up(&chip->mixer_mutex); return 1; } up(&chip->mixer_mutex); return 0;}static snd_kcontrol_new_t vx_control_iec958_mask = { .access = SNDRV_CTL_ELEM_ACCESS_READ, .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,MASK), .info = vx_iec958_info, /* shared */ .get = vx_iec958_mask_get,};static snd_kcontrol_new_t vx_control_iec958 = { .iface = SNDRV_CTL_ELEM_IFACE_PCM, .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), .info = vx_iec958_info, .get = vx_iec958_get, .put = vx_iec958_put};/* * VU meter */#define METER_MAX 0xff#define METER_SHIFT 16static int vx_vu_meter_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = METER_MAX; return 0;}static int vx_vu_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); struct vx_vu_meter meter[2]; int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; vx_get_audio_vu_meter(chip, audio, capture, meter); ucontrol->value.integer.value[0] = meter[0].vu_level >> METER_SHIFT; ucontrol->value.integer.value[1] = meter[1].vu_level >> METER_SHIFT; return 0;}static int vx_peak_meter_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); struct vx_vu_meter meter[2]; int audio = kcontrol->private_value & 0xff; int capture = (kcontrol->private_value >> 8) & 1; vx_get_audio_vu_meter(chip, audio, capture, meter); ucontrol->value.integer.value[0] = meter[0].peak_level >> METER_SHIFT; ucontrol->value.integer.value[1] = meter[1].peak_level >> METER_SHIFT; return 0;}static int vx_saturation_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo){ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; uinfo->count = 2; uinfo->value.integer.min = 0; uinfo->value.integer.max = 1; return 0;}static int vx_saturation_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol){ vx_core_t *chip = snd_kcontrol_chip(kcontrol); struct vx_vu_meter meter[2]; int audio = kcontrol->private_value & 0xff; vx_get_audio_vu_meter(chip, audio, 1, meter); /* capture only */ ucontrol->value.integer.value[0] = meter[0].saturated; ucontrol->value.integer.value[1] = meter[1].saturated; return 0;}static snd_kcontrol_new_t vx_control_vu_meter = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, /* name will be filled later */ .info = vx_vu_meter_info, .get = vx_vu_meter_get,};static snd_kcontrol_new_t vx_control_peak_meter = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, /* name will be filled later */ .info = vx_vu_meter_info, /* shared */ .get = vx_peak_meter_get,};static snd_kcontrol_new_t vx_control_saturation = { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Input Saturation", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, .info = vx_saturation_info, .get = vx_saturation_get,};/* * */int snd_vx_mixer_new(vx_core_t *chip){ unsigned int i, c; int err; snd_kcontrol_new_t temp; snd_card_t *card = chip->card; char name[32]; strcpy(card->mixername, card->driver); /* output level controls */ for (i = 0; i < chip->hw->num_outs; i++) { temp = vx_control_output_level; temp.index = i; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } /* PCM volumes, switches, monitoring */ for (i = 0; i < chip->hw->num_outs; i++) { int val = i * 2; temp = vx_control_audio_gain; temp.index = i; temp.name = "PCM Playback Volume"; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; temp = vx_control_output_switch; temp.index = i; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; temp = vx_control_monitor_gain; temp.index = i; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; temp = vx_control_monitor_switch; temp.index = i; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } for (i = 0; i < chip->hw->num_outs; i++) { temp = vx_control_audio_gain; temp.index = i; temp.name = "PCM Capture Volume"; temp.private_value = (i * 2) | (1 << 8); if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } /* Audio source */ if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_audio_src, chip))) < 0) return err; /* clock mode */ if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_clock_mode, chip))) < 0) return err; /* IEC958 controls */ if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958_mask, chip))) < 0) return err; if ((err = snd_ctl_add(card, snd_ctl_new1(&vx_control_iec958, chip))) < 0) return err; /* VU, peak, saturation meters */ for (c = 0; c < 2; c++) { static char *dir[2] = { "Output", "Input" }; for (i = 0; i < chip->hw->num_ins; i++) { int val = (i * 2) | (c << 8); if (c == 1) { temp = vx_control_saturation; temp.index = i; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } sprintf(name, "%s VU Meter", dir[c]); temp = vx_control_vu_meter; temp.index = i; temp.name = name; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; sprintf(name, "%s Peak Meter", dir[c]); temp = vx_control_peak_meter; temp.index = i; temp.name = name; temp.private_value = val; if ((err = snd_ctl_add(card, snd_ctl_new1(&temp, chip))) < 0) return err; } } vx_reset_audio_levels(chip); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -