Hi!
I wrote a quick&dirty cmdline tool to dump and restore the internal
mixer state of an RME card (no matter if handled by snd_hdsp or
snd_hdspm, so this should apply to almost all RME cards except the new
MADIFX).
I call it hdspdump for now, if you like, grab it here:
http://adi.loris.tv/hdspdump.c
Almost no sanity checks, it's proof of concept atm. For your
convenience, I'll also attach it to this mail (who knows what will
happen to the URL above in the future...)
Idea is as follows:
1. Run hdspmixer ONCE to make your desired mix.
2. Run hdspdump hw:DSP > dumpfile to dump the current mixer state.
3. Run hdspdump hw:DSP write < dumpfile to restore the mixer state.
Of course, you can have multiple files for different mixes.
It's most likely used for headless setups with static signal routing.
I have only tested it on my Multiface, so if you have other RME gear and
have a few minutes to waste, I'm happy to hear from you.
Cheers
/* compile with gcc -std=gnu99 -o hdspdump hdspdump.c -lasound */
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>
void usage(char *name) {
fprintf(stderr, "usage: %s cardname [write]\n", name);
fprintf(stderr, "Example: %s hw:DSP > dumpfile\n", name);
fprintf(stderr, "Example: %s hw:DSP write < dumpfile\n", name);
}
void error_and_out(int err) {
fprintf(stderr, "ALSA error: %s\n", snd_strerror(err));
exit(err);
}
int main(int argc, char **argv) {
int err;
char *cardname;
snd_hwdep_info_t *info;
snd_hwdep_info_alloca(&info);
snd_ctl_elem_id_t *id;
snd_ctl_elem_value_t *ctl;
snd_ctl_t *handle;
int write = 0;
if (argc < 2) {
usage(argv[0]);
exit(1);
}
cardname = argv[1];
if (argc > 2 && (0 == strcmp("write", argv[2]))) {
write = 1;
}
snd_ctl_elem_value_alloca(&ctl);
snd_ctl_elem_id_alloca(&id);
snd_ctl_elem_id_set_name(id, "Mixer");
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_HWDEP);
snd_ctl_elem_id_set_device(id, 0);
snd_ctl_elem_id_set_index(id, 0);
snd_ctl_elem_value_set_id(ctl, id);
if ((err = snd_ctl_open(&handle, cardname, SND_CTL_NONBLOCK)) < 0) {
error_and_out(err);
}
for (int source = 0; source < 128; source++) {
for (int dest = 0; dest < 64; dest++) {
snd_ctl_elem_value_set_integer(ctl, 0, source);
snd_ctl_elem_value_set_integer(ctl, 1, dest);
if (write) {
char buf[1024];
fgets(buf, sizeof(buf), stdin);
snd_ctl_elem_value_set_integer(ctl, 2,
atoi(buf));
if ((err = snd_ctl_elem_write(handle, ctl)) < 0) {
snd_ctl_close(handle);
error_and_out(err);
}
} else {
if ((err = snd_ctl_elem_read(handle, ctl)) < 0) {
snd_ctl_close(handle);
error_and_out(err);
}
printf("%li\n", snd_ctl_elem_value_get_integer(ctl, 2));
}
}
}
snd_ctl_close(handle);
}