mirror of
https://github.com/alsa-project/alsa-utils
synced 2025-01-03 04:39:43 +01:00
Compare commits
6 commits
70615ba71b
...
3c5d3bf607
Author | SHA1 | Date | |
---|---|---|---|
|
3c5d3bf607 | ||
|
21e0adfa3b | ||
|
095b064af6 | ||
|
e26aa680aa | ||
|
0188f93f02 | ||
|
ffc63f76de |
3 changed files with 223 additions and 19 deletions
|
@ -362,7 +362,7 @@ static void show_text(const uint32_t *ump)
|
|||
len = 0;
|
||||
|
||||
for (i = 0; i < 12 && len < (int)sizeof(textbuf); i++) {
|
||||
textbuf[len] = fh->meta.data[i / 4] >> ((3 - (i % 4)) * 8);
|
||||
textbuf[len] = snd_ump_get_byte(ump, 4 + i);
|
||||
if (!textbuf[len])
|
||||
break;
|
||||
switch (textbuf[len]) {
|
||||
|
|
|
@ -664,8 +664,7 @@ static void dump_ump_system_event(const unsigned int *ump)
|
|||
static unsigned char ump_sysex7_data(const unsigned int *ump,
|
||||
unsigned int offset)
|
||||
{
|
||||
offset += 2;
|
||||
return (ump[offset / 4] >> ((3 - (offset & 3)) * 8)) & 0xff;
|
||||
return snd_ump_get_byte(ump, offset + 2);
|
||||
}
|
||||
|
||||
static void dump_ump_sysex_status(const char *prefix, unsigned int status)
|
||||
|
@ -698,8 +697,8 @@ static void dump_ump_sysex_event(const unsigned int *ump)
|
|||
dump_ump_sysex_status("SysEx", snd_ump_sysex_msg_status(ump));
|
||||
length = snd_ump_sysex_msg_length(ump);
|
||||
printf(" length %d ", length);
|
||||
if (length > 14)
|
||||
length = 14;
|
||||
if (length > 6)
|
||||
length = 6;
|
||||
for (i = 0; i < length; i++)
|
||||
printf("%s%02x", i ? ":" : "", ump_sysex7_data(ump, i));
|
||||
printf("\n");
|
||||
|
@ -708,8 +707,7 @@ static void dump_ump_sysex_event(const unsigned int *ump)
|
|||
static unsigned char ump_sysex8_data(const unsigned int *ump,
|
||||
unsigned int offset)
|
||||
{
|
||||
offset += 3;
|
||||
return (ump[offset / 4] >> ((3 - (offset & 3)) * 8)) & 0xff;
|
||||
return snd_ump_get_byte(ump, offset + 3);
|
||||
}
|
||||
|
||||
static void dump_ump_sysex8_event(const unsigned int *ump)
|
||||
|
@ -728,6 +726,45 @@ static void dump_ump_sysex8_event(const unsigned int *ump)
|
|||
printf("\n");
|
||||
}
|
||||
|
||||
static void dump_ump_mixed_data_event(const unsigned int *ump)
|
||||
{
|
||||
const snd_ump_msg_mixed_data_t *m =
|
||||
(const snd_ump_msg_mixed_data_t *)ump;
|
||||
int i;
|
||||
|
||||
printf("Group %2d, ", group_number(snd_ump_msg_group(ump)));
|
||||
switch (snd_ump_sysex_msg_status(ump)) {
|
||||
case SND_UMP_MIXED_DATA_SET_STATUS_HEADER:
|
||||
printf("MDS Header id=0x%x, bytes=%d, chunk=%d/%d, manufacturer=0x%04x, device=0x%04x, sub_id=0x%04x 0x%04x\n",
|
||||
m->header.mds_id, m->header.bytes,
|
||||
m->header.chunk, m->header.chunks,
|
||||
m->header.manufacturer, m->header.device,
|
||||
m->header.sub_id_1, m->header.sub_id_2);
|
||||
break;
|
||||
case SND_UMP_MIXED_DATA_SET_STATUS_PAYLOAD:
|
||||
printf("MDS Payload id=0x%x, ", m->payload.mds_id);
|
||||
for (i = 0; i < 14; i++)
|
||||
printf("%s%02x", i ? ":" : "",
|
||||
snd_ump_get_byte(ump, i + 2));
|
||||
printf("\n");
|
||||
break;
|
||||
default:
|
||||
printf("Extended Data (status 0x%x)\n",
|
||||
snd_ump_sysex_msg_status(ump));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void dump_ump_extended_data_event(const unsigned int *ump)
|
||||
{
|
||||
unsigned char status = snd_ump_sysex_msg_status(ump);
|
||||
|
||||
if (status < 4)
|
||||
dump_ump_sysex8_event(ump);
|
||||
else
|
||||
dump_ump_mixed_data_event(ump);
|
||||
}
|
||||
|
||||
static void print_ump_string(const unsigned int *ump, unsigned int fmt,
|
||||
unsigned int offset, int maxlen)
|
||||
{
|
||||
|
@ -736,17 +773,12 @@ static void print_ump_string(const unsigned int *ump, unsigned int fmt,
|
|||
int i = 0;
|
||||
|
||||
do {
|
||||
buf[i] = (*ump >> (24 - offset)) & 0xff;
|
||||
buf[i] = snd_ump_get_byte(ump, offset);
|
||||
if (!buf[i])
|
||||
break;
|
||||
if (buf[i] < 0x20)
|
||||
buf[i] = '.';
|
||||
if (offset == 24) {
|
||||
offset = 0;
|
||||
ump++;
|
||||
} else {
|
||||
offset += 8;
|
||||
}
|
||||
offset++;
|
||||
} while (++i < maxlen);
|
||||
buf[i] = 0;
|
||||
|
||||
|
@ -780,12 +812,12 @@ static void dump_ump_stream_event(const unsigned int *ump)
|
|||
break;
|
||||
case SND_UMP_STREAM_MSG_STATUS_EP_NAME:
|
||||
printf("EP Name ");
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 16, 14);
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 2, 14);
|
||||
printf("\n");
|
||||
break;
|
||||
case SND_UMP_STREAM_MSG_STATUS_PRODUCT_ID:
|
||||
printf("Product Id ");
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 16, 14);
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 2, 14);
|
||||
printf("\n");
|
||||
break;
|
||||
case SND_UMP_STREAM_MSG_STATUS_STREAM_CFG_REQUEST:
|
||||
|
@ -810,7 +842,7 @@ static void dump_ump_stream_event(const unsigned int *ump)
|
|||
case SND_UMP_STREAM_MSG_STATUS_FB_NAME:
|
||||
printf("Product Id ");
|
||||
printf("FB Name #%02d ", (ump[0] >> 8) & 0xff);
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 24, 13);
|
||||
print_ump_string(ump, (ump[0] >> 26) & 3, 3, 13);
|
||||
printf("\n");
|
||||
break;
|
||||
case SND_UMP_STREAM_MSG_STATUS_START_CLIP:
|
||||
|
@ -959,7 +991,7 @@ static void dump_ump_flex_data_event(const unsigned int *ump)
|
|||
if (fh->meta.status_bank == SND_UMP_FLEX_DATA_MSG_BANK_METADATA ||
|
||||
fh->meta.status_bank == SND_UMP_FLEX_DATA_MSG_BANK_PERF_TEXT) {
|
||||
printf("Meta (%s) ", ump_meta_prefix(fh));
|
||||
print_ump_string(ump + 1, fh->meta.format, 0, 12);
|
||||
print_ump_string(ump, fh->meta.format, 4, 12);
|
||||
printf("\n");
|
||||
return;
|
||||
}
|
||||
|
@ -995,7 +1027,7 @@ static void dump_ump_event(const snd_seq_ump_event_t *ev)
|
|||
dump_ump_sysex_event(ev->ump);
|
||||
break;
|
||||
case SND_UMP_MSG_TYPE_EXTENDED_DATA:
|
||||
dump_ump_sysex8_event(ev->ump);
|
||||
dump_ump_extended_data_event(ev->ump);
|
||||
break;
|
||||
case SND_UMP_MSG_TYPE_FLEX_DATA:
|
||||
dump_ump_flex_data_event(ev->ump);
|
||||
|
|
|
@ -921,6 +921,172 @@ static int pre_process_arrays(struct tplg_pre_processor *tplg_pp, snd_config_t *
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int pre_process_subtree_copy(struct tplg_pre_processor *tplg_pp, snd_config_t *curr,
|
||||
snd_config_t *top)
|
||||
{
|
||||
snd_config_iterator_t i, next;
|
||||
snd_config_t *subtrees;
|
||||
int ret;
|
||||
|
||||
ret = snd_config_search(curr, "SubTreeCopy", &subtrees);
|
||||
if (ret < 0)
|
||||
return 0;
|
||||
|
||||
snd_config_for_each(i, next, subtrees) {
|
||||
snd_config_t *n, *source_cfg, *target_cfg, *type_cfg;
|
||||
snd_config_t *source_tree, *target_tree, *tmp, *subtree_cfg;
|
||||
const char *id, *source_id;
|
||||
const char *type = NULL;
|
||||
const char *target_id = NULL;
|
||||
bool override = false;
|
||||
|
||||
n = snd_config_iterator_entry(i);
|
||||
ret = snd_config_get_id(n, &id);
|
||||
if (ret < 0) {
|
||||
SNDERR("Failed to get ID for subtree copy\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the type of copy ex: override/extend if set, by default override is false */
|
||||
ret = snd_config_search(n, "type", &type_cfg);
|
||||
if (ret >= 0) {
|
||||
ret = snd_config_get_string(type_cfg, &type);
|
||||
if (ret >= 0) {
|
||||
if (strcmp(type, "override") && strcmp(type, "extend")) {
|
||||
SNDERR("Invalid value for sub tree copy type %s\n", type);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!strcmp(type, "override"))
|
||||
override = true;
|
||||
}
|
||||
}
|
||||
|
||||
ret = snd_config_search(n, "source", &source_cfg);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to get source config for subtree %s\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* if the target node is not set, the subtree will be copied to current node */
|
||||
ret = snd_config_search(n, "target", &target_cfg);
|
||||
if (ret >= 0) {
|
||||
snd_config_t *temp_target;
|
||||
char *s;
|
||||
|
||||
ret = snd_config_get_string(target_cfg, &target_id);
|
||||
if (ret < 0) {
|
||||
SNDERR("Invalid target id for subtree %s\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* create a temporary node with target_id and merge with top to avoid
|
||||
* failure in case the target node ID doesn't exist already
|
||||
*/
|
||||
s = tplg_snprintf("%s {}", target_id);
|
||||
if (!s)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = snd_config_load_string(&temp_target, s, 0);
|
||||
free(s);
|
||||
if (ret < 0) {
|
||||
SNDERR("Cannot create temp node with target id %s\n", target_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_config_merge(top, temp_target, false);
|
||||
if (ret < 0) {
|
||||
SNDERR("Cannot merge temp node with target id %s\n", target_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_config_search(top, target_id, &target_tree);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to get target tree %s\n", target_id);
|
||||
return ret;
|
||||
}
|
||||
} else {
|
||||
target_tree = curr;
|
||||
}
|
||||
|
||||
/* get the source tree node */
|
||||
ret = snd_config_get_string(source_cfg, &source_id);
|
||||
if (ret < 0) {
|
||||
SNDERR("Invalid source node id for subtree %s\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = snd_config_search(top, source_id, &source_tree);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to get source tree %s\n", source_id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get the subtree to be merged */
|
||||
ret = snd_config_search(n, "tree", &subtree_cfg);
|
||||
if (ret < 0)
|
||||
subtree_cfg = NULL;
|
||||
|
||||
/* make a temp copy of the source tree */
|
||||
ret = snd_config_copy(&tmp, source_tree);
|
||||
if (ret < 0) {
|
||||
SNDERR("failed to copy source tree for subtreecopy %s\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* merge the current block with the source tree */
|
||||
ret = snd_config_merge(tmp, subtree_cfg, override);
|
||||
if (ret < 0) {
|
||||
snd_config_delete(tmp);
|
||||
SNDERR("Failed to merge source tree w/ subtree %s\n", id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* merge the merged block to the target tree */
|
||||
ret = snd_config_merge(target_tree, tmp, override);
|
||||
if (ret < 0) {
|
||||
snd_config_delete(tmp);
|
||||
SNDERR("Failed to merge subtree %s w/ target\n", id);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* all subtree copies have been processed, remove the node */
|
||||
snd_config_delete(subtrees);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pre_process_subtree_copies(struct tplg_pre_processor *tplg_pp, snd_config_t *top,
|
||||
snd_config_t *curr)
|
||||
{
|
||||
snd_config_iterator_t i, next;
|
||||
int ret;
|
||||
|
||||
if (snd_config_get_type(curr) != SND_CONFIG_TYPE_COMPOUND)
|
||||
return 0;
|
||||
|
||||
/* process subtreecopies at this node */
|
||||
ret = pre_process_subtree_copy(tplg_pp, curr, top);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
/* process subtreecopies at all child nodes */
|
||||
snd_config_for_each(i, next, curr) {
|
||||
snd_config_t *n;
|
||||
|
||||
n = snd_config_iterator_entry(i);
|
||||
|
||||
/* process subtreecopies at this node */
|
||||
ret = pre_process_subtree_copies(tplg_pp, top, n);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* version < 1.2.6 */
|
||||
|
||||
int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_size,
|
||||
|
@ -980,6 +1146,12 @@ int pre_process(struct tplg_pre_processor *tplg_pp, char *config, size_t config_
|
|||
fprintf(stderr, "Failed to process object arrays in input config\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
err = pre_process_subtree_copies(tplg_pp, tplg_pp->input_cfg, tplg_pp->input_cfg);
|
||||
if (err < 0) {
|
||||
SNDERR("Failed to process subtree copies in input config\n");
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
err = pre_process_config(tplg_pp, tplg_pp->input_cfg);
|
||||
|
|
Loading…
Reference in a new issue