Browse Source

Add the kmxtool program

master
Damien Goutte-Gattat 9 years ago
parent
commit
31671a412e
  1. 4
      src/Makefile.am
  2. 194
      src/kmxtool.c
  3. 162
      src/microx.c
  4. 124
      src/microx.h

4
src/Makefile.am

@ -1,7 +1,9 @@
bin_PROGRAMS = asysex
bin_PROGRAMS = asysex kmxtool
asysex_SOURCES = asysex.c midi.h midi.c sysex.h sysex.c manufacturers.h
kmxtool_SOURCES = kmxtool.c microx.c microx.h midi.c midi.h sysex.c sysex.h
AM_CPPFLAGS = -I$(top_srcdir)/lib
AM_LDFLAGS = -L$(top_builddir)/lib
LDADD = -lcvasysex

194
src/kmxtool.c

@ -0,0 +1,194 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include <getopt.h>
#include <err.h>
#include <microx.h>
/* Globals. */
static midi_io_t *midi = NULL;
/* Help and informations about the program. */
static void
usage(int status)
{
puts("\
Usage: kmxtool [options]\n\
Send/receive data to/from a connected microX synthesizer.\n");
puts("Options:\n\
-h, --help Display this help message.\n\
-v, --version Display the version message.\n\
");
puts("\
-p, --port PORT Specify MIDI port to use.\n\
");
printf("Report bugs to <%s>.\n", PACKAGE_BUGREPORT);
exit(status);
}
static void
info(void)
{
printf("\
kmxtool %s\n\
Copyright (C) 2012 Damien Goutte-Gattat\n\
\n\
This program is released under the GNU General Public License.\n\
See the COPYING file or <http://www.gnu.org/licenses/gpl.html>.\n\
", VERSION);
exit(EXIT_SUCCESS);
}
/* Helper functions. */
static void
cleanup(void)
{
if ( midi ) {
midi_close(midi);
midi = NULL;
}
}
static void
print_microx_status(struct kmx_microx_status *s)
{
static char *modes[] = { "COMBI PLAY", "COMBI EDIT", "PROG PLAY",
"PROG EDIT", "MULTI", "GLOBAL" };
static char *clock[] = { "Internal", "Ext-MIDI", "Ext-USB", "AUTO" };
static char *flter[] = { "All", "Odd", "Even" };
static char *yesno[] = { "No", "Yes" };
static char *bnkmp[] = { "KORG", "GM" };
printf("Global channel: %d\n", s->global_channel);
printf("Active mode: %s\n",
s->active_mode == DEMO ? "DEMO" : modes[s->active_mode]);
printf("Status of Global mode:\n");
printf(" Local Control: %s\n", yesno[s->global.local_control]);
printf(" Clock Source: %s\n", clock[s->global.clock_source]);
printf(" Bank Map: %s\n", bnkmp[s->global.bank_map]);
printf(" Memorize Mode on Power On: %s\n", yesno[s->global.memorize_mode]);
printf(" Rec. Ext.Realtime Command: %s\n", yesno[s->global.rec_ext_rt_cmd]);
printf(" Enable Program Change: %s\n", yesno[s->global.prgm_change]);
printf(" Enable Bank Change: %s\n", yesno[s->global.bank_change]);
printf(" Enable Combination Change: %s\n", yesno[s->global.comb_change]);
printf(" Enable Control Change: %s\n", yesno[s->global.ctrl_change]);
printf(" Enable Aftertouch: %s\n", yesno[s->global.aftertouch]);
printf(" Note filter: %s\n", flter[s->global.note_filter]);
printf(" Protected Memory:\n");
printf(" Program: %s\n", yesno[s->global.protected_memory.program]);
printf(" Bank: %s\n", yesno[s->global.protected_memory.bank]);
printf(" Multi: %s\n", yesno[s->global.protected_memory.multi]);
printf(" Drums: %s\n", yesno[s->global.protected_memory.drum]);
printf(" Arpeggio Patterns: %s\n", yesno[s->global.protected_memory.arpeggio]);
printf(" Ext.Controllers: %s\n", yesno[s->global.protected_memory.ext_ctrl]);
printf("Status of Program mode:\n");
printf(" Current Bank: %c\n", 'A' + s->program.current_bank);
printf(" Current Program: %d\n", s->program.current_program);
printf("Status of Combination mode:\n");
printf(" Current Bank: %c\n", 'A' + s->combination.current_bank);
printf(" Current Combination: %d\n", s->combination.current_combination);
printf("Status of Multi mode:\n");
printf(" Current Multi: %d\n", s->multi.current_multi);
printf(" Control Track: %d\n", s->multi.control_track + 1);
printf("Status of Ext.Controllers:\n");
printf(" Ext.Controllers Enabled: %s\n", yesno[s->ext_ctrl.enabled]);
printf(" Current Controller: %d\n", s->ext_ctrl.current);
}
/* Main function. */
int
main(int argc, char **argv)
{
char c, *port;
struct kmx_microx_version version;
struct kmx_microx_status status;
struct option options[] = {
{ "help", 0, NULL, 'h' },
{ "version", 0, NULL, 'v' },
{ "port", 1, NULL, 'p' },
{ NULL, 0, NULL, 0 }
};
setprogname(argv[0]);
setlocale(LC_ALL, "");
atexit(cleanup);
port = DEFAULT_MIDI_PORT;
while ( (c = getopt_long(argc, argv, "hvp:", options, NULL)) != -1 ) {
switch ( c ) {
case 'h':
usage(EXIT_SUCCESS);
break;
case '?':
usage(EXIT_FAILURE);
break;
case 'v':
info();
break;
case 'p':
port = optarg;
break;
}
}
if ( ! (midi = midi_open(port)) )
errx(EXIT_FAILURE, "cannot open MIDI port %s", port);
if ( kmx_microx_identify(midi, &version) < 0 )
errx(EXIT_FAILURE, "cannot identify microX device");
printf("%s: KORG microX synthesizer, version %02d.%02d.%02d.%02d\n",
port, version.major, version.minor, version.release, version.build);
if ( kmx_microx_query_status(midi, &status) < 0 )
errx(EXIT_FAILURE, "cannot query microX status");
print_microx_status(&status);
return EXIT_SUCCESS;
}

162
src/microx.c

@ -0,0 +1,162 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <microx.h>
#include <sysex.h>
int
kmx_microx_identify(midi_io_t *midi,
struct kmx_microx_version *version)
{
int n;
midi_device_id_t devid;
if ( (n = sysex_identify(midi, &devid)) < 0 )
return KMX_IO_ERROR;
else if ( n == 0 )
return KMX_INVALID_REPLY;
if ( devid.manufacturer != KORG_ID )
return KMX_NOT_KORG;
if ( devid.family != MICROX_ID || devid.model != MICROX_SUB_ID )
return KMX_NOT_MICROX;
if ( version ) {
version->major = devid.version & 0xFF;
version->minor = (devid.version >> 8) & 0xFF;
version->release = (devid.version >> 16) & 0xFF;
version->build = (devid.version >> 24) & 0xFF;
}
return 0;
}
int
kmx_microx_query_status(midi_io_t *midi,
struct kmx_microx_status *s)
{
ssize_t n;
unsigned char reply[64];
unsigned char query[] = { 0xF0, /* SysEx message begin */
0x42, /* KORG manufacturer ID */
0x30, /* SysEx channel (1) */
0x7A, /* End of SysEx header */
0x12, /* Mode and state request */
0xF7 /* SysEx message end */ };
if ( (n = sysex_query(midi, query, sizeof(query),
reply, sizeof(reply))) < 0 )
return KMX_IO_ERROR;
/*
* Expected Mode and state Reply (27 bytes):
* Byte # Value Meaning
* 0 0xF0 SysEx message begin
* 1 0x42 KORG manufacturer ID
* 2 0x3n Global channel (n = 0x0 ~ 0xF)
* 3 0x7A End of SysEx header
* 4 0x42 Mode and state reply
* 5 0xnn Current mode (one of kmx_microx_mode)
* 6 0x06 Status of Global mode
* 7 0xnn Global mode setting data 1
* bit 0: Local Control Off/On
* bits 1,2: MIDI Clock (one of kmx_microx_clock)
* bit 3: (Reserved)
* bit 4: Bank MAP KORG/GM
* bit 5: Power On Mode Reset/Memorize
* bit 6: Receive Ext.Realtime Command Off/On
* 8 0xnn Global mode setting data 2
* bit 0: Enable Program Change Off/On
* bit 1: Enable Bank Change Off/On
* bit 2: Enable Combination Change Off/On
* bit 3: Enable Aftertouch Off/On
* bit 4: Enable Control Change Off/On
* bits 5,6: Note Filter All/Even/Odd
* 9 0xnn Global mode setting data 3 (Memory Protection)
* bit 0: Program
* bit 1: Combination
* bit 2: Multi
* bit 3: Drums
* bit 4: ArpeggioPattern
* bit 5: Ext.Control
* 10 0x02 Status of Program mode
* 11 0x0n Current Bank (n = 0x0 ~ 0x4, bank A ~ E)
* 12 0xnn Current Program (n = 0x0 ~ 0x7F)
* 13 0x00 (Reserved)
* 14 0x00 Status of Combination mode
* 15 0x0n Current Bank (n = 0x0 ~ 0x2, bank A ~ C)
* 16 0xnn Current Combination (n = 0x0 ~ 0x7F)
* 17 0x00 (Reserved)
* 18 0x04 Status of Multi mode
* 19 0x00 (Reserved)
* 20 0xnn Current Multi (n = 0x0 ~ 0x7F)
* 21 0x0n Control Track (n = 0x0 ~ 0xF, track 1 ~ 16)
* 22 0x21 Status of Ext.Controller
* 23 0x0n Ext.Controller Off/On
* 24 0xnn Current Controller (n = 0x0 ~ 0x3F)
* 25 0x00 (Reserved)
* 26 0xF7 SysEx message end
*/
if ( n != 27 || reply[4] != 0x42 )
return KMX_INVALID_REPLY;
if ( reply[1] != KORG_ID )
return KMX_NOT_KORG;
if ( s ) {
s->global_channel = reply[2] & 0xF;
s->active_mode = reply[5];
s->global.local_control = reply[7] & 0x1;
s->global.clock_source = reply[7] >> 1 & 0x3;
s->global.bank_map = reply[7] >> 4 & 0x1;
s->global.memorize_mode = reply[7] >> 5 & 0x1;
s->global.rec_ext_rt_cmd = reply[7] >> 6 & 0x1;
s->global.prgm_change = reply[8] & 0x1;
s->global.bank_change = reply[8] >> 1 & 0x1;
s->global.comb_change = reply[8] >> 2 & 0x1;
s->global.aftertouch = reply[8] >> 3 & 0x1;
s->global.ctrl_change = reply[8] >> 4 & 0x1;
s->global.note_filter = reply[8] >> 5 & 0x3;
s->global.protected_memory.program = reply[9] & 0x1;
s->global.protected_memory.bank = reply[9] >> 1 & 0x1;
s->global.protected_memory.multi = reply[9] >> 2 & 0x1;
s->global.protected_memory.drum = reply[9] >> 3 & 0x1;
s->global.protected_memory.arpeggio = reply[9] >> 4 & 0x1;
s->global.protected_memory.ext_ctrl = reply[9] >> 5 & 0x1;
s->program.current_bank = reply[11];
s->program.current_program = reply[12];
s->combination.current_bank = reply[15];
s->combination.current_combination = reply[16];
s->multi.current_multi = reply[20];
s->multi.control_track = reply[21];
s->ext_ctrl.enabled = reply[23];
s->ext_ctrl.current = reply[24];
}
return 0;
}

124
src/microx.h

@ -0,0 +1,124 @@
/*
* kmxtool - KORG microX utility
* Copyright (C) 2012 Damien Goutte-Gattat
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ICP20121016_MICROX_H
#define ICP20121016_MICROX_H
#include <midi.h>
/* Identifiers. */
#define KORG_ID 0x42
#define MICROX_ID 0x7A
#define MICROX_SUB_ID 0x09
/* Error codes. */
#define KMX_IO_ERROR -1
#define KMX_INVALID_REPLY -2
#define KMX_NOT_KORG -3
#define KMX_NOT_MICROX -4
struct kmx_microx_version
{
unsigned char major;
unsigned char minor;
unsigned char release;
unsigned char build;
};
enum kmx_microx_mode
{
COMBI_PLAY = 0x00,
COMBI_EDIT,
PROG_PLAY,
PROG_EDIT,
MULTI,
GLOBAL,
DEMO = 0x7F
};
enum kmx_microx_clock
{
INTERNAL = 0x00,
EXT_MIDI,
EXT_USB,
AUTO
};
struct kmx_microx_status
{
unsigned char global_channel;
enum kmx_microx_mode active_mode;
struct {
unsigned char local_control;
enum kmx_microx_clock clock_source;
unsigned char bank_map;
unsigned char memorize_mode;
unsigned char rec_ext_rt_cmd;
unsigned char prgm_change;
unsigned char bank_change;
unsigned char comb_change;
unsigned char ctrl_change;
unsigned char aftertouch;
unsigned char note_filter;
struct {
unsigned char program;
unsigned char bank;
unsigned char multi;
unsigned char drum;
unsigned char arpeggio;
unsigned char ext_ctrl;
} protected_memory;
} global;
struct {
unsigned char current_bank;
unsigned char current_program;
} program;
struct {
unsigned char current_bank;
unsigned char current_combination;
} combination;
struct {
unsigned char current_multi;
unsigned char control_track;
} multi;
struct {
unsigned char enabled;
unsigned char current;
} ext_ctrl;
};
#ifdef __cpluscplus
extern "C" {
#endif
int
kmx_microx_identify(midi_io_t *, struct kmx_microx_version *);
int
kmx_microx_query_status(midi_io_t *, struct kmx_microx_status *);
#ifdef __cplusplus
}
#endif
#endif /* !ICP20121016_MICROX_H */
Loading…
Cancel
Save