/** * \brief Load an HCTL with all elements and sort them * \param hctl HCTL handle * \return 0 on success otherwise a negative error code */ int snd_hctl_load(snd_hctl_t *hctl) { snd_ctl_elem_list_t list; int err = 0; unsigned int idx; assert(hctl); assert(hctl->ctl); assert(hctl->count == 0); assert(list_empty(&hctl->elems)); memset(&list, 0, sizeof(list)); if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0) goto _end; while (list.count != list.used) { err = snd_ctl_elem_list_alloc_space(&list, list.count); if (err < 0) goto _end; if ((err = snd_ctl_elem_list(hctl->ctl, &list)) < 0) goto _end; } if (hctl->alloc < list.count) { hctl->alloc = list.count; free(hctl->pelems); hctl->pelems = malloc(hctl->alloc * sizeof(*hctl->pelems)); if (!hctl->pelems) { err = -ENOMEM; goto _end; } } for (idx = 0; idx < list.count; idx++) { snd_hctl_elem_t *elem; elem = calloc(1, sizeof(snd_hctl_elem_t)); if (elem == NULL) { snd_hctl_free(hctl); err = -ENOMEM; goto _end; } elem->id = list.pids[idx]; elem->hctl = hctl; elem->compare_weight = get_compare_weight(&elem->id); hctl->pelems[idx] = elem; list_add_tail(&elem->list, &hctl->elems); hctl->count++; } if (!hctl->compare) hctl->compare = snd_hctl_compare_default; snd_hctl_sort(hctl); for (idx = 0; idx < hctl->count; idx++) { int res = snd_hctl_throw_event(hctl, SNDRV_CTL_EVENT_MASK_ADD, hctl->pelems[idx]); if (res < 0) return res; } err = snd_ctl_subscribe_events(hctl->ctl, 1); _end: free(list.pids); return err; }
static int open_ctl(const char *name, snd_ctl_t **ctlp) { snd_ctl_t *ctl; if (snd_ctl_open(&ctl, name, SND_CTL_READONLY) < 0) { fprintf(stderr, "Cannot open ctl %s\n", name); return 1; } if (snd_ctl_subscribe_events(ctl, 1) < 0) { fprintf(stderr, "Cannot open subscribe events to ctl %s\n", name); snd_ctl_close(ctl); return 1; } *ctlp = ctl; return 0; }
int main(void) { struct elem_set_trial trial = {0}; unsigned int i; int err; snd_ctl_elem_id_alloca(&trial.id); err = snd_ctl_open(&trial.handle, "hw:0", 0); if (err < 0) return EXIT_FAILURE; err = snd_ctl_subscribe_events(trial.handle, 1); if (err < 0) return EXIT_FAILURE; /* Test all of types. */ for (i = 0; i < SND_CTL_ELEM_TYPE_LAST; ++i) { trial.type = i + 1; /* Assign type-dependent operations. */ switch (trial.type) { case SND_CTL_ELEM_TYPE_BOOLEAN: trial.element_count = 900; trial.member_count = 128; trial.dimension[0] = 4; trial.dimension[1] = 4; trial.dimension[2] = 8; trial.dimension[3] = 0; trial.add_elem_set = add_bool_elem_set; trial.check_elem_props = NULL; trial.change_elem_members = change_bool_elem_members; break; case SND_CTL_ELEM_TYPE_INTEGER: trial.element_count = 900; trial.member_count = 128; trial.dimension[0] = 128; trial.dimension[1] = 0; trial.dimension[2] = 0; trial.dimension[3] = 0; trial.add_elem_set = add_int_elem_set; trial.check_elem_props = check_int_elem_props; trial.change_elem_members = change_int_elem_members; break; case SND_CTL_ELEM_TYPE_ENUMERATED: trial.element_count = 900; trial.member_count = 128; trial.dimension[0] = 16; trial.dimension[1] = 8; trial.dimension[2] = 0; trial.dimension[3] = 0; trial.add_elem_set = add_enum_elem_set; trial.check_elem_props = check_enum_elem_props; trial.change_elem_members = change_enum_elem_members; break; case SND_CTL_ELEM_TYPE_BYTES: trial.element_count = 900; trial.member_count = 512; trial.dimension[0] = 8; trial.dimension[1] = 4; trial.dimension[2] = 8; trial.dimension[3] = 2; trial.add_elem_set = add_bytes_elem_set; trial.check_elem_props = NULL; trial.change_elem_members = change_bytes_elem_members; break; case SND_CTL_ELEM_TYPE_IEC958: trial.element_count = 1; trial.member_count = 1; trial.dimension[0] = 0; trial.dimension[1] = 0; trial.dimension[2] = 0; trial.dimension[3] = 0; trial.add_elem_set = add_iec958_elem_set; trial.check_elem_props = NULL; trial.change_elem_members = change_iec958_elem_members; break; case SND_CTL_ELEM_TYPE_INTEGER64: default: trial.element_count = 900; trial.member_count = 64; trial.dimension[0] = 0; trial.dimension[1] = 0; trial.dimension[2] = 0; trial.dimension[3] = 0; trial.add_elem_set = add_int64_elem_set; trial.check_elem_props = check_int64_elem_props; trial.change_elem_members = change_int64_elem_members; break; } /* Test an operation to add an element set. */ err = add_elem_set(&trial); if (err < 0) { printf("Fail to add an element set with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } err = check_event(&trial, SND_CTL_EVENT_MASK_ADD, trial.element_count); if (err < 0) { printf("Fail to check some events to add elements with " "%s type.\n", snd_ctl_elem_type_name(trial.type)); break; } /* Check properties of each element in this element set. */ err = check_elem_set_props(&trial); if (err < 0) { printf("Fail to check propetries of each element with " "%s type.\n", snd_ctl_elem_type_name(trial.type)); break; } /* * Test operations to change the state of members in each * element in the element set. */ err = check_elems(&trial); if (err < 0) { printf("Fail to change status of each element with %s " "type.\n", snd_ctl_elem_type_name(trial.type)); break; } err = check_event(&trial, SND_CTL_EVENT_MASK_VALUE, trial.element_count); if (err < 0) { printf("Fail to check some events to change status of " "each elements with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } /* * Test an operation to change threshold data of this element set, * except for IEC958 type. */ if (trial.type != SND_CTL_ELEM_TYPE_IEC958) { err = check_tlv(&trial); if (err < 0) { printf("Fail to change threshold level of an " "element set with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } err = check_event(&trial, SND_CTL_EVENT_MASK_TLV, 1); if (err < 0) { printf("Fail to check an event to change " "threshold level of an an element set " "with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } } /* Test an operation to remove elements in this element set. */ err = snd_ctl_elem_remove(trial.handle, trial.id); if (err < 0) { printf("Fail to remove elements with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } err = check_event(&trial, SND_CTL_EVENT_MASK_REMOVE, trial.element_count); if (err < 0) { printf("Fail to check some events to remove each " "element with %s type.\n", snd_ctl_elem_type_name(trial.type)); break; } } if (err < 0) { printf("%s\n", snd_strerror(err)); /* To ensure. */ snd_ctl_elem_remove(trial.handle, trial.id); return EXIT_FAILURE; } return EXIT_SUCCESS; }