Browse Source

Rework dumping procedures

develop
Damien Goutte-Gattat 8 years ago
parent
commit
3618f56691
  1. 69
      src/kmxtool.c
  2. 318
      src/microx.c
  3. 23
      src/microx.h

69
src/kmxtool.c

@ -65,9 +65,6 @@ Send/receive data to/from a connected microX synthesizer.\n");
-d, --dump-data ID Dump the specified slot.\n\
-l, --load-data ID Load program read from standard\n\
input into the specified slot.\n\
-t, --data-type {program|combination|multi|drumkit|arpeggio|extset}\n\
Specify the type of data to dump\n\
or load. Default is `program'.\n\
");
printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
@ -158,11 +155,16 @@ do_list_programs(midi_io_t *midi)
size_t len;
int n;
unsigned char *reply, *cursor, bank, program;
struct kmx_microx_dump dump;
len = MICROX_PROGRAM_SIZE * MICROX_N_PROGRAM;
dump.type = PROGRAM_DATA;
dump.load = 0;
dump.bank = KMX_MICROX_DUMP_ALL;
len = kmx_microx_get_dump_size(&dump);
reply = xmalloc(len);
if ( (n = kmx_microx_dump(midi, PROGRAM_DATA, "????", reply, len)) < 0 )
if ( (n = kmx_microx_dump(midi, &dump, reply, len)) < 0 )
errx(EXIT_FAILURE, "cannot dump data: %s", kmx_microx_error(midi, n));
for ( cursor = reply, bank = 'A'; bank < 'F'; bank++ ) {
@ -179,24 +181,6 @@ do_list_programs(midi_io_t *midi)
free(reply);
}
struct kmx_data_type
{
enum kmx_microx_data_type code;
size_t size;
const char *name;
};
struct kmx_data_type kmx_data_types[] =
{
{ PROGRAM_DATA, MICROX_PROGRAM_SIZE, "program" },
{ COMBINATION_DATA, MICROX_COMBINATION_SIZE, "combination" },
{ MULTI_DATA, MICROX_MULTI_SIZE, "multi" },
{ DRUMKIT_DATA, MICROX_DRUMKIT_SIZE, "drumkit" },
{ ARPEGGIO_DATA, MICROX_ARPEGGIO_SIZE, "arpeggio" },
{ EXTSET_DATA, MICROX_EXTSET_SIZE, "extset" },
{ 0, 0, NULL }
};
/* Main function. */
@ -207,7 +191,7 @@ main(int argc, char **argv)
int e, mode;
struct kmx_microx_version version;
struct kmx_microx_status status;
struct kmx_data_type *type;
struct kmx_microx_dump dump;
struct option options[] = {
{ "help", 0, NULL, 'h' },
@ -227,7 +211,7 @@ main(int argc, char **argv)
port = DEFAULT_MIDI_PORT;
mode = MODE_STATUS;
type = kmx_data_types;
dump.load = 0;
while ( (c = getopt_long(argc, argv, "hvp:sd:l:t:L",
options, NULL)) != -1 ) {
@ -262,17 +246,6 @@ main(int argc, char **argv)
param = optarg;
break;
case 't':
while ( type->name ) {
if ( strcmp(type->name, optarg) == 0 )
break;
type += 1;
}
if ( type->name == NULL )
errx(EXIT_FAILURE, "invalid data type: %s", optarg);
break;
case 'L':
mode = MODE_PROGRAM_LIST;
break;
@ -297,28 +270,34 @@ main(int argc, char **argv)
print_microx_status(&status);
}
else if ( mode == MODE_DATA_DUMP ) {
unsigned char *program;
unsigned char *data;
int n;
program = xmalloc(type->size);
if ( kmx_microx_parse_dump_request(param, &dump) < 0 )
errx(EXIT_FAILURE, "invalid dump request: %s", param);
if ( (n = kmx_microx_dump(midi, type->code, param, program,
type->size)) < 0 )
n = kmx_microx_get_dump_size(&dump);
data = xmalloc(n);
if ( (n = kmx_microx_dump(midi, &dump, data, n)) < 0 )
errx(EXIT_FAILURE, "cannot dump data: %s",
kmx_microx_error(midi, n));
fprinthd(stdout, program, n, 0);
fprinthd(stdout, data, n, 0);
}
else if ( mode == MODE_DATA_LOAD ) {
unsigned char *program;
unsigned char *data;
ssize_t n;
program = NULL;
n = freadhda(stdin, &program, NULL);
if ( kmx_microx_parse_dump_request(param, &dump) < 0 )
errx(EXIT_FAILURE, "invalid load request: %s", param);
data = NULL;
n = freadhda(stdin, &data, NULL);
if ( n < 1 )
err(EXIT_FAILURE, "cannot read data");
if ( (n = kmx_microx_load(midi, type->code, param, program, n)) < 0 )
if ( (n = kmx_microx_load(midi, &dump, data, n)) < 0 )
errx(EXIT_FAILURE, "cannot load data: %s",
kmx_microx_error(midi, n));
}

318
src/microx.c

@ -221,110 +221,248 @@ kmx_microx_error(midi_io_t *midi, int e)
return msg;
}
struct dump {
unsigned char query_code;
unsigned char reply_code;
size_t data_size;
};
static struct dump dumps[] = {
{ 0x1C, 0x4C, MICROX_PROGRAM_SIZE },
{ 0x1D, 0x4D, MICROX_COMBINATION_SIZE },
{ 0x18, 0x48, MICROX_MULTI_SIZE },
{ 0x0D, 0x52, MICROX_DRUMKIT_SIZE },
{ 0x34, 0x69, MICROX_ARPEGGIO_SIZE },
{ 0x1E, 0x6E, MICROX_EXTSET_SIZE }
static struct {
unsigned char query;
unsigned char reply;
} dump_codes[] = {
{ 0x1C, 0x4C },
{ 0x1D, 0x4D },
{ 0x18, 0x48 },
{ 0x0D, 0x52 },
{ 0x34, 0x69 },
{ 0x1E, 0x6E }
};
static int
get_dump_parameters(enum kmx_microx_data_type type,
const char *what,
unsigned char *buffer,
int load,
size_t *size)
parse_int(const char *s)
{
unsigned char program, bank;
int val;
switch ( type ) {
case PROGRAM_DATA:
bank = what[0];
if ( bank != '?' && (bank < 'A' || bank > 'E') )
return KMX_INVALID_QUERY;
if ( bank == '?' ) { /* Dump all programs. */
buffer[0] = 0;
buffer[1] = 0;
*size = MICROX_PROGRAM_SIZE * MICROX_N_PROGRAM;
}
else if ( what[1] == '?' ) { /* Dump all programs in bank. */
buffer[0] = 0x10 + (bank - 'A');
buffer[1] = 0;
*size = MICROX_PROGRAM_SIZE * 128;
}
else if ( sscanf(&(what[1]), "%03hhd", &program) == 1 &&
program < 128 ) { /* Dump specified program. */
buffer[0] = 0x20 + (bank - 'A');
buffer[1] = program;
*size = MICROX_PROGRAM_SIZE;
val = 0;
while ( *s && val >= 0 ) {
if ( *s >= '0' && *s <= '9' )
val = val * 10 + *s - '0';
else
val = -1;
s += 1;
}
return val;
}
int
kmx_microx_parse_dump_request(const char *what, struct kmx_microx_dump *dump)
{
int val, ret;
char bank;
ret = 0;
switch ( *what++ ) {
case 'P':
dump->type = PROGRAM_DATA;
bank = *what++;
if ( bank == '*' )
dump->bank = KMX_MICROX_DUMP_ALL;
else if ( bank >= 'A' && bank <= 'E' ) {
dump->bank = bank - 'A';
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 128 )
dump->program = val - 1;
else
ret = -1;
}
else
return KMX_INVALID_QUERY;
ret = -1;
break;
if ( load ) {
buffer[2] = buffer[1];
buffer[1] = buffer[0];
buffer[0] = 1;
case 'C':
dump->type = COMBINATION_DATA;
bank = *what++;
if ( bank == '*' )
dump->bank = KMX_MICROX_DUMP_ALL;
else if ( bank >= 'A' && bank <= 'C' ) {
dump->bank = bank - 'A';
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 128 )
dump->program = val - 1;
else
ret = -1;
}
else
ret = -1;
break;
case 'M':
dump->type = MULTI_DATA;
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 128 )
dump->program = val - 1;
else
ret = -1;
break;
case 'D':
dump->type = DRUMKIT_DATA;
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 40 )
dump->program = val - 1;
else
ret = -1;
break;
case 'A':
dump->type = ARPEGGIO_DATA;
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 251 )
dump->program = val - 1;
else
ret = -1;
break;
case 'E':
dump->type = EXTSET_DATA;
if ( *what == '*' )
dump->program = KMX_MICROX_DUMP_ALL;
else if ( (val = parse_int(what)) >= 1 && val <= 64 )
dump->program = val - 1;
else
ret = -1;
break;
default:
ret = -1;
}
return ret;
}
size_t
kmx_microx_get_dump_size(struct kmx_microx_dump *dump)
{
size_t s;
switch ( dump->type ) {
case PROGRAM_DATA:
s = MICROX_PROGRAM_SIZE;
if ( dump->bank == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_PROGRAM;
else if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= 128;
break;
case COMBINATION_DATA:
if ( sscanf(what, "%c%03hhd", &bank, &program) != 2 )
return KMX_INVALID_QUERY;
if ( (bank < 'A' || bank > 'C') || program > 127 )
return KMX_INVALID_QUERY;
buffer[0] = 0x20 + (bank - 'A');
buffer[1] = program;
*size = MICROX_COMBINATION_SIZE;
if ( load ) {
buffer[2] = buffer[1];
buffer[1] = buffer[0];
buffer[0] = 0;
s = MICROX_COMBINATION_SIZE;
if ( dump->bank == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_COMBINATION;
else if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= 128;
break;
case MULTI_DATA:
s = MICROX_MULTI_SIZE;
if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_MULTI;
break;
case DRUMKIT_DATA:
s = MICROX_DRUMKIT_SIZE;
if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_DRUMKIT;
break;
case ARPEGGIO_DATA:
s = MICROX_ARPEGGIO_SIZE;
if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_ARPEGGIO;
break;
case EXTSET_DATA:
s = MICROX_EXTSET_SIZE;
if ( dump->program == KMX_MICROX_DUMP_ALL )
s *= MICROX_N_EXTSET;
break;
}
return s;
}
static int
get_dump_parameters(struct kmx_microx_dump *dump,
unsigned char *buffer)
{
buffer[0] = dump->load ? dump_codes[dump->type].reply
: dump_codes[dump->type].query;
switch ( dump->type ) {
case PROGRAM_DATA:
if ( dump->bank != KMX_MICROX_DUMP_ALL ) {
if ( dump->program == KMX_MICROX_DUMP_ALL )
buffer[1] = 0x10 + dump->bank;
else {
if ( dump->load ) {
buffer[1] = 1;
buffer[2] = 0x20 + dump->bank;
buffer[3] = dump->program;
}
else {
buffer[1] = 0x20 + dump->bank;
buffer[2] = dump->program;
}
}
}
break;
case COMBINATION_DATA:
if ( dump->bank != KMX_MICROX_DUMP_ALL ) {
if ( dump->program == KMX_MICROX_DUMP_ALL )
buffer[1] = 0x10 + dump->bank;
else {
if ( dump->load ) {
buffer[2] = 0x20 + dump->bank;
buffer[3] = dump->program;
}
else {
buffer[1] = 0x20 + dump->bank;
buffer[2] = dump->program;
}
}
}
break;
case MULTI_DATA:
if ( sscanf(what, "%02hhd", &program) != 1 || program > 127 )
return KMX_INVALID_QUERY;
buffer[0] = 1;
buffer[1] = program;
*size = MICROX_MULTI_SIZE;
if ( dump->program != KMX_MICROX_DUMP_ALL ) {
buffer[1] = 1;
buffer[2] = dump->program;
}
break;
case DRUMKIT_DATA:
if ( sscanf(what, "%03hhd", &program) != 1 || program > 39 )
return KMX_INVALID_QUERY;
buffer[0] = 1;
buffer[1] = program;
*size = MICROX_DRUMKIT_SIZE;
if ( dump->program != KMX_MICROX_DUMP_ALL ) {
buffer[1] = 1;
buffer[2] = dump->program;
}
break;
case ARPEGGIO_DATA:
if ( sscanf(what, "%03hhd", &program) != 1 || program > 250 )
return KMX_INVALID_QUERY;
buffer[0] = 0x40;
buffer[1] = program >> 7;
buffer[2] = program & 0x7F;
*size = MICROX_ARPEGGIO_SIZE;
if ( dump->program != KMX_MICROX_DUMP_ALL ) {
buffer[1] = 0x40;
buffer[2] = dump->program >> 7;
buffer[3] = dump->program & 0x7F;
}
break;
case EXTSET_DATA:
if ( sscanf(what, "%02hhd", &program) != 1 || program > 63 )
return KMX_INVALID_QUERY;
buffer[0] = 1;
buffer[1] = program;
*size = MICROX_EXTSET_SIZE;
if ( dump->program != KMX_MICROX_DUMP_ALL ) {
buffer[1] = 1;
buffer[2] = dump->program;
}
break;
}
@ -392,11 +530,10 @@ kmx_microx_read_dump(midi_io_t *midi,
}
int
kmx_microx_dump(midi_io_t *midi,
enum kmx_microx_data_type type,
const char *what,
unsigned char *data,
size_t len)
kmx_microx_dump(midi_io_t *midi,
struct kmx_microx_dump *dump,
unsigned char *data,
size_t len)
{
size_t n;
unsigned char query[] = { 0xF0, /* SysEx message begin */
@ -409,23 +546,21 @@ kmx_microx_dump(midi_io_t *midi,
0x00, /* Dump parameter 3 */
0xF7 /* SysEx message end */ };
query[4] = dumps[type].query_code;
if ( get_dump_parameters(type, what, &(query[5]), 0, &n) < 0 )
if ( get_dump_parameters(dump, &(query[4])) < 0 )
return KMX_INVALID_QUERY;
if ( len < n )
if ( len < kmx_microx_get_dump_size(dump) )
return KMX_BUFFER_TOO_SMALL;
if ( (n = midi_write(midi, query, sizeof(query))) < 0 )
return KMX_IO_ERROR;
return kmx_microx_read_dump(midi, dumps[type].reply_code, data, len);
return kmx_microx_read_dump(midi, dump_codes[dump->type].reply, data, len);
}
int
kmx_microx_load(midi_io_t *midi,
enum kmx_microx_data_type type,
const char *what,
struct kmx_microx_dump *dump,
unsigned char *data,
size_t len)
{
@ -441,11 +576,10 @@ kmx_microx_load(midi_io_t *midi,
0x00, /* Dump parameter 3 */ };
unsigned char reply[7];
buffer[4] = dumps[type].reply_code;
if ( get_dump_parameters(type, what, &(buffer[5]), 1, &n) < 0 )
if ( get_dump_parameters(dump, &(buffer[4])) < 0 )
return KMX_INVALID_QUERY;
if ( len < n )
if ( len < kmx_microx_get_dump_size(dump) )
return KMX_BUFFER_TOO_SMALL;
n = 8;

23
src/microx.h

@ -151,6 +151,16 @@ struct kmx_microx_status
} ext_ctrl;
};
#define KMX_MICROX_DUMP_ALL -1
struct kmx_microx_dump
{
enum kmx_microx_data_type type;
char load;
char bank;
short program;
};
#ifdef __cpluscplus
extern "C" {
#endif
@ -164,6 +174,13 @@ kmx_microx_query_status(midi_io_t *, struct kmx_microx_status *);
const char *
kmx_microx_error(midi_io_t *, int);
int
kmx_microx_parse_dump_request(const char *,
struct kmx_microx_dump *);
size_t
kmx_microx_get_dump_size(struct kmx_microx_dump *);
int
kmx_microx_read_dump(midi_io_t *,
unsigned char,
@ -172,15 +189,13 @@ kmx_microx_read_dump(midi_io_t *,
int
kmx_microx_dump(midi_io_t *,
enum kmx_microx_data_type,
const char *,
struct kmx_microx_dump *,
unsigned char *,
size_t);
int
kmx_microx_load(midi_io_t *,
enum kmx_microx_data_type,
const char *,
struct kmx_microx_dump *,
unsigned char *,
size_t );

Loading…
Cancel
Save