📄 mixer_oss.c
字号:
int active){ snd_card_t *card = fmixer->card; struct slot *slot = (struct slot *)pslot->private_data; read_lock(&card->control_rwlock); snd_mixer_oss_put_volume1_sw(fmixer, pslot, slot->kcontrol[SNDRV_MIXER_OSS_ITEM_CROUTE], active, active, 1); read_unlock(&card->control_rwlock); return 0;}static int snd_mixer_oss_get_recsrc2(snd_mixer_oss_file_t *fmixer, 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; read_lock(&card->control_rwlock); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); snd_runtime_check(kctl != NULL, return -ENOENT); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err); snd_runtime_check(!(err = kctl->get(kctl, &uctl)), read_unlock(&card->control_rwlock); return err); read_unlock(&card->control_rwlock); for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; pslot = &fmixer->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; } } return 0;}static int snd_mixer_oss_put_recsrc2(snd_mixer_oss_file_t *fmixer, 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, idx; read_lock(&card->control_rwlock); kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0); snd_runtime_check(kctl != NULL, read_unlock(&card->control_rwlock); return -ENOENT); memset(&uinfo, 0, sizeof(uinfo)); memset(&uctl, 0, sizeof(uctl)); snd_runtime_check(!(err = kctl->info(kctl, &uinfo)), read_unlock(&card->control_rwlock); return err); for (idx = 0; idx < 32; idx++) { if (!(mixer->mask_recsrc & (1 << idx))) continue; pslot = &fmixer->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; } snd_runtime_check(slot != NULL, goto __unlock); for (idx = 0; idx < uinfo.count; idx++) uctl.value.enumerated.item[idx] = slot->capture_item; snd_runtime_check((err = kctl->put(kctl, &uctl)) >= 0, ); if (err > 0) snd_ctl_notify(fmixer->card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id); __unlock: read_unlock(&card->control_rwlock); return 0;}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; int err; kcontrol = snd_mixer_oss_test_id(mixer, name, index); if (kcontrol == NULL) return 0; snd_runtime_check((err = kcontrol->info(kcontrol, &info)) >= 0, return err); slot->kcontrol[item] = kcontrol; if (info.count > slot->channels) slot->channels = info.count; slot->present |= 1 << item; return 0;}static void snd_mixer_oss_slot_free(snd_mixer_oss_slot_t *chn){ kfree(chn->private_data);}static void snd_mixer_oss_build_input(snd_mixer_oss_t *mixer, struct snd_mixer_oss_assign_table *ptr){ struct slot slot; struct slot *pslot; snd_kcontrol_t *kctl; snd_mixer_oss_slot_t *rslot; char str[64]; memset(&slot, 0, sizeof(slot)); if (snd_mixer_oss_build_test(mixer, &slot, ptr->name, ptr->index, SNDRV_MIXER_OSS_ITEM_GLOBAL)) return; sprintf(str, "%s Switch", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_GSWITCH)) return; sprintf(str, "%s Route", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_GROUTE)) return; sprintf(str, "%s Volume", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_GVOLUME)) return; sprintf(str, "%s Playback Switch", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_PSWITCH)) return; sprintf(str, "%s Playback Route", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_PROUTE)) return; sprintf(str, "%s Playback Volume", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_PVOLUME)) return; sprintf(str, "%s Capture Switch", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_CSWITCH)) return; sprintf(str, "%s Capture Route", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_CROUTE)) return; sprintf(str, "%s Capture Volume", ptr->name); if (snd_mixer_oss_build_test(mixer, &slot, str, ptr->index, SNDRV_MIXER_OSS_ITEM_CVOLUME)) return; if (ptr->index == 0 && (kctl = snd_mixer_oss_test_id(mixer, "Capture Source", 0)) != NULL) { snd_ctl_elem_info_t uinfo; memset(&uinfo, 0, sizeof(uinfo)); if (kctl->info(kctl, &uinfo)) return; strcpy(str, ptr->name); if (!strcmp(str, "Master")) strcpy(str, "Mix"); if (!strcmp(str, "Master Mono")) strcpy(str, "Mix Mono"); slot.capture_item = 0; if (!strcmp(uinfo.value.enumerated.name, str)) { slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE; } else { for (slot.capture_item = 1; slot.capture_item < uinfo.value.enumerated.items; slot.capture_item++) { uinfo.value.enumerated.item = slot.capture_item; if (kctl->info(kctl, &uinfo)) return; if (!strcmp(uinfo.value.enumerated.name, str)) { slot.present |= SNDRV_MIXER_OSS_PRESENT_CAPTURE; break; } } } } if (slot.present != 0) { pslot = (struct slot *)kmalloc(sizeof(slot), GFP_KERNEL); snd_runtime_check(pslot != NULL, return); *pslot = slot; pslot->signature = SNDRV_MIXER_OSS_SIGNATURE; rslot = &mixer->slots[ptr->oss_id]; rslot->stereo = slot.channels > 1 ? 1 : 0; rslot->get_volume = snd_mixer_oss_get_volume1; rslot->put_volume = snd_mixer_oss_put_volume1; /* note: ES18xx have both Capture Source and XX Capture Volume !!! */ if (slot.present & SNDRV_MIXER_OSS_PRESENT_CSWITCH) { rslot->get_recsrc = snd_mixer_oss_get_recsrc1_sw; rslot->put_recsrc = snd_mixer_oss_put_recsrc1_sw; } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CROUTE) { rslot->get_recsrc = snd_mixer_oss_get_recsrc1_route; rslot->put_recsrc = snd_mixer_oss_put_recsrc1_route; } else if (slot.present & SNDRV_MIXER_OSS_PRESENT_CAPTURE) { mixer->mask_recsrc |= 1 << ptr->oss_id; } rslot->private_data = pslot; rslot->private_free = snd_mixer_oss_slot_free; }}static void snd_mixer_oss_build(snd_mixer_oss_t *mixer){ static struct snd_mixer_oss_assign_table table[] = { { SOUND_MIXER_VOLUME, "Master", 0 }, { SOUND_MIXER_BASS, "Tone Control - Bass", 0 }, { SOUND_MIXER_TREBLE, "Tone Control - Treble", 0 }, { SOUND_MIXER_SYNTH, "Synth", 0 }, { SOUND_MIXER_PCM, "PCM", 0 }, { SOUND_MIXER_SPEAKER, "PC Speaker", 0 }, { SOUND_MIXER_LINE, "Line", 0 }, { SOUND_MIXER_MIC, "Mic", 0 }, { SOUND_MIXER_CD, "CD", 0 }, { SOUND_MIXER_IMIX, "Monitor Mix", 0 }, { SOUND_MIXER_ALTPCM, "PCM", 1 }, { SOUND_MIXER_RECLEV, "-- nothing --", 0 }, { SOUND_MIXER_IGAIN, "Capture", 0 }, { SOUND_MIXER_OGAIN, "Playback", 0 }, { SOUND_MIXER_LINE1, "Aux", 0 }, { SOUND_MIXER_LINE2, "Aux", 1 }, { SOUND_MIXER_LINE3, "Aux", 2 }, { SOUND_MIXER_DIGITAL1, "Digital", 0 }, { SOUND_MIXER_DIGITAL2, "Digital", 1 }, { SOUND_MIXER_DIGITAL3, "Digital", 2 }, { SOUND_MIXER_PHONEIN, "Phone", 0 }, { SOUND_MIXER_PHONEOUT, "Phone", 1 }, { SOUND_MIXER_VIDEO, "Video", 0 }, { SOUND_MIXER_RADIO, "Radio", 0 }, { SOUND_MIXER_MONITOR, "Monitor", 0 } }; static struct snd_mixer_oss_assign_table fm_table = { SOUND_MIXER_SYNTH, "FM", 0 }; int idx; for (idx = 0; idx < sizeof(table) / sizeof(struct snd_mixer_oss_assign_table); idx++) snd_mixer_oss_build_input(mixer, &table[idx]); if (mixer->slots[SOUND_MIXER_SYNTH].get_volume == NULL) snd_mixer_oss_build_input(mixer, &fm_table); if (mixer->mask_recsrc) { mixer->get_recsrc = snd_mixer_oss_get_recsrc2; mixer->put_recsrc = snd_mixer_oss_put_recsrc2; }}/* * */static int snd_mixer_oss_free1(void *private){ snd_mixer_oss_t *mixer = snd_magic_cast(snd_mixer_oss_t, private, return -ENXIO); snd_card_t * card; int idx; snd_assert(mixer != NULL, return -ENXIO); card = mixer->card; snd_assert(mixer == card->mixer_oss, return -ENXIO); card->mixer_oss = NULL; for (idx = 0; idx < 31; idx++) { snd_mixer_oss_slot_t *chn = &mixer->slots[idx]; if (chn->private_free) chn->private_free(chn); } snd_magic_kfree(mixer); return 0;}static int snd_mixer_oss_notify_handler(snd_card_t * card, int free_flag){ if (!free_flag) { snd_mixer_oss_t *mixer; char name[128]; int idx, err; mixer = snd_magic_kcalloc(snd_mixer_oss_t, sizeof(snd_mixer_oss_t), GFP_KERNEL); if (mixer == NULL) return -ENOMEM; sprintf(name, "mixer%i%i", card->number, 0); if ((err = snd_register_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, card, 0, &snd_mixer_oss_reg, name)) < 0) { snd_printk("unable to register OSS mixer device %i:%i\n", card->number, 0); snd_magic_kfree(mixer); return err; } mixer->card = card; strcpy(mixer->name, name); snd_oss_info_register(SNDRV_OSS_INFO_DEV_MIXERS, card->number, name); for (idx = 0; idx < 31; idx++) mixer->slots[idx].number = idx; card->mixer_oss = mixer; snd_mixer_oss_build(mixer); } else { snd_mixer_oss_t *mixer = card->mixer_oss; if (mixer == NULL) return 0; snd_oss_info_unregister(SNDRV_OSS_INFO_DEV_MIXERS, mixer->card->number); snd_unregister_oss_device(SNDRV_OSS_DEVICE_TYPE_MIXER, mixer->card, 0); return snd_mixer_oss_free1(mixer); } return 0;}static int __init alsa_mixer_oss_init(void){ int idx; snd_mixer_oss_notify_callback = snd_mixer_oss_notify_handler; for (idx = 0; idx < SNDRV_CARDS; idx++) { if (snd_cards[idx]) snd_mixer_oss_notify_handler(snd_cards[idx], 0); } return 0;}static void __exit alsa_mixer_oss_exit(void){ int idx; snd_mixer_oss_notify_callback = NULL; for (idx = 0; idx < SNDRV_CARDS; idx++) { if (snd_cards[idx]) snd_mixer_oss_notify_handler(snd_cards[idx], 1); }}module_init(alsa_mixer_oss_init)module_exit(alsa_mixer_oss_exit)EXPORT_SYMBOL(snd_mixer_oss_ioctl_card);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -