音频调试工具tinymix 源码浅析

源码浅析

针对上篇文章中的kcontrol与ucontrol的区别,在此粘上源码,主要负责实现应用层至底层的参数传递,ucontrol的数据类型为snd_ctl_elem_value,结构体具体如下

struct snd_ctl_elem_value {
 916     struct snd_ctl_elem_id id;  /* W: element ID */
 917     unsigned int indirect: 1;   /* W: indirect access - obsoleted */
 918     union {
 919         union {
 920             long value[128];
 921             long *value_ptr;    /* obsoleted */
 922         } integer;
 923         union {
 924             long long value[64];
 925             long long *value_ptr;   /* obsoleted */
 926         } integer64;
 927         union {
 928             unsigned int item[128];
 929             unsigned int *item_ptr; /* obsoleted */
 930         } enumerated;
 931         union {
 932             unsigned char data[512];
 933             unsigned char *data_ptr;    /* obsoleted */
 934         } bytes;
 935         struct snd_aes_iec958 iec958;
 936     } value;        /* RO */
 937     struct timespec tstamp;
 938     unsigned char reserved[128-sizeof(struct timespec)];
 939 };
 940

420 int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value)
421 {
422     struct snd_ctl_elem_value ev;
423     int ret;
424
425     if (!ctl || (id >= ctl->info->count))
426         return -EINVAL;
427
428     memset(&ev, 0, sizeof(ev));
429     ev.id.numid = ctl->info->id.numid;
430     ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev);
431     if (ret < 0)
432         return ret;
433
434     switch (ctl->info->type) {
435     case SNDRV_CTL_ELEM_TYPE_BOOLEAN:
436         ev.value.integer.value[id] = !!value;
437         break;
438
439     case SNDRV_CTL_ELEM_TYPE_INTEGER:
440         ev.value.integer.value[id] = value;
441         break;
442
443     case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
444         ev.value.enumerated.item[id] = value;
445         break;
446
447     case SNDRV_CTL_ELEM_TYPE_BYTES:
448         ev.value.bytes.data[id] = value;
449         break;
450
451     default:
452         return -EINVAL;
453     }
454
455     return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev);
456 }

usage

static void usage (void) {
    fprintf(stderr,
"tinymix [options] [control name/#] [value to set]\n"
"    options:\n"
"    --device|-D <card#>   - use the given card # instead of 0.\n"
"    --all-values|-a       - show all possible values/ranges for control.\n"
"    --tabs-only|-t        - separate all output columns/values with tabs.\n"
"    --value-only|-v       - show only the value for the selected control.\n"
            );
}

触发kcontrol回调流程

main
->tinymix_set_value
->mixer_ctl_set_value
->ioctl
->snd_ctl_elem_write_user --内核钩子函数
->snd_ctl_elem_write
->kcontrol中的put回调函数,源码如下

static int snd_ctl_elem_write(struct snd_card *card, struct snd_ctl_file *file,
			      struct snd_ctl_elem_value *control)
{
	struct snd_kcontrol *kctl;
	struct snd_kcontrol_volatile *vd;
	unsigned int index_offset;
	int result;

	down_read(&card->controls_rwsem);
	kctl = snd_ctl_find_id(card, &control->id);
	if (kctl == NULL) {
		result = -ENOENT;
	} else {
		index_offset = snd_ctl_get_ioff(kctl, &control->id);
		vd = &kctl->vd[index_offset];
		if (!(vd->access & SNDRV_CTL_ELEM_ACCESS_WRITE) ||
		    kctl->put == NULL ||
		    (file && vd->owner && vd->owner != file)) {
			result = -EPERM;
		} else {
			snd_ctl_build_ioff(&control->id, kctl, index_offset);
			//此处回调kcontrol的put回调函数
			result = kctl->put(kctl, control);
		}
		if (result > 0) {
			struct snd_ctl_elem_id id = control->id;
			up_read(&card->controls_rwsem);
			snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &id);
			return 0;
		}
	}
	up_read(&card->controls_rwsem);
	return result;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值