📄 mixer_oss.c
字号:
#define SNDRV_MIXER_OSS_ITEM_PSWITCH 4#define SNDRV_MIXER_OSS_ITEM_PROUTE 5#define SNDRV_MIXER_OSS_ITEM_PVOLUME 6#define SNDRV_MIXER_OSS_ITEM_CSWITCH 7#define SNDRV_MIXER_OSS_ITEM_CROUTE 8#define SNDRV_MIXER_OSS_ITEM_CVOLUME 9#define SNDRV_MIXER_OSS_ITEM_CAPTURE 10#define SNDRV_MIXER_OSS_ITEM_COUNT 11#define SNDRV_MIXER_OSS_PRESENT_GLOBAL (1<<0)#define SNDRV_MIXER_OSS_PRESENT_GSWITCH (1<<1)#define SNDRV_MIXER_OSS_PRESENT_GROUTE (1<<2)#define SNDRV_MIXER_OSS_PRESENT_GVOLUME (1<<3)#define SNDRV_MIXER_OSS_PRESENT_PSWITCH (1<<4)#define SNDRV_MIXER_OSS_PRESENT_PROUTE (1<<5)#define SNDRV_MIXER_OSS_PRESENT_PVOLUME (1<<6)#define SNDRV_MIXER_OSS_PRESENT_CSWITCH (1<<7)#define SNDRV_MIXER_OSS_PRESENT_CROUTE (1<<8)#define SNDRV_MIXER_OSS_PRESENT_CVOLUME (1<<9)#define SNDRV_MIXER_OSS_PRESENT_CAPTURE (1<<10)struct slot { unsigned int signature; unsigned int present; unsigned int channels; unsigned int numid[SNDRV_MIXER_OSS_ITEM_COUNT]; unsigned int capture_item; struct snd_mixer_oss_assign_table *assigned; unsigned int allocated: 1;};#define ID_UNKNOWN ((unsigned int)-1)static snd_kcontrol_t *snd_mixer_oss_test_id(snd_mixer_oss_t *mixer, const char *name, int index){ snd_card_t * card = mixer->card; snd_ctl_elem_id_t id; memset(&id, 0, sizeof(id)); id.iface = SNDRV_CTL_ELEM_IFACE_MIXER; strcpy(id.name, name); id.index = index; return snd_ctl_find_id(card, &id);}static void snd_mixer_oss_get_volume1_vol(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, unsigned int numid, int *left, int *right){ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; snd_kcontrol_t *kctl; snd_card_t *card = fmixer->card; if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { up_read(&card->controls_rwsem); return; } uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; if (kctl->info(kctl, uinfo)) goto __unalloc; if (kctl->get(kctl, uctl)) goto __unalloc; if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) goto __unalloc; *left = snd_mixer_oss_conv1(uctl->value.integer.value[0], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[0]); if (uinfo->count > 1) *right = snd_mixer_oss_conv1(uctl->value.integer.value[1], uinfo->value.integer.min, uinfo->value.integer.max, &pslot->volume[1]); __unalloc: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo);}static void snd_mixer_oss_get_volume1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, unsigned int numid, int *left, int *right, int route){ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; snd_kcontrol_t *kctl; snd_card_t *card = fmixer->card; if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { up_read(&card->controls_rwsem); return; } uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; if (kctl->info(kctl, uinfo)) goto __unalloc; if (kctl->get(kctl, uctl)) goto __unalloc; if (!uctl->value.integer.value[0]) { *left = 0; if (uinfo->count == 1) *right = 0; } if (uinfo->count > 1 && !uctl->value.integer.value[route ? 3 : 1]) *right = 0; __unalloc: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo);}static int snd_mixer_oss_get_volume1(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *left, int *right){ struct slot *slot = (struct slot *)pslot->private_data; *left = *right = 100; if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { snd_mixer_oss_get_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); } if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } return 0;}static void snd_mixer_oss_put_volume1_vol(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, unsigned int numid, int left, int right){ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; snd_kcontrol_t *kctl; snd_card_t *card = fmixer->card; int res; if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) return; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; if (kctl->info(kctl, uinfo)) goto __unalloc; if (uinfo->type == SNDRV_CTL_ELEM_TYPE_BOOLEAN && uinfo->value.integer.min == 0 && uinfo->value.integer.max == 1) goto __unalloc; uctl->value.integer.value[0] = snd_mixer_oss_conv2(left, uinfo->value.integer.min, uinfo->value.integer.max); if (uinfo->count > 1) uctl->value.integer.value[1] = snd_mixer_oss_conv2(right, uinfo->value.integer.min, uinfo->value.integer.max); if ((res = kctl->put(kctl, uctl)) < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo);}static void snd_mixer_oss_put_volume1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, unsigned int numid, int left, int right, int route){ snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; snd_kcontrol_t *kctl; snd_card_t *card = fmixer->card; int res; if (numid == ID_UNKNOWN) return; down_read(&card->controls_rwsem); if ((kctl = snd_ctl_find_numid(card, numid)) == NULL) { up_read(&fmixer->card->controls_rwsem); return; } uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) goto __unalloc; if (kctl->info(kctl, uinfo)) goto __unalloc; if (uinfo->count > 1) { uctl->value.integer.value[0] = left > 0 ? 1 : 0; uctl->value.integer.value[route ? 3 : 1] = right > 0 ? 1 : 0; if (route) { uctl->value.integer.value[1] = uctl->value.integer.value[2] = 0; } } else { uctl->value.integer.value[0] = (left > 0 || right > 0) ? 1 : 0; } if ((res = kctl->put(kctl, uctl)) < 0) goto __unalloc; if (res > 0) snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unalloc: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo);}static int snd_mixer_oss_put_volume1(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int left, int right){ struct slot *slot = (struct slot *)pslot->private_data; if (slot->present & SNDRV_MIXER_OSS_PRESENT_PVOLUME) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PVOLUME], left, right); if (slot->present & SNDRV_MIXER_OSS_PRESENT_CVOLUME) snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GVOLUME) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GVOLUME], left, right); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GLOBAL) { snd_mixer_oss_put_volume1_vol(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GLOBAL], left, right); } if (left || right) { if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } else { if (slot->present & SNDRV_MIXER_OSS_PRESENT_PSWITCH) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GSWITCH) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GSWITCH], left, right, 0); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_PROUTE) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_PROUTE], left, right, 1); } else if (slot->present & SNDRV_MIXER_OSS_PRESENT_GROUTE) { snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_GROUTE], left, right, 1); } } return 0;}static int snd_mixer_oss_get_recsrc1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *active){ struct slot *slot = (struct slot *)pslot->private_data; int left, right; left = right = 1; snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], &left, &right, 0); *active = (left || right) ? 1 : 0; return 0;}static int snd_mixer_oss_get_recsrc1_route(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int *active){ struct slot *slot = (struct slot *)pslot->private_data; int left, right; left = right = 1; snd_mixer_oss_get_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], &left, &right, 1); *active = (left || right) ? 1 : 0; return 0;}static int snd_mixer_oss_put_recsrc1_sw(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int active){ struct slot *slot = (struct slot *)pslot->private_data; snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CSWITCH], active, active, 0); return 0;}static int snd_mixer_oss_put_recsrc1_route(snd_mixer_oss_file_t *fmixer, snd_mixer_oss_slot_t *pslot, int active){ struct slot *slot = (struct slot *)pslot->private_data; snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->numid[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1); return 0;}static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int *active_index){ snd_card_t *card = fmixer->card; snd_mixer_oss_t *mixer = fmixer->mixer; snd_kcontrol_t *kctl; snd_mixer_oss_slot_t *pslot; struct slot *slot; snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; int err, idx; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { err = -ENOMEM; goto __unlock; } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); if (! kctl) { err = -ENOENT; goto __unlock; } if ((err = kctl->info(kctl, uinfo)) < 0) goto __unlock; if ((err = kctl->get(kctl, uctl)) < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; pslot = &mixer->slots[idx]; slot = (struct slot *)pslot->private_data; if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) continue; if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) continue; if (slot->capture_item == uctl->value.enumerated.item[0]) { *active_index = idx; break; } } err = 0; __unlock: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo); return err;}static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, unsigned int active_index){ snd_card_t *card = fmixer->card; snd_mixer_oss_t *mixer = fmixer->mixer; snd_kcontrol_t *kctl; snd_mixer_oss_slot_t *pslot; struct slot *slot = NULL; snd_ctl_elem_info_t *uinfo; snd_ctl_elem_value_t *uctl; int err; unsigned int idx; uinfo = kzalloc(sizeof(*uinfo), GFP_KERNEL); uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (uinfo == NULL || uctl == NULL) { err = -ENOMEM; goto __unlock; } down_read(&card->controls_rwsem); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); if (! kctl) { err = -ENOENT; goto __unlock; } if ((err = kctl->info(kctl, uinfo)) < 0) goto __unlock; for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; pslot = &mixer->slots[idx]; slot = (struct slot *)pslot->private_data; if (slot->signature != SNDRV_MIXER_OSS_SIGNATURE) continue; if (!(slot->present & SNDRV_MIXER_OSS_PRESENT_CAPTURE)) continue; if (idx == active_index) break; slot = NULL; } if (! slot) goto __unlock; for (idx = 0; idx < uinfo->count; idx++) uctl->value.enumerated.item[idx] = slot->capture_item; err = kctl->put(kctl, uctl); if (err > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); err = 0; __unlock: up_read(&card->controls_rwsem); kfree(uctl); kfree(uinfo); return err;}struct snd_mixer_oss_assign_table { int oss_id; const char *name; int index;};static int snd_mixer_oss_build_test(snd_mixer_oss_t *mixer, struct slot *slot, const char *name, int index, int item){ snd_ctl_elem_info_t *info; snd_kcontrol_t *kcontrol; snd_card_t *card = mixer->card; int err; down_read(&card->controls_rwsem); kcontrol = snd_mixer_oss_test_id(mixer, name, index); if (kcontrol == NULL) { up_read(&card->controls_rwsem); return 0; } info = kmalloc(sizeof(*info), GFP_KERNEL); if (! info) { up_read(&card->controls_rwsem); return -ENOMEM; } if ((err = kcontrol->info(kcontrol, info)) < 0) { up_read(&card->controls_rwsem); kfree(info); return err; } slot->numid[item] = kcontrol->id.numid; up_read(&card->controls_rwsem); if (info->count > slot->channels) slot->channels = info->count; slot->present |= 1 << item; kfree(info); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -